Commit 78f35887 authored by Cai Wei's avatar Cai Wei

feat(*): 补充遗漏测试标识点

parent 95a47813
Pipeline #1317 failed
# Cypress Studio 启动器使用说明
## 概述
DC-TOM 项目提供了跨平台的 Cypress Studio 启动器,自动处理开发服务器启动和 Cypress Studio 的启动顺序。
## 功能特性
**自动启动开发服务器** - 确保测试环境就绪
**智能端口检测** - 自动检测端口占用情况
**跨平台支持** - Windows/macOS/Linux 全平台兼容
**进程管理** - 自动清理和停止相关进程
**错误处理** - 详细的错误提示和解决方案
## 快速开始
### 通用方法 (推荐)
```bash
# 启动 Cypress Studio (自动启动开发服务器)
npm run studio
# 查看帮助信息
npm run studio:help
# 使用原有命令
npm run cy:open:studio
```
### Windows 专用方法
```cmd
# 方法1: 使用 npm 脚本
npm run studio:win
# 方法2: 直接运行批处理文件
start-studio.bat
# 方法3: 双击 start-studio.bat 文件
```
### macOS/Linux 方法
```bash
# 使用 Node.js 脚本
node start-studio.cjs
# 如果仍有 bash 脚本 (需要可执行权限)
./start-studio.sh
```
## 启动流程
1. **环境检查** - 验证 Node.js、npm、npx 是否可用
2. **端口检测** - 检查 localhost:3000 是否被占用
3. **启动开发服务器** - 如果端口空闲,运行 `npm run dev`
4. **等待就绪** - 等待开发服务器完全启动并响应
5. **启动 Cypress Studio** - 开发环境就绪后启动 Studio
## 故障排除
### 常见问题
**问题**: Windows 下无法执行 `.sh` 脚本
**解决**: 使用 `npm run studio``start-studio.bat`
**问题**: 端口 3000 被占用
**解决**:
- 启动器会自动跳过开发服务器启动
- 手动停止占用端口的进程
- 或修改项目配置使用其他端口
**问题**: Node.js 或 npm 未找到
**解决**:
- 安装 Node.js: https://nodejs.org
- 确保 Node.js 在系统 PATH 中
- 重新打开终端/命令提示符
**问题**: Cypress 启动失败
**解决**:
- 运行 `npm install` 安装项目依赖
- 检查 Cypress 是否正确安装
- 尝试单独运行 `npx cypress open`
### 手动清理
如果启动器意外退出,可能需要手动清理进程:
```bash
# macOS/Linux
pkill -f "vite"
pkill -f "cypress"
# Windows (命令提示符)
taskkill /f /im node.exe
taskkill /f /im cypress.exe
```
## 文件说明
| 文件名 | 用途 | 平台支持 |
|--------|------|----------|
| `start-studio.cjs` | Node.js 启动脚本 | 全平台 |
| `start-studio.bat` | Windows 批处理文件 | Windows |
| `start-studio.sh` | Bash 脚本 (如存在) | macOS/Linux |
## 自定义配置
### 修改端口
如果需要修改开发服务器端口,编辑 `vite.config.js`:
```javascript
export default defineConfig({
server: {
port: 3001 // 修改为其他端口
}
})
```
同时更新启动器脚本中的端口检测逻辑。
### 添加启动参数
`package.json` 中自定义脚本:
```json
{
"scripts": {
"studio:custom": "node start-studio.cjs --custom-arg"
}
}
```
## 技术细节
- **进程管理**: 使用 Node.js `child_process` 模块
- **端口检测**: HTTP 服务器监听测试
- **跨平台**: 自动检测操作系统并调整命令
- **错误处理**: 完整的错误捕获和用户友好提示
## 支持
如果遇到问题,请:
1. 检查 Node.js 版本 (推荐 18+)
2. 确保项目依赖已安装 (`npm install`)
3. 查看启动器输出的错误信息
4. 参考本文档的故障排除部分
---
**注意**: 该启动器专为 DC-TOM 项目设计,但可以适配其他 Vue + Vite + Cypress 项目。
\ No newline at end of file
...@@ -7,8 +7,11 @@ ...@@ -7,8 +7,11 @@
"dev": "vite --mode development", "dev": "vite --mode development",
"build": "vite build", "build": "vite build",
"preview": "vite preview", "preview": "vite preview",
"cy:open": "vite --mode development && cypress open", "cy:open": "cypress open",
"cy:open:studio": "./start-studio.sh", "cy:open:studio": "node start-studio.cjs",
"studio": "node start-studio.cjs",
"studio:help": "node start-studio.cjs --help",
"studio:win": "start-studio.bat",
"cy:run": "cypress run", "cy:run": "cypress run",
"cy:run:studio": "cypress run --spec 'cypress/e2e/studio-generated/*.cy.js'", "cy:run:studio": "cypress run --spec 'cypress/e2e/studio-generated/*.cy.js'",
"cy:run:ci": "cypress run --browser chrome --headless", "cy:run:ci": "cypress run --browser chrome --headless",
......
<template > <template >
<div class="hamburger" @click="toggleClick"> <div class="hamburger" @click="toggleClick" data-testid="hamburger-menu">
<svg <svg
:class="{'is-active':isActive}" :class="{'is-active':isActive}"
class="hamburger-icon" class="hamburger-icon"
......
<template> <template>
<div class="layout-box"> <div class="layout-box" data-testid="layout-container">
<div class="left" :class="{ colWidth: sidebar }"> <div class="left" :class="{ colWidth: sidebar }" data-testid="layout-sidebar">
<menuCom></menuCom> <menuCom></menuCom>
</div> </div>
<div class="right" :class="{ extend: sidebar }"> <div class="right" :class="{ extend: sidebar }" data-testid="layout-main">
<div class="header"> <div class="header" data-testid="layout-header">
<hamburger <hamburger
class="hamburger-container" class="hamburger-container"
@toggleClick="toggleSideBar" @toggleClick="toggleSideBar"
:is-active="sidebar" :is-active="sidebar"
/> />
<h3>E-Core / DC-TOM 管理平台</h3> <h3>E-Core / DC-TOM 管理平台</h3>
<div class="go-tom" @click="goTom" v-if="!currentDomain.includes('screen.bmetech.com')">EcoTOM 三流合一</div> <div class="go-tom" @click="goTom" v-if="!currentDomain.includes('screen.bmetech.com')" data-testid="go-tom-button">EcoTOM 三流合一</div>
<div class="right-block"> <div class="right-block" data-testid="header-right-block">
<el-dropdown class="right-menu-item" trigger="click"> <el-dropdown class="right-menu-item" trigger="click">
<div class="user-info"> <div class="user-info" data-testid="user-info">
<svg <svg
color="red" color="red"
data-icon-name="user-circle" data-icon-name="user-circle"
...@@ -54,8 +54,8 @@ ...@@ -54,8 +54,8 @@
</el-dropdown> </el-dropdown>
</div> </div>
</div> </div>
<div class="content"> <div class="content" data-testid="layout-content">
<div class="breadcrumb-container"> <div class="breadcrumb-container" data-testid="breadcrumb-container">
<el-breadcrumb separator="/"> <el-breadcrumb separator="/">
<el-breadcrumb-item <el-breadcrumb-item
v-for="(item, index) in breadcrumbList" v-for="(item, index) in breadcrumbList"
......
<template> <template>
<div class="page-container collectorList all-select-btn"> <div class="page-container collectorList all-select-btn" data-testid="about-view-container">
<div class="content-box"> <div class="content-box" data-testid="content-box">
<div class="search"> <div class="search" data-testid="search-area">
<el-form :inline="true" :model="formInline" class="demo-form-inline"> <el-form :inline="true" :model="formInline" class="demo-form-inline" data-testid="search-form">
<el-form-item label="事件名称"> <el-form-item label="事件名称">
<el-input <el-input
v-model="formInline.eventName" v-model="formInline.eventName"
placeholder="请输入事件名称" placeholder="请输入事件名称"
style="width: 200px" style="width: 200px"
clearable clearable
data-testid="event-name-input"
/> />
</el-form-item> </el-form-item>
<el-form-item label="发生位置"> <el-form-item label="发生位置">
...@@ -17,6 +18,7 @@ ...@@ -17,6 +18,7 @@
placeholder="请输入发生位置" placeholder="请输入发生位置"
style="width: 200px" style="width: 200px"
clearable clearable
data-testid="location-input"
/> />
</el-form-item> </el-form-item>
<el-form-item label="除尘器名称"> <el-form-item label="除尘器名称">
...@@ -25,15 +27,17 @@ ...@@ -25,15 +27,17 @@
placeholder="请输入除尘器名称" placeholder="请输入除尘器名称"
style="width: 200px" style="width: 200px"
clearable clearable
data-testid="duster-name-input"
/> />
</el-form-item> </el-form-item>
<el-form-item label="设备类型"> <el-form-item label="设备类型">
<el-select v-model="formInline.deviceType" style="width: 200px"> <el-select v-model="formInline.deviceType" style="width: 200px" data-testid="device-type-select">
<el-option <el-option
v-for="i in typeList.list" v-for="i in typeList.list"
:key="i" :key="i"
:label="`${i.desc}`" :label="`${i.desc}`"
:value="i.code" :value="i.code"
:data-testid="`device-type-option-${i.code}`"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
...@@ -46,13 +50,14 @@ ...@@ -46,13 +50,14 @@
end-placeholder="结束时间" end-placeholder="结束时间"
popper-class="date-picker-popper" popper-class="date-picker-popper"
:teleported="false" :teleported="false"
data-testid="alarm-date-picker"
/> />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="default" class="reset-btn-balck-theme" @click="onReset" <el-button type="default" class="reset-btn-balck-theme" @click="onReset" data-testid="reset-button"
>重置</el-button >重置</el-button
> >
<el-button type="default" class="search-btn-balck-theme" @click="onSubmit" <el-button type="default" class="search-btn-balck-theme" @click="onSubmit" data-testid="search-button"
>查询</el-button >查询</el-button
> >
<el-button <el-button
...@@ -60,20 +65,21 @@ ...@@ -60,20 +65,21 @@
style="width: 140px" style="width: 140px"
class="export-btn-balck-theme" class="export-btn-balck-theme"
@click="openRound()" @click="openRound()"
data-testid="suspend-device-button"
>挂起设备</el-button >挂起设备</el-button
> >
</el-form-item> </el-form-item>
<br /> <br />
<el-form-item> <el-form-item>
<el-radio-group v-model="formInline.suspendFlag" @change="onSubmit"> <el-radio-group v-model="formInline.suspendFlag" @change="onSubmit" data-testid="suspend-flag-radio-group">
<el-radio value="1">挂起期间告警</el-radio> <el-radio value="1" data-testid="suspend-flag-radio-during">挂起期间告警</el-radio>
<el-radio value="0">非挂起期间告警</el-radio> <el-radio value="0" data-testid="suspend-flag-radio-normal">非挂起期间告警</el-radio>
<el-radio value="2">全部告警</el-radio> <el-radio value="2" data-testid="suspend-flag-radio-all">全部告警</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
<div class="table-box"> <div class="table-box" data-testid="table-container">
<common-table <common-table
ref="pageRef" ref="pageRef"
:data="tableData.list" :data="tableData.list"
...@@ -88,12 +94,13 @@ ...@@ -88,12 +94,13 @@
next: '后一页', next: '后一页',
jumper: '跳至', jumper: '跳至',
}" }"
data-testid="alarm-table"
> >
<template #index="{ $index }"> <template #index="{ $index }">
{{ getIndex($index) }} {{ getIndex($index) }}
</template> </template>
<template #operate="{ row }"> <template #operate="{ row }">
<span class="health-score green-color" @click="openDialog(row)">暂挂起</span> <span class="health-score green-color" @click="openDialog(row)" data-testid="suspend-action-link">暂挂起</span>
</template> </template>
</common-table> </common-table>
</div> </div>
...@@ -106,22 +113,24 @@ ...@@ -106,22 +113,24 @@
width="500px" width="500px"
:close-on-click-modal="false" :close-on-click-modal="false"
:close-on-press-escape="false" :close-on-press-escape="false"
data-testid="suspend-dialog"
> >
<div class="equd_body"> <div class="equd_body" data-testid="dialog-body">
<el-form <el-form
ref="ruleFormRef" ref="ruleFormRef"
:model="equSubmitInfo" :model="equSubmitInfo"
:rules="rules" :rules="rules"
class="equd_form" class="equd_form"
data-testid="suspend-form"
> >
<span <span
>是否要对<span class="bold">{{ clickItem.name }}</span >是否要对<span class="bold">{{ clickItem.name }}</span
>不再告警:</span >不再告警:</span
> >
<el-form-item> <el-form-item>
<el-radio-group v-model="equSubmitInfo.noAlarm" @change="onSubmit"> <el-radio-group v-model="equSubmitInfo.noAlarm" @change="onSubmit" data-testid="no-alarm-radio-group">
<el-radio value="1"></el-radio> <el-radio value="1" data-testid="no-alarm-radio-yes"></el-radio>
<el-radio value="0"></el-radio> <el-radio value="0" data-testid="no-alarm-radio-no"></el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="开始时间" prop="startTime"> <el-form-item label="开始时间" prop="startTime">
...@@ -130,6 +139,7 @@ ...@@ -130,6 +139,7 @@
type="datetime" type="datetime"
placeholder="选择开始时间" placeholder="选择开始时间"
popper-class="date-picker-popper" popper-class="date-picker-popper"
data-testid="start-time-picker"
/> />
</el-form-item> </el-form-item>
<el-form-item label="结束时间" prop="endTime"> <el-form-item label="结束时间" prop="endTime">
...@@ -138,23 +148,24 @@ ...@@ -138,23 +148,24 @@
type="datetime" type="datetime"
placeholder="选择结束时间" placeholder="选择结束时间"
popper-class="date-picker-popper" popper-class="date-picker-popper"
data-testid="end-time-picker"
/> />
</el-form-item> </el-form-item>
<el-form-item label="原因分类" prop="reasonCategory"> <el-form-item label="原因分类" prop="reasonCategory">
<el-select v-model="equSubmitInfo.reasonCategory" style="width: 220px;"> <el-select v-model="equSubmitInfo.reasonCategory" style="width: 220px;" data-testid="reason-category-select">
<el-option v-for="item in reasonCategoryList" :key="item.key" :value="item.key" :label="item.value"></el-option> <el-option v-for="item in reasonCategoryList" :key="item.key" :value="item.key" :label="item.value" :data-testid="`reason-category-option-${item.key}`"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="原因描述" prop="reasonDescription" style="padding-left: 10px;"> <el-form-item label="原因描述" prop="reasonDescription" style="padding-left: 10px;">
<el-input v-model="equSubmitInfo.reasonDescription" type="textarea" style="width: 220px;"></el-input> <el-input v-model="equSubmitInfo.reasonDescription" type="textarea" style="width: 220px;" data-testid="reason-description-textarea"></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
<template #footer> <template #footer>
<span class="dialog-footer "> <span class="dialog-footer " data-testid="dialog-footer">
<el-button type="default" class="cancel-btn-balck-theme" @click="equDialog = false">取消</el-button> <el-button type="default" class="cancel-btn-balck-theme" @click="equDialog = false" data-testid="cancel-button">取消</el-button>
<el-button type="default" class="search-btn-balck-theme" @click="equPending(ruleFormRef)"> <el-button type="default" class="search-btn-balck-theme" @click="equPending(ruleFormRef)" data-testid="confirm-button">
确认 确认
</el-button> </el-button>
</span> </span>
......
...@@ -4,15 +4,16 @@ ...@@ -4,15 +4,16 @@
:title="title" :title="title"
:width="width" :width="width"
@close="closeDialog" @close="closeDialog"
data-testid="custom-dialog"
> >
<div> <div data-testid="dialog-content">
<slot name="content"></slot> <slot name="content"></slot>
<slot></slot> <slot></slot>
</div> </div>
<template #footer> <template #footer>
<div class="dialog-footer all-select-btn"> <div class="dialog-footer all-select-btn" data-testid="dialog-footer">
<el-button type="default" @click="closeDialog" class="search-btn-balck-theme">关闭</el-button> <el-button type="default" @click="closeDialog" class="search-btn-balck-theme" data-testid="close-button">关闭</el-button>
<el-button type="default" v-if="btnGroup.length" v-for="item in btnGroup" class="reset-btn-balck-theme" :key="item.attrKey" @click="handleBtn(item.attrKey)"> <el-button type="default" v-if="btnGroup.length" v-for="item in btnGroup" class="reset-btn-balck-theme" :key="item.attrKey" @click="handleBtn(item.attrKey)" :data-testid="`dialog-button-${item.attrKey}`">
{{item.label}} {{item.label}}
</el-button> </el-button>
</div> </div>
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
:key="item.productionLineId" :key="item.productionLineId"
:label="item.productionLineName" :label="item.productionLineName"
:value="item.productionLineId" :value="item.productionLineId"
:data-testid="`production-line-option-${item.productionLineId}`"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
...@@ -29,12 +30,13 @@ ...@@ -29,12 +30,13 @@
placeholder="请选择" placeholder="请选择"
data-testid="my-agency-device-type-select" data-testid="my-agency-device-type-select"
> >
<el-option label="全部" value="" /> <el-option label="全部" value="" data-testid="device-type-option-all" />
<el-option <el-option
v-for="(item, index) in basicConfiguration.deviceList" v-for="(item, index) in basicConfiguration.deviceList"
index="item.id" index="item.id"
:label="item.desc" :label="item.desc"
:value="item.code" :value="item.code"
:data-testid="`device-type-option-${item.code}`"
> >
</el-option> </el-option>
</el-select> </el-select>
...@@ -112,17 +114,19 @@ ...@@ -112,17 +114,19 @@
:btn-group="doneDialog.btnGroup" :btn-group="doneDialog.btnGroup"
@handleBtn="saveDeal" @handleBtn="saveDeal"
@close:showDialog="doneDialog.show = false" @close:showDialog="doneDialog.show = false"
data-testid="done-dialog"
> >
<div class="form-box"> <div class="form-box" data-testid="done-dialog-form-box">
<el-form ref="form" :model="formModel"> <el-form ref="form" :model="formModel" data-testid="done-dialog-form">
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="24"> <el-col :span="24">
<div class="label-title">闭环控制分派</div> <div class="label-title" data-testid="loop-control-dispatch-title">闭环控制分派</div>
<el-form-item label="已分派人:"> <el-form-item label="已分派人:" data-testid="assigned-person-form-item">
<el-tag <el-tag
v-for="(ele, eIndex) in personTag" v-for="(ele, eIndex) in personTag"
:key="ele.name" :key="ele.name"
:type="ele.type" :type="ele.type"
:data-testid="`assigned-person-tag-${eIndex}`"
> >
{{ ele.name }} {{ ele.name }}
</el-tag> </el-tag>
...@@ -131,17 +135,17 @@ ...@@ -131,17 +135,17 @@
</el-row> </el-row>
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="24"> <el-col :span="24">
<div class="label-title">闭环控制信息</div> <div class="label-title" data-testid="loop-control-info-title">闭环控制信息</div>
<div class="alarm-content"> <div class="alarm-content" data-testid="loop-control-info-content">
<div class="content-item"> <div class="content-item" data-testid="ticket-number-item">
<span class="name">编号:</span> <span class="name">编号:</span>
<span class="value">{{ workSheetDetail?.workTicketNo }}</span> <span class="value">{{ workSheetDetail?.workTicketNo }}</span>
</div> </div>
<div class="content-item"> <div class="content-item" data-testid="create-time-item">
<span class="name">创建时间:</span> <span class="name">创建时间:</span>
<span class="value">{{ workSheetDetail?.createTime }}</span> <span class="value">{{ workSheetDetail?.createTime }}</span>
</div> </div>
<div class="content-item"> <div class="content-item" data-testid="loop-control-status-item">
<span class="name">闭环控制状态:</span> <span class="name">闭环控制状态:</span>
<span class="value work-status">{{ <span class="value work-status">{{
workSheetDetail?.desc workSheetDetail?.desc
...@@ -152,8 +156,8 @@ ...@@ -152,8 +156,8 @@
</el-row> </el-row>
<el-row :gutter="24" v-if="workSheetDetail?.warnType !== 5"> <el-row :gutter="24" v-if="workSheetDetail?.warnType !== 5">
<el-col :span="24"> <el-col :span="24">
<div class="label-title">告警信息</div> <div class="label-title" data-testid="alarm-info-title">告警信息</div>
<div class="alarm-content"> <div class="alarm-content" data-testid="alarm-info-content">
<div class="content-item"> <div class="content-item">
<span class="name">所属工序:</span> <span class="name">所属工序:</span>
<span class="value">{{ <span class="value">{{
...@@ -287,8 +291,8 @@ ...@@ -287,8 +291,8 @@
</el-row> </el-row>
<el-row :gutter="24" v-if="workSheetDetail?.relationAnalysis"> <el-row :gutter="24" v-if="workSheetDetail?.relationAnalysis">
<el-col :span="24"> <el-col :span="24">
<div class="label-title">数据异常定位分析</div> <div class="label-title" data-testid="data-exception-analysis-title">数据异常定位分析</div>
<div class="alarm-content"> <div class="alarm-content" data-testid="data-exception-analysis-content">
<div class="content-item"> <div class="content-item">
<span class="name">离线原因:</span> <span class="name">离线原因:</span>
<span class="value">{{ <span class="value">{{
...@@ -301,6 +305,7 @@ ...@@ -301,6 +305,7 @@
style="margin-left: 80px" style="margin-left: 80px"
class="led-btn" class="led-btn"
@click="openPage(workSheetDetail)" @click="openPage(workSheetDetail)"
data-testid="related-ledger-button"
>关联台账</el-button >关联台账</el-button
> >
</div> </div>
...@@ -309,8 +314,8 @@ ...@@ -309,8 +314,8 @@
</el-row> </el-row>
<el-row :gutter="24" v-if="workSheetDetail?.warnType === 5"> <el-row :gutter="24" v-if="workSheetDetail?.warnType === 5">
<el-col :span="24"> <el-col :span="24">
<div class="label-title">道路信息</div> <div class="label-title" data-testid="road-info-title">道路信息</div>
<div class="alarm-content"> <div class="alarm-content" data-testid="road-info-content">
<div class="content-item"> <div class="content-item">
<span class="name">发生位置:</span> <span class="name">发生位置:</span>
<span class="value"> <span class="value">
...@@ -404,8 +409,8 @@ ...@@ -404,8 +409,8 @@
<el-row :gutter="24" v-if="workSheetDetail?.alarmImags"> <el-row :gutter="24" v-if="workSheetDetail?.alarmImags">
<el-col> <el-col>
<div class="label-title">告警图片</div> <div class="label-title" data-testid="alarm-images-title">告警图片</div>
<div class="demo-image__preview"> <div class="demo-image__preview" data-testid="alarm-images-preview">
<div <div
class="image-preview" class="image-preview"
v-for="(item, index) in alarmImg" v-for="(item, index) in alarmImg"
...@@ -558,20 +563,21 @@ ...@@ -558,20 +563,21 @@
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="24"> <el-col :span="24">
<div class="label-title">原因分析</div> <div class="label-title" data-testid="reason-analysis-title">原因分析</div>
<el-input <el-input
class="input-style" class="input-style"
v-model="dialogReason" v-model="dialogReason"
type="textarea" type="textarea"
:rows="3" :rows="3"
placeholder="请输入内容" placeholder="请输入内容"
data-testid="reason-analysis-textarea"
/> />
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="24"> <el-col :span="24">
<div class="label-title">处理措施</div> <div class="label-title" data-testid="handle-measures-title">处理措施</div>
<div> <div>
<el-input <el-input
class="input-style" class="input-style"
...@@ -579,6 +585,7 @@ ...@@ -579,6 +585,7 @@
type="textarea" type="textarea"
:rows="3" :rows="3"
placeholder="请输入内容" placeholder="请输入内容"
data-testid="handle-measures-textarea"
/> />
</div> </div>
</el-col> </el-col>
...@@ -593,37 +600,42 @@ ...@@ -593,37 +600,42 @@
:width="assignDialog.width" :width="assignDialog.width"
@handleBtn="saveAssign" @handleBtn="saveAssign"
@close:showDialog="assignDialog.show = false" @close:showDialog="assignDialog.show = false"
data-testid="assign-dialog"
> >
<el-form> <el-form data-testid="assign-dialog-form">
<el-form-item label="分派人:"> <el-form-item label="分派人:" data-testid="assign-person-form-item">
<div class="inline-box"> <div class="inline-box">
<el-select <el-select
v-model="handlerPeopleId" v-model="handlerPeopleId"
filterable filterable
placeholder="请选择分派人" placeholder="请选择分派人"
data-testid="assign-person-select"
> >
<el-option <el-option
v-for="(item, i) in handlerPeople" v-for="(item, i) in handlerPeople"
:key="i" :key="i"
:label="item.name" :label="item.name"
:value="item.id" :value="item.id"
:data-testid="`assign-person-option-${item.id}`"
></el-option> ></el-option>
</el-select> </el-select>
<el-button <el-button
type="default" type="default"
class="addBtn search-btn-balck-theme" class="addBtn search-btn-balck-theme"
@click="addPerson" @click="addPerson"
data-testid="add-person-button"
>新增</el-button >新增</el-button
> >
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="已分派人:"> <el-form-item label="已分派人:" data-testid="assigned-person-list-form-item">
<el-tag <el-tag
v-for="(ele, eIndex) in personTag" v-for="(ele, eIndex) in personTag"
:key="ele.name" :key="ele.name"
closable closable
@close="delPerson(eIndex)" @close="delPerson(eIndex)"
:type="ele.type" :type="ele.type"
:data-testid="`assigned-person-list-tag-${eIndex}`"
> >
{{ ele.name }} {{ ele.name }}
</el-tag> </el-tag>
...@@ -637,30 +649,34 @@ ...@@ -637,30 +649,34 @@
:width="bagDialog.width" :width="bagDialog.width"
@handleBtn="saveBag" @handleBtn="saveBag"
@close:showDialog="bagDialog.show = false" @close:showDialog="bagDialog.show = false"
data-testid="bag-dialog"
> >
<el-form> <el-form data-testid="bag-dialog-form">
<el-form-item label="第几行:"> <el-form-item label="第几行:" data-testid="bag-row-form-item">
<el-select <el-select
v-model="bagRow" v-model="bagRow"
placeholder="请选择第几行" placeholder="请选择第几行"
@change="getCol" @change="getCol"
data-testid="bag-row-select"
> >
<el-option <el-option
v-for="item in rowList" v-for="item in rowList"
:key="item" :key="item"
:label="item" :label="item"
:value="item" :value="item"
:data-testid="`bag-row-option-${item}`"
> >
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="第几列:"> <el-form-item label="第几列:" data-testid="bag-col-form-item">
<el-select v-model="bagCol" placeholder="请选择第几列"> <el-select v-model="bagCol" placeholder="请选择第几列" data-testid="bag-col-select">
<el-option <el-option
v-for="item in colList" v-for="item in colList"
:key="item" :key="item"
:label="item" :label="item"
:value="item" :value="item"
:data-testid="`bag-col-option-${item}`"
> >
</el-option> </el-option>
</el-select> </el-select>
......
<template> <template>
<div class="my-agency all-select-btn"> <div class="my-agency all-select-btn" data-testid="my-done-container">
<el-form :inline="true" :model="formInline" class="demo-form-inline"> <el-form :inline="true" :model="formInline" class="demo-form-inline" data-testid="search-form">
<el-form-item label="事件名称:"> <el-form-item label="事件名称:">
<el-input v-model="formInline.eventName"> </el-input> <el-input v-model="formInline.eventName" data-testid="event-name-input"> </el-input>
</el-form-item> </el-form-item>
<el-form-item label="发生位置:"> <el-form-item label="发生位置:">
<el-input v-model="formInline.keyword" placeholder="请输入"></el-input> <el-input v-model="formInline.keyword" placeholder="请输入" data-testid="location-input"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="所属工序:"> <el-form-item label="所属工序:">
<el-select <el-select
v-model="formInline.productionLineId" v-model="formInline.productionLineId"
placeholder="请选择" placeholder="请选择"
style="width: 180px" style="width: 180px"
data-testid="production-line-select"
> >
<el-option <el-option
v-for="(item, index) in basicConfiguration.productLineList" v-for="(item, index) in basicConfiguration.productLineList"
:key="item.productionLineId" :key="item.productionLineId"
:label="item.productionLineName" :label="item.productionLineName"
:value="item.productionLineId" :value="item.productionLineId"
:data-testid="`production-line-option-${item.productionLineId}`"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
...@@ -26,13 +28,15 @@ ...@@ -26,13 +28,15 @@
v-model="formInline.deviceType" v-model="formInline.deviceType"
style="width: 180px" style="width: 180px"
placeholder="请选择" placeholder="请选择"
data-testid="device-type-select"
> >
<el-option label="全部" value="" /> <el-option label="全部" value="" data-testid="device-type-option-all" />
<el-option <el-option
v-for="(item, index) in basicConfiguration.deviceList" v-for="(item, index) in basicConfiguration.deviceList"
:key="item.code" :key="item.code"
:label="item.desc" :label="item.desc"
:value="item.code" :value="item.code"
:data-testid="`device-type-option-${item.code}`"
> >
</el-option> </el-option>
</el-select> </el-select>
...@@ -47,21 +51,23 @@ ...@@ -47,21 +51,23 @@
format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss"
popper-class="date-picker-popper" popper-class="date-picker-popper"
data-testid="create-time-picker"
/> />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="default" class="reset-btn-balck-theme" @click="onReset" <el-button type="default" class="reset-btn-balck-theme" @click="onReset" data-testid="reset-button"
>重置</el-button >重置</el-button
> >
<el-button <el-button
type="default" type="default"
class="search-btn-balck-theme" class="search-btn-balck-theme"
@click="onSearch" @click="onSearch"
data-testid="search-button"
>查询</el-button >查询</el-button
> >
</el-form-item> </el-form-item>
</el-form> </el-form>
<div class="table-box"> <div class="table-box" data-testid="table-container">
<common-table <common-table
ref="pageRef" ref="pageRef"
:data="tableData" :data="tableData"
...@@ -76,6 +82,7 @@ ...@@ -76,6 +82,7 @@
next: '后一页', next: '后一页',
jumper: '跳至', jumper: '跳至',
}" }"
data-testid="done-table"
> >
<template #index="{ $index }"> <template #index="{ $index }">
{{ getIndex($index) }} {{ getIndex($index) }}
...@@ -86,7 +93,7 @@ ...@@ -86,7 +93,7 @@
</span> </span>
</template> </template>
<template #operation="{ row }"> <template #operation="{ row }">
<span class="view-btn green-color" @click="handleView(row)"> <span class="view-btn green-color" @click="handleView(row)" data-testid="view-action-link">
查看 查看
</span> </span>
<!-- <span class="table-btn">|</span> <!-- <span class="table-btn">|</span>
...@@ -105,22 +112,23 @@ ...@@ -105,22 +112,23 @@
:title="viewDialog.title" :title="viewDialog.title"
:width="viewDialog.width" :width="viewDialog.width"
@close:showDialog="viewDialog.show = false" @close:showDialog="viewDialog.show = false"
data-testid="view-dialog"
> >
<div class="form-box"> <div class="form-box" data-testid="dialog-form-box">
<el-form ref="form" :model="formModel"> <el-form ref="form" :model="formModel" data-testid="view-form">
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="24"> <el-col :span="24">
<div class="label-title">闭环控制信息</div> <div class="label-title" data-testid="loop-control-info-title">闭环控制信息</div>
<div class="alarm-content"> <div class="alarm-content" data-testid="loop-control-info-content">
<div class="content-item"> <div class="content-item" data-testid="ticket-number-item">
<span class="name">编号:</span> <span class="name">编号:</span>
<span class="value">{{ workSheetDetail.workTicketNo }}</span> <span class="value">{{ workSheetDetail.workTicketNo }}</span>
</div> </div>
<div class="content-item"> <div class="content-item" data-testid="create-time-item">
<span class="name">创建时间:</span> <span class="name">创建时间:</span>
<span class="value">{{ workSheetDetail.createTime }}</span> <span class="value">{{ workSheetDetail.createTime }}</span>
</div> </div>
<div class="content-item"> <div class="content-item" data-testid="loop-control-status-item">
<span class="name">闭环控制状态:</span> <span class="name">闭环控制状态:</span>
<span class="value work-status">{{ <span class="value work-status">{{
workSheetDetail.desc workSheetDetail.desc
...@@ -132,8 +140,8 @@ ...@@ -132,8 +140,8 @@
<el-row :gutter="24" v-if="workSheetDetail.warnType !== 5"> <el-row :gutter="24" v-if="workSheetDetail.warnType !== 5">
<el-col :span="24"> <el-col :span="24">
<div class="label-title">告警信息</div> <div class="label-title" data-testid="alarm-info-title">告警信息</div>
<div class="alarm-content"> <div class="alarm-content" data-testid="alarm-info-content">
<div class="content-item"> <div class="content-item">
<span class="name">所属工序:</span> <span class="name">所属工序:</span>
<span class="value">{{ <span class="value">{{
...@@ -259,8 +267,8 @@ ...@@ -259,8 +267,8 @@
<el-row :gutter="24" v-if="workSheetDetail?.warnType === 5"> <el-row :gutter="24" v-if="workSheetDetail?.warnType === 5">
<el-col :span="24"> <el-col :span="24">
<div class="label-title">道路信息</div> <div class="label-title" data-testid="road-info-title">道路信息</div>
<div class="alarm-content"> <div class="alarm-content" data-testid="road-info-content">
<div class="content-item"> <div class="content-item">
<span class="name">发生位置:</span> <span class="name">发生位置:</span>
<span class="value"> <span class="value">
...@@ -362,8 +370,8 @@ ...@@ -362,8 +370,8 @@
" "
> >
<el-col :span="24"> <el-col :span="24">
<div class="label-title">问题描述</div> <div class="label-title" data-testid="problem-description-title">问题描述</div>
<div class="input-style-text"> <div class="input-style-text" data-testid="problem-description-content">
{{ workSheetDetail.forwards[0].forward }} {{ workSheetDetail.forwards[0].forward }}
</div> </div>
<div <div
...@@ -379,18 +387,20 @@ ...@@ -379,18 +387,20 @@
<el-row :gutter="24" v-if="workSheetDetail?.alarmImags"> <el-row :gutter="24" v-if="workSheetDetail?.alarmImags">
<el-col> <el-col>
<div class="label-title">告警图片</div> <div class="label-title" data-testid="alarm-images-title">告警图片</div>
<div class="demo-image__preview"> <div class="demo-image__preview" data-testid="alarm-images-preview">
<div <div
class="image-preview" class="image-preview"
v-for="(item, index) in alarmImg" v-for="(item, index) in alarmImg"
:key="index" :key="index"
:data-testid="`alarm-image-${index}`"
> >
<el-image <el-image
style="width: 100px; height: 100px" style="width: 100px; height: 100px"
:lazy="true" :lazy="true"
:src="item" :src="item"
:preview-src-list="alarmImg" :preview-src-list="alarmImg"
:data-testid="`alarm-image-el-${index}`"
></el-image> ></el-image>
</div> </div>
</div> </div>
...@@ -406,8 +416,8 @@ ...@@ -406,8 +416,8 @@
" "
> >
<el-col :span="24"> <el-col :span="24">
<div class="label-title">排放提示</div> <div class="label-title" data-testid="emission-tips-title">排放提示</div>
<div class="tips-content"> <div class="tips-content" data-testid="emission-tips-content">
<div class="content-item"> <div class="content-item">
<span class="name"> <span class="name">
后半小时内平均排放放浓度不得超 后半小时内平均排放放浓度不得超
...@@ -428,18 +438,20 @@ ...@@ -428,18 +438,20 @@
<el-row :gutter="24" v-if="srcList.length"> <el-row :gutter="24" v-if="srcList.length">
<el-col :span="24"> <el-col :span="24">
<div class="label-title">告警图片</div> <div class="label-title" data-testid="scene-images-title">告警图片</div>
<div class="demo-image__preview"> <div class="demo-image__preview" data-testid="scene-images-preview">
<div <div
class="image-preview" class="image-preview"
v-for="(item, index) in srcList" v-for="(item, index) in srcList"
:key="index" :key="index"
:data-testid="`scene-image-${index}`"
> >
<el-image <el-image
style="width: 100px; height: 100px" style="width: 100px; height: 100px"
:lazy="true" :lazy="true"
:src="item" :src="item"
:preview-src-list="srcList" :preview-src-list="srcList"
:data-testid="`scene-image-el-${index}`"
></el-image> ></el-image>
</div> </div>
</div> </div>
...@@ -451,7 +463,7 @@ ...@@ -451,7 +463,7 @@
v-if="functionAuthority && functionAuthority.close_loop_upgrade" v-if="functionAuthority && functionAuthority.close_loop_upgrade"
> >
<el-col :span="24" class="deal-line-wrap"> <el-col :span="24" class="deal-line-wrap">
<div class="label-title">落实管理制度</div> <div class="label-title" data-testid="management-system-title">落实管理制度</div>
<div <div
class="processing-records" class="processing-records"
:class="[ :class="[
...@@ -463,11 +475,13 @@ ...@@ -463,11 +475,13 @@
workSheetDetail.levelManageList && workSheetDetail.levelManageList &&
workSheetDetail.levelManageList.length > 0 workSheetDetail.levelManageList.length > 0
" "
data-testid="management-system-records"
> >
<div <div
class="processing-records-item" class="processing-records-item"
v-for="(item, index) in workSheetDetail.levelManageList" v-for="(item, index) in workSheetDetail.levelManageList"
:key="index" :key="index"
:data-testid="`management-record-${index}`"
> >
<div class="steps-line"> <div class="steps-line">
<div class="header" v-show="index !== 0"></div> <div class="header" v-show="index !== 0"></div>
...@@ -499,8 +513,8 @@ ...@@ -499,8 +513,8 @@
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="24"> <el-col :span="24">
<div class="label-title">原因分析</div> <div class="label-title" data-testid="reason-analysis-title">原因分析</div>
<div class="input-style"> <div class="input-style" data-testid="reason-analysis-content">
{{ workSheetDetail.reason || "暂无信息" }} {{ workSheetDetail.reason || "暂无信息" }}
</div> </div>
</el-col> </el-col>
...@@ -508,18 +522,20 @@ ...@@ -508,18 +522,20 @@
<el-row :gutter="24" v-if="imgUrlList.length"> <el-row :gutter="24" v-if="imgUrlList.length">
<el-col :span="24"> <el-col :span="24">
<div class="label-title">现场图片</div> <div class="label-title" data-testid="field-images-title">现场图片</div>
<div class="demo-image__preview"> <div class="demo-image__preview" data-testid="field-images-preview">
<div <div
class="image-preview" class="image-preview"
v-for="(item, index) in imgUrlList" v-for="(item, index) in imgUrlList"
:key="index" :key="index"
:data-testid="`field-image-${index}`"
> >
<el-image <el-image
style="width: 100px; height: 100px" style="width: 100px; height: 100px"
:lazy="true" :lazy="true"
:src="item" :src="item"
:preview-src-list="imgUrlList" :preview-src-list="imgUrlList"
:data-testid="`field-image-el-${index}`"
></el-image> ></el-image>
</div> </div>
</div> </div>
...@@ -536,8 +552,8 @@ ...@@ -536,8 +552,8 @@
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="24"> <el-col :span="24">
<div class="label-title">处理措施</div> <div class="label-title" data-testid="handle-measures-title">处理措施</div>
<div class="input-style"> <div class="input-style" data-testid="handle-measures-content">
{{ workSheetDetail.measure || "暂无信息" }} {{ workSheetDetail.measure || "暂无信息" }}
</div> </div>
</el-col> </el-col>
...@@ -548,10 +564,11 @@ ...@@ -548,10 +564,11 @@
v-if="workSheetDetail.warnType && workSheetDetail.warnType === 5" v-if="workSheetDetail.warnType && workSheetDetail.warnType === 5"
> >
<el-col :span="24"> <el-col :span="24">
<div class="label-title">改善情况</div> <div class="label-title" data-testid="improvement-situation-title">改善情况</div>
<div <div
class="improve-situation" class="improve-situation"
v-if="workSheetDetail.analyzeResult" v-if="workSheetDetail.analyzeResult"
data-testid="improvement-situation-content"
> >
<div class="improve-situation-item"> <div class="improve-situation-item">
<span>改善前</span> <span>改善前</span>
...@@ -615,8 +632,8 @@ ...@@ -615,8 +632,8 @@
" "
> >
<el-col :span="24"> <el-col :span="24">
<div class="label-title">改善情况</div> <div class="label-title" data-testid="improvement-comparison-title">改善情况</div>
<div class="improve-situation"> <div class="improve-situation" data-testid="improvement-comparison-content">
<div class="improve-situation-item"> <div class="improve-situation-item">
<span>告警值</span> <span>告警值</span>
<span class="value"> <span class="value">
...@@ -644,17 +661,19 @@ ...@@ -644,17 +661,19 @@
v-if="workSheetDetail.forwards && workSheetDetail.forwards.length" v-if="workSheetDetail.forwards && workSheetDetail.forwards.length"
> >
<el-col :span="24" class="deal-line-wrap"> <el-col :span="24" class="deal-line-wrap">
<div class="label-title">处理记录</div> <div class="label-title" data-testid="processing-records-title">处理记录</div>
<div <div
class="processing-records" class="processing-records"
:class="[ :class="[
workSheetDetail.forwards.length == 1 ? 'one-record' : '', workSheetDetail.forwards.length == 1 ? 'one-record' : '',
]" ]"
data-testid="processing-records-content"
> >
<div <div
class="processing-records-item" class="processing-records-item"
v-for="(item, index) in workSheetDetail.forwards" v-for="(item, index) in workSheetDetail.forwards"
:key="index" :key="index"
:data-testid="`processing-record-${index}`"
> >
<div class="steps-line"> <div class="steps-line">
<div class="header" v-show="index !== 0"></div> <div class="header" v-show="index !== 0"></div>
...@@ -700,15 +719,17 @@ ...@@ -700,15 +719,17 @@
:width="rejectDialog.width" :width="rejectDialog.width"
@handleBtn="saveReject" @handleBtn="saveReject"
@close:showDialog="rejectDialog.show = false" @close:showDialog="rejectDialog.show = false"
data-testid="reject-dialog"
> >
<el-form> <el-form data-testid="reject-form">
<el-form-item label="驳回原因"> <el-form-item label="驳回原因">
<el-select v-model="rejectType"> <el-select v-model="rejectType" data-testid="reject-type-select">
<el-option <el-option
v-for="(item, i) in reasonList" v-for="(item, i) in reasonList"
:key="i" :key="i"
:label="item.description" :label="item.description"
:value="item.rejectType" :value="item.rejectType"
:data-testid="`reject-type-option-${item.rejectType}`"
> >
</el-option> </el-option>
</el-select> </el-select>
...@@ -720,6 +741,7 @@ ...@@ -720,6 +741,7 @@
v-model="rejectReason" v-model="rejectReason"
:autosize="{ minRows: 2, maxRows: 12 }" :autosize="{ minRows: 2, maxRows: 12 }"
placeholder="请输入内容" placeholder="请输入内容"
data-testid="reject-reason-textarea"
> >
</el-input> </el-input>
</el-col> </el-col>
...@@ -733,30 +755,34 @@ ...@@ -733,30 +755,34 @@
:width="bagDialog.width" :width="bagDialog.width"
@handleBtn="saveBag" @handleBtn="saveBag"
@close:showDialog="bagDialog.show = false" @close:showDialog="bagDialog.show = false"
data-testid="bag-dialog"
> >
<el-form> <el-form data-testid="bag-form">
<el-form-item label="第几行:"> <el-form-item label="第几行:">
<el-select <el-select
v-model="bagRow" v-model="bagRow"
placeholder="请选择第几行" placeholder="请选择第几行"
@change="getCol" @change="getCol"
data-testid="bag-row-select"
> >
<el-option <el-option
v-for="item in rowList" v-for="item in rowList"
:key="item" :key="item"
:label="item" :label="item"
:value="item" :value="item"
:data-testid="`bag-row-option-${item}`"
> >
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="第几列:"> <el-form-item label="第几列:">
<el-select v-model="bagCol" placeholder="请选择第几列"> <el-select v-model="bagCol" placeholder="请选择第几列" data-testid="bag-col-select">
<el-option <el-option
v-for="item in colList" v-for="item in colList"
:key="item" :key="item"
:label="item" :label="item"
:value="item" :value="item"
:data-testid="`bag-col-option-${item}`"
> >
</el-option> </el-option>
</el-select> </el-select>
......
...@@ -92,23 +92,26 @@ ...@@ -92,23 +92,26 @@
width="1000px" width="1000px"
:close-on-click-modal="false" :close-on-click-modal="false"
:close-on-press-escape="false" :close-on-press-escape="false"
data-testid="dust-line-dialog"
> >
<div class="input-group"> <div class="input-group" data-testid="dust-selector-group">
<span>除尘器名称:</span> <span>除尘器名称:</span>
<el-select <el-select
v-model="selectDustNo" v-model="selectDustNo"
@change="changeDust" @change="changeDust"
style="width: 120px" style="width: 120px"
data-testid="dust-name-select"
> >
<el-option <el-option
v-for="i in dustList.list" v-for="i in dustList.list"
:key="i" :key="i"
:label="`${i.dusterName}`" :label="`${i.dusterName}`"
:value="i.dusterNo" :value="i.dusterNo"
:data-testid="`dust-option-${i.dusterNo}`"
/> />
</el-select> </el-select>
</div> </div>
<div class="echartBox"> <div class="echartBox" data-testid="chart-container">
<chartLine :dustLineInfo="dustLineInfo.list"></chartLine> <chartLine :dustLineInfo="dustLineInfo.list"></chartLine>
</div> </div>
<!-- <template #footer> <!-- <template #footer>
......
<template> <template>
<div ref="chartRef" class="chart-line"></div> <div ref="chartRef" class="chart-line" data-testid="chart-line-container"></div>
</template> </template>
<script setup> <script setup>
......
<template> <template>
<div class="svg-box"> <div class="svg-box" data-testid="map-svg-container">
<div class="svg-main"> <div class="svg-main" data-testid="svg-main">
<img src="@/assets/map.png" alt="" /> <img src="@/assets/map.png" alt="" />
<div class="spot-box"> <div class="spot-box" data-testid="spot-box">
<div <div
v-for="(spot, index) in spots" v-for="(spot, index) in spots"
:key="index" :key="index"
...@@ -15,11 +15,12 @@ ...@@ -15,11 +15,12 @@
left: spot.x + '%', left: spot.x + '%',
top: spot.y + '%', top: spot.y + '%',
}" }"
:data-testid="`map-spot-${index}`"
> >
<div class="pulse"></div> <div class="pulse" data-testid="spot-pulse"></div>
<!-- 连接线和详情窗 --> <!-- 连接线和详情窗 -->
<transition name="line"> <transition name="line">
<div class="connector-line" v-if="activeSpot === index"></div> <div class="connector-line" v-if="activeSpot === index" data-testid="connector-line"></div>
</transition> </transition>
<transition <transition
name="detail" name="detail"
...@@ -30,10 +31,11 @@ ...@@ -30,10 +31,11 @@
<div <div
class="detail-window" class="detail-window"
v-if="activeSpot === index && showDetail" v-if="activeSpot === index && showDetail"
data-testid="detail-window"
> >
<div class="detail-title">{{ spot.name }}</div> <div class="detail-title" data-testid="detail-title">{{ spot.name }}</div>
<div class="detail-content"> <div class="detail-content" data-testid="detail-content">
<div class="detail-item"> <div class="detail-item" data-testid="detail-status-item">
<span class="label">状态:</span> <span class="label">状态:</span>
<span class="value" :class="`text-status-${spot.status}`">{{ <span class="value" :class="`text-status-${spot.status}`">{{
getStatusText(spot.status) getStatusText(spot.status)
...@@ -43,9 +45,9 @@ ...@@ -43,9 +45,9 @@
<span class="label">数值:</span> <span class="label">数值:</span>
<span class="value">{{ spot.value }}</span> <span class="value">{{ spot.value }}</span>
</div> --> </div> -->
<div class="detail-item"> <div class="detail-item" data-testid="detail-description-item">
<span class="label">描述:</span> <span class="label">描述:</span>
<div class="value"> <div class="value" data-testid="description-list">
<span class="value-item" v-for="(item, index) in spot.description" :key="index">{{ item }}</span> <span class="value-item" v-for="(item, index) in spot.description" :key="index">{{ item }}</span>
<span class="value-item" v-if="spot.description.length === 0">暂无</span> <span class="value-item" v-if="spot.description.length === 0">暂无</span>
</div> </div>
......
...@@ -3,15 +3,17 @@ ...@@ -3,15 +3,17 @@
class="message-list" class="message-list"
@mouseenter="pauseScroll" @mouseenter="pauseScroll"
@mouseleave="resumeScroll" @mouseleave="resumeScroll"
data-testid="message-list-container"
> >
<div class="message-wrapper" ref="messageWrapper"> <div class="message-wrapper" ref="messageWrapper" data-testid="message-wrapper">
<div <div
class="message-item" class="message-item"
v-for="(message, index) in extendedList" v-for="(message, index) in extendedList"
:key="index" :key="index"
:data-testid="`message-item-${index}`"
> >
<span class="time">{{ message.date }}</span> <span class="time">{{ message.date }}</span>
<div class="content"> <div class="content" data-testid="message-content">
<span class="title">{{ message.dusterName }}</span <span class="title">{{ message.dusterName }}</span
>{{ message.message }} >{{ message.message }}
</div> </div>
......
<template> <template>
<div class="page-container bag-monitoring-container"> <div class="page-container bag-monitoring-container" data-testid="bag-monitoring-container">
<div class="header"> <div class="header" data-testid="bag-monitoring-header">
<div class="select-container"> <div class="select-container" data-testid="device-select-container">
<span class="select-label">检测仪器</span> <span class="select-label">检测仪器</span>
<el-select v-model="selectedDevice" placeholder="1#布袋检测仪" @change="handleDeviceChange"> <el-select v-model="selectedDevice" placeholder="1#布袋检测仪" @change="handleDeviceChange" data-testid="device-select">
<el-option <el-option
v-for="item in deviceList" v-for="item in deviceList"
:key="item.deviceNo" :key="item.deviceNo"
:label="item.deviceName" :label="item.deviceName"
:value="item.deviceNo" :value="item.deviceNo"
:data-testid="`device-option-${item.deviceNo}`"
></el-option> ></el-option>
</el-select> </el-select>
</div> </div>
<div class="title">BME布袋监测 - {{ dusterName }}</div> <div class="title" data-testid="monitoring-title">BME布袋监测 - {{ dusterName }}</div>
</div> </div>
<div class="chart-container"> <div class="chart-container" data-testid="chart-container">
<div class="chart-wrapper" ref="chartRef"></div> <div class="chart-wrapper" ref="chartRef" data-testid="chart-wrapper"></div>
<div class="chart-wrapper no-data" v-if="chartData.xData.length === 0"> <div class="chart-wrapper no-data" v-if="chartData.xData.length === 0" data-testid="no-data-wrapper">
<div class="no-data-text">暂无数据</div> <div class="no-data-text" data-testid="no-data-text">暂无数据</div>
</div> </div>
</div> </div>
<div class="data-panel" :class="{ collapsed: !isPanelOpen }"> <div class="data-panel" :class="{ collapsed: !isPanelOpen }" data-testid="data-panel">
<div <div
class="panel-toggle" class="panel-toggle"
:class="{ :class="{
...@@ -30,33 +31,34 @@ ...@@ -30,33 +31,34 @@
'expanded-icon': isPanelOpen, 'expanded-icon': isPanelOpen,
}" }"
@click="togglePanel" @click="togglePanel"
data-testid="panel-toggle"
> >
<el-icon v-if="isPanelOpen"><ArrowRightBold /></el-icon> <el-icon v-if="isPanelOpen"><ArrowRightBold /></el-icon>
<el-icon v-if="!isPanelOpen"><ArrowLeftBold /></el-icon> <el-icon v-if="!isPanelOpen"><ArrowLeftBold /></el-icon>
</div> </div>
<div class="data-box"> <div class="data-box" data-testid="data-box">
<div class="data-item"> <div class="data-item" data-testid="data-item-1">
<div>时间: {{ currentData.time }}</div> <div>时间: {{ currentData.time }}</div>
<div>仓室: {{ currentData.compartNo }}</div> <div>仓室: {{ currentData.compartNo }}</div>
<div>反吹: {{ currentData.blowBack }}</div> <div>反吹: {{ currentData.blowBack }}</div>
</div> </div>
<div class="data-item"> <div class="data-item" data-testid="data-item-2">
<div>DI3: {{ currentData.di3 }}</div> <div>DI3: {{ currentData.di3 }}</div>
<div>排: {{ currentData.row }}</div> <div>排: {{ currentData.row }}</div>
<div>实时值: {{ currentData.realData }}</div> <div>实时值: {{ currentData.realData }}</div>
</div> </div>
<div class="data-item"> <div class="data-item" data-testid="data-item-3">
<div>基线值: {{ currentData.baseline }}</div> <div>基线值: {{ currentData.baseline }}</div>
<div>Delay: {{ currentData.delay }}</div> <div>Delay: {{ currentData.delay }}</div>
<div>totaltime: {{ currentData.totalTime }}</div> <div>totaltime: {{ currentData.totalTime }}</div>
</div> </div>
<div class="data-item"> <div class="data-item" data-testid="data-item-4">
<div>next:{{ currentData.next }}</div> <div>next:{{ currentData.next }}</div>
<div>valve:{{ currentData.valveNo }}</div> <div>valve:{{ currentData.valveNo }}</div>
<div>DI_TIME={{ currentData.diTime }}</div> <div>DI_TIME={{ currentData.diTime }}</div>
</div> </div>
<div class="data-item"> <div class="data-item" data-testid="data-item-5">
<div>peak={{ currentData.peak }}</div> <div>peak={{ currentData.peak }}</div>
</div> </div>
</div> </div>
...@@ -66,76 +68,78 @@ ...@@ -66,76 +68,78 @@
</div> --> </div> -->
</div> </div>
<div class="time-controls"> <div class="time-controls" data-testid="time-controls">
<div class="time-desc"> <div class="time-desc" data-testid="time-desc">
<span class="icon"></span> <span class="icon"></span>
<span class="time-desc-text">当前实时信号:</span> <span class="time-desc-text">当前实时信号:</span>
<span class="time-desc-value">{{ currentData.compartNo }}仓 / {{ currentData.row }}</span> <span class="time-desc-value">{{ currentData.compartNo }}仓 / {{ currentData.row }}</span>
</div> </div>
<div> <div data-testid="navigation-controls">
<el-button @click="navigateBackward"> <el-button @click="navigateBackward" data-testid="navigate-backward-button">
<el-icon><ArrowLeftBold />向前</el-icon> <el-icon><ArrowLeftBold />向前</el-icon>
</el-button> </el-button>
<el-button @click="navigateForward"> <el-button @click="navigateForward" data-testid="navigate-forward-button">
<el-icon><ArrowRightBold />向后</el-icon> <el-icon><ArrowRightBold />向后</el-icon>
</el-button> </el-button>
<span class="time-label">间隔</span> <span class="time-label" data-testid="time-label">间隔</span>
<el-input v-model="timeInterval" class="time-input"></el-input> <el-input v-model="timeInterval" class="time-input" data-testid="time-interval-input"></el-input>
<span class="time-unit">分钟</span> <span class="time-unit" data-testid="time-unit">分钟</span>
<el-button @click="reset">重置</el-button> <el-button @click="reset" data-testid="reset-button">重置</el-button>
</div> </div>
</div> </div>
<div class="data-table"> <div class="data-table" data-testid="data-table">
<table> <table data-testid="monitoring-table">
<thead> <thead data-testid="table-head">
<tr> <tr data-testid="table-header-row">
<th>名称</th> <th data-testid="table-header-name">名称</th>
<th v-for="(value, index) in tableData" :key="index"> <th v-for="(value, index) in tableData" :key="index" :data-testid="`table-header-${index}`">
{{ value.compartName }} {{ value.compartName }}
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody data-testid="table-body">
<tr> <tr data-testid="peak-value-r-row">
<td>峰值{{ currentData.row }}排_R</td> <td data-testid="peak-value-r-label">峰值{{ currentData.row }}排_R</td>
<td <td
v-for="(value, index) in tableData" v-for="(value, index) in tableData"
:key="'r' + index" :key="'r' + index"
:class="{ :class="{
'online-style': value.compartNo === currentData.compartNo, 'online-style': value.compartNo === currentData.compartNo,
}" }"
:data-testid="`peak-value-r-${index}`"
> >
{{ value.peakValueR }} {{ value.peakValueR }}
</td> </td>
</tr> </tr>
<tr> <tr data-testid="peak-value-h-row">
<td>峰值_H</td> <td data-testid="peak-value-h-label">峰值_H</td>
<td v-for="(value, index) in tableData" :key="'h' + index"> <td v-for="(value, index) in tableData" :key="'h' + index" :data-testid="`peak-value-h-${index}`">
{{ value.peakValueH }} {{ value.peakValueH }}
</td> </td>
</tr> </tr>
<tr> <tr data-testid="status-row">
<td>状态</td> <td data-testid="status-label">状态</td>
<td <td
v-for="(value, index) in tableData" v-for="(value, index) in tableData"
:key="'s' + index" :key="'s' + index"
:class="{ error: value.status === 1 }" :class="{ error: value.status === 1 }"
:data-testid="`status-${index}`"
> >
{{ value.status === 1 ? "故障" : "正常" }} {{ value.status === 1 ? "故障" : "正常" }}
</td> </td>
</tr> </tr>
<tr> <tr data-testid="blow-back-row">
<td>反吹中</td> <td data-testid="blow-back-label">反吹中</td>
<td v-for="(value, index) in tableData" :key="'b' + index"> <td v-for="(value, index) in tableData" :key="'b' + index" :data-testid="`blow-back-${index}`">
{{ value.blowBack }} {{ value.blowBack }}
</td> </td>
</tr> </tr>
<tr> <tr data-testid="valley-value-row">
<td>谷值</td> <td data-testid="valley-value-label">谷值</td>
<td v-for="(value, index) in tableData" :key="'v' + index"> <td v-for="(value, index) in tableData" :key="'v' + index" :data-testid="`valley-value-${index}`">
{{ value.valleyValue}} {{ value.valleyValue}}
</td> </td>
</tr> </tr>
......
<template> <template>
<div class="gsap-number-container"> <div class="gsap-number-container" data-testid="gsap-number-container">
<div :class="['value', colorClass]" ref="numberElement">{{ isStringMode ? stringValue : displayValue }}</div> <div :class="['value', colorClass]" ref="numberElement" data-testid="number-value">{{ isStringMode ? stringValue : displayValue }}</div>
</div> </div>
</template> </template>
......
<template> <template>
<!-- 方形进度条 --> <!-- 方形进度条 -->
<div class="healthy-progress"> <div class="healthy-progress" data-testid="healthy-progress-container">
<div <div
class="h-8 rounded overflow-hidden border healthy-progress-bar" class="h-8 rounded overflow-hidden border healthy-progress-bar"
:class="borderColor" :class="borderColor"
data-testid="healthy-progress-bar"
> >
<div <div
id="square-progress-bar" id="square-progress-bar"
class="healthy-progress-bar h-full transition-all duration-500 ease-out bg-gradient-to-r from-secondary to-green-400 diagonal-pattern-animation" class="healthy-progress-bar h-full transition-all duration-500 ease-out bg-gradient-to-r from-secondary to-green-400 diagonal-pattern-animation"
:class="diagonalPatternColor" :class="diagonalPatternColor"
data-testid="square-progress-bar"
></div> ></div>
<div class="justify-between items-center mb-2 healthy-text-position"> <div class="justify-between items-center mb-2 healthy-text-position" data-testid="healthy-text-position">
<span class="font-semibold">健康度:</span> <span class="font-semibold">健康度:</span>
<span id="square-progress-value" class="text-lg font-bold"> 45%</span> <span id="square-progress-value" class="text-lg font-bold"> 45%</span>
</div> </div>
......
<template> <template>
<div class="title layout1"> <div class="title layout1" data-testid="warn-title-container">
<span class="warn-title">{{ title }}</span> <span class="warn-title">{{ title }}</span>
<span class="jump-icon" @click="toDetail">>></span> <span class="jump-icon" @click="toDetail">>></span>
</div> </div>
<div class="content"> <div class="content" data-testid="warn-content-container">
<div class="item" v-for="item in listInfo" :key="item"> <div class="item" v-for="item in listInfo" :key="item" data-testid="warn-item">
<span class="msg-icon"></span> <span class="msg-icon"></span>
{{ item }} {{ item }}
</div> </div>
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
:key="item.dusterNo" :key="item.dusterNo"
:label="item.dusterName" :label="item.dusterName"
:value="item.dusterNo" :value="item.dusterNo"
:data-testid="`duster-option-${item.dusterNo}`"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
...@@ -43,7 +44,7 @@ ...@@ -43,7 +44,7 @@
<div class="left-box" data-testid="dust-monitoring-charts-section"> <div class="left-box" data-testid="dust-monitoring-charts-section">
<div class="part1 layout3" data-testid="dust-monitoring-charts-container"> <div class="part1 layout3" data-testid="dust-monitoring-charts-container">
<div class="chart-box" v-for="(item, index) in chartData" :key="item" :data-testid="`dust-monitoring-chart-${index}`"> <div class="chart-box" v-for="(item, index) in chartData" :key="item" :data-testid="`dust-monitoring-chart-${index}`">
<div :id="'chart' + index" class="chart-item"></div> <div :id="'chart' + index" class="chart-item" :data-testid="`chart-item-${index}`"></div>
</div> </div>
</div> </div>
<div class="warn-info" data-testid="dust-monitoring-warnings"> <div class="warn-info" data-testid="dust-monitoring-warnings">
...@@ -63,7 +64,7 @@ ...@@ -63,7 +64,7 @@
<div class="part2" data-testid="dust-monitoring-details-section"> <div class="part2" data-testid="dust-monitoring-details-section">
<div class="dust-title" data-testid="dust-monitoring-title">{{ dusterName }}</div> <div class="dust-title" data-testid="dust-monitoring-title">{{ dusterName }}</div>
<div class="dust-info" data-testid="dust-monitoring-info-grid"> <div class="dust-info" data-testid="dust-monitoring-info-grid">
<div class="info-item" v-for="item in dustInfo" :key="item.label"> <div class="info-item" v-for="item in dustInfo" :key="item.label" data-testid="dust-info-item">
<span class="label">{{ item.label }}</span> <span class="label">{{ item.label }}</span>
<span class="value"> <span class="value">
<gsapNumber :value="item.value" :animationType="'count'" :animationInterval="10000" /> <gsapNumber :value="item.value" :animationType="'count'" :animationInterval="10000" />
...@@ -73,17 +74,17 @@ ...@@ -73,17 +74,17 @@
<div></div> <div></div>
</div> </div>
<div class="indicator-box" data-testid="dust-monitoring-gauges"> <div class="indicator-box" data-testid="dust-monitoring-gauges">
<div class="indicator-item" id="indicatorOne"></div> <div class="indicator-item" id="indicatorOne" data-testid="indicator-one"></div>
<div class="indicator-item" id="indicatorTwo"></div> <div class="indicator-item" id="indicatorTwo" data-testid="indicator-two"></div>
</div> </div>
<div class="position-info" data-testid="dust-monitoring-status-matrix"> <div class="position-info" data-testid="dust-monitoring-status-matrix">
<div class="left" v-if="detailObj.compartHealthList.length > 0"> <div class="left" v-if="detailObj.compartHealthList.length > 0" data-testid="compartment-health-matrix">
<div class="part" v-for="(list, index) in detailObj.compartHealthList" :key="index"> <div class="part" v-for="(list, index) in detailObj.compartHealthList" :key="index" data-testid="compartment-row">
<div class="point" :class="{ <div class="point" :class="{
'status-normal': item.healthStatus === 1, 'status-normal': item.healthStatus === 1,
'status-error': item.healthStatus === 2, 'status-error': item.healthStatus === 2,
'status-warning': item.healthStatus === 3, 'status-warning': item.healthStatus === 3,
}" v-for="item in detailObj.compartHealthList[index]" :key="item" @click="handleStatusDotClick()"> }" v-for="item in detailObj.compartHealthList[index]" :key="item" @click="handleStatusDotClick()" data-testid="compartment-status-dot">
</div> </div>
</div> </div>
</div> </div>
...@@ -97,15 +98,15 @@ ...@@ -97,15 +98,15 @@
</div> --> </div> -->
</div> </div>
<div class="other-info" data-testid="dust-monitoring-compartment-info"> <div class="other-info" data-testid="dust-monitoring-compartment-info">
<div class="other-info-item"> <div class="other-info-item" data-testid="backflush-compartment-info">
<p class="label">反吹仓室:</p> <p class="label">反吹仓室:</p>
<p>{{ detailObj.bachflushCompart }}</p> <p>{{ detailObj.bachflushCompart }}</p>
</div> </div>
<div class="other-info-item"> <div class="other-info-item" data-testid="leakage-compartment-info">
<p class="label">泄露仓室:</p> <p class="label">泄露仓室:</p>
<p>{{ detailObj.leakageCompart }}</p> <p>{{ detailObj.leakageCompart }}</p>
</div> </div>
<div class="other-info-item"> <div class="other-info-item" data-testid="fault-compartment-info">
<p class="label">故障仓室:</p> <p class="label">故障仓室:</p>
<p>{{ detailObj.faultCompart }}</p> <p>{{ detailObj.faultCompart }}</p>
</div> </div>
......
<template> <template>
<el-dialog :model-value="modelValue" :title="editData ? '编辑除尘器' : '新增除尘器'" width="500px" :close-on-click-modal="false" <el-dialog :model-value="modelValue" :title="editData ? '编辑除尘器' : '新增除尘器'" width="500px" :close-on-click-modal="false"
:close-on-press-escape="false" @update:model-value="cancel"> :close-on-press-escape="false" @update:model-value="cancel" data-testid="add-dust-collector-dialog">
<div class="add-dust-form all-select-btn"> <div class="add-dust-form all-select-btn" data-testid="add-dust-form">
<div class="form-item"> <div class="form-item" data-testid="dust-type-selector">
<div class="selector-wrap"> <div class="selector-wrap" data-testid="selector-wrap">
<el-select v-model="formData.dustType" placeholder="除尘器选择" style="width: 238px" filterable remote <el-select v-model="formData.dustType" placeholder="除尘器选择" style="width: 238px" filterable remote
:remote-method="handleSearch" :loading="loading"> :remote-method="handleSearch" :loading="loading" data-testid="dust-type-select">
<el-option v-for="item in dustTypeOptions" :key="item.deviceNo" :label="item.deviceName" <el-option v-for="item in dustTypeOptions" :key="item.deviceNo" :label="item.deviceName"
:value="item.deviceNo" /> :value="item.deviceNo" :data-testid="`dust-type-option-${item.deviceNo}`" />
</el-select> </el-select>
<el-button type="deafault" size="default" class="search-btn-balck-theme" @click="selectDustType">选择</el-button> <el-button type="deafault" size="default" class="search-btn-balck-theme" @click="selectDustType" data-testid="select-dust-type-button">选择</el-button>
</div> </div>
</div> </div>
<div class="form-content"> <div class="form-content" data-testid="form-content">
<el-form ref="formRef" :model="formData" label-width="120px" :rules="rules"> <el-form ref="formRef" :model="formData" label-width="120px" :rules="rules" data-testid="dust-collector-form">
<el-form-item label="除尘器名称" prop="name"> <el-form-item label="除尘器名称" prop="name" data-testid="dust-name-form-item">
<el-input v-model="formData.name" placeholder="请输入" /> <el-input v-model="formData.name" placeholder="请输入" data-testid="dust-name-input" />
</el-form-item> </el-form-item>
<el-form-item label="除尘器编号" prop="code"> <el-form-item label="除尘器编号" prop="code" data-testid="dust-code-form-item">
<el-input v-model="formData.code" placeholder="请输入" /> <el-input v-model="formData.code" placeholder="请输入" data-testid="dust-code-input" />
</el-form-item> </el-form-item>
<el-form-item label="所属工序" prop="process"> <el-form-item label="所属工序" prop="process" data-testid="process-form-item">
<el-select v-model="formData.process" placeholder="工序选择"> <el-select v-model="formData.process" placeholder="工序选择" data-testid="process-select">
<el-option v-for="item in processOptions" :key="item.productionLineId" :label="item.productionLineName" <el-option v-for="item in processOptions" :key="item.productionLineId" :label="item.productionLineName"
:value="item.productionLineId" /> :value="item.productionLineId" :data-testid="`process-option-${item.productionLineId}`" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="仓室数量" prop="chamberCount"> <el-form-item label="仓室数量" prop="chamberCount" data-testid="chamber-count-form-item">
<el-input v-model.number="formData.chamberCount" placeholder="请输入" /> <el-input v-model.number="formData.chamberCount" placeholder="请输入" data-testid="chamber-count-input" />
</el-form-item> </el-form-item>
<el-form-item label="电磁阀数量" prop="valveCount"> <el-form-item label="电磁阀数量" prop="valveCount" data-testid="valve-count-form-item">
<el-input v-model.number="formData.valveCount" placeholder="请输入" /> <el-input v-model.number="formData.valveCount" placeholder="请输入" data-testid="valve-count-input" />
</el-form-item> </el-form-item>
<el-form-item label="合理压差范围" required> <el-form-item label="合理压差范围" required data-testid="pressure-range-form-item">
<div class="range-input"> <div class="range-input" data-testid="pressure-range-input">
<el-form-item prop="pressureMin" class="coordinate-item"> <el-form-item prop="pressureMin" class="coordinate-item" data-testid="pressure-min-form-item">
<el-input v-model.number="formData.pressureMin" placeholder="请输入" /> <el-input v-model.number="formData.pressureMin" placeholder="请输入" data-testid="pressure-min-input" />
</el-form-item> </el-form-item>
<span class="separator"></span> <span class="separator" data-testid="pressure-separator"></span>
<el-form-item prop="pressureMax" class="coordinate-item"> <el-form-item prop="pressureMax" class="coordinate-item" data-testid="pressure-max-form-item">
<el-input v-model.number="formData.pressureMax" placeholder="请输入" /> <el-input v-model.number="formData.pressureMax" placeholder="请输入" data-testid="pressure-max-input" />
</el-form-item> </el-form-item>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="服务器IP" prop="serverIp" required> <el-form-item label="服务器IP" prop="serverIp" required data-testid="server-ip-form-item">
<el-input v-model="formData.serverIp" placeholder="请输入" /> <el-input v-model="formData.serverIp" placeholder="请输入" data-testid="server-ip-input" />
</el-form-item> </el-form-item>
<el-form-item label="二维图坐标" required> <el-form-item label="二维图坐标" required data-testid="coordinate-form-item">
<div class="coordinate-inputs"> <div class="coordinate-inputs" data-testid="coordinate-inputs">
<el-form-item prop="coordinateX" class="coordinate-item"> <el-form-item prop="coordinateX" class="coordinate-item" data-testid="coordinate-x-form-item">
<el-input v-model.number="formData.coordinateX" placeholder="X坐标"> <el-input v-model.number="formData.coordinateX" placeholder="X坐标" data-testid="coordinate-x-input">
<template #prefix>X:</template> <template #prefix>X:</template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="coordinateY" class="coordinate-item"> <el-form-item prop="coordinateY" class="coordinate-item" data-testid="coordinate-y-form-item">
<el-input v-model.number="formData.coordinateY" placeholder="Y坐标"> <el-input v-model.number="formData.coordinateY" placeholder="Y坐标" data-testid="coordinate-y-input">
<template #prefix>Y:</template> <template #prefix>Y:</template>
</el-input> </el-input>
</el-form-item> </el-form-item>
...@@ -71,10 +71,10 @@ ...@@ -71,10 +71,10 @@
</el-form> </el-form>
</div> </div>
<div class="form-footer"> <div class="form-footer" data-testid="form-footer">
<el-button @click="cancel" class="cancel-btn-balck-theme">取消</el-button> <el-button @click="cancel" class="cancel-btn-balck-theme" data-testid="cancel-button">取消</el-button>
<el-button type="default" class="search-btn-balck-theme" @click="submitForm">确认</el-button> <el-button type="default" class="search-btn-balck-theme" @click="submitForm" data-testid="confirm-button">确认</el-button>
</div> </div>
</div> </div>
</el-dialog> </el-dialog>
......
...@@ -7,30 +7,33 @@ ...@@ -7,30 +7,33 @@
:close-on-press-escape="false" :close-on-press-escape="false"
@update:model-value="$emit('update:modelValue', $event)" @update:model-value="$emit('update:modelValue', $event)"
@open="initializeState" @open="initializeState"
data-testid="room-setting-dialog"
> >
<el-form :model="roomForm" label-width="120px"> <el-form :model="roomForm" label-width="120px" data-testid="room-form">
<el-form-item label="仓室数量:"> <el-form-item label="仓室数量:" data-testid="total-rooms-form-item">
<el-input <el-input
v-model="roomForm.totalRooms" v-model="roomForm.totalRooms"
controls-position="right" controls-position="right"
style="width: 150px" style="width: 150px"
disabled disabled
data-testid="total-rooms-input"
/> />
</el-form-item> </el-form-item>
<el-form-item label="仓室分几排:"> <el-form-item label="仓室分几排:" data-testid="rows-form-item">
<el-input-number <el-input-number
v-model="roomForm.rows" v-model="roomForm.rows"
:min="0" :min="0"
:max="20" :max="20"
controls-position="right" controls-position="right"
@change="handleRowsChange" @change="handleRowsChange"
data-testid="rows-input-number"
/> />
</el-form-item> </el-form-item>
</el-form> </el-form>
<!-- 分布表格 --> <!-- 分布表格 -->
<div class="distribution-table"> <div class="distribution-table" data-testid="distribution-table">
<div class="table-title"> <div class="table-title" data-testid="table-title">
仓室数量分布 仓室数量分布
<div <div
v-if="distributionDiff > 0" v-if="distributionDiff > 0"
...@@ -38,6 +41,7 @@ ...@@ -38,6 +41,7 @@
'distribution-warning', 'distribution-warning',
distributionDiff > 0 ? 'warning-less' : 'warning-less', distributionDiff > 0 ? 'warning-less' : 'warning-less',
]" ]"
data-testid="distribution-warning"
> >
当前仓室总数{{ distributionDiff > 0 ? "大于" : "小于" }}默认仓室数量 当前仓室总数{{ distributionDiff > 0 ? "大于" : "小于" }}默认仓室数量
{{ Math.abs(distributionDiff) }} 个,请修改。 {{ Math.abs(distributionDiff) }} 个,请修改。
...@@ -49,13 +53,14 @@ ...@@ -49,13 +53,14 @@
size="small" size="small"
border border
:resizable="false" :resizable="false"
data-testid="distribution-data-table"
> >
<el-table-column prop="compartPositionRow" label="排" width="180"> <el-table-column prop="compartPositionRow" label="排" width="180" data-testid="row-column">
<template #default="{ row }"> <template #default="{ row }">
<span>{{ row.compartPositionRow }}</span> <span data-testid="row-label">{{ row.compartPositionRow }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="compartPositionColumnNum" label="仓数量"> <el-table-column prop="compartPositionColumnNum" label="仓数量" data-testid="count-column">
<template #default="{ row }"> <template #default="{ row }">
<el-input-number <el-input-number
v-model="row.compartPositionColumnNum" v-model="row.compartPositionColumnNum"
...@@ -64,6 +69,7 @@ ...@@ -64,6 +69,7 @@
controls-position="right" controls-position="right"
size="small" size="small"
@change="handleDistributionChange" @change="handleDistributionChange"
:data-testid="`room-count-input-${row.compartPositionRow}`"
/> />
</template> </template>
</el-table-column> </el-table-column>
...@@ -71,13 +77,14 @@ ...@@ -71,13 +77,14 @@
</div> </div>
<template #footer> <template #footer>
<span class="dialog-footer all-select-btn"> <span class="dialog-footer all-select-btn" data-testid="dialog-footer">
<el-button @click="$emit('update:modelValue', false)" class="cancel-btn-balck-theme">取消</el-button> <el-button @click="$emit('update:modelValue', false)" class="cancel-btn-balck-theme" data-testid="cancel-button">取消</el-button>
<el-button <el-button
type="default" type="default"
class="search-btn-balck-theme" class="search-btn-balck-theme"
@click="handleConfirm" @click="handleConfirm"
:disabled="distributionDiff > 0" :disabled="distributionDiff > 0"
data-testid="confirm-button"
> >
确认 确认
</el-button> </el-button>
......
...@@ -6,32 +6,34 @@ ...@@ -6,32 +6,34 @@
:close-on-click-modal="false" :close-on-click-modal="false"
:close-on-press-escape="false" :close-on-press-escape="false"
@update:model-value="cancel" @update:model-value="cancel"
data-testid="valve-setting-dialog"
> >
<div class="valve-setting all-select-btn"> <div class="valve-setting all-select-btn" data-testid="valve-setting-container">
<div class="setting-row"> <div class="setting-row" data-testid="valve-setting-controls">
<div class="input-group"> <div class="input-group" data-testid="total-valves-input-group">
<span>电磁阀总数量:</span> <span data-testid="total-valves-label">电磁阀总数量:</span>
<el-input v-model="valveForm.total" style="width: 120px" disabled /> <el-input v-model="valveForm.total" style="width: 120px" disabled data-testid="total-valves-input" />
</div> </div>
<el-button type="default" class="search-btn-balck-theme" @click="handleAverageDistribute" <el-button type="default" class="search-btn-balck-theme" @click="handleAverageDistribute" data-testid="average-distribute-button"
>平均分布生成</el-button >平均分布生成</el-button
> >
</div> </div>
<div class="table-title">仓室脉冲阀数量分布</div> <div class="table-title" data-testid="valve-table-title">仓室脉冲阀数量分布</div>
<div class="setting-row"> <div class="setting-row" data-testid="setting-row-controls">
<div class="input-group"> <div class="input-group" data-testid="compartment-number-select">
<span>仓室编号:</span> <span data-testid="compartment-number-label">仓室编号:</span>
<el-select v-model="valveForm.frontCompartNo" style="width: 120px" @change="handleRoomChange"> <el-select v-model="valveForm.frontCompartNo" style="width: 120px" @change="handleRoomChange" data-testid="compartment-select">
<el-option <el-option
v-for="cell in statusData" v-for="cell in statusData"
:key="cell.frontCompartNo" :key="cell.frontCompartNo"
:label="`${cell.frontCompartNo}仓`" :label="`${cell.frontCompartNo}仓`"
:value="cell.frontCompartNo" :value="cell.frontCompartNo"
:data-testid="`compartment-option-${cell.frontCompartNo}`"
/> />
</el-select> </el-select>
</div> </div>
<div class="input-group"> <div class="input-group" data-testid="valve-distribution-input">
<span>电磁阀分布数量:</span> <span data-testid="valve-distribution-label">电磁阀分布数量:</span>
<el-input-number <el-input-number
v-model="valveForm.valveNum" v-model="valveForm.valveNum"
:min="0" :min="0"
...@@ -39,23 +41,25 @@ ...@@ -39,23 +41,25 @@
style="width: 120px" style="width: 120px"
@change="handleValveNumChange" @change="handleValveNumChange"
:class="{ 'is-error': errorMessage }" :class="{ 'is-error': errorMessage }"
data-testid="valve-distribution-number-input"
/> />
</div> </div>
<div class="input-group"> <div class="input-group" data-testid="bag-quantity-input">
<span>布袋数量:</span> <span data-testid="bag-quantity-label">布袋数量:</span>
<el-input-number <el-input-number
v-model="valveForm.bagNum" v-model="valveForm.bagNum"
:min="0" :min="0"
controls-position="right" controls-position="right"
style="width: 120px" style="width: 120px"
@change="handleBagNumChange" @change="handleBagNumChange"
data-testid="bag-quantity-number-input"
/> />
</div> </div>
</div> </div>
<!-- 错误提示 --> <!-- 错误提示 -->
<div v-if="errorMessage" class="error-message"> <div v-if="errorMessage" class="error-message" data-testid="error-message">
<i class="el-icon-warning"></i> <i class="el-icon-warning" data-testid="error-icon"></i>
{{ errorMessage }} {{ errorMessage }}
</div> </div>
...@@ -65,38 +69,40 @@ ...@@ -65,38 +69,40 @@
class="save-btn" class="save-btn"
@click="handleSave" @click="handleSave"
:disabled="!!errorMessage || valveForm.valveNum === null || valveForm.bagNum === null" :disabled="!!errorMessage || valveForm.valveNum === null || valveForm.bagNum === null"
data-testid="set-button"
>设置</el-button> >设置</el-button>
</div> --> </div> -->
</div> </div>
<!-- 分布表格 --> <!-- 分布表格 -->
<div class="bagNum-table"> <div class="bagNum-table" data-testid="valve-distribution-table">
<div class="table-title"> <div class="table-title" data-testid="distribution-table-title">
仓室脉冲阀数量分布 仓室脉冲阀数量分布
<span class="valve-valveNum-info"> <span class="valve-valveNum-info" data-testid="valve-count-info">
(当前分配: {{ currentTotalValves }}/{{ valveForm.total }}) (当前分配: {{ currentTotalValves }}/{{ valveForm.total }})
</span> </span>
</div> </div>
<div class="valve-bagNum-grid"> <div class="valve-bagNum-grid" data-testid="valve-grid">
<div class="valve-row"> <div class="valve-row" data-testid="valve-row">
<div <div
v-for="(cell, colIndex) in statusData" v-for="(cell, colIndex) in statusData"
:key="colIndex" :key="colIndex"
class="valve-cell" class="valve-cell"
:class="{ 'active-cell': cell.frontCompartNo === valveForm.frontCompartNo }" :class="{ 'active-cell': cell.frontCompartNo === valveForm.frontCompartNo }"
@click="valveForm.frontCompartNo = cell.frontCompartNo; handleRoomChange(cell.frontCompartNo)" @click="valveForm.frontCompartNo = cell.frontCompartNo; handleRoomChange(cell.frontCompartNo)"
:data-testid="`valve-cell-${cell.frontCompartNo}`"
> >
<div class="cell-index">{{ cell.frontCompartNo }}</div> <div class="cell-index" data-testid="cell-index">{{ cell.frontCompartNo }}</div>
<div class="cell-value">{{ cell.valveNum }} <span>({{ cell.bagNum }})</span></div> <div class="cell-value" data-testid="cell-value">{{ cell.valveNum }} <span data-testid="cell-bag-count">({{ cell.bagNum }})</span></div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer" data-testid="valve-dialog-footer">
<el-button @click="cancel" class="cancel-btn-balck-theme">取消</el-button> <el-button @click="cancel" class="cancel-btn-balck-theme" data-testid="cancel-button">取消</el-button>
<el-button type="default" class="search-btn-balck-theme" @click="handleConfirm" :disabled="!!errorMessage"> <el-button type="default" class="search-btn-balck-theme" @click="handleConfirm" :disabled="!!errorMessage" data-testid="save-button">
保存 保存
</el-button> </el-button>
</span> </span>
......
...@@ -38,12 +38,13 @@ ...@@ -38,12 +38,13 @@
:filter-method="filterProductionLine" :filter-method="filterProductionLine"
data-testid="dust-production-line-select" data-testid="dust-production-line-select"
> >
<el-option key="all" label="全部" value="all" /> <el-option key="all" label="全部" value="all" data-testid="production-line-option-all" />
<el-option <el-option
v-for="item in productionLineFiltered" v-for="item in productionLineFiltered"
:key="item.productionLineId" :key="item.productionLineId"
:label="item.productionLineName" :label="item.productionLineName"
:value="item.productionLineId" :value="item.productionLineId"
:data-testid="`production-line-option-${item.productionLineId}`"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
......
<template> <template>
<div class="container el-self-container all-select-btn" v-if="dialogVisible"> <div class="container el-self-container all-select-btn" v-if="dialogVisible" data-testid="params-settings-container">
<div class="close-box" @click="cancelFun"> <div class="close-box" @click="cancelFun" data-testid="close-button">
<el-icon size="25"><Close /></el-icon> <el-icon size="25"><Close /></el-icon>
</div> </div>
<h1 class="title">sensor设置信息</h1> <h1 class="title">sensor设置信息</h1>
<div class="content-box"> <div class="content-box" data-testid="content-box">
<div class="grid-container"> <div class="grid-container" data-testid="grid-container">
<!-- 左侧参数设置 --> <!-- 左侧参数设置 -->
<div class="setting-group"> <div class="setting-group" data-testid="left-settings">
<div <div
class="setting-row" class="setting-row"
v-for="item in leftInfoEnum" v-for="item in leftInfoEnum"
...@@ -22,29 +22,33 @@ ...@@ -22,29 +22,33 @@
style="margin-right: 10px" style="margin-right: 10px"
v-if="item.type2 === 'checkbox'" v-if="item.type2 === 'checkbox'"
v-model="infoObj[item.propKey2]" v-model="infoObj[item.propKey2]"
:data-testid="`left-checkbox-${item.propKey2}`"
></el-checkbox> ></el-checkbox>
{{ item.label }} {{ item.label }}
</span> </span>
<el-input <el-input
v-if="item.type === 'input'" v-if="item.type === 'input'"
v-model="infoObj[item.propKey]" v-model="infoObj[item.propKey]"
:data-testid="`left-input-${item.propKey}`"
></el-input> ></el-input>
<el-select <el-select
v-model="infoObj[item.propKey]" v-model="infoObj[item.propKey]"
v-if="item.type === 'select'" v-if="item.type === 'select'"
:data-testid="`left-select-${item.propKey}`"
> >
<el-option <el-option
v-for="option in item.options" v-for="option in item.options"
:key="option.code" :key="option.code"
:label="option.name" :label="option.name"
:value="option.code" :value="option.code"
:data-testid="`left-select-option-${option.code}`"
></el-option> ></el-option>
</el-select> </el-select>
</div> </div>
</div> </div>
<!-- 右侧参数设置 --> <!-- 右侧参数设置 -->
<div class="setting-group"> <div class="setting-group" data-testid="right-settings">
<div <div
class="setting-row" class="setting-row"
v-for="item in rightInfoEnum" v-for="item in rightInfoEnum"
...@@ -54,24 +58,25 @@ ...@@ -54,24 +58,25 @@
<el-input <el-input
v-if="item.type === 'input'" v-if="item.type === 'input'"
v-model="infoObj[item.propKey]" v-model="infoObj[item.propKey]"
:data-testid="`right-input-${item.propKey}`"
></el-input> ></el-input>
</div> </div>
</div> </div>
</div> </div>
<!-- 复选框区域 --> <!-- 复选框区域 -->
<div class="checkbox-group"> <div class="checkbox-group" data-testid="checkbox-group-1">
<label class="custom-checkbox"> <label class="custom-checkbox">
<input type="checkbox" v-model="infoObj.onlineBackblow" /> 在线反吹 <input type="checkbox" v-model="infoObj.onlineBackblow" data-testid="online-backblow-checkbox" /> 在线反吹
</label> </label>
<label class="custom-checkbox"> <label class="custom-checkbox">
<input type="checkbox" v-model="infoObj.fastBlow" /> 快/慢 <input type="checkbox" v-model="infoObj.fastBlow" data-testid="fast-blow-checkbox" /> 快/慢
</label> </label>
<label class="custom-checkbox"> <label class="custom-checkbox">
<input type="checkbox" v-model="infoObj.d01Alarm" /> DO1报警 <input type="checkbox" v-model="infoObj.d01Alarm" data-testid="d01-alarm-checkbox" /> DO1报警
</label> </label>
<label class="custom-checkbox"> <label class="custom-checkbox">
<input type="checkbox" v-model="infoObj.d13Alarm" /> DI3有效 <input type="checkbox" v-model="infoObj.d13Alarm" data-testid="d13-alarm-checkbox" /> DI3有效
</label> </label>
</div> </div>
...@@ -81,59 +86,62 @@ ...@@ -81,59 +86,62 @@
type="textarea" type="textarea"
:rows="4" :rows="4"
v-model="infoObj.compartSort" v-model="infoObj.compartSort"
data-testid="compart-sort-textarea"
></el-input> ></el-input>
<!-- 复选框区域 --> <!-- 复选框区域 -->
<div class="checkbox-group mgr10"> <div class="checkbox-group mgr10" data-testid="checkbox-group-2">
<label class="custom-checkbox"> <label class="custom-checkbox">
<input type="checkbox" v-model="infoObj.diInput" /> DI接入Y/N <input type="checkbox" v-model="infoObj.diInput" data-testid="di-input-checkbox" /> DI接入Y/N
</label> </label>
<label class="custom-checkbox"> <label class="custom-checkbox">
<input type="checkbox" v-model="infoObj.showEarlyWarn" /> 显示预警 <input type="checkbox" v-model="infoObj.showEarlyWarn" data-testid="show-early-warn-checkbox" /> 显示预警
</label> </label>
<div class="setting-row"> <div class="setting-row" data-testid="device-relation-setting">
<span class="device-label">关联设备</span> <span class="device-label">关联设备</span>
<el-select v-model="infoObj.relateDevicesNum" placeholder="请选择"> <el-select v-model="infoObj.relateDevicesNum" placeholder="请选择" data-testid="relate-devices-select">
<el-option <el-option
v-for="(item, index) in 21" v-for="(item, index) in 21"
:key="item" :key="item"
:value="index" :value="index"
:label="index" :label="index"
:data-testid="`relate-device-option-${index}`"
></el-option> ></el-option>
</el-select> </el-select>
</div> </div>
</div> </div>
<!-- 复选框区域 --> <!-- 复选框区域 -->
<div class="checkbox-group mgr10"> <div class="checkbox-group mgr10" data-testid="checkbox-group-3">
<div class="select-input"> <div class="select-input" data-testid="valve-device-setting">
<label class="custom-checkbox"> <label class="custom-checkbox">
<input <input
type="checkbox" type="checkbox"
checked checked
v-model="infoObj.hasLiftValveCommunicationIp" v-model="infoObj.hasLiftValveCommunicationIp"
data-testid="has-lift-valve-checkbox"
/> />
脉冲阀设备Y/N 通信IP 脉冲阀设备Y/N 通信IP
</label> </label>
<div style="margin-left: 10px"> <div style="margin-left: 10px" data-testid="ip-input-container">
<el-input v-model="infoObj.liftValveCommunicationIp"></el-input> <el-input v-model="infoObj.liftValveCommunicationIp" data-testid="lift-valve-ip-input"></el-input>
</div> </div>
</div> </div>
<div> <div data-testid="pulse-blow-setting">
<label class="custom-checkbox"> <label class="custom-checkbox">
<input type="checkbox" v-model="infoObj.indoorPulseBlow"/> 室内脉冲轮流喷吹 <input type="checkbox" v-model="infoObj.indoorPulseBlow" data-testid="indoor-pulse-blow-checkbox"/> 室内脉冲轮流喷吹
</label> </label>
</div> </div>
</div> </div>
</div> </div>
<!-- 操作按钮 --> <!-- 操作按钮 -->
<div class="button-group"> <div class="button-group" data-testid="button-group">
<button class="btn search-btn-balck-theme" @click="confirmFun">确认</button> <button class="btn search-btn-balck-theme" @click="confirmFun" data-testid="confirm-button">确认</button>
<button class="btn cancel-btn-balck-theme" @click="cancelFun">取消</button> <button class="btn cancel-btn-balck-theme" @click="cancelFun" data-testid="cancel-button">取消</button>
</div> </div>
</div> </div>
<div class="mask" v-if="dialogVisible" @click="cancelFun"></div> <div class="mask" v-if="dialogVisible" @click="cancelFun" data-testid="dialog-mask"></div>
</template> </template>
<script setup> <script setup>
import { ref, reactive, computed, defineEmits, onMounted, watch } from "vue"; import { ref, reactive, computed, defineEmits, onMounted, watch } from "vue";
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
:key="item.productionLineId" :key="item.productionLineId"
:label="item.productionLineName" :label="item.productionLineName"
:value="item.productionLineId" :value="item.productionLineId"
:data-testid="`equipment-production-line-option-${item.productionLineId}`"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
...@@ -47,6 +48,7 @@ ...@@ -47,6 +48,7 @@
:key="item.deviceTypeId" :key="item.deviceTypeId"
:label="item.deviceType" :label="item.deviceType"
:value="item.deviceTypeId" :value="item.deviceTypeId"
:data-testid="`equipment-device-type-option-${item.deviceTypeId}`"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
......
<template> <template>
<div class="page-container collectorList all-select-btn"> <div class="page-container collectorList all-select-btn" data-testid="suspend-management-container">
<div class="content-box"> <div class="content-box" data-testid="content-box">
<div class="search"> <div class="search" data-testid="search-area">
<el-form :inline="true" :model="formInline" class="demo-form-inline"> <el-form :inline="true" :model="formInline" class="demo-form-inline" data-testid="search-form">
<el-form-item label="项目名称"> <el-form-item label="项目名称">
<el-select v-model="formInline.projectId" style="width: 200px"> <el-select v-model="formInline.projectId" style="width: 200px" data-testid="project-select">
<el-option <el-option
v-for="i in nameList.list" v-for="i in nameList.list"
:key="i" :key="i"
:label="`${i.name}`" :label="`${i.name}`"
:value="i.id" :value="i.id"
:data-testid="`project-option-${i.id}`"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="设备类型"> <el-form-item label="设备类型">
<el-select v-model="formInline.deviceType" style="width: 200px"> <el-select v-model="formInline.deviceType" style="width: 200px" data-testid="device-type-select">
<el-option <el-option
v-for="i in typeList.list" v-for="i in typeList.list"
:key="i" :key="i"
:label="`${i.desc}`" :label="`${i.desc}`"
:value="i.code" :value="i.code"
:data-testid="`device-type-option-${i.code}`"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="原因分类"> <el-form-item label="原因分类">
<el-select v-model="formInline.reasonCategory" style="width: 200px"> <el-select v-model="formInline.reasonCategory" style="width: 200px" data-testid="reason-category-select">
<el-option <el-option
v-for="i in reasonList.list" v-for="i in reasonList.list"
:key="i" :key="i"
:label="`${i.value}`" :label="`${i.value}`"
:value="i.key" :value="i.key"
:data-testid="`reason-category-option-${i.key}`"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="default" class="reset-btn-balck-theme" @click="onReset" <el-button type="default" class="reset-btn-balck-theme" @click="onReset" data-testid="reset-button"
>重置</el-button >重置</el-button
> >
<el-button type="default" class="search-btn-balck-theme" @click="onSubmit" <el-button type="default" class="search-btn-balck-theme" @click="onSubmit" data-testid="search-button"
>查询</el-button >查询</el-button
> >
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
<div class="table-box"> <div class="table-box" data-testid="table-container">
<common-table <common-table
ref="pageRef" ref="pageRef"
:data="tableData.list" :data="tableData.list"
...@@ -59,12 +62,13 @@ ...@@ -59,12 +62,13 @@
next: '后一页', next: '后一页',
jumper: '跳至', jumper: '跳至',
}" }"
data-testid="suspend-management-table"
> >
<template #index="{ $index }"> <template #index="{ $index }">
{{ getIndex($index) }} {{ getIndex($index) }}
</template> </template>
<template #operate="{ row }"> <template #operate="{ row }">
<span class="health-score green-color" @click="linkTo(row)">挂起期间告警</span> <span class="health-score green-color" @click="linkTo(row)" data-testid="suspend-alarm-link">挂起期间告警</span>
</template> </template>
<!-- <template #operation="{ row }"> <!-- <template #operation="{ row }">
<span class="view-btn" @click="handleView(row)">详情</span> <span class="view-btn" @click="handleView(row)">详情</span>
......
@echo off
REM DC-TOM Cypress Studio 启动器 - Windows 批处理版本
REM 功能: 先启动开发服务器,然后启动 Cypress Studio
echo.
echo [INFO] DC-TOM Cypress Studio 启动器 - Windows 版本
echo [INFO] 运行平台: Windows
echo.
REM 检查 Node.js 是否安装
node --version >nul 2>&1
if errorlevel 1 (
echo [ERROR] Node.js 未安装或不在 PATH 中
echo 请先安装 Node.js: https://nodejs.org
pause
exit /b 1
)
REM 检查 npm 是否可用
npm --version >nul 2>&1
if errorlevel 1 (
echo [ERROR] npm 未安装或不在 PATH 中
pause
exit /b 1
)
REM 运行 Node.js 脚本
echo [INFO] 启动 Cypress Studio 启动器...
node start-studio.cjs %*
REM 检查脚本执行结果
if errorlevel 1 (
echo.
echo [ERROR] 启动器执行失败
echo 可能的解决方案:
echo 1. 确保项目依赖已安装: npm install
echo 2. 检查 Cypress 是否正确安装
echo 3. 确保端口 3000 未被占用
pause
exit /b 1
)
echo.
echo [INFO] 启动器执行完成
pause
\ No newline at end of file
#!/usr/bin/env node
/**
* DC-TOM Cypress Studio 启动器
* 跨平台支持 (Windows/macOS/Linux)
* 功能: 先启动开发服务器,然后启动 Cypress Studio
*/
const { spawn, exec } = require('child_process');
const http = require('http');
const os = require('os');
// 颜色定义 (Windows CMD 支持的 ANSI 颜色)
const colors = {
reset: '\x1b[0m',
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
cyan: '\x1b[36m'
};
// 日志函数
const log = {
info: (msg) => console.log(`${colors.blue}ℹ️ ${msg}${colors.reset}`),
success: (msg) => console.log(`${colors.green}✅ ${msg}${colors.reset}`),
warning: (msg) => console.log(`${colors.yellow}⚠️ ${msg}${colors.reset}`),
error: (msg) => console.log(`${colors.red}❌ ${msg}${colors.reset}`),
plain: (msg) => console.log(msg)
};
// 全局变量
let devServerProcess = null;
let isWindows = os.platform() === 'win32';
// 检查端口是否被占用
function checkPort(port) {
return new Promise((resolve) => {
const server = http.createServer();
server.listen(port, () => {
server.close(() => resolve(false)); // 端口未被占用
});
server.on('error', () => resolve(true)); // 端口被占用
});
}
// 等待开发服务器启动
function waitForServer(url, maxAttempts = 30) {
return new Promise((resolve) => {
let attempts = 0;
const checkServer = () => {
attempts++;
const request = http.get(url, (res) => {
if (res.statusCode === 200) {
resolve(true);
} else if (attempts < maxAttempts) {
setTimeout(checkServer, 1000);
} else {
resolve(false);
}
});
request.on('error', () => {
if (attempts < maxAttempts) {
process.stdout.write('.');
setTimeout(checkServer, 1000);
} else {
resolve(false);
}
});
request.setTimeout(2000, () => {
request.destroy();
if (attempts < maxAttempts) {
process.stdout.write('.');
setTimeout(checkServer, 1000);
} else {
resolve(false);
}
});
};
checkServer();
});
}
// 启动开发服务器
async function startDevServer() {
const portOccupied = await checkPort(3000);
if (portOccupied) {
log.warning('端口 3000 已被占用,跳过开发服务器启动');
log.info('如果需要重新启动,请先停止现有的服务');
return true;
}
log.info('启动开发服务器...');
return new Promise((resolve) => {
// Windows 和 Unix 系统使用不同的命令
const npmCommand = isWindows ? 'npm.cmd' : 'npm';
devServerProcess = spawn(npmCommand, ['run', 'dev'], {
cwd: process.cwd(),
stdio: ['pipe', 'pipe', 'pipe'],
shell: isWindows
});
devServerProcess.stdout.on('data', (data) => {
const output = data.toString();
if (output.includes('Local:') && output.includes('localhost:3000')) {
log.success(`开发服务器启动成功 (PID: ${devServerProcess.pid})`);
resolve(true);
}
});
devServerProcess.stderr.on('data', (data) => {
// Vite 的一些输出会到 stderr,但不一定是错误
const output = data.toString();
if (output.includes('Local:') && output.includes('localhost:3000')) {
log.success(`开发服务器启动成功 (PID: ${devServerProcess.pid})`);
resolve(true);
}
});
devServerProcess.on('error', (error) => {
log.error(`开发服务器启动失败: ${error.message}`);
resolve(false);
});
devServerProcess.on('exit', (code) => {
if (code !== 0) {
log.error(`开发服务器异常退出,代码: ${code}`);
resolve(false);
}
});
// 设置超时
setTimeout(() => {
log.info('等待开发服务器启动...');
waitForServer('http://localhost:3000').then((serverReady) => {
if (serverReady) {
log.success('开发服务器已就绪');
resolve(true);
} else {
log.error('开发服务器启动超时');
resolve(false);
}
});
}, 3000);
});
}
// 启动 Cypress Studio
function startCypressStudio() {
log.info('启动 Cypress Studio...');
log.info('Cypress Studio 将在新窗口中打开');
log.info('您可以在 Studio 中录制和编辑测试用例');
const npxCommand = isWindows ? 'npx.cmd' : 'npx';
const cypressProcess = spawn(npxCommand, ['cypress', 'open', '--config', 'experimentalStudio=true'], {
cwd: process.cwd(),
stdio: 'inherit',
shell: isWindows
});
cypressProcess.on('error', (error) => {
log.error(`Cypress Studio 启动失败: ${error.message}`);
cleanup();
process.exit(1);
});
cypressProcess.on('exit', (code) => {
log.info('Cypress Studio 已关闭');
cleanup();
process.exit(code || 0);
});
}
// 清理函数
function cleanup() {
log.info('正在清理进程...');
if (devServerProcess && !devServerProcess.killed) {
log.info(`停止开发服务器 (PID: ${devServerProcess.pid})`);
if (isWindows) {
// Windows 需要强制终止整个进程树
exec(`taskkill /pid ${devServerProcess.pid} /T /F`, (error) => {
if (error) {
log.warning('无法自动停止开发服务器,请手动终止');
}
});
} else {
devServerProcess.kill('SIGTERM');
}
}
}
// 显示使用说明
function showUsage() {
log.plain('用法: node start-studio.js [选项]');
log.plain('');
log.plain('选项:');
log.plain(' --help, -h 显示此帮助信息');
log.plain('');
log.plain('功能:');
log.plain(' 1. 自动启动开发服务器 (localhost:3000)');
log.plain(' 2. 等待服务器就绪');
log.plain(' 3. 启动 Cypress Studio');
log.plain('');
log.plain('注意:');
log.plain(' - 支持 Windows/macOS/Linux');
log.plain(' - 如果端口 3000 已被占用,将跳过开发服务器启动');
log.plain(' - 关闭 Cypress Studio 时,开发服务器也会自动停止');
log.plain(' - 使用 Ctrl+C 可以同时停止两个服务');
}
// 主函数
async function main() {
// 处理命令行参数
if (process.argv.includes('--help') || process.argv.includes('-h')) {
showUsage();
return;
}
console.log();
log.info('🚀 DC-TOM Cypress Studio 启动器');
log.info(`📦 运行平台: ${os.platform()} ${os.arch()}`);
console.log();
// 启动开发服务器
const serverStarted = await startDevServer();
if (serverStarted) {
console.log();
log.success('开发环境准备就绪');
console.log();
// 启动 Cypress Studio
startCypressStudio();
} else {
log.error('无法启动开发服务器,Cypress Studio 启动已取消');
process.exit(1);
}
}
// 设置退出处理
process.on('SIGINT', () => {
log.info('\n收到中断信号,正在退出...');
cleanup();
process.exit(0);
});
process.on('SIGTERM', () => {
log.info('\n收到终止信号,正在退出...');
cleanup();
process.exit(0);
});
process.on('exit', () => {
cleanup();
});
// 运行主函数
main().catch((error) => {
log.error(`启动器发生错误: ${error.message}`);
cleanup();
process.exit(1);
});
\ No newline at end of file
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