Browse Source

feat: 调试,首页ui

master
guoapeng 1 week ago
parent
commit
d2d63717c8
  1. 5
      eslint.config.js
  2. 7
      package.json
  3. 81
      src/components/common/FTChart/index.vue
  4. 1
      src/layouts/default.vue
  5. 2
      src/main.ts
  6. 43
      src/stores/debugStore.ts
  7. 73
      src/types/debug.d.ts
  8. 777
      src/views/debug/index.vue
  9. 642
      src/views/home/index.vue
  10. 2
      src/views/login/index.vue
  11. 5
      tsconfig.json
  12. 12
      vite.config.ts

5
eslint.config.js

@ -14,6 +14,11 @@ export default lintConfig({
'antfu/top-level-function': 0,
'ts/no-use-before-define': 0,
'no-alert': 0,
'unused-imports/no-unused-vars': 0,
},
globals: { process: 'readonly' },
extends: [
'plugin:vue/vue3-recommended',
'plugin:vue-pug/vue3-recommended',
],
})

7
package.json

@ -31,6 +31,7 @@
"autoprefixer": "^10.4.20",
"axios": "1.8.2",
"cssnano": "^7.0.6",
"echarts": "^5.6.0",
"element-plus": "^2.9.5",
"express": "^5.1.0",
"konva": "^9.3.18",
@ -56,23 +57,29 @@
"@typescript-eslint/eslint-plugin": "^8.25.0",
"@typescript-eslint/parser": "^8.25.0",
"@vitejs/plugin-vue": "^5.2.1",
"@vitejs/plugin-vue-jsx": "^5.0.1",
"@vue/eslint-config-prettier": "^10.2.0",
"@vue/language-plugin-pug": "^3.0.3",
"concurrently": "^9.1.2",
"eslint": "^9.21.0",
"eslint-config-prettier": "^10.0.2",
"eslint-plugin-prettier": "^5.2.3",
"eslint-plugin-vue": "^9.32.0",
"eslint-plugin-vue-pug": "^0.6.2",
"husky": "^9.1.7",
"lint-staged": "^15.4.3",
"prettier": "^3.5.2",
"pug": "^3.0.3",
"sass": "^1.85.1",
"semver": "^7.7.1",
"stylus": "^0.64.0",
"typescript": "^5.7.3",
"unplugin-auto-import": "^19.1.1",
"unplugin-vue-components": "^28.4.1",
"vite": "6.2.6",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-eslint": "^1.8.1",
"vue-eslint-parser": "^10.2.0",
"vue-tsc": "^2.2.4"
},
"husky": {

81
src/components/common/FTChart/index.vue

@ -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
src/layouts/default.vue

@ -451,6 +451,7 @@ const containerStatus = computed(() => {
border-radius: 10px;
box-shadow: 0 0 1px rgba(0, 0, 0, 0.1);
padding: 10px;
overflow: hidden;
}
.footer-expand {
padding: 10px 15px 10px 85px !important;

2
src/main.ts

@ -1,5 +1,6 @@
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import FtButton from 'components/common/FTButton/index.vue'
import FtChart from 'components/common/FTChart/index.vue'
import FtDialog from 'components/common/FTDialog/index.vue'
import FtStream from 'components/common/FTStream/index.vue'
import FtTable from 'components/common/FTTable/index.vue'
@ -21,6 +22,7 @@ app.component('FtTable', FtTable)
app.component('FtButton', FtButton)
app.component('FtDialog', FtDialog)
app.component('FtStream', FtStream)
app.component('FtChart', FtChart)
app
.use(router)
.use(ElementPlus, { locale, zIndex: 3000 })

43
src/stores/debugStore.ts

@ -7,32 +7,51 @@ import { useSystemStore } from 'stores/systemStore'
export const useDebugStore = defineStore('debug', {
state: (): Debug.DebugStore => ({
formData: {
liquidModule: {
liquidMotor: {
absolutely: {},
relative: {},
},
liquidPump: {
},
lightModule: {
color: 'green',
},
// 加热区
heatArea: {
heatModuleCode: 'heat_module_01',
heatModuleCode: 'heat_module_1',
},
// 转运模组
transferModule: {
// X轴
xMotorData: {
absolutely: {},
bigMotorData: {
absolute: {},
relative: {},
},
smallMotorData: {
absolute: {},
relative: {},
},
// z轴
zMotorData: {
absolutely: {},
absolute: {},
relative: {},
},
// 夹爪
clawMotorData: {
},
},
peristalticPumpData: {
ceramicPump: {
pumpCode: 'ceramic_pump_1',
},
brushlessPump: {
pumpCode: 'brushless_pump_1',
},
stepPump: {
pumpCode: 'step_pump_1',
},
},
titrationModule: {
absolute: { motorCode: 'titration_motor_1' },
relative: { motorCode: 'titration_motor_1' },
},
door: {
magnetStirMotor: {
absolute: { motorCode: 'magnet_stir_motor_1' },
relative: { motorCode: 'magnet_stir_motor_1' },
},
},
}),

73
src/types/debug.d.ts

@ -3,29 +3,38 @@ declare namespace Debug {
formData: FormData
}
interface FormData {
liquidModule: LiquidModule
heatArea: HeatArea
transferModule: TransferModule
door: Door
peristalticPumpData: PeristalticPump
titrationModule: TitrationModule
lightModule: LightModule
magnetStirMotor: MagnetStirMotor
}
interface Door {
speed?: number
interface MagnetStirMotor {
absolute: MotorData & {
motorCode: 'magnet_stir_motor_1' | 'magnet_stir_motor_2'
}
relative: MotorData & {
motorCode: 'magnet_stir_motor_1' | 'magnet_stir_motor_2'
}
}
interface LiquidModule {
liquidMotor: {
absolutely: MotorData
relative: MotorData
interface TitrationModule {
absolute: MotorData & {
motorCode: 'titration_motor_1' | 'titration_motor_2'
}
relative: MotorData & {
motorCode: 'titration_motor_1' | 'titration_motor_2'
}
liquidPump: LiquidPumpData
}
interface LiquidPumpData {
speed?: number
volume?: number
interface LightModule {
color: 'red' | 'green' | 'yellow'
}
interface HeatArea {
heatModuleCode: 'heat_module_01' | 'heat_module_02' | 'heat_module_03'
heatModuleCode: 'heat_module_1' | 'heat_module_2'
temperature?: number
}
@ -36,15 +45,45 @@ declare namespace Debug {
position?: number
}
interface RoboticArmMotorData {
angle?: number
speed?: number
times?: number
position?: number
}
interface PumpData {
speed?: number
volume?: number
direction?: 'forward' | 'backward'
}
interface PeristalticPump {
ceramicPump: PumpData & {
pumpCode: 'ceramic_pump_1' | 'ceramic_pump_2'
}
brushlessPump: PumpData & {
pumpCode: 'brushless_pump_1' | 'brushless_pump_2' | 'brushless_pump_3' | 'brushless_pump_4' | 'brushless_pump_5' | 'brushless_pump_6' | 'brushless_pump_7' | 'brushless_pump_8' | 'brushless_pump_9' | 'brushless_pump_10'
}
stepPump: PumpData & {
pumpCode: 'step_pump_1' | 'step_pump_2' | 'step_pump_3'
}
}
interface TransferModule {
xMotorData: {
absolutely: MotorData
relative: MotorData
bigMotorData: {
absolute: RoboticArmMotorData
relative: RoboticArmMotorData
}
smallMotorData: {
absolute: RoboticArmMotorData
relative: RoboticArmMotorData
}
zMotorData: {
absolutely: MotorData
absolute: MotorData
relative: MotorData
}
clawMotorData: MotorData
}
}

777
src/views/debug/index.vue

@ -1,5 +1,4 @@
<script lang="ts" setup>
import SavePosition from 'components/SavePosition/index.vue'
import { socket } from 'libs/socket'
import { cmdNameMap, formatDateTime } from 'libs/utils'
import { useDebugStore } from 'stores/debugStore'
@ -43,428 +42,376 @@ const commandHandle = async (command: string, params?: unknown) => {
}
</script>
<template>
<div class="debug-content">
<el-row class="button-content">
<el-col :span="8">
<div class="button-box">
<ft-button type="primary" :click-handle="() => commandHandle('enable_all_motor')">
使能所有电机
</ft-button>
</div>
</el-col>
<el-col :span="8">
<div class="button-box">
<ft-button type="primary" :click-handle="() => commandHandle('disable_all_motor')">
失能所有电机
</ft-button>
</div>
</el-col>
<el-col :span="8">
<div class="button-box">
<ft-button type="primary" :click-handle="() => commandHandle('stop_all_motor')">
停止所有电机
</ft-button>
</div>
</el-col>
</el-row>
<el-row :gutter="10" class="card-content">
<el-col :span="8">
<el-card>
<template #header>
<div class="card-header">
<span>转运模组</span>
</div>
</template>
<el-divider>X轴电机</el-divider>
<div class="card-box">
<el-form>
<el-form-item label="距离">
<el-input v-model="debugStore.formData.transferModule.xMotorData.relative.distance" type="number" placeholder="请输入距离">
<template #append>
mm
</template>
</el-input>
</el-form-item>
<el-form-item label="速度">
<el-input v-model="debugStore.formData.transferModule.xMotorData.relative.speed" type="number" placeholder="请输入速度">
<template #append>
rpm/min
</template>
</el-input>
</el-form-item>
<el-form-item label="循环">
<el-input v-model="debugStore.formData.transferModule.xMotorData.relative.times" type="number" placeholder="请输入次数">
<template #append>
</template>
</el-input>
</el-form-item>
<el-form-item>
<ft-button size="small" type="primary" :click-handle="() => commandHandle('x_move_by', { ...debugStore.formData.transferModule.xMotorData.relative, distance: debugStore.formData.transferModule.xMotorData.relative.distance })">
前进
</ft-button>
<ft-button size="small" class="stop-button" :click-handle="() => commandHandle('x_stop')">
停止
</ft-button>
<ft-button size="small" type="primary" :click-handle="() => commandHandle('x_move_by', { ...debugStore.formData.transferModule.xMotorData.relative, distance: -(debugStore.formData.transferModule.xMotorData.relative.distance ?? 0) })">
后退
</ft-button>
<ft-button type="primary" size="small" :click-handle="() => commandHandle('x_origin')">
回原点
</ft-button>
<ft-button size="small" type="primary" :click-handle="() => commandHandle('x_enable')">
电机使能
</ft-button>
<ft-button size="small" :click-handle="() => commandHandle('x_disable')">
电机失能
</ft-button>
</el-form-item>
</el-form>
</div>
<el-divider>Z轴电机</el-divider>
<div class="card-box">
<el-form>
<el-form-item label="距离">
<el-input v-model="debugStore.formData.transferModule.zMotorData.relative.distance" type="number" placeholder="请输入距离">
<template #append>
mm
</template>
</el-input>
</el-form-item>
<el-form-item label="速度">
<el-input v-model="debugStore.formData.transferModule.zMotorData.relative.speed" type="number" placeholder="请输入速度">
<template #append>
rpm/min
</template>
</el-input>
</el-form-item>
<el-form-item label="循环">
<el-input v-model="debugStore.formData.transferModule.zMotorData.relative.times" type="number" placeholder="请输入次数">
<template #append>
</template>
</el-input>
</el-form-item>
<el-form-item>
<ft-button size="small" type="primary" :click-handle="() => commandHandle('z_move_by', { ...debugStore.formData.transferModule.zMotorData.relative, distance: debugStore.formData.transferModule.zMotorData.relative.distance })">
前进
</ft-button>
<ft-button size="small" class="stop-button" :click-handle="() => commandHandle('z_stop')">
停止
</ft-button>
<ft-button size="small" type="primary" :click-handle="() => commandHandle('z_move_by', { ...debugStore.formData.transferModule.zMotorData.relative, distance: -(debugStore.formData.transferModule.zMotorData.relative.distance ?? 0) })">
后退
</ft-button>
<ft-button type="primary" size="small" :click-handle="() => commandHandle('z_origin')">
回原点
</ft-button>
<ft-button size="small" type="primary" :click-handle="() => commandHandle('z_enable')">
电机使能
</ft-button>
<ft-button size="small" :click-handle="() => commandHandle('z_disable')">
电机失能
</ft-button>
</el-form-item>
</el-form>
</div>
</el-card>
</el-col>
<el-col :span="8">
<el-card>
<template #header>
<div class="card-header">
<span>加液模组</span>
</div>
</template>
<el-divider>加液臂</el-divider>
<div class="card-box">
<el-form>
<el-form-item label="距离">
<el-input v-model="debugStore.formData.liquidModule.liquidMotor.relative.distance" type="number" placeholder="请输入距离">
<template #append>
mm
</template>
</el-input>
</el-form-item>
<el-form-item label="速度">
<el-input v-model="debugStore.formData.liquidModule.liquidMotor.relative.speed" type="number" placeholder="请输入速度">
<template #append>
rpm/min
</template>
</el-input>
</el-form-item>
<el-form-item label="循环">
<el-input v-model="debugStore.formData.liquidModule.liquidMotor.relative.times" type="number" placeholder="请输入次数">
<template #append>
</template>
</el-input>
</el-form-item>
<el-form-item>
<ft-button size="small" type="primary" :click-handle="() => commandHandle('liquid_motor_move_by', { ...debugStore.formData.liquidModule.liquidMotor.relative, distance: debugStore.formData.liquidModule.liquidMotor.relative.distance })">
前进
</ft-button>
<ft-button size="small" class="stop-button" :click-handle="() => commandHandle('liquid_motor_stop')">
停止
</ft-button>
<ft-button size="small" type="primary" :click-handle="() => commandHandle('liquid_motor_move_by', { ...debugStore.formData.liquidModule.liquidMotor.relative, distance: -(debugStore.formData.liquidModule.liquidMotor.relative.distance ?? 0) })">
后退
</ft-button>
<ft-button type="primary" size="small" :click-handle="() => commandHandle('liquid_motor_origin')">
回原点
</ft-button>
<ft-button size="small" type="primary" :click-handle="() => commandHandle('liquid_motor_enable')">
电机使能
</ft-button>
<ft-button size="small" :click-handle="() => commandHandle('liquid_motor_disable')">
电机失能
</ft-button>
</el-form-item>
</el-form>
</div>
<el-divider>液体阀门转换</el-divider>
<div class="card-box">
<el-form-item>
<ft-button size="small" type="primary" :click-handle="() => commandHandle('liquid_valve_open_thick')">
浓硝酸
</ft-button>
<ft-button size="small" type="primary" :click-handle="() => commandHandle('liquid_valve_open_thin')">
稀硝酸
</ft-button>
<ft-button size="small" type="primary" :click-handle="() => commandHandle('liquid_valve_open_water')">
蒸馏水
</ft-button>
<ft-button type="primary" size="small" :click-handle="() => commandHandle('liquid_valve_open_waste')">
废液
</ft-button>
<ft-button type="primary" size="small" :click-handle="() => commandHandle('liquid_valve_open_vacant')">
关闭
</ft-button>
</el-form-item>
</div>
<el-divider>加液泵</el-divider>
<div class="card-box">
<el-form>
<el-form-item label="速度">
<el-input v-model="debugStore.formData.liquidModule.liquidPump.speed" type="number" placeholder="请输入速度">
<template #append>
rpm/min
</template>
</el-input>
</el-form-item>
<el-form-item>
<ft-button size="small" type="primary" :click-handle="() => commandHandle('liquid_pump_start', { ...debugStore.formData.liquidModule.liquidPump, direction: 'forward' })">
正转
</ft-button>
<ft-button size="small" class="stop-button" :click-handle="() => commandHandle('liquid_pump_stop')">
停止
</ft-button>
<ft-button size="small" type="primary" class="stop-button" :click-handle="() => commandHandle('liquid_pump_start', { ...debugStore.formData.liquidModule.liquidPump, direction: 'backward' })">
反转
</ft-button>
</el-form-item>
<el-form-item label="容量">
<el-input v-model="debugStore.formData.liquidModule.liquidPump.speed" type="number" placeholder="请输入容量">
<template #append>
mL
</template>
</el-input>
</el-form-item>
<el-form-item>
<ft-button size="small" type="primary" :click-handle="() => commandHandle('liquid_pump_add', { ...debugStore.formData.liquidModule.liquidPump })">
加液
</ft-button>
<ft-button size="small" class="stop-button" :click-handle="() => commandHandle('liquid_pump_stop')">
停止
</ft-button>
<ft-button size="small" type="primary" class="stop-button" :click-handle="() => commandHandle('liquid_pump_reduce', { ...debugStore.formData.liquidModule.liquidPump })">
抽液
</ft-button>
</el-form-item>
</el-form>
</div>
</el-card>
</el-col>
<el-col :span="8">
<el-card>
<template #header>
<div class="card-header">
<span>加热模组</span>
<div>
<el-select v-model="debugStore.formData.heatArea.heatModuleCode" style="width: 150px" placeholder="请选择区域">
<el-option v-for="item in 4" :key="item" :label="`加热区${item}`" :value="`heat_module_0${item}`" />
</el-select>
</div>
</div>
</template>
<el-divider>加热棒</el-divider>
<div class="card-box">
<el-form>
<el-form-item label="温度">
<el-input v-model="debugStore.formData.heatArea.temperature" type="number" placeholder="请输入温度">
<template #append>
</template>
</el-input>
</el-form-item>
<el-form-item>
<ft-button size="small" type="primary" :click-handle="() => commandHandle('heater_start', { heatModuleCode: debugStore.formData.heatArea.heatModuleCode })">
开始加热
</ft-button>
<ft-button size="small" class="stop-button" :click-handle="() => commandHandle('heater_stop', { heatModuleCode: debugStore.formData.heatArea.heatModuleCode })">
停止加热
</ft-button>
</el-form-item>
</el-form>
</div>
<el-divider>风扇</el-divider>
<div class="card-box">
<ft-button size="small" type="primary" :click-handle="() => commandHandle('fan_start', { heatModuleCode: debugStore.formData.heatArea.heatModuleCode })">
打开风扇
</ft-button>
<ft-button size="small" class="stop-button" :click-handle="() => commandHandle('fan_stop', { heatModuleCode: debugStore.formData.heatArea.heatModuleCode })">
关闭风扇
</ft-button>
</div>
</el-card>
<el-card>
<template #header>
<div class="card-header">
<span></span>
</div>
</template>
<div class="card-box">
<el-form>
<el-form-item label="速度">
<el-input v-model="debugStore.formData.door.speed" type="number" placeholder="请输入速度">
<template #append>
rpm/min
</template>
</el-input>
</el-form-item>
<el-form-item>
<ft-button size="small" type="primary" :click-handle="() => commandHandle('door_open', { ...debugStore.formData.door })">
开门
</ft-button>
<ft-button size="small" class="stop-button" :click-handle="() => commandHandle('door_stop')">
停止
</ft-button>
<ft-button size="small" type="primary" :click-handle="() => commandHandle('door_close', { ...debugStore.formData.door })">
关门
</ft-button>
<ft-button size="small" type="primary" :click-handle="() => commandHandle('door_enable')">
电机使能
</ft-button>
<ft-button size="small" :click-handle="() => commandHandle('door_disable')">
电机失能
</ft-button>
</el-form-item>
</el-form>
</div>
</el-card>
<el-card>
<template #header>
<div class="card-header">
<span>蜂鸣器</span>
</div>
</template>
<div class="card-box">
<el-form>
<el-form-item>
<ft-button size="small" type="primary" :click-handle="() => commandHandle('beep_open', { mode: 'info' })">
消息提示音
</ft-button>
<ft-button size="small" type="primary" class="stop-button" :click-handle="() => commandHandle('beep_open', { mode: 'alarm' })">
报警提示音
</ft-button>
<ft-button size="small" :click-handle="() => commandHandle('beep_close')">
关闭声音
</ft-button>
</el-form-item>
</el-form>
</div>
</el-card>
</el-col>
</el-row>
<SavePosition v-if="savePositionVisible" @ok="savePositionVisible = false" @cancel="savePositionVisible = false" />
</div>
<template lang="pug">
div.debug-content
el-row.button-content
el-col(:span="8")
div.button-box
ft-button(type="primary", :click-handle="() => commandHandle('enable_all_motor')")
| 使能所有电机
el-col(:span="8")
div.button-box
ft-button(type="primary", :click-handle="() => commandHandle('disable_all_motor')")
| 失能所有电机
el-col(:span="8")
div.button-box
ft-button(type="primary", :click-handle="() => commandHandle('stop_all_motor')")
| 停止所有电机
el-row(:gutter="10", class="card-content")
el-col(:span="8")
el-card
template(#header)
div.card-header
span 转运模组
el-divider 机械臂-大臂
div.card-box
el-form
el-form-item(label="角度")
el-input(v-model="debugStore.formData.transferModule.bigMotorData.relative.angle", type="number", placeholder="请输入角度")
template(#append)
| °
el-form-item(label="速度")
el-input(v-model="debugStore.formData.transferModule.bigMotorData.relative.speed", type="number", placeholder="请输入速度")
template(#append)
| rpm/min
el-form-item(label="循环")
el-input(v-model="debugStore.formData.transferModule.bigMotorData.relative.times", type="number", placeholder="请输入次数")
template(#append)
|
el-form-item
ft-button(size="small", type="primary", :click-handle="() => commandHandle('robotic_arm_big_move_by', { ...debugStore.formData.transferModule.bigMotorData.relative, angle: debugStore.formData.transferModule.bigMotorData.relative.angle })")
| 右转
ft-button(size="small", class="stop-button", :click-handle="() => commandHandle('robotic_arm_big_stop')")
| 停止
ft-button(size="small", type="primary", :click-handle="() => commandHandle('robotic_arm_big_move_by', { ...debugStore.formData.transferModule.bigMotorData.relative, angle: -(debugStore.formData.transferModule.bigMotorData.relative.angle ?? 0) })")
| 左转
ft-button(type="primary", size="small", :click-handle="() => commandHandle('robotic_arm_big_origin')")
| 回原点
ft-button(size="small", type="primary", :click-handle="() => commandHandle('robotic_arm_big_enable')")
| 电机使能
ft-button(size="small", :click-handle="() => commandHandle('robotic_arm_big_disable')")
| 电机失能
el-form-item(label="角度")
el-input(v-model="debugStore.formData.transferModule.bigMotorData.absolute.angle", type="number", placeholder="请输入目标角度")
template(#append)
| °
el-form-item(label="速度")
el-input(v-model="debugStore.formData.transferModule.bigMotorData.absolute.speed", type="number", placeholder="请输入速度")
template(#append)
| rpm/min
el-form-item
ft-button(size="small", type="primary", :click-handle="() => commandHandle('robotic_arm_big_move_to', debugStore.formData.transferModule.bigMotorData.absolute)")
| 开始
ft-button(size="small", class="stop-button", :click-handle="() => commandHandle('robotic_arm_big_stop')")
| 停止
el-divider 机械臂-小臂
div.card-box
el-form
el-form-item(label="角度")
el-input(v-model="debugStore.formData.transferModule.smallMotorData.relative.angle", type="number", placeholder="请输入角度")
template(#append)
| °
el-form-item(label="速度")
el-input(v-model="debugStore.formData.transferModule.smallMotorData.relative.speed", type="number", placeholder="请输入速度")
template(#append)
| rpm/min
el-form-item(label="循环")
el-input(v-model="debugStore.formData.transferModule.smallMotorData.relative.times", type="number", placeholder="请输入次数")
template(#append)
|
el-form-item
ft-button(size="small", type="primary", :click-handle="() => commandHandle('robotic_arm_small_move_by', { ...debugStore.formData.transferModule.smallMotorData.relative, distance: debugStore.formData.transferModule.smallMotorData.relative.angle })")
| 前进
ft-button(size="small", class="stop-button", :click-handle="() => commandHandle('robotic_arm_small_stop')")
| 停止
ft-button(size="small", type="primary", :click-handle="() => commandHandle('robotic_arm_small_move_by', { ...debugStore.formData.transferModule.smallMotorData.relative, distance: -(debugStore.formData.transferModule.smallMotorData.relative.angle ?? 0) })")
| 后退
ft-button(type="primary", size="small", :click-handle="() => commandHandle('robotic_arm_small_origin')")
| 回原点
ft-button(size="small", type="primary", :click-handle="() => commandHandle('robotic_arm_small_enable')")
| 电机使能
ft-button(size="small", :click-handle="() => commandHandle('robotic_arm_small_disable')")
| 电机失能
el-divider Z轴电机
div.card-box
el-form
el-form-item(label="距离")
el-input(v-model="debugStore.formData.transferModule.zMotorData.relative.distance", type="number", placeholder="请输入距离")
template(#append)
| mm
el-form-item(label="速度")
el-input(v-model="debugStore.formData.transferModule.zMotorData.relative.speed", type="number", placeholder="请输入速度")
template(#append)
| rpm/min
el-form-item(label="循环")
el-input(v-model="debugStore.formData.transferModule.zMotorData.relative.times", type="number", placeholder="请输入次数")
template(#append)
|
el-form-item
ft-button(size="small", type="primary", :click-handle="() => commandHandle('z_move_by', { ...debugStore.formData.transferModule.zMotorData.relative, distance: debugStore.formData.transferModule.zMotorData.relative.distance })")
| 前进
ft-button(size="small", class="stop-button", :click-handle="() => commandHandle('z_stop')")
| 停止
ft-button(size="small", type="primary", :click-handle="() => commandHandle('z_move_by', { ...debugStore.formData.transferModule.zMotorData.relative, distance: -(debugStore.formData.transferModule.zMotorData.relative.distance ?? 0) })")
| 后退
ft-button(type="primary", size="small", :click-handle="() => commandHandle('z_origin')")
| 回原点
ft-button(size="small", type="primary", :click-handle="() => commandHandle('z_enable')")
| 电机使能
ft-button(size="small", :click-handle="() => commandHandle('z_disable')")
| 电机失能
el-divider 夹爪电机
div.card-box
el-form
el-form-item(label="距离")
el-input(v-model="debugStore.formData.transferModule.clawMotorData.distance", type="number", placeholder="请输入距离")
template(#append)
| mm
el-form-item(label="速度")
el-input(v-model="debugStore.formData.transferModule.clawMotorData.speed", type="number", placeholder="请输入速度")
template(#append)
| rpm/min
el-form-item(label="循环")
el-input(v-model="debugStore.formData.transferModule.clawMotorData.times", type="number", placeholder="请输入次数")
template(#append)
|
el-form-item
ft-button(size="small", type="primary", :click-handle="() => commandHandle('claw_open', { ...debugStore.formData.transferModule.clawMotorData, distance: debugStore.formData.transferModule.clawMotorData.distance })")
| 打开
ft-button(size="small", type="primary", :click-handle="() => commandHandle('claw_close', { ...debugStore.formData.transferModule.clawMotorData, distance: -(debugStore.formData.transferModule.clawMotorData.distance ?? 0) })")
| 闭合
el-col(:span="8")
el-card
template(#header)
div.card-header
span 蠕动泵
el-divider 陶瓷蠕动泵
div.card-box
el-form
el-form-item(label="容量")
el-input(v-model="debugStore.formData.peristalticPumpData.ceramicPump.volume", type="number", placeholder="请输入容量")
template(#append)
| mL
el-form-item(label="速度")
el-input(v-model="debugStore.formData.peristalticPumpData.ceramicPump.speed", type="number", placeholder="请输入速度")
template(#append)
| rpm/min
el-form-item(label="泵")
el-select(v-model="debugStore.formData.peristalticPumpData.ceramicPump.pumpCode", placeholder="请选择泵")
el-option(v-for="item in 2", :key="item", :label="`泵-${item}`", :value="`ceramic_pump_${item}`")
el-form-item
ft-button(size="small", type="primary", :click-handle="() => commandHandle('ceramic_pump_open', { ...debugStore.formData.peristalticPumpData.ceramicPump, direction: 'forward' })")
| 正转
ft-button(size="small", class="stop-button", :click-handle="() => commandHandle('ceramic_pump_close')")
| 停止
ft-button(size="small", type="primary", class="stop-button", :click-handle="() => commandHandle('ceramic_pump_open', { ...debugStore.formData.peristalticPumpData.ceramicPump, direction: 'backward' })")
| 反转
el-divider 无刷蠕动泵
div.card-box
el-form
el-form-item(label="容量")
el-input(v-model="debugStore.formData.peristalticPumpData.brushlessPump.volume", type="number", placeholder="请输入容量")
template(#append)
| mL
el-form-item(label="速度")
el-input(v-model="debugStore.formData.peristalticPumpData.brushlessPump.speed", type="number", placeholder="请输入速度")
template(#append)
| rpm/min
el-form-item(label="泵")
el-select(v-model="debugStore.formData.peristalticPumpData.brushlessPump.pumpCode", placeholder="请选择泵")
el-option(v-for="item in 10", :key="item", :label="`泵-${item}`", :value="`brushless_pump_${item}`")
el-form-item
ft-button(size="small", type="primary", :click-handle="() => commandHandle('brushless_pump_open', { ...debugStore.formData.peristalticPumpData.brushlessPump, direction: 'forward' })")
| 正转
ft-button(size="small", class="stop-button", :click-handle="() => commandHandle('brushless_pump_close')")
| 停止
ft-button(size="small", type="primary", class="stop-button", :click-handle="() => commandHandle('brushless_pump_open', { ...debugStore.formData.peristalticPumpData.brushlessPump, direction: 'backward' })")
| 反转
el-divider 步进蠕动泵
div.card-box
el-form
el-form-item(label="容量")
el-input(v-model="debugStore.formData.peristalticPumpData.stepPump.volume", type="number", placeholder="请输入容量")
template(#append)
| mL
el-form-item(label="速度")
el-input(v-model="debugStore.formData.peristalticPumpData.stepPump.speed", type="number", placeholder="请输入速度")
template(#append)
| rpm/min
el-form-item(label="泵")
el-select(v-model="debugStore.formData.peristalticPumpData.stepPump.pumpCode", type="number", placeholder="请选择泵")
el-option(v-for="item in 3", :key="item", :label="`泵-${item}`", :value="`step_pump_${item}`")
el-form-item
ft-button(size="small", type="primary", :click-handle="() => commandHandle('brushless_pump_open', { ...debugStore.formData.peristalticPumpData.stepPump, direction: 'forward' })")
| 正转
ft-button(size="small", class="stop-button", :click-handle="() => commandHandle('brushless_pump_close')")
| 停止
ft-button(size="small", type="primary", class="stop-button", :click-handle="() => commandHandle('brushless_pump_open', { ...debugStore.formData.peristalticPumpData.stepPump, direction: 'backward' })")
| 反转
el-card
template(#header)
div.card-header
span 滴定移动电机
div.card-box
el-form
el-form-item(label="距离")
el-input(v-model="debugStore.formData.titrationModule.relative.distance", type="number", placeholder="请输入距离")
template(#append)
| mm
el-form-item(label="速度")
el-input(v-model="debugStore.formData.titrationModule.relative.speed", type="number", placeholder="请输入速度")
template(#append)
| rpm/min
el-form-item(label="循环")
el-input(v-model="debugStore.formData.titrationModule.relative.times", type="number", placeholder="请输入次数")
template(#append)
|
el-form-item(label="电机")
el-select(v-model="debugStore.formData.titrationModule.relative.motorCode", placeholder="请选择电机")
el-option(v-for="item in 2", :key="item", :label="`电机${item}`", :value="`titration_motor_${item}`")
el-form-item
ft-button(size="small", type="primary", :click-handle="() => commandHandle('titration_motor_move_by', { ...debugStore.formData.titrationModule.relative, distance: debugStore.formData.titrationModule.relative.distance })")
| 前进
ft-button(size="small", class="stop-button", :click-handle="() => commandHandle('titration_motor_stop', { motorCode: debugStore.formData.titrationModule.relative.motorCode })")
| 停止
ft-button(size="small", type="primary", :click-handle="() => commandHandle('z_move_by', { ...debugStore.formData.titrationModule.relative, distance: -(debugStore.formData.titrationModule.relative.distance ?? 0) })")
| 后退
ft-button(type="primary", size="small", :click-handle="() => commandHandle('titration_motor_origin', { motorCode: debugStore.formData.titrationModule.relative.motorCode })")
| 回原点
ft-button(size="small", type="primary", :click-handle="() => commandHandle('z_enable', { motorCode: debugStore.formData.titrationModule.relative.motorCode })")
| 电机使能
ft-button(size="small", :click-handle="() => commandHandle('z_disable', { motorCode: debugStore.formData.titrationModule.relative.motorCode })")
| 电机失能
el-col(:span="8")
el-card
template(#header)
div.card-header
span 加热模组
el-divider 加热棒
div.card-box
el-form
el-form-item(label="温度")
el-input(v-model="debugStore.formData.heatArea.temperature", type="number", placeholder="请输入温度")
template(#append)
|
el-form-item(label="区域")
el-select(v-model="debugStore.formData.heatArea.heatModuleCode", placeholder="请选择区域")
el-option(v-for="item in 2", :key="item", :label="`加热区${item}`", :value="`heat_module_${item}`")
el-form-item
ft-button(size="small", type="primary", :click-handle="() => commandHandle('heater_start', debugStore.formData.heatArea)")
| 开始加热
ft-button(size="small", class="stop-button", :click-handle="() => commandHandle('heater_stop', debugStore.formData.heatArea)")
| 停止加热
el-card
template(#header)
div.card-header
span 指示灯
div.card-box
el-form
el-form-item(label="颜色")
el-select(v-model="debugStore.formData.lightModule.color", placeholder="请选择颜色")
el-option(v-for="item in [{ value: 'red', label: '红色' }, { value: 'yellow', label: '黄色' }, { value: 'green', label: '绿色' }]", :key="item.value", :label="item.label", :value="item.value")
el-form-item
ft-button(size="small", type="primary", :click-handle="() => commandHandle('door_open', { ...debugStore.formData.door })")
| 开启
ft-button(size="small", class="stop-button", :click-handle="() => commandHandle('door_stop')")
| 关闭
el-card
template(#header)
div.card-header
span 磁子搅拌电机
div.card-box
el-form
el-form-item(label="距离")
el-input(v-model="debugStore.formData.magnetStirMotor.relative.distance", type="number", placeholder="请输入距离")
template(#append)
| mm
el-form-item(label="速度")
el-input(v-model="debugStore.formData.magnetStirMotor.relative.speed", type="number", placeholder="请输入速度")
template(#append)
| rpm/min
el-form-item(label="循环")
el-input(v-model="debugStore.formData.magnetStirMotor.relative.times", type="number", placeholder="请输入次数")
template(#append)
|
el-form-item(label="电机")
el-select(v-model="debugStore.formData.magnetStirMotor.relative.motorCode", placeholder="请选择电机")
el-option(v-for="item in 2", :key="item", :label="`电机${item}`", :value="`magnet_stir_motor_${item}`")
el-form-item
ft-button(size="small", type="primary", :click-handle="() => commandHandle('magnet_stir_motor_move_by', { ...debugStore.formData.magnetStirMotor.relative, distance: debugStore.formData.magnetStirMotor.relative.distance })")
| 前进
ft-button(size="small", class="stop-button", :click-handle="() => commandHandle('magnet_stir_motor_stop', { motorCode: debugStore.formData.magnetStirMotor.relative.motorCode })")
| 停止
ft-button(size="small", type="primary", :click-handle="() => commandHandle('magnet_stir_motor_move_by', { ...debugStore.formData.magnetStirMotor.relative, distance: -(debugStore.formData.magnetStirMotor.relative.distance ?? 0) })")
| 后退
ft-button(type="primary", size="small", :click-handle="() => commandHandle('magnet_stir_motor_origin', { motorCode: debugStore.formData.magnetStirMotor.relative.motorCode })")
| 回原点
ft-button(size="small", type="primary", :click-handle="() => commandHandle('magnet_stir_motor_enable', { motorCode: debugStore.formData.magnetStirMotor.relative.motorCode })")
| 电机使能
ft-button(size="small", :click-handle="() => commandHandle('magnet_stir_motor_disable', { motorCode: debugStore.formData.magnetStirMotor.relative.motorCode })")
| 电机失能
el-divider 磁子投放
ft-button(size="small", type="primary", :click-handle="() => commandHandle('magnet_open')")
| 打开磁子投放开关
ft-button(size="small", :click-handle="() => commandHandle('magnet_close')")
| 关闭磁子投放开关
SavePosition(v-if="savePositionVisible", @ok="savePositionVisible = false", @cancel="savePositionVisible = false")
</template>
<style lang="scss" scoped>
.debug-content {
overflow: hidden;
max-height: 100%;
.button-content {
height: 40px;
}
.card-content {
height: calc(100% - 40px);
overflow: auto;
}
}
<style lang="stylus" scoped>
.debug-content
overflow hidden
max-height 100%
.button-content
height 40px
.card-content
height calc(100% - 40px)
overflow auto
.el-card {
margin-bottom: 10px;
}
.el-card
margin-bottom 10px
:deep(.el-card__header) {
padding: 5px 10px;
}
:deep(.el-card__header)
padding 5px 10px
background rgba(0, 0, 0, 0.03)
.el-input, .el-select {
width: 100%;
}
.el-input, .el-select
width 100%
.el-form-item {
margin-bottom: 10px;
margin-right: 10px;
}
.el-form-item
margin-bottom 10px
margin-right 0
.card-box {
//display: flex;
//align-items: center;
}
.card-header
display flex
align-items center
justify-content space-between
:deep(.el-card__header) {
background:rgba(0,0,0,0.03);
}
.select-label
margin-right 10px
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
}
:deep(.el-card__body)
padding 10px 5px
.select-label {
margin-right: 10px;
}
:deep(.el-card__body) {
padding:10px 5px;
}
.el-form-item__content {
.ft-button {
margin-bottom: 10px;
}
}
.button-box {
display: flex;
justify-content: center;
}
:deep(.el-form-item).button-center {
.el-form-item__content {
width: 100%;
display: flex;
justify-content: center;
}
}
.stop-button {
margin-right:8px;
font-weight: 900;
margin-left:3px
}
.el-divider {
margin: 15px 0;
}
.el-form-item__content
.ft-button
margin-bottom 10px
.button-box
display flex
justify-content center
:deep(.el-form-item).button-center
.el-form-item__content
width 100%
display flex
justify-content center
.stop-button
margin-right 8px
font-weight 900
margin-left 3px
.el-divider
margin 15px 0
</style>

642
src/views/home/index.vue

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

2
src/views/login/index.vue

@ -13,7 +13,7 @@ const router = useRouter()
const sys = useSystemStore()
const formRef = ref()
setToken('login success')
const rules = {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },

5
tsconfig.json

@ -34,5 +34,8 @@
"types": ["vite/client", "jest", "node", "element-plus/global.d.ts", "lodash"],
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "src/**/**/*.vue", "components/**/*.vue"],
"exclude": [
]
],
"vueCompilerOptions": {
"plugins": ["@vue/language-plugin-pug"]
}
}

12
vite.config.ts

@ -41,8 +41,18 @@ export default defineConfig(({ mode }) => {
},
},
},
optimizeDeps: {
include: ['pug'],
},
plugins: [
vue(),
vue({
template: {
preprocessOptions: {
// 配置 Pug 预处理器
pug: {},
},
},
}),
AutoImport({
imports: [
'vue',

Loading…
Cancel
Save