Commit 8814cb68 by 延飞 李

OEE 时间利用率中日均运行时间统计显示的百分比改为显示分钟

parent 9d819237
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<title>OEE时间利用率</title> <title>OEE时间利用率</title>
<meta <meta
content="width=device-width,initial-scale=1.0, maximum-scale=1.0,user-scalable=0" content="width=device-width,initial-scale=1.0, maximum-scale=1.0,user-scalable=0"
name="viewport" name="viewport"
/> />
<!-- 本地资源引用 --> <!-- 本地资源引用 -->
<link rel="stylesheet" href="/roke_workstation_api/static/html/routing/element-ui/index.css" /> <link rel="stylesheet" href="/roke_workstation_api/static/html/routing/element-ui/index.css" />
<script src="/roke_workstation_api/static/html/routing/js/echarts.min.js"></script> <script src="/roke_workstation_api/static/html/routing/js/echarts.min.js"></script>
<script src="/roke_workstation_api/static/html/routing/js/moment.min.js"></script> <script src="/roke_workstation_api/static/html/routing/js/moment.min.js"></script>
<script src="/roke_workstation_api/static/html/routing/js/vue.js"></script> <script src="/roke_workstation_api/static/html/routing/js/vue.js"></script>
<script src="/roke_workstation_api/static/html/routing/js/axios.min.js"></script> <script src="/roke_workstation_api/static/html/routing/js/axios.min.js"></script>
<script src="/roke_workstation_api/static/html/routing/element-ui/index.js"></script> <script src="/roke_workstation_api/static/html/routing/element-ui/index.js"></script>
</head> </head>
<body id="bodyId" style="display: none"> <body id="bodyId" style="display: none">
<div id="app"> <div id="app">
<!-- v-show="performanceShow" --> <!-- v-show="performanceShow" -->
<!-- v-loading.body.fullscreen.lock="idle_rate_loading" --> <!-- v-loading.body.fullscreen.lock="idle_rate_loading" -->
<!-- 新增:多设备空闲率图表 --> <!-- 新增:多设备空闲率图表 -->
<div class="multi-utilization-chart glass-effect"> <div class="multi-utilization-chart glass-effect">
<div class="section-title"> <div class="section-title">
<div class="title-bar"></div> <div class="title-bar"></div>
<span class="title-text">多设备空闲率对比</span> <span class="title-text">多设备空闲率对比</span>
</div> </div>
<div <div
id="multiUtilizationChart" id="multiUtilizationChart"
ref="multiUtilizationChart" ref="multiUtilizationChart"
style="width: 100%; height: 280px" style="width: 100%; height: 280px"
></div> ></div>
</div> </div>
<!-- 单设备图表的设备选择器 --> <!-- 单设备图表的设备选择器 -->
<div class="chart-select-wrapper"> <div class="chart-select-wrapper">
<span class="select-label">设备</span> <span class="select-label">设备</span>
<el-select <el-select
v-model="selectedDevice" v-model="selectedDevice"
placeholder="请选择设备" placeholder="请选择设备"
size="small" size="small"
clearable clearable
@change="selDeviceChange" @change="selDeviceChange"
class="chart-select" class="chart-select"
> >
<el-option <el-option
v-for="(item,index) in deviceList" v-for="(item,index) in deviceList"
:label="item.name" :label="item.name"
:value="item.code" :value="item.code"
:key="index" :key="index"
> >
</el-option> </el-option>
</el-select> </el-select>
</div> </div>
<div class="utilization-chart glass-effect"> <div class="utilization-chart glass-effect">
<div class="section-title"> <div class="section-title">
<div class="title-bar"></div> <div class="title-bar"></div>
<span class="title-text">设备空闲率</span> <span class="title-text">设备空闲率</span>
</div> </div>
<div id="utilizationChart" ref="utilizationChart" style="width: 100%; height: 280px"></div> <div id="utilizationChart" ref="utilizationChart" style="width: 100%; height: 280px"></div>
</div> </div>
<!-- 底部状态图 --> <!-- 底部状态图 -->
<!-- v-loading.body.fullscreen.lock="chart_loading" --> <!-- v-loading.body.fullscreen.lock="chart_loading" -->
<div class="status-chart glass-effect"> <div class="status-chart glass-effect">
<div class="section-title"> <div class="section-title">
<div class="title-bar"></div> <div class="title-bar"></div>
<span class="title-text">日均运行时间统计</span> <span class="title-text">日均运行时间统计(分钟)</span>
</div> </div>
<div class="chart-container"> <div class="chart-container">
<!-- 图例区域 --> <!-- 图例区域 -->
<div class="flex_legend"> <div class="flex_legend">
<div class="single_sty"> <div class="single_sty">
<div style="background-color: red"></div> <div style="background-color: red"></div>
<span>故障</span> <span>故障</span>
</div> </div>
<div class="single_sty"> <div class="single_sty">
<div style="background-color: yellow"></div> <div style="background-color: yellow"></div>
<span>等待</span> <span>等待</span>
</div> </div>
<div class="single_sty"> <div class="single_sty">
<div style="background-color: green"></div> <div style="background-color: green"></div>
<span>运行</span> <span>运行</span>
</div> </div>
<div class="single_sty"> <div class="single_sty">
<div style="background-color: gray"></div> <div style="background-color: gray"></div>
<span>关机</span> <span>关机</span>
</div> </div>
</div> </div>
<!-- Y轴刻度 --> <!-- Y轴刻度 -->
<div class="y-axis"> <div class="y-axis">
<span v-for="(value, index) in yAxisValues" :key="index" class="y-axis-label"> <span v-for="(value, index) in yAxisValues" :key="index" class="y-axis-label">
[[value]] [[value]]
<span class="unit">%</span> <span class="unit">分钟</span>
</span> </span>
</div> </div>
<!-- 图表主体区域 --> <!-- 图表主体区域 -->
<div class="chart-content"> <div class="chart-content">
<div class="horizontal-lines"> <div class="horizontal-lines">
<div v-for="(value, index) in yAxisValues" :key="index" class="horizontal-line"></div> <div v-for="(value, index) in yAxisValues" :key="index" class="horizontal-line"></div>
</div> </div>
<!-- 改为单个容器包含柱状图和X轴标签 --> <!-- 改为单个容器包含柱状图和X轴标签 -->
<div class="columns-container"> <div class="columns-container">
<div <div
class="column-with-label" class="column-with-label"
v-for="(item, dayIndex) in pickingOrderList" v-for="(item, dayIndex) in pickingOrderList"
:key="dayIndex" :key="dayIndex"
> >
<!-- 柱状图部分 --> <!-- 柱状图部分 -->
<div class="column-group"> <div class="column-group">
<div class="column-stack"> <div class="column-stack">
<div <div
class="column-segment" class="column-segment"
v-for="(segment, stackIndex) in item" v-for="(segment, stackIndex) in item"
:key="stackIndex" :key="stackIndex"
:style="{ :style="{
'height': calculateHeight(segment.duration_percentage) + '%', 'height': calculateHeightByMinutes(convertSecondsToMinutes(segment.duration)) + '%',
'background-color': segment.state, 'background-color': segment.state,
'margin-top': '0px' 'margin-top': '0px'
}" }"
> >
<el-tooltip <el-tooltip
effect="dark" effect="dark"
:content="calculateHeight(segment.duration_percentage) + '%'" :content="convertSecondsToMinutes(segment.duration) + '分钟'"
placement="top" placement="top"
> >
<div style="height: 100%; width: 100%"></div> <div style="height: 100%; width: 100%"></div>
</el-tooltip> </el-tooltip>
</div> </div>
</div> </div>
</div> </div>
<!-- X轴标签部分 - 直接绑定在柱状图下方 --> <!-- X轴标签部分 - 直接绑定在柱状图下方 -->
<div class="x-axis-label">[[ latestDateList[dayIndex] ]]</div> <div class="x-axis-label">[[ latestDateList[dayIndex] ]]</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</body> </body>
<script> <script>
// 发送消息给父页面(关闭odoo的菜单弹窗) // 发送消息给父页面(关闭odoo的菜单弹窗)
document.addEventListener("click", () => { document.addEventListener("click", () => {
window.parent.postMessage("hidePopover", "*"); window.parent.postMessage("hidePopover", "*");
}); });
let vue = new Vue({ let vue = new Vue({
el: "#app", el: "#app",
delimiters: ["[[", "]]"], // 替换原本vue的[[ key ]]取值方式(与odoo使用的jinja2冲突问题) delimiters: ["[[", "]]"], // 替换原本vue的[[ key ]]取值方式(与odoo使用的jinja2冲突问题)
data() { data() {
return { return {
windowHeight: window.innerHeight, // 窗口高度 windowHeight: window.innerHeight, // 窗口高度
// baseURL: "https://workstation.rokeris.com", // 基地址 https://workstation.rokeris.com // baseURL: "https://workstation.rokeris.com", // 基地址 https://workstation.rokeris.com
// baseURL: "http://qdry.dws.rokecloud.com", // baseURL: "http://qdry.dws.rokecloud.com",
baseURL: "", // 基地址 https://workstation.rokeris.com baseURL: "", // 基地址 https://workstation.rokeris.com
localURL: "https://dws-platform.xbg.rokeris.com/dev-api", // 基地址 https://workstation.rokeris.com localURL: "https://dws-platform.xbg.rokeris.com/dev-api", // 基地址 https://workstation.rokeris.com
idle_rate_loading: false, // 加载效果 idle_rate_loading: false, // 加载效果
chart_loading: false, chart_loading: false,
deviceList: [], // 设备列表 deviceList: [], // 设备列表
selectedDevice: null, // 选中的设备 selectedDevice: null, // 选中的设备
yAxisValues: ["100", "80", "60", "40", "20", "0"], // Y轴刻度值 yAxisValues: ["1440", "1152", "864", "576", "288", "0"], // Y轴刻度值(分钟)
pickingOrderList: [], // 拣选单列表 pickingOrderList: [], // 拣选单列表
dateList: [], // 日期列表 dateList: [], // 日期列表
start_time: "", // 开始时间 start_time: "", // 开始时间
end_time: "", // 结束时间 end_time: "", // 结束时间
utilizationChart: null, // 设备空闲率图表实例变量 utilizationChart: null, // 设备空闲率图表实例变量
multiUtilizationChart: null, // 新增:多设备空闲率图表实例变量 multiUtilizationChart: null, // 新增:多设备空闲率图表实例变量
plan_time_list: null, plan_time_list: null,
latestDateList: [], latestDateList: [],
factory_code: "8d8dec6e-0d44-11f0-9692-00163e04c506", factory_code: "8d8dec6e-0d44-11f0-9692-00163e04c506",
}; };
}, },
computed: { computed: {
// 选中设备的信息 // 选中设备的信息
selDeviceInfo() { selDeviceInfo() {
return this.deviceList.find((item) => item.id == this.selectedDevice); return this.deviceList.find((item) => item.id == this.selectedDevice);
}, },
}, },
created() { created() {
if (this.getUrlSearch("factory_code")) { if (this.getUrlSearch("factory_code")) {
this.factory_code = this.getUrlSearch("factory_code"); //截取url后面的参数 this.factory_code = this.getUrlSearch("factory_code"); //截取url后面的参数
} }
this.get_device_list(); this.get_device_list();
// 先设置好日期范围,以便后续使用 // 先设置好日期范围,以便后续使用
this.latestDateList = this.getLastTenDays(); this.latestDateList = this.getLastTenDays();
this.$nextTick(() => { this.$nextTick(() => {
document.getElementById("bodyId").style.display = "block"; document.getElementById("bodyId").style.display = "block";
// 在DOM渲染后初始化图表 // 在DOM渲染后初始化图表
if (this.$refs.utilizationChart) { if (this.$refs.utilizationChart) {
this.initUtilizationChart(); this.initUtilizationChart();
} }
// 初始化多设备空闲率图表 // 初始化多设备空闲率图表
if (this.$refs.multiUtilizationChart) { if (this.$refs.multiUtilizationChart) {
this.initMultiUtilizationChart(); this.initMultiUtilizationChart();
} }
}); });
window.addEventListener("resize", this.handleResize); window.addEventListener("resize", this.handleResize);
// 获取最后指定天数的日期 // 获取最后指定天数的日期
this.dateList = this.getLastAssignDays(); this.dateList = this.getLastAssignDays();
}, },
methods: { methods: {
// 获取所有已绑定设备数据 // 获取所有已绑定设备数据
async getAllEquipmentData(data_list) { async getAllEquipmentData(data_list) {
try { try {
// 发送请求获取所有已绑定设备数据 // 发送请求获取所有已绑定设备数据
const response = await axios({ const response = await axios({
method: "post", method: "post",
url: this.baseURL + "/roke/workstation/equipment/get_equipment_data", url: this.baseURL + "/roke/workstation/equipment/get_equipment_data",
data: {}, data: {},
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
}); });
// 处理JSON-RPC格式的响应 // 处理JSON-RPC格式的响应
if (response.data && response.data.result && response.data.result.code === 0) { if (response.data && response.data.result && response.data.result.code === 0) {
// 存储所有设备数据 // 存储所有设备数据
data_list.forEach((data_item) => { data_list.forEach((data_item) => {
response.data.result.data.forEach((item) => { response.data.result.data.forEach((item) => {
if (data_item.device_code == item.code) { if (data_item.device_code == item.code) {
this.deviceList.push(item); this.deviceList.push(item);
} }
}); });
}); });
this.get_plan_time(); this.get_plan_time();
console.log("获取到所有已绑定设备数据:", this.deviceList.length, "条"); console.log("获取到所有已绑定设备数据:", this.deviceList.length, "条");
} else { } else {
const errorMsg = response.data.result const errorMsg = response.data.result
? response.data.result.message ? response.data.result.message
: "获取所有已绑定设备数据失败"; : "获取所有已绑定设备数据失败";
throw new Error(errorMsg); throw new Error(errorMsg);
} }
} catch (error) { } catch (error) {
console.error("获取所有已绑定设备数据出错:", error); console.error("获取所有已绑定设备数据出错:", error);
throw error; throw error;
} }
}, },
// 获取日均运行时间统计 // 获取日均运行时间统计
get_daily_running_time() { get_daily_running_time() {
if (!this.selectedDevice) { if (!this.selectedDevice) {
this.pickingOrderList = []; this.pickingOrderList = [];
return; return;
} }
this.idle_rate_loading = true; this.idle_rate_loading = true;
axios({ axios({
method: "post", method: "post",
url: this.localURL + "/public/device_efficiency/daily_running_time", url: this.localURL + "/public/device_efficiency/daily_running_time",
data: { data: {
device_code: this.selectedDevice, device_code: this.selectedDevice,
}, },
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
}) })
.then((res) => { .then((res) => {
if (res.data.code == 200) { if (res.data.code == 200) {
this.pickingOrderList = res.data.data.daily_running_list; this.pickingOrderList = res.data.data.daily_running_list;
// 调用一致性检查 // 调用一致性检查
this.ensureAlignmentData(); this.ensureAlignmentData();
} else { } else {
this.$message.error("获取日均运行时间失败"); this.$message.error("获取日均运行时间失败");
} }
this.idle_rate_loading = false; this.idle_rate_loading = false;
}) })
.catch((err) => { .catch((err) => {
this.idle_rate_loading = false; this.idle_rate_loading = false;
this.$message.error("获取日均运行时间接口捕获到错误"); this.$message.error("获取日均运行时间接口捕获到错误");
}); });
}, },
// 获取设备列表 // 获取设备列表
get_device_list() { get_device_list() {
axios({ axios({
method: "get", method: "get",
url: this.localURL + "/public/device_efficiency/device_list/" + this.factory_code, url: this.localURL + "/public/device_efficiency/device_list/" + this.factory_code,
data: {}, data: {},
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
}) })
.then((res) => { .then((res) => {
if (res.data.code == 200) { if (res.data.code == 200) {
// this.deviceList = res.data.data // this.deviceList = res.data.data
this.getAllEquipmentData(res.data.data); this.getAllEquipmentData(res.data.data);
} else { } else {
this.$message.error("设备列表数据获取失败!"); this.$message.error("设备列表数据获取失败!");
} }
}) })
.catch((err) => {}); .catch((err) => {});
}, },
// 获取设备编号 设备计划运行时间 plan_time_list 参数 // 获取设备编号 设备计划运行时间 plan_time_list 参数
get_plan_time() { get_plan_time() {
axios({ axios({
method: "post", method: "post",
url: this.baseURL + "/roke/workstation/equipment/get_plan_time", url: this.baseURL + "/roke/workstation/equipment/get_plan_time",
data: {}, data: {},
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
}) })
.then((res) => { .then((res) => {
if (res.data.result.code == 0) { if (res.data.result.code == 0) {
this.plan_time_list = res.data.result.data; this.plan_time_list = res.data.result.data;
// 只有在选择了设备时才调用单设备空闲率接口 // 只有在选择了设备时才调用单设备空闲率接口
if (this.selectedDevice) { if (this.selectedDevice) {
this.get_series_utilization_rate(); this.get_series_utilization_rate();
} }
// 初始化多设备图表 // 初始化多设备图表
if (this.multiUtilizationChart) { if (this.multiUtilizationChart) {
this.get_series_utilization_rate_top_5(); this.get_series_utilization_rate_top_5();
} }
} }
}) })
.catch((err) => {}); .catch((err) => {});
}, },
// 获取OEE报表:近十天设备空闲率 // 获取OEE报表:近十天设备空闲率
get_series_utilization_rate() { get_series_utilization_rate() {
this.chart_loading = true; this.chart_loading = true;
axios({ axios({
method: "post", method: "post",
url: this.localURL + "/public/device_efficiency/series_utilization_rate", url: this.localURL + "/public/device_efficiency/series_utilization_rate",
data: { data: {
device_code: this.selectedDevice, device_code: this.selectedDevice,
plan_time_list: this.plan_time_list, plan_time_list: this.plan_time_list,
}, },
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
}) })
.then((res) => { .then((res) => {
if (res.data.code == 200) { if (res.data.code == 200) {
this.initUtilizationChart(res.data.data); this.initUtilizationChart(res.data.data);
} else { } else {
this.$message.error("设备空闲率获取失败!"); this.$message.error("设备空闲率获取失败!");
} }
this.chart_loading = false; this.chart_loading = false;
}) })
.catch((err) => { .catch((err) => {
this.chart_loading = false; this.chart_loading = false;
this.$message.error("设备空闲率捕获到错误!"); this.$message.error("设备空闲率捕获到错误!");
}); });
}, },
// 选择设备改变事件 // 选择设备改变事件
selDeviceChange(el) { selDeviceChange(el) {
// 只有在选择了设备时才调用接口 // 只有在选择了设备时才调用接口
if (this.selectedDevice) { if (this.selectedDevice) {
this.get_series_utilization_rate(); this.get_series_utilization_rate();
} else { } else {
// 当设备被清空时,清空折线图数据 // 当设备被清空时,清空折线图数据
this.initUtilizationChart([]); this.initUtilizationChart([]);
} }
// 同时更新柱状图数据 // 同时更新柱状图数据
this.get_daily_running_time(); this.get_daily_running_time();
}, },
// 处理窗口大小变化修改图表大小 // 处理窗口大小变化修改图表大小
handleResize() { handleResize() {
if (this.utilizationChart) this.utilizationChart.resize(); if (this.utilizationChart) this.utilizationChart.resize();
if (this.multiUtilizationChart) this.multiUtilizationChart.resize(); if (this.multiUtilizationChart) this.multiUtilizationChart.resize();
}, },
// 初始化设备空闲率图表 // 初始化设备空闲率图表
initUtilizationChart(data = []) { initUtilizationChart(data = []) {
// 延迟初始化,确保DOM已完全渲染 // 延迟初始化,确保DOM已完全渲染
setTimeout(() => { setTimeout(() => {
// 确保元素存在 // 确保元素存在
const chartDom = document.getElementById("utilizationChart"); const chartDom = document.getElementById("utilizationChart");
if (!chartDom) { if (!chartDom) {
console.error("找不到utilizationChart元素"); console.error("找不到utilizationChart元素");
return; return;
} }
// 如果已有实例,先销毁 // 如果已有实例,先销毁
if (this.utilizationChart) { if (this.utilizationChart) {
this.utilizationChart.dispose(); this.utilizationChart.dispose();
} }
// 初始化图表 // 初始化图表
this.utilizationChart = echarts.init(chartDom); this.utilizationChart = echarts.init(chartDom);
const option = { const option = {
grid: { grid: {
left: "3%", left: "3%",
right: "4%", right: "4%",
bottom: "3%", bottom: "3%",
top: "8%", top: "8%",
containLabel: true, containLabel: true,
}, },
tooltip: { tooltip: {
trigger: "axis", trigger: "axis",
formatter: "{b} : {c}%", formatter: "{b} : {c}%",
}, },
xAxis: { xAxis: {
type: "category", type: "category",
data: this.latestDateList, data: this.latestDateList,
axisLine: { axisLine: {
lineStyle: { lineStyle: {
color: "#fff", color: "#fff",
}, },
}, },
axisLabel: { axisLabel: {
color: "#fff", color: "#fff",
rotate: this.latestDateList[0].length > 5 ? 30 : 0, // 如果日期文本较长则旋转标签 rotate: this.latestDateList[0].length > 5 ? 30 : 0, // 如果日期文本较长则旋转标签
}, },
}, },
yAxis: { yAxis: {
type: "value", type: "value",
min: 0, min: 0,
max: 100, max: 100,
interval: 20, interval: 20,
axisLine: { axisLine: {
show: false, show: false,
}, },
axisTick: { axisTick: {
show: false, show: false,
}, },
splitLine: { splitLine: {
lineStyle: { lineStyle: {
color: "rgba(255, 255, 255, 0.1)", color: "rgba(255, 255, 255, 0.1)",
}, },
}, },
axisLabel: { axisLabel: {
color: "#fff", color: "#fff",
formatter: "{value}%", formatter: "{value}%",
}, },
}, },
series: [ series: [
{ {
name: "设备空闲率", name: "设备空闲率",
type: "line", type: "line",
smooth: true, smooth: true,
symbol: "circle", symbol: "circle",
symbolSize: 8, symbolSize: 8,
label: { label: {
show: data.length > 0, show: data.length > 0,
position: "top", position: "top",
color: "#FFFFFF", color: "#FFFFFF",
fontSize: 12, fontSize: 12,
formatter: "{c}%", formatter: "{c}%",
}, },
lineStyle: { lineStyle: {
color: "#36cfc9", color: "#36cfc9",
width: 3, width: 3,
}, },
itemStyle: { itemStyle: {
color: "#36cfc9", color: "#36cfc9",
}, },
data: data.length > 0 ? data.map((item) => (item > 100 ? 100 : item)) : [], data: data.length > 0 ? data.map((item) => (item > 100 ? 100 : item)) : [],
}, },
], ],
}; };
this.utilizationChart.setOption(option); this.utilizationChart.setOption(option);
// 手动触发resize以确保正确渲染 // 手动触发resize以确保正确渲染
this.utilizationChart.resize(); this.utilizationChart.resize();
}, 300); // 延迟300ms初始化 }, 300); // 延迟300ms初始化
}, },
// 计算高度百分比 // 将秒转换为分钟
calculateHeight(hours) { convertSecondsToMinutes(seconds) {
// 直接使用百分比值 return Math.round(seconds / 60);
// yAxisValues = ["100", "80", "60", "40", "20", "0"],每个刻度区间是20% },
// 确保高度在0-100%之间
return Math.min(Math.max(hours, 0), 100); // 基于分钟数计算高度百分比
}, calculateHeightByMinutes(minutes) {
// 获取最后指定天数的日期 // 将分钟数转换为相对于1440分钟(一天)的百分比
getLastAssignDays(num = 10) { const percentage = (minutes / 1440) * 100;
const dates = []; return Math.min(Math.max(percentage, 0), 100);
for (let i = num - 1; i >= 0; i--) { },
const date = new Date(); // 获取最后指定天数的日期
date.setDate(date.getDate() - i); getLastAssignDays(num = 10) {
const year = date.getFullYear(); const dates = [];
const month = String(date.getMonth() + 1).padStart(2, "0"); for (let i = num - 1; i >= 0; i--) {
const day = String(date.getDate()).padStart(2, "0"); const date = new Date();
dates.push(`${year}-${month}-${day}`); date.setDate(date.getDate() - i);
} const year = date.getFullYear();
this.start_time = dates[0]; // 第一天 const month = String(date.getMonth() + 1).padStart(2, "0");
this.end_time = dates[dates.length - 1]; // 最后一天 const day = String(date.getDate()).padStart(2, "0");
return dates; dates.push(`${year}-${month}-${day}`);
}, }
// 改进日期格式化方法 this.start_time = dates[0]; // 第一天
getLastTenDays() { this.end_time = dates[dates.length - 1]; // 最后一天
const dates = []; return dates;
const formattedDates = []; },
const endDate = new Date(); // 改进日期格式化方法
this.end_time = moment(endDate).format("YYYY-MM-DD"); getLastTenDays() {
const startDate = new Date(); const dates = [];
startDate.setDate(startDate.getDate() - 9); const formattedDates = [];
this.start_time = moment(startDate).format("YYYY-MM-DD"); const endDate = new Date();
this.end_time = moment(endDate).format("YYYY-MM-DD");
for (let i = 0; i < 10; i++) { const startDate = new Date();
const date = new Date(startDate); startDate.setDate(startDate.getDate() - 9);
date.setDate(startDate.getDate() + i); this.start_time = moment(startDate).format("YYYY-MM-DD");
dates.push(date);
// 修改为MM-DD格式 for (let i = 0; i < 10; i++) {
const month = String(date.getMonth() + 1).padStart(2, "0"); const date = new Date(startDate);
const day = String(date.getDate()).padStart(2, "0"); date.setDate(startDate.getDate() + i);
formattedDates.push(`${month}-${day}`); dates.push(date);
} // 修改为MM-DD格式
const month = String(date.getMonth() + 1).padStart(2, "0");
this.dateList = dates; const day = String(date.getDate()).padStart(2, "0");
return formattedDates; formattedDates.push(`${month}-${day}`);
}, }
// 在methods中添加
ensureAlignmentData() { this.dateList = dates;
// 确保X轴标签数量与柱状图数量一致 return formattedDates;
this.$nextTick(() => { },
if (this.pickingOrderList.length !== this.latestDateList.length) { // 在methods中添加
console.warn( ensureAlignmentData() {
"柱状图数量与X轴标签数量不一致", // 确保X轴标签数量与柱状图数量一致
"柱状图:", this.$nextTick(() => {
this.pickingOrderList.length, if (this.pickingOrderList.length !== this.latestDateList.length) {
"X轴标签:", console.warn(
this.latestDateList.length "柱状图数量与X轴标签数量不一致",
); "柱状图:",
} this.pickingOrderList.length,
}); "X轴标签:",
}, this.latestDateList.length
// 通过网址跳转过来的页面,截取后面的参数 );
getUrlSearch(name) { }
// 未传参,返回空 });
if (!name) return ""; },
// 查询参数:先通过search取值,如果取不到就通过hash来取 // 通过网址跳转过来的页面,截取后面的参数
var after = window.location.search; getUrlSearch(name) {
after = after.substr(1) || window.location.hash.split("?")[1]; // 未传参,返回空
// 地址栏URL没有查询参数,返回空 if (!name) return "";
if (!after) return null; // 查询参数:先通过search取值,如果取不到就通过hash来取
// 如果查询参数中没有"name",返回空 var after = window.location.search;
if (after.indexOf(name) === -1) return null; after = after.substr(1) || window.location.hash.split("?")[1];
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); // 地址栏URL没有查询参数,返回空
// 当地址栏参数存在中文时,需要解码,不然会乱码 if (!after) return null;
var r = decodeURI(after).match(reg); // 如果查询参数中没有"name",返回空
// 如果url中"name"没有值,返回空 if (after.indexOf(name) === -1) return null;
if (!r) return null; var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
return r[2]; // 当地址栏参数存在中文时,需要解码,不然会乱码
}, var r = decodeURI(after).match(reg);
// 初始化多设备空闲率图表 // 如果url中"name"没有值,返回空
initMultiUtilizationChart() { if (!r) return null;
setTimeout(() => { return r[2];
const chartDom = document.getElementById("multiUtilizationChart"); },
if (!chartDom) { // 初始化多设备空闲率图表
console.error("找不到multiUtilizationChart元素"); initMultiUtilizationChart() {
return; setTimeout(() => {
} const chartDom = document.getElementById("multiUtilizationChart");
if (!chartDom) {
if (this.multiUtilizationChart) { console.error("找不到multiUtilizationChart元素");
this.multiUtilizationChart.dispose(); return;
} }
this.multiUtilizationChart = echarts.init(chartDom); if (this.multiUtilizationChart) {
}, 300); this.multiUtilizationChart.dispose();
}, }
// 新增:获取多设备空闲率数据(Top 5)
get_series_utilization_rate_top_5() { this.multiUtilizationChart = echarts.init(chartDom);
// 构造设备列表参数 }, 300);
const device_code_list = this.deviceList.map((device) => ({ },
device_name: device.name, // 新增:获取多设备空闲率数据(Top 5)
device_code: device.code, get_series_utilization_rate_top_5() {
})); // 构造设备列表参数
const device_code_list = this.deviceList.map((device) => ({
axios({ device_name: device.name,
method: "post", device_code: device.code,
url: this.localURL + "/public/device_efficiency/series_utilization_rate_top_5", }));
data: {
device_code_list: device_code_list, axios({
plan_time_list: this.plan_time_list || {}, method: "post",
}, url: this.localURL + "/public/device_efficiency/series_utilization_rate_top_5",
headers: { "Content-Type": "application/json" }, data: {
}) device_code_list: device_code_list,
.then((res) => { plan_time_list: this.plan_time_list || {},
if (res.data.code == 200) { },
this.updateMultiChartWithTopDevices(res.data.data); headers: { "Content-Type": "application/json" },
} else { })
this.$message.error("多设备空闲率获取失败!"); .then((res) => {
} if (res.data.code == 200) {
}) this.updateMultiChartWithTopDevices(res.data.data);
.catch((err) => { } else {
this.$message.error("多设备空闲率接口捕获到错误!"); this.$message.error("多设备空闲率获取失败!");
console.error("多设备空闲率接口错误:", err); }
}); })
}, .catch((err) => {
// 新增:用多设备数据更新图表 this.$message.error("多设备空闲率接口捕获到错误!");
updateMultiChartWithTopDevices(data) { console.error("多设备空闲率接口错误:", err);
if (!data.device_data || !Array.isArray(data.device_data)) { });
console.error("多设备数据格式错误"); },
return; // 新增:用多设备数据更新图表
} updateMultiChartWithTopDevices(data) {
if (!data.device_data || !Array.isArray(data.device_data)) {
const series = data.device_data.map((device) => ({ console.error("多设备数据格式错误");
name: device.device_name, return;
type: "line", }
smooth: true,
symbol: "circle", const series = data.device_data.map((device) => ({
symbolSize: 6, name: device.device_name,
lineStyle: { type: "line",
width: 2, smooth: true,
}, symbol: "circle",
data: device.utilization_rates.map((item) => (item > 100 ? 100 : item)), symbolSize: 6,
})); lineStyle: {
width: 2,
const option = { },
grid: { data: device.utilization_rates.map((item) => (item > 100 ? 100 : item)),
left: "3%", }));
right: "4%",
bottom: "3%", const option = {
top: "15%", grid: {
containLabel: true, left: "3%",
}, right: "4%",
tooltip: { bottom: "3%",
trigger: "axis", top: "15%",
formatter: function (params) { containLabel: true,
let result = params[0].axisValue + "<br/>"; },
params.forEach((param) => { tooltip: {
result += param.marker + param.seriesName + ": " + param.value + "%<br/>"; trigger: "axis",
}); formatter: function (params) {
return result; let result = params[0].axisValue + "<br/>";
}, params.forEach((param) => {
}, result += param.marker + param.seriesName + ": " + param.value + "%<br/>";
legend: { });
top: "5%", return result;
textStyle: { },
color: "#fff", },
}, legend: {
}, top: "5%",
xAxis: { textStyle: {
type: "category", color: "#fff",
data: this.latestDateList, },
axisLine: { },
lineStyle: { xAxis: {
color: "#fff", type: "category",
}, data: this.latestDateList,
}, axisLine: {
axisLabel: { lineStyle: {
color: "#fff", color: "#fff",
rotate: this.latestDateList[0].length > 5 ? 30 : 0, },
}, },
}, axisLabel: {
yAxis: { color: "#fff",
type: "value", rotate: this.latestDateList[0].length > 5 ? 30 : 0,
min: 0, },
max: 100, },
interval: 20, yAxis: {
axisLine: { type: "value",
show: false, min: 0,
}, max: 100,
axisTick: { interval: 20,
show: false, axisLine: {
}, show: false,
splitLine: { },
lineStyle: { axisTick: {
color: "rgba(255, 255, 255, 0.1)", show: false,
}, },
}, splitLine: {
axisLabel: { lineStyle: {
color: "#fff", color: "rgba(255, 255, 255, 0.1)",
formatter: "{value}%", },
}, },
}, axisLabel: {
series: series, color: "#fff",
color: ["#36cfc9", "#1890ff", "#722ed1", "#eb2f96", "#fa8c16", "#52c41a", "#faad14"], formatter: "{value}%",
}; },
},
// 使用 setOption 的第二个参数 true 来完全替换配置,确保正确切换 series: series,
this.multiUtilizationChart.setOption(option, true); color: ["#36cfc9", "#1890ff", "#722ed1", "#eb2f96", "#fa8c16", "#52c41a", "#faad14"],
this.multiUtilizationChart.resize(); };
},
}, // 使用 setOption 的第二个参数 true 来完全替换配置,确保正确切换
beforeDestroy() { this.multiUtilizationChart.setOption(option, true);
// 页面销毁移除resize事件监听 this.multiUtilizationChart.resize();
window.removeEventListener("resize", this.handleResize); },
// 清理图表实例 },
if (this.utilizationChart) { beforeDestroy() {
this.utilizationChart.dispose(); // 页面销毁移除resize事件监听
} window.removeEventListener("resize", this.handleResize);
if (this.multiUtilizationChart) { // 清理图表实例
this.multiUtilizationChart.dispose(); if (this.utilizationChart) {
} this.utilizationChart.dispose();
}, }
}); if (this.multiUtilizationChart) {
</script> this.multiUtilizationChart.dispose();
}
<style> },
/* 基础样式 */ });
* { </script>
margin: 0;
padding: 0; <style>
box-sizing: border-box; /* 基础样式 */
} * {
margin: 0;
body { padding: 0;
background-color: #0c1217; box-sizing: border-box;
background-size: cover; }
color: #fff;
overflow: hidden; body {
} background-color: #0c1217;
background-size: cover;
#app { color: #fff;
/* width: 100vw; */ overflow: hidden;
height: 100vh; }
padding: 20px;
display: flex; #app {
flex-direction: column; /* width: 100vw; */
gap: 10px; height: 100vh;
overflow-y: auto; padding: 20px;
} display: flex;
flex-direction: column;
/* 玻璃态效果 */ gap: 10px;
.glass-effect { overflow-y: auto;
background: rgba(6, 82, 158, 0.65); }
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1); /* 玻璃态效果 */
border-radius: 15px; .glass-effect {
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37); background: rgba(6, 82, 158, 0.65);
} backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
.section-title { border-radius: 15px;
position: relative; box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
margin-bottom: 20px; }
display: flex;
align-items: center; .section-title {
justify-content: flex-start; position: relative;
padding-left: 20px; margin-bottom: 20px;
} display: flex;
align-items: center;
.title-text { justify-content: flex-start;
font-size: 16px; padding-left: 20px;
font-weight: 500; }
color: #fff;
} .title-text {
font-size: 16px;
.title-bar { font-weight: 500;
width: 4px; color: #fff;
height: 18px; }
background-color: #1890ff;
margin-right: 8px; .title-bar {
border-radius: 2px; width: 4px;
} height: 18px;
background-color: #1890ff;
.el-progress__text { margin-right: 8px;
white-space: pre-wrap; border-radius: 2px;
line-height: 1.5; }
}
.el-progress__text {
/* 底部状态图样式 */ white-space: pre-wrap;
.status-chart { line-height: 1.5;
padding: 20px 20px 15px 20px; }
height: auto;
min-height: 460px; /* 底部状态图样式 */
position: relative; .status-chart {
margin-bottom: 10px; padding: 20px 20px 15px 20px;
} height: auto;
min-height: 460px;
.chart-header { position: relative;
display: flex; margin-bottom: 10px;
align-items: center; }
gap: 20px;
margin: 10px 0; .chart-header {
} display: flex;
align-items: center;
.chart-container { gap: 20px;
width: 100%; margin: 10px 0;
margin: 0 auto; }
position: relative;
padding: 10px 40px 5px 40px; .chart-container {
height: 370px; width: 100%;
} margin: 0 auto;
position: relative;
.columns-container { padding: 10px 40px 5px 40px;
position: absolute; height: 370px;
top: 0; }
left: 60px;
width: calc(100% - 70px); .columns-container {
height: 330px; position: absolute;
display: flex; top: 0;
justify-content: space-between; left: 60px;
padding: 0 10px; width: calc(100% - 70px);
} height: 330px;
display: flex;
.column-group { justify-content: space-between;
width: 30px; padding: 0 10px;
height: 280px; }
display: flex;
flex-direction: column; .column-group {
align-items: center; width: 30px;
} height: 280px;
display: flex;
.column-stack { flex-direction: column;
width: 100%; align-items: center;
height: 100%; }
display: flex;
flex-direction: column-reverse; .column-stack {
background-color: transparent; width: 100%;
} height: 100%;
display: flex;
/* Y轴样式 */ flex-direction: column-reverse;
.y-axis { background-color: transparent;
position: absolute; }
height: 280px;
width: 50px; /* Y轴样式 */
z-index: 2; .y-axis {
} position: absolute;
height: 280px;
.y-axis-label { width: 50px;
position: absolute; z-index: 2;
left: 10px; }
font-size: 14px;
font-weight: normal; .y-axis-label {
text-align: right; position: absolute;
transform: translateY(-50%); left: 10px;
white-space: nowrap; font-size: 14px;
} font-weight: normal;
text-align: right;
/* 水平网格线调整 */ transform: translateY(-50%);
.horizontal-lines { white-space: nowrap;
position: absolute; }
width: 100%;
height: 280px; /* 水平网格线调整 */
top: 0; .horizontal-lines {
left: 0; position: absolute;
} width: 100%;
height: 280px;
.horizontal-line { top: 0;
position: absolute; left: 0;
width: 100%; }
height: 1px;
background-color: rgba(255, 255, 255, 0.1); .horizontal-line {
left: 0; position: absolute;
} width: 100%;
height: 1px;
/* 精确调整Y轴刻度和水平线位置 */ background-color: rgba(255, 255, 255, 0.1);
.y-axis-label:nth-child(1), left: 0;
.horizontal-line:nth-child(1) { }
top: 0;
} /* 精确调整Y轴刻度和水平线位置 */
.y-axis-label:nth-child(1),
/* 100% */ .horizontal-line:nth-child(1) {
.y-axis-label:nth-child(2), top: 0;
.horizontal-line:nth-child(2) { }
top: 56px;
} /* 100% */
.y-axis-label:nth-child(2),
/* 80% */ .horizontal-line:nth-child(2) {
.y-axis-label:nth-child(3), top: 56px;
.horizontal-line:nth-child(3) { }
top: 112px;
} /* 80% */
.y-axis-label:nth-child(3),
/* 60% */ .horizontal-line:nth-child(3) {
.y-axis-label:nth-child(4), top: 112px;
.horizontal-line:nth-child(4) { }
top: 168px;
} /* 60% */
.y-axis-label:nth-child(4),
/* 40% */ .horizontal-line:nth-child(4) {
.y-axis-label:nth-child(5), top: 168px;
.horizontal-line:nth-child(5) { }
top: 224px;
} /* 40% */
.y-axis-label:nth-child(5),
/* 20% */ .horizontal-line:nth-child(5) {
.y-axis-label:nth-child(6), top: 224px;
.horizontal-line:nth-child(6) { }
top: 280px;
} /* 20% */
.y-axis-label:nth-child(6),
/* 0% */ .horizontal-line:nth-child(6) {
top: 280px;
/* X轴样式调整 */ }
.x-axis {
display: none; /* 0% */
}
/* X轴样式调整 */
.grid-area { .x-axis {
width: 100%; display: none;
height: 280px; }
position: relative;
overflow: visible; .grid-area {
} width: 100%;
height: 280px;
/* 图例样式优化 */ position: relative;
.flex_legend { overflow: visible;
display: flex; }
justify-content: center;
align-items: center; /* 图例样式优化 */
gap: 20px; .flex_legend {
margin-bottom: 15px; display: flex;
} justify-content: center;
align-items: center;
.single_sty { gap: 20px;
display: flex; margin-bottom: 15px;
align-items: center; }
}
.single_sty {
.single_sty div { display: flex;
width: 20px; align-items: center;
height: 10px; }
margin-right: 8px;
border-radius: 2px; .single_sty div {
} width: 20px;
height: 10px;
.single_sty span { margin-right: 8px;
color: #fff; border-radius: 2px;
font-size: 14px; }
}
.single_sty span {
.chart-content { color: #fff;
position: relative; font-size: 14px;
width: calc(100% - 60px); }
height: 280px;
margin-top: 10px; .chart-content {
margin-left: 60px; position: relative;
} width: calc(100% - 60px);
height: 280px;
.unit { margin-top: 10px;
font-size: 12px; margin-left: 60px;
margin-left: 4px; }
color: rgba(255, 255, 255, 0.7);
} .unit {
font-size: 12px;
/* 动画效果 */ margin-left: 4px;
@keyframes fadeIn { color: rgba(255, 255, 255, 0.7);
from { }
opacity: 0;
transform: translateY(20px); /* 动画效果 */
} @keyframes fadeIn {
from {
to { opacity: 0;
opacity: 1; transform: translateY(20px);
transform: translateY(0); }
}
} to {
opacity: 1;
.status-chart { transform: translateY(0);
animation: fadeIn 0.8s ease-out; }
} }
/* Element UI 样式覆盖 */ .status-chart {
.el-select { animation: fadeIn 0.8s ease-out;
width: 180px; }
}
/* Element UI 样式覆盖 */
.chart-header h4 { .el-select {
font-size: 14px; width: 180px;
color: #fff; }
margin: 0;
} .chart-header h4 {
font-size: 14px;
/* Element UI 深色主题样式覆盖 */ color: #fff;
.el-select { margin: 0;
width: 180px; }
}
/* Element UI 深色主题样式覆盖 */
/* 输入框样式 */ .el-select {
.el-select .el-input__inner { width: 180px;
background: rgba(255, 255, 255, 0.1); }
border: 1px solid rgba(255, 255, 255, 0.2);
color: #fff; /* 输入框样式 */
} .el-select .el-input__inner {
background: rgba(255, 255, 255, 0.1);
/* 下拉图标颜色 */ border: 1px solid rgba(255, 255, 255, 0.2);
.el-select .el-input__icon { color: #fff;
color: #fff; }
}
/* 下拉图标颜色 */
/* 下拉面板样式 */ .el-select .el-input__icon {
.el-select-dropdown { color: #fff;
background: rgba(31, 45, 61, 0.95); }
border: 1px solid rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px); /* 下拉面板样式 */
} .el-select-dropdown {
background: rgba(31, 45, 61, 0.95);
/* 下拉选项样式 */ border: 1px solid rgba(255, 255, 255, 0.1);
.el-select-dropdown__item { backdrop-filter: blur(10px);
color: #fff; }
}
/* 下拉选项样式 */
/* 下拉选项悬停样式 */ .el-select-dropdown__item {
.el-select-dropdown__item.hover, color: #fff;
.el-select-dropdown__item:hover { }
background-color: rgba(64, 158, 255, 0.2);
} /* 下拉选项悬停样式 */
.el-select-dropdown__item.hover,
/* 选中项样式 */ .el-select-dropdown__item:hover {
.el-select-dropdown__item.selected { background-color: rgba(64, 158, 255, 0.2);
color: #409eff; }
background-color: rgba(64, 158, 255, 0.1);
} /* 选中项样式 */
.el-select-dropdown__item.selected {
/* 禁用项样式 */ color: #409eff;
.el-select-dropdown__item.is-disabled { background-color: rgba(64, 158, 255, 0.1);
color: rgba(255, 255, 255, 0.3); }
}
/* 禁用项样式 */
/* 聚焦时的边框颜色 */ .el-select-dropdown__item.is-disabled {
.el-select .el-input.is-focus .el-input__inner { color: rgba(255, 255, 255, 0.3);
border-color: #409eff; }
}
/* 聚焦时的边框颜色 */
/* 选择框占位符颜色 */ .el-select .el-input.is-focus .el-input__inner {
.el-select .el-input__inner::placeholder { border-color: #409eff;
color: rgba(255, 255, 255, 0.5); }
}
/* 选择框占位符颜色 */
/* 在样式部分添加以下代码 */ .el-select .el-input__inner::placeholder {
.utilization-chart { color: rgba(255, 255, 255, 0.5);
width: 100% !important; }
padding: 15px 20px;
margin-bottom: 15px; /* 在样式部分添加以下代码 */
} .utilization-chart {
width: 100% !important;
.utilization-chart .section-title { padding: 15px 20px;
display: flex; margin-bottom: 15px;
align-items: center; }
margin-bottom: 15px;
} .utilization-chart .section-title {
display: flex;
.utilization-chart .title-bar { align-items: center;
width: 4px; margin-bottom: 15px;
height: 18px; }
background-color: #1890ff;
margin-right: 8px; .utilization-chart .title-bar {
border-radius: 2px; width: 4px;
} height: 18px;
background-color: #1890ff;
.utilization-chart .title-text { margin-right: 8px;
font-size: 16px; border-radius: 2px;
font-weight: 500; }
color: #fff;
} .utilization-chart .title-text {
font-size: 16px;
/* 新增单元结构样式 */ font-weight: 500;
.column-with-label { color: #fff;
display: flex; }
flex-direction: column;
align-items: center; /* 新增单元结构样式 */
width: 40px; .column-with-label {
/* 稍微宽一点,给标签留足空间 */ display: flex;
} flex-direction: column;
align-items: center;
/* 调整柱状图容器样式 */ width: 40px;
.columns-container { /* 稍微宽一点,给标签留足空间 */
position: absolute; }
top: 0;
left: 60px; /* 调整柱状图容器样式 */
width: calc(100% - 70px); .columns-container {
height: 320px; position: absolute;
/* 增加高度,包含X轴标签 */ top: 0;
display: flex; left: 60px;
justify-content: space-between; width: calc(100% - 70px);
padding: 0 10px; height: 320px;
} /* 增加高度,包含X轴标签 */
display: flex;
/* 柱状图组样式 */ justify-content: space-between;
.column-group { padding: 0 10px;
width: 40px; }
height: 280px;
/* 固定高度为图表区域高度 */ /* 柱状图组样式 */
display: flex; .column-group {
flex-direction: column; width: 40px;
align-items: center; height: 280px;
} /* 固定高度为图表区域高度 */
display: flex;
/* X轴标签样式 */ flex-direction: column;
.x-axis-label { align-items: center;
margin-top: 10px; }
font-size: 12px;
text-align: center; /* X轴标签样式 */
width: 100%; .x-axis-label {
color: #fff; margin-top: 10px;
} font-size: 12px;
text-align: center;
/* 移除原有X轴容器样式 */ width: 100%;
.x-axis { color: #fff;
display: none; }
}
/* 移除原有X轴容器样式 */
/* 新增:多设备空闲率图表样式 */ .x-axis {
.multi-utilization-chart { display: none;
width: 100% !important; }
padding: 15px 20px;
margin-bottom: 15px; /* 新增:多设备空闲率图表样式 */
} .multi-utilization-chart {
width: 100% !important;
.multi-utilization-chart .section-title { padding: 15px 20px;
display: flex; margin-bottom: 15px;
align-items: center; }
margin-bottom: 15px;
} .multi-utilization-chart .section-title {
display: flex;
.multi-utilization-chart .title-bar { align-items: center;
width: 4px; margin-bottom: 15px;
height: 18px; }
background-color: #1890ff;
margin-right: 8px; .multi-utilization-chart .title-bar {
border-radius: 2px; width: 4px;
} height: 18px;
background-color: #1890ff;
.multi-utilization-chart .title-text { margin-right: 8px;
font-size: 16px; border-radius: 2px;
font-weight: 500; }
color: #fff;
} .multi-utilization-chart .title-text {
font-size: 16px;
.utilization-chart .section-title { font-weight: 500;
display: flex; color: #fff;
align-items: center; }
margin-bottom: 15px;
} .utilization-chart .section-title {
display: flex;
/* 新增:图表选择器容器样式 */ align-items: center;
.chart-select-container { margin-bottom: 15px;
margin-left: auto; }
margin-right: 20px;
display: flex; /* 新增:图表选择器容器样式 */
align-items: center; .chart-select-container {
gap: 8px; margin-left: auto;
} margin-right: 20px;
display: flex;
/* 新增:卡片外部选择器包装器样式 */ align-items: center;
.chart-select-wrapper { gap: 8px;
display: flex; }
align-items: center;
gap: 8px; /* 新增:卡片外部选择器包装器样式 */
margin-bottom: 8px; .chart-select-wrapper {
padding-left: 4px; display: flex;
} align-items: center;
gap: 8px;
.select-label { margin-bottom: 8px;
color: #fff; padding-left: 4px;
font-size: 14px; }
white-space: nowrap;
} .select-label {
color: #fff;
.chart-select { font-size: 14px;
width: 250px; white-space: nowrap;
} }
/* 针对图表内选择器的Element UI样式覆盖 */ .chart-select {
.chart-select .el-input__inner { width: 250px;
background: rgba(255, 255, 255, 0.1); }
border: 1px solid rgba(255, 255, 255, 0.2);
color: #fff; /* 针对图表内选择器的Element UI样式覆盖 */
font-size: 12px; .chart-select .el-input__inner {
height: 32px; background: rgba(255, 255, 255, 0.1);
} border: 1px solid rgba(255, 255, 255, 0.2);
color: #fff;
.chart-select .el-input__icon { font-size: 12px;
color: #fff; height: 32px;
} }
.chart-select .el-input__inner::placeholder { .chart-select .el-input__icon {
color: rgba(255, 255, 255, 0.5); color: #fff;
} }
.chart-select .el-input.is-focus .el-input__inner { .chart-select .el-input__inner::placeholder {
border-color: #409eff; color: rgba(255, 255, 255, 0.5);
} }
</style>
</html> .chart-select .el-input.is-focus .el-input__inner {
border-color: #409eff;
}
</style>
</html>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment