12 changed files with 799 additions and 851 deletions
-
5eslint.config.js
-
7package.json
-
81src/components/common/FTChart/index.vue
-
1src/layouts/default.vue
-
2src/main.ts
-
43src/stores/debugStore.ts
-
73src/types/debug.d.ts
-
777src/views/debug/index.vue
-
642src/views/home/index.vue
-
2src/views/login/index.vue
-
5tsconfig.json
-
12vite.config.ts
@ -0,0 +1,81 @@ |
|||
<script lang="ts" setup> |
|||
import type { EChartsOption } from 'echarts/types/dist/shared' |
|||
import * as echarts from 'echarts' |
|||
import { markRaw, nextTick, onMounted, ref, watch } from 'vue' |
|||
|
|||
interface Props { |
|||
option?: EChartsOption |
|||
} |
|||
const props = withDefaults(defineProps<Props>(), { |
|||
option: undefined, |
|||
}) |
|||
|
|||
const emits = defineEmits(['onClick', 'getInstance']) |
|||
|
|||
const chart = ref() |
|||
let myChart: undefined | echarts.ECharts |
|||
onMounted(() => { |
|||
setOption() |
|||
window.addEventListener('resize', () => { |
|||
resize() |
|||
}) |
|||
}) |
|||
const setOption = () => { |
|||
myChart = echarts.getInstanceByDom(chart.value as HTMLElement) |
|||
if (!myChart) { |
|||
myChart = markRaw(echarts.init(chart.value as HTMLElement, null, { renderer: 'svg' })) |
|||
} |
|||
const series = myChart?.getOption()?.series |
|||
myChart.clear() |
|||
if (props.option) { |
|||
const option = markRaw(props.option) |
|||
if (series && series?.length > 0) { |
|||
option.series = series |
|||
} |
|||
myChart?.setOption(option, true) |
|||
setTimeout(() => { |
|||
resize() |
|||
}, 100) |
|||
} |
|||
myChart.on('click', (params) => { |
|||
emits('onClick', params) |
|||
}) |
|||
emits('getInstance', myChart) |
|||
} |
|||
|
|||
const updateOption = (data: any) => { |
|||
myChart?.setOption(data) |
|||
} |
|||
const resize = () => { |
|||
nextTick(() => { |
|||
const option = myChart?.getOption() |
|||
option && myChart?.setOption(option, { notMerge: true }) |
|||
myChart?.resize() |
|||
}) |
|||
} |
|||
watch( |
|||
() => props.option, |
|||
() => |
|||
|
|||
nextTick(() => { |
|||
console.log('有变化了', props.option) |
|||
setOption() |
|||
}), |
|||
{ deep: true }, |
|||
) |
|||
defineExpose({ |
|||
resize, |
|||
updateOption, |
|||
}) |
|||
</script> |
|||
|
|||
<template> |
|||
<div ref="chart" class="my-chart" /> |
|||
</template> |
|||
|
|||
<style lang="scss" scoped> |
|||
.my-chart { |
|||
width: 100%; |
|||
height: 100%; |
|||
} |
|||
</style> |
@ -1,418 +1,252 @@ |
|||
<script setup lang="ts"> |
|||
import { trayIn } from 'apis/home' |
|||
import AddLiquid from 'components/home/AddLiquid/index.vue' |
|||
import CheckCraft from 'components/home/CheckCraft/index.vue' |
|||
import ExecuteCraft from 'components/home/ExecuteCraft/index.vue' |
|||
import ExtractLiquid from 'components/home/ExtractLiquid/index.vue' |
|||
import FillSolution from 'components/home/FillSolution/index.vue' |
|||
import SetTemperature from 'components/home/SetTemperature/index.vue' |
|||
|
|||
import StartClean from 'components/home/StartClean/index.vue' |
|||
import StartExperiment from 'components/home/StartExperiment/index.vue' |
|||
import Tube from 'components/home/Tube/index.vue' |
|||
import { ElMessageBox } from 'element-plus' |
|||
import { FtMessage } from 'libs/message' |
|||
import { socket } from 'libs/socket' |
|||
import { cmdNameMap, formatDateTime } from 'libs/utils' |
|||
import { useHomeStore } from 'stores/homeStore' |
|||
import { useSystemStore } from 'stores/systemStore' |
|||
import { computed, onMounted, onUnmounted, provide, ref } from 'vue' |
|||
|
|||
const homeStore = useHomeStore() |
|||
const systemStore = useSystemStore() |
|||
|
|||
onMounted(() => { |
|||
socket.init(receiveMessage, 'cmd_debug') |
|||
socket.init(receiveMessage, 'cmd_response') |
|||
}) |
|||
|
|||
onUnmounted(() => { |
|||
socket.unregisterCallback(receiveMessage, 'cmd_debug') |
|||
socket.unregisterCallback(receiveMessage, 'cmd_response') |
|||
import { watch } from 'vue' |
|||
|
|||
const option = ref({ |
|||
grid: { |
|||
left: '5%', |
|||
right: '5%', |
|||
top: '5%', |
|||
bottom: '20%', |
|||
}, |
|||
xAxis: { |
|||
type: 'category', |
|||
}, |
|||
yAxis: { |
|||
type: 'value', |
|||
}, |
|||
series: [ |
|||
{ |
|||
data: [150, 230, 224, 218, 135, 147, 260], |
|||
type: 'line', |
|||
showSymbol: true, |
|||
symbolSize: 10, |
|||
}, |
|||
], |
|||
}) |
|||
|
|||
let currentCommandId = '' |
|||
const receiveMessage = (data: Socket.cmdData) => { |
|||
data.commandId === currentCommandId && systemStore.pushSystemList(data) |
|||
if (['start', 'success', 'fail'].includes(data.status)) { |
|||
const cmdName = cmdNameMap[data.command as keyof typeof cmdNameMap] || data.command |
|||
systemStore.insertLog({ cmdName, status: data.status as System.SystemLog['status'], time: formatDateTime() }) |
|||
} |
|||
} |
|||
|
|||
const selectedHeatArea = computed(() => { |
|||
return homeStore.heatAreaList.find(item => item.selected) |
|||
}) |
|||
const list = [ |
|||
'2025年7月23 14:12:00 1号滴定位开始执行.....', |
|||
'2025年7月23 14:12:00 1号滴定位开始执行.....', |
|||
'2025年7月23 14:12:00 1号滴定位开始执行.....', |
|||
'2025年7月23 14:12:00 1号滴定位开始执行.....', |
|||
'2025年7月23 14:12:00 1号滴定位开始执行.....', |
|||
'2025年7月23 14:12:00 1号滴定位开始执行.....', |
|||
'2025年7月23 14:12:00 1号滴定位开始执行.....', |
|||
'2025年7月23 14:12:00 1号滴定位开始执行.....', |
|||
'2025年7月23 14:12:00 1号滴定位开始执行.....', |
|||
'2025年7月23 14:12:00 1号滴定位开始执行.....', |
|||
|
|||
const startVisible = ref(false) |
|||
] |
|||
|
|||
const selectCraftVisible = ref(false) |
|||
const chartBox = ref(null) |
|||
|
|||
const executeCraftHandle = async () => { |
|||
selectCraftVisible.value = true |
|||
} |
|||
const systemStore = useSystemStore() |
|||
|
|||
const setTemperatureVisible = ref(false) |
|||
const currentTemperatureData = ref<{ id: string, label: string | undefined }>({ |
|||
id: '', |
|||
label: 'A-1', |
|||
watch(() => systemStore.menuExpand, () => { |
|||
chartBox.value.resize() |
|||
}) |
|||
provide('currentTemperatureData', currentTemperatureData) |
|||
const setTemperature = (data: System.HeatArea) => { |
|||
const craft = systemStore.systemStatus.trays?.find(item => item.heatModuleCode === data.moduleCode)?.crafts |
|||
if (craft?.craft) { |
|||
FtMessage.warning(`当前加热区已绑定工艺`) |
|||
return |
|||
} |
|||
currentTemperatureData.value = { |
|||
id: data.moduleCode, |
|||
label: homeStore.heatAreaList.find(item => item.value === data.moduleCode)?.label, |
|||
} |
|||
setTemperatureVisible.value = true |
|||
} |
|||
|
|||
const fillSolutionVisible = ref(false) |
|||
|
|||
const addLiquidVisible = ref(false) |
|||
|
|||
const cleanVisible = ref(false) |
|||
|
|||
const extractLiquidVisible = ref(false) |
|||
|
|||
const commandHandle = async (command: string, params?: unknown) => { |
|||
currentCommandId = Date.now().toString() |
|||
const data = { |
|||
commandId: currentCommandId, |
|||
command, |
|||
params, |
|||
} |
|||
await homeStore.sendControl(data) |
|||
} |
|||
|
|||
const move_to_liquid_area = async () => { |
|||
if (!selectedHeatArea.value?.value) { |
|||
await ElMessageBox.confirm( |
|||
'是否要将上料区托盘移至加液位? ', |
|||
'提示', |
|||
{ |
|||
confirmButtonText: '确认', |
|||
showClose: false, |
|||
closeOnClickModal: false, |
|||
closeOnPressEscape: false, |
|||
type: 'warning', |
|||
customClass: 'init-message', |
|||
}, |
|||
) |
|||
} |
|||
await commandHandle('move_to_liquid_area', { heatModuleCode: selectedHeatArea.value?.value }) |
|||
} |
|||
|
|||
const move_to_feed_area = async () => { |
|||
if (!selectedHeatArea.value?.value) { |
|||
await ElMessageBox.confirm( |
|||
'是否要将加液位托盘移至上料区? ', |
|||
'提示', |
|||
{ |
|||
confirmButtonText: '确认', |
|||
showClose: false, |
|||
closeOnClickModal: false, |
|||
closeOnPressEscape: false, |
|||
type: 'warning', |
|||
customClass: 'init-message', |
|||
}, |
|||
) |
|||
} |
|||
await commandHandle('move_to_feed_area', { heatModuleCode: selectedHeatArea.value?.value }) |
|||
} |
|||
|
|||
const move_to_anneal_area = async () => { |
|||
if (!selectedHeatArea.value?.value) { |
|||
await ElMessageBox.confirm( |
|||
'是否要将加液位或上料区的托盘移至退火区? ', |
|||
'提示', |
|||
{ |
|||
confirmButtonText: '确认', |
|||
showClose: false, |
|||
closeOnClickModal: false, |
|||
closeOnPressEscape: false, |
|||
type: 'warning', |
|||
customClass: 'init-message', |
|||
}, |
|||
) |
|||
} |
|||
await commandHandle('move_to_anneal_area', { heatModuleCode: selectedHeatArea.value?.value }) |
|||
} |
|||
|
|||
const trayInHandle = async () => { |
|||
await trayIn() |
|||
FtMessage.success('设置放入托盘成功') |
|||
} |
|||
|
|||
// const trayOutHandle = async () => { |
|||
// await trayOut() |
|||
// } |
|||
|
|||
const checkCraftVisible = ref(false) |
|||
|
|||
const moreVisible = ref(false) |
|||
|
|||
const cleanHandle = async () => { |
|||
await ElMessageBox.confirm( |
|||
'请确认已把托盘放至上料位或移至加液位? ', |
|||
'提示', |
|||
{ |
|||
confirmButtonText: '确认', |
|||
showClose: false, |
|||
closeOnClickModal: false, |
|||
closeOnPressEscape: false, |
|||
type: 'warning', |
|||
customClass: 'init-message', |
|||
}, |
|||
) |
|||
cleanVisible.value = true |
|||
} |
|||
|
|||
const addLiquidHandle = async () => { |
|||
await ElMessageBox.confirm( |
|||
'请确认已把托盘放至上料位或移至加液位? ', |
|||
'提示', |
|||
{ |
|||
confirmButtonText: '确认', |
|||
showClose: false, |
|||
closeOnClickModal: false, |
|||
closeOnPressEscape: false, |
|||
type: 'warning', |
|||
customClass: 'init-message', |
|||
}, |
|||
) |
|||
addLiquidVisible.value = true |
|||
} |
|||
|
|||
const extractLiquidHandle = async () => { |
|||
await ElMessageBox.confirm( |
|||
'请确认已把托盘放至上料位或移至加液位? ', |
|||
'提示', |
|||
{ |
|||
confirmButtonText: '确认', |
|||
showClose: false, |
|||
closeOnClickModal: false, |
|||
closeOnPressEscape: false, |
|||
type: 'warning', |
|||
customClass: 'init-message', |
|||
}, |
|||
) |
|||
extractLiquidVisible.value = true |
|||
} |
|||
</script> |
|||
|
|||
<template> |
|||
<div class="home-page"> |
|||
<div class="page-top"> |
|||
<Tube |
|||
v-for="(item, index) in systemStore.systemStatus.heatModule" |
|||
:key="item.moduleCode" |
|||
:data="item" |
|||
@select-change="homeStore.selectChange(index)" |
|||
@set-temperature="setTemperature(item)" |
|||
/> |
|||
</div> |
|||
<div class="button-box"> |
|||
<el-row style="width: 100%; height: 100%" :gutter="20"> |
|||
<el-col :span="24"> |
|||
<div style="padding: 30px 0;display: grid; gap: 20px; grid-template-columns: repeat(4, 1fr);grid-template-rows: repeat(1, 1fr);height: 100%"> |
|||
<el-card> |
|||
<ft-button type="primary" size="large" :disabled="!systemStore.systemStatus.doorModule.actionable" :click-handle="() => commandHandle('door_open')"> |
|||
开门 |
|||
</ft-button> |
|||
<ft-button type="primary" size="large" :disabled="!systemStore.systemStatus.doorModule.actionable" :click-handle="() => commandHandle('door_close')"> |
|||
关门 |
|||
</ft-button> |
|||
</el-card> |
|||
|
|||
<el-card> |
|||
<ft-button type="primary" size="large" :click-handle="trayInHandle"> |
|||
放入托盘 |
|||
</ft-button> |
|||
<ft-button type="primary" size="large" :click-handle="() => commandHandle('out_tray', { heatModuleCode: selectedHeatArea!.value })" :disabled="!selectedHeatArea"> |
|||
取出托盘 |
|||
</ft-button> |
|||
</el-card> |
|||
<el-card> |
|||
<ft-button type="primary" style="margin: auto 0;" class="manual-button" size="large" :click-handle="executeCraftHandle"> |
|||
执行工艺 |
|||
</ft-button> |
|||
<!-- <ft-button type="primary" size="large" :click-handle="() => checkCraftVisible = true"> --> |
|||
<!-- <el-icon v-if="systemStore.errorCraft" color="#DF1515" size="15" style="margin-right: 5px"> --> |
|||
<!-- <WarningFilled /> --> |
|||
<!-- </el-icon> --> |
|||
<!-- 异常工艺 --> |
|||
<!-- </ft-button> --> |
|||
</el-card> |
|||
<el-card> |
|||
<el-popover |
|||
:visible="moreVisible" |
|||
placement="left-start" |
|||
width="auto" |
|||
trigger="click" |
|||
popper-class="button-popper" |
|||
> |
|||
<template #reference> |
|||
<ft-button type="primary" size="large" style="margin: auto 0;" class="manual-button" @click="moreVisible = !moreVisible"> |
|||
手动操作 |
|||
</ft-button> |
|||
</template> |
|||
<template #default> |
|||
<div class="container-box"> |
|||
<ft-button type="primary" size="large" :disabled="!selectedHeatArea" :click-handle="() => commandHandle('heater_start', { heatModuleCode: selectedHeatArea!.value })"> |
|||
开始加热 |
|||
</ft-button> |
|||
<ft-button type="primary" size="large" :disabled="!selectedHeatArea || selectedHeatArea?.label === '退火区'" :click-handle="() => commandHandle('dry_start', { heatModuleCode: selectedHeatArea!.value })"> |
|||
开始烘干 |
|||
</ft-button> |
|||
|
|||
<ft-button type="primary" size="large" :disabled="!selectedHeatArea || selectedHeatArea?.label !== '退火区'" :click-handle="() => commandHandle('anneal_start', { heatModuleCode: selectedHeatArea!.value })"> |
|||
开始退火 |
|||
</ft-button> |
|||
|
|||
<ft-button type="primary" size="large" :disabled="!selectedHeatArea" :click-handle="() => commandHandle('heater_stop', { heatModuleCode: selectedHeatArea!.value })"> |
|||
停止加热 |
|||
</ft-button> |
|||
|
|||
<ft-button type="primary" size="large" :disabled="!selectedHeatArea" :click-handle="() => commandHandle('fan_start', { heatModuleCode: selectedHeatArea!.value })"> |
|||
开始降温 |
|||
</ft-button> |
|||
|
|||
<ft-button type="primary" size="large" :disabled="!selectedHeatArea" :click-handle="() => commandHandle('fan_stop', { heatModuleCode: selectedHeatArea!.value })"> |
|||
停止降温 |
|||
</ft-button> |
|||
|
|||
<ft-button type="primary" size="large" :click-handle="() => commandHandle('move_to_heat_area', { heatModuleCode: selectedHeatArea!.value })" :disabled="!selectedHeatArea"> |
|||
移至加热位 |
|||
</ft-button> |
|||
|
|||
<ft-button type="primary" size="large" :click-handle="move_to_liquid_area"> |
|||
移至加液位 |
|||
</ft-button> |
|||
<ft-button type="primary" size="large" :click-handle="move_to_feed_area"> |
|||
移至上料区 |
|||
</ft-button> |
|||
<ft-button type="primary" size="large" :click-handle="move_to_anneal_area"> |
|||
移至退火位 |
|||
</ft-button> |
|||
<ft-button type="primary" size="large" @click="cleanHandle"> |
|||
开始清洗 |
|||
</ft-button> |
|||
|
|||
<ft-button type="primary" size="large" @click=" fillSolutionVisible = true"> |
|||
预充管路 |
|||
</ft-button> |
|||
|
|||
<ft-button type="primary" size="large" @click="addLiquidHandle"> |
|||
添加溶液 |
|||
</ft-button> |
|||
|
|||
<ft-button type="primary" size="large" @click="extractLiquidHandle"> |
|||
抽取溶液 |
|||
</ft-button> |
|||
<ft-button type="primary" size="large" :click-handle="() => commandHandle('drain_liquid')"> |
|||
关机排空 |
|||
</ft-button> |
|||
<ft-button type="primary" size="large" :click-handle="() => commandHandle('liquid_motor_origin')"> |
|||
加液臂回原点 |
|||
</ft-button> |
|||
<ft-button type="primary" size="large" :click-handle="() => commandHandle('z_origin')"> |
|||
z轴回原点 |
|||
</ft-button> |
|||
<ft-button type="primary" size="large" :click-handle="() => commandHandle('x_origin')"> |
|||
x轴回原点 |
|||
</ft-button> |
|||
</div> |
|||
</template> |
|||
</el-popover> |
|||
</el-card> |
|||
</div> |
|||
</el-col> |
|||
</el-row> |
|||
</div> |
|||
<CheckCraft v-if="checkCraftVisible" @close="checkCraftVisible = false" /> |
|||
<StartExperiment v-if="startVisible" @ok="startVisible = false" @cancel="startVisible = false" /> |
|||
<StartClean v-if="cleanVisible" @ok="cleanVisible = false" @cancel="cleanVisible = false" /> |
|||
<ExecuteCraft v-if="selectCraftVisible" @ok="selectCraftVisible = false" @cancel="selectCraftVisible = false" /> |
|||
<SetTemperature v-if="setTemperatureVisible" @ok="setTemperatureVisible = false" @cancel="setTemperatureVisible = false" /> |
|||
<AddLiquid v-if="addLiquidVisible" @ok="addLiquidVisible = false" @cancel="addLiquidVisible = false" /> |
|||
<ExtractLiquid v-if="extractLiquidVisible" @ok="extractLiquidVisible = false" @cancel="extractLiquidVisible = false" /> |
|||
<FillSolution v-if="fillSolutionVisible" @ok="fillSolutionVisible = false" @cancel="fillSolutionVisible = false" /> |
|||
</div> |
|||
<template lang="pug"> |
|||
div.home-container |
|||
el-row(:gutter="15") |
|||
el-col(:span="18") |
|||
div.home-left |
|||
div.left-top |
|||
el-card |
|||
div.tube-box(v-for="item in 16" :key="item") |
|||
span.serial-number {{item.toString().padStart(2, '0')}} |
|||
span 体积: 000000 |
|||
span 结果: 00.00% |
|||
el-card |
|||
div.tube-box(v-for="item in 16" :key="item",class="tube-box-success") |
|||
span.serial-number {{(item+16).toString().padStart(2, '0')}} |
|||
span 体积: 00000 |
|||
span 结果: 00.00% |
|||
div.left-bottom |
|||
el-card |
|||
div.home-chart |
|||
ft-chart(:option="option" ref="chartBox") |
|||
div.home-log |
|||
div.log-box |
|||
p.log-text(v-for="item in list" :key="item") {{item}} |
|||
el-col(:span="6") |
|||
div.home-right |
|||
div.right-photo |
|||
el-card |
|||
div.img-box |
|||
el-image(src="https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg" ) |
|||
el-image(src="https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg" ) |
|||
div.right-heat |
|||
el-card |
|||
template(#header) |
|||
span 加热位 |
|||
div.content-box |
|||
div.heat-box |
|||
p.title 加热位1 |
|||
div.heat-box |
|||
p.title 加热位2 |
|||
div.right-titration |
|||
el-card |
|||
template(#header) |
|||
span 滴定位 |
|||
div.content-box |
|||
div.titration-box |
|||
p.title 滴定位1 |
|||
div.titration-box |
|||
p.title 滴定位2 |
|||
div.right-button |
|||
ft-button 手动滴定 |
|||
ft-button 预充管路 |
|||
ft-button 自动滴定 |
|||
ft-button 清洗管路 |
|||
ft-button 排空管路 |
|||
</template> |
|||
|
|||
<style scoped lang="scss"> |
|||
.home-page { |
|||
.page-top{ |
|||
height: 65%; |
|||
border-radius: 8px; |
|||
padding: 0 10px 10px; |
|||
display: grid; |
|||
grid-template-columns: repeat(4, 1fr); /* 创建3列等宽轨道 */ |
|||
grid-template-rows: repeat(1, auto); /* 创建2行自动高度 */ |
|||
gap: 10px; |
|||
justify-content: center; /* 水平居中 */ |
|||
align-items: center; |
|||
} |
|||
.button-box { |
|||
height: 35%; |
|||
//display: grid; |
|||
//grid-template-columns: repeat(6, 1fr); /* 创建3列等宽轨道 */ |
|||
//grid-template-rows: repeat(4, 1fr); /* 创建2行自动高度 */ |
|||
//gap: 10px 20px; |
|||
.ft-button { |
|||
//width: 100px; |
|||
font-weight: bold; |
|||
margin-right: 0; |
|||
|
|||
.my-button { |
|||
padding: 0 !important; |
|||
border: 3px solid #1989fa !important; |
|||
} |
|||
} |
|||
} |
|||
|
|||
} |
|||
.el-col { |
|||
height: 100%; |
|||
} |
|||
.manual-box { |
|||
width: 100%; |
|||
height: 100%; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
} |
|||
.container-box { |
|||
width: 600px; |
|||
display: grid; |
|||
grid-template-columns: repeat(4, 1fr); |
|||
grid-template-rows: repeat(2, 1fr); |
|||
gap: 10px; |
|||
|
|||
} |
|||
.manual-button { |
|||
height: 80px; |
|||
line-height: 80px; |
|||
text-align: center; |
|||
border-radius: 10px; |
|||
:deep(.my-button) { |
|||
height: 100%; |
|||
} |
|||
} |
|||
|
|||
:deep(.el-card__body){ |
|||
width: 100%; |
|||
height: 100%; |
|||
display: flex; |
|||
flex-direction: column; |
|||
justify-content: space-between; |
|||
.ft-button { |
|||
box-shadow: 0 0 25px rgba(0,0,0,0.2); |
|||
} |
|||
} |
|||
<style scoped lang="stylus"> |
|||
.home-container |
|||
background-color #F6F6F6 !important |
|||
padding 0 |
|||
.el-row |
|||
height 100% |
|||
.el-col |
|||
height 100% |
|||
.home-left, .home-right |
|||
border-radius 10px |
|||
height 100% |
|||
background-color #fff |
|||
padding 10px |
|||
.home-left |
|||
display flex |
|||
flex-direction column |
|||
justify-content space-between |
|||
.left-top |
|||
height calc(50% - 5px) |
|||
display flex |
|||
justify-content space-between |
|||
.el-card |
|||
width calc(50% - 5px) |
|||
height 100% |
|||
background #F7F7F7 |
|||
border-radius 10px !important |
|||
box-shadow none |
|||
border none |
|||
:deep(.el-card__body) |
|||
background #F7F7F7 |
|||
border-radius 10px!important |
|||
padding 10px |
|||
display grid |
|||
grid-template-columns repeat(4, 1fr) |
|||
grid-template-rows repeat(4, 1fr) |
|||
grid-gap 4px |
|||
height 100% |
|||
.tube-box-success |
|||
background #12C290 !important |
|||
color #fff !important |
|||
.tube-box |
|||
font-size 10px |
|||
display flex |
|||
flex-direction column |
|||
justify-content space-between |
|||
background #EBEFF4 |
|||
border-radius: 10px |
|||
padding 5px 2px |
|||
color #606266 |
|||
border 2px solid #ffffff |
|||
.serial-number |
|||
font-size 14px |
|||
font-weight 900 |
|||
.left-bottom |
|||
height calc(50% - 5px) |
|||
.el-card |
|||
width 100% |
|||
height 100% |
|||
:deep(.el-card__body) |
|||
height 100% |
|||
padding 10px |
|||
overflow hidden |
|||
.home-chart |
|||
height 50% |
|||
width 100% |
|||
.home-log |
|||
height 50% |
|||
padding 10px |
|||
width 100% |
|||
background #F7F7F7 |
|||
border-radius 5px |
|||
.log-box |
|||
height 100% |
|||
overflow-y auto |
|||
.log-text |
|||
font-size 12px |
|||
color #606266 |
|||
//margin-bottom 5px |
|||
.log-text |
|||
font-size 10px |
|||
color #606266 |
|||
margin-bottom 5px |
|||
.home-right |
|||
display grid |
|||
grid-template-rows repeat(4, 1fr) |
|||
grid-gap 10px |
|||
.right-button |
|||
display grid |
|||
grid-template-columns repeat(2, 1fr) |
|||
grid-template-rows repeat(3, 1fr) |
|||
gap 5px |
|||
:deep(.ft-button) |
|||
margin 0 !important |
|||
.my-button |
|||
padding 5px 10px |
|||
.el-card |
|||
width 100% |
|||
height 100% |
|||
background #F7F7F7 |
|||
border-radius 10px !important |
|||
box-shadow none |
|||
border none |
|||
display flex |
|||
flex-direction column |
|||
:deep(.el-card__header) |
|||
background rgba(0, 38, 77, 0.102); |
|||
padding 5px 20px |
|||
color #393F46 |
|||
font-size 12px |
|||
font-weight 600 |
|||
:deep(.el-card__body) |
|||
flex 1 |
|||
padding 10px |
|||
overflow hidden |
|||
//display flex |
|||
.img-box |
|||
width 100% |
|||
height 100% |
|||
display flex |
|||
gap 10px |
|||
.content-box |
|||
//flex 1 |
|||
height 100% |
|||
width 100% |
|||
display flex |
|||
justify-content space-between |
|||
align-items center |
|||
.heat-box, .titration-box |
|||
height 80px |
|||
width 80px |
|||
background: #EBEFF4 |
|||
border-radius 50% |
|||
border: 1px solid #fff |
|||
position relative |
|||
overflow hidden |
|||
.title |
|||
position absolute |
|||
bottom 0 |
|||
left 0 |
|||
width 100% |
|||
height 25px |
|||
line-height 25px |
|||
font-size 10px |
|||
text-align center |
|||
background: rgba(0, 38, 77, 0.1) |
|||
</style> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue