自检页面调试完成

This commit is contained in:
xu
2026-09-10 14:10:40 +08:00
parent 0baf228c67
commit 32878a9a80
34 changed files with 595 additions and 1568 deletions
Binary file not shown.
File diff suppressed because it is too large Load Diff
+37
View File
@@ -1,5 +1,9 @@
#include "global.h"
#include <QStyle>
#include <QApplication>
#include <QPushButton>
#include <QEvent>
#include <QGraphicsDropShadowEffect>
// 启动 500ms 闪烁:每 500ms 切换一次动态属性,QSS 据此在 40%↔100% 透明度间切换
QTimer* startBlink(QWidget* w, const char* prop)
@@ -43,6 +47,39 @@ QString cancelButtonStyle(int fontPx)
.arg(fontPx).arg(C::DANGER);
}
// ===================== 按钮焦点光圈 =====================
ButtonFocusGlow::ButtonFocusGlow(const QColor& glow, QObject* parent)
: QObject(parent), m_glow(glow)
{
}
bool ButtonFocusGlow::eventFilter(QObject* obj, QEvent* ev)
{
if (ev->type() == QEvent::FocusIn || ev->type() == QEvent::FocusOut) {
QWidget* w = qobject_cast<QWidget*>(obj);
if (w && qobject_cast<QPushButton*>(w)) {
if (ev->type() == QEvent::FocusIn) {
if (!w->graphicsEffect()) { // 挂一圈发光(偏移 0 → 四周光晕)
QGraphicsDropShadowEffect* g = new QGraphicsDropShadowEffect(w);
g->setBlurRadius(55); // 光晕大小(越大越强)
g->setOffset(0, 0);
g->setColor(m_glow);
w->setGraphicsEffect(g);
}
} else {
w->setGraphicsEffect(nullptr); // Qt 会删除旧效果
}
}
}
return QObject::eventFilter(obj, ev);
}
void installButtonFocusGlow(QApplication* app)
{
if (app)
app->installEventFilter(new ButtonFocusGlow(QColor("#7FBBFF"), app)); // 亮蓝,深色底更醒目
}
QString appStyleSheet()
{
const QString s = QString(R"QSS(
+21
View File
@@ -7,6 +7,9 @@
#include <QWidget>
#include <QTimer>
#include <QVariant>
#include <QColor>
class QApplication;
// ===================== 画布与全局常量 =====================
// 屏幕分辨率(1920×1080 横屏);若部署在更低分辨率屏,可按同一比例整体缩放
@@ -118,6 +121,24 @@ void stopBlink(QWidget* w, const char* prop = "blink");
// 退出/取消按钮预设样式:被选中(悬停/按下/焦点)时红底白字
QString cancelButtonStyle(int fontPx = 60);
// ===================== 按钮焦点光圈 =====================
// 全局事件过滤器:任意 QPushButton 获得焦点时,在其四周加一圈发光(QSS 无法实现光晕)
class ButtonFocusGlow : public QObject
{
Q_OBJECT
public:
explicit ButtonFocusGlow(const QColor& glow = QColor("#3D8BFD"), QObject* parent = nullptr);
protected:
bool eventFilter(QObject* obj, QEvent* ev) override;
private:
QColor m_glow;
};
// 为整个应用安装按钮焦点光圈
void installButtonFocusGlow(QApplication* app);
// 全局 QSS 样式表
QString appStyleSheet();
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -30,6 +30,7 @@ debug/manualdisinfect.o
debug/debugmaintain.o
debug/faultquery.o
debug/moc_mainwindow.o
debug/moc_global.o
debug/moc_appcontext.o
debug/moc_udpcommunication.o
debug/moc_mockvehicle.o
@@ -30,6 +30,7 @@ release/manualdisinfect.o
release/debugmaintain.o
release/faultquery.o
release/moc_mainwindow.o
release/moc_global.o
release/moc_appcontext.o
release/moc_udpcommunication.o
release/moc_mockvehicle.o
+1
View File
@@ -7,6 +7,7 @@ int main(int argc, char *argv[])
QApplication a(argc, argv);
a.setStyleSheet(appStyleSheet());
installButtonFocusGlow(&a); // 按钮获得焦点时显示光圈
MainWindow w;
w.showFullScreen();
+3 -1
View File
@@ -54,7 +54,9 @@ MainWindow::MainWindow(QWidget* parent)
m_ctx->comm()->start();
// 初始页面:开机密码
m_stack->setCurrentIndex(PageBoot);
// m_stack->setCurrentIndex(PageBoot);
// 免密码直接进自检页(恢复原流程时改回上面的 PageBoot)
m_stack->setCurrentIndex(PageSelfCheck);
}
MainWindow::~MainWindow()
+84 -63
View File
@@ -20,56 +20,67 @@ SelfCheckPage::SelfCheckPage(AppContext* ctx, QWidget* parent)
root->setSpacing(0);
m_titleBar = new TitleBar(ctx, this);
m_titleBar->setTitle("自检界面");
m_titleBar->setTitle("系统启动及自检");
root->addWidget(m_titleBar);
// 主区
QHBoxLayout* main = new QHBoxLayout();
main->setContentsMargins(36, 16, 36, 16);
main->setSpacing(32);
main->setContentsMargins(20, 30, 20, 30);
main->setSpacing(40);
// 左按钮列(垂直居中 + 平均分布)
// 两侧按钮统一样式:字号在此统一调整;按钮会拉伸填满整列(sideBtnH 为最小高度)
const int sideBtnH = 200;
const QString sideBtnStyle = "font-size:60px;";
auto makeSideBtn = [&](const QString& text, const QString& variant, QWidget* parent) {
QPushButton* b = button(text, variant, parent);
b->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); // 纵向可拉伸
b->setMinimumHeight(sideBtnH);
b->setStyleSheet(sideBtnStyle);
return b;
};
// 左按钮列(按钮按列高平分,填满整列)
QWidget* left = new QWidget(this);
QVBoxLayout* leftLay = new QVBoxLayout(left);
leftLay->setContentsMargins(0, 0, 0, 0);
leftLay->setSpacing(8);
QPushButton* faultQuery = button("故障查询", "", left);
faultQuery->setFixedHeight(120);
connect(faultQuery, &QPushButton::clicked, this, [this]() { emit navigate(PageFault); });
m_ignore = button("忽略故障", "", left);
m_ignore->setFixedHeight(120);
leftLay->setContentsMargins(20, 220, 20, 220);
leftLay->setSpacing(220);
m_faultQuery = makeSideBtn("故障查询", "", left);
connect(m_faultQuery, &QPushButton::clicked, this, [this]() { emit navigate(PageFault); });
m_ignore = makeSideBtn("忽略故障", "", left);
connect(m_ignore, &QPushButton::clicked, this, &SelfCheckPage::onIgnoreFault);
m_ignore->setEnabled(false);
leftLay->addStretch(1);
leftLay->addWidget(faultQuery);
leftLay->addStretch(1);
leftLay->addWidget(m_ignore);
leftLay->addStretch(1);
left->setFixedWidth(270);
leftLay->addWidget(m_faultQuery, 1);
leftLay->addWidget(m_ignore, 1);
left->setFixedWidth(300);
main->addWidget(left);
// 中央区
QWidget* center = new QWidget(this);
QVBoxLayout* centerLay = new QVBoxLayout(center);
centerLay->setContentsMargins(0, 0, 0, 0);
centerLay->setSpacing(12);
centerLay->setSpacing(0);
m_status = label("自检中", 36, C::WARNING, true, center);
centerLay->addStretch(1); // 上方留白
m_status = label("自检中", 60, C::WARNING, true, center);
m_status->setAlignment(Qt::AlignCenter);
centerLay->addWidget(m_status);
centerLay->addSpacing(16);
// 10 个自检项,两列
QGridLayout* grid = new QGridLayout();
grid->setSpacing(12);
grid->setSpacing(8);
const QString names[10] = {
"通信系统", "底盘通信", "机械臂通信", "洗消通信", "传感器信号",
"清水液位", "球阀D1开启", "球阀D1关闭", "球阀D2开启", "球阀D2关闭"
};
for (int i = 0; i < 10; ++i) {
LedIndicator* led = new LedIndicator(names[i], center);
led->setState(LedIndicator::Off);
QLabel* res = label("待检测", 20, C::TEXT_SUB, false, center);
res->setFixedWidth(120);
led->setFixedHeight(80);
led->setRadius(26);
led->setTextPixelSize(60);
QLabel* res = label("", 50, C::TEXT_SUB, false, center);
res->setFixedWidth(200);
QWidget* row = new QWidget(center);
QHBoxLayout* rowLay = new QHBoxLayout(row);
rowLay->setContentsMargins(0, 0, 0, 0);
@@ -79,41 +90,38 @@ SelfCheckPage::SelfCheckPage(AppContext* ctx, QWidget* parent)
m_leds.append(led);
m_results.append(res);
}
centerLay->addLayout(grid, 1);
resetItems(); // 初始化 10 个自检项
centerLay->addLayout(grid);
// 进度条
centerLay->addSpacing(50); // 文字与进度条之间的间隙
// 进度条(位于屏幕约 3/4 高度处,文字全部在其上方)
m_progress = new QProgressBar(center);
m_progress->setRange(0, 100);
m_progress->setValue(0);
m_progress->setFixedHeight(54);
m_progress->setFormat("%p%(0/10)");
m_progress->setFixedHeight(60);
centerLay->addWidget(m_progress);
centerLay->addStretch(3); // 下方留白(更大)→ 进度条落在约 3/4 处
main->addWidget(center, 1);
// 右按钮列(垂直居中 + 平均分布)
// 右按钮列(按钮按列高平分,填满整列)
QWidget* right = new QWidget(this);
QVBoxLayout* rightLay = new QVBoxLayout(right);
rightLay->setContentsMargins(0, 0, 0, 0);
rightLay->setSpacing(8);
QPushButton* help = button("操作说明", "", right);
help->setFixedHeight(120);
rightLay->setContentsMargins(20, 140, 20, 140);
rightLay->setSpacing(140);
QPushButton* help = makeSideBtn("操作说明", "", right);
connect(help, &QPushButton::clicked, this, &SelfCheckPage::onHelp);
QPushButton* start = button("启动自检", "primary", right);
start->setFixedHeight(120);
QPushButton* start = makeSideBtn("启动自检", "", right);
connect(start, &QPushButton::clicked, this, &SelfCheckPage::startSelfCheck);
m_job = button("作业选择", "", right);
m_job->setFixedHeight(120);
m_job = makeSideBtn("作业选择", "", right);
connect(m_job, &QPushButton::clicked, this, &SelfCheckPage::onJobSelect);
m_job->setEnabled(false);
rightLay->addStretch(1);
rightLay->addWidget(help);
rightLay->addStretch(1);
rightLay->addWidget(start);
rightLay->addStretch(1);
rightLay->addWidget(m_job);
rightLay->addStretch(1);
right->setFixedWidth(270);
rightLay->addWidget(help, 1);
rightLay->addWidget(start, 1);
rightLay->addWidget(m_job, 1);
right->setFixedWidth(300);
main->addWidget(right);
root->addLayout(main, 1);
@@ -130,6 +138,23 @@ void SelfCheckPage::showEvent(QShowEvent* ev)
m_autoStarted = true;
startSelfCheck();
}
// 进入后聚焦:自检进行中聚焦“故障查询”;已完成后聚焦“作业选择”
QTimer::singleShot(0, this, [this]() {
if (m_job->isEnabled())
m_job->setFocus();
else
m_faultQuery->setFocus();
});
}
// 复位 10 个自检项:指示灯置灰、结果“待检测”
void SelfCheckPage::resetItems()
{
for (int i = 0; i < 10; ++i) {
m_leds[i]->setState(LedIndicator::Off);
m_results[i]->setText("待检测");
m_results[i]->setStyleSheet(QString("color:%1;font-size:60px;").arg(C::TEXT_SUB));
}
}
void SelfCheckPage::startSelfCheck()
@@ -138,14 +163,9 @@ void SelfCheckPage::startSelfCheck()
m_job->setEnabled(false);
m_ignore->setEnabled(false);
m_progress->setValue(0);
m_progress->setFormat("%p%(0/10)");
m_status->setText("自检中");
m_status->setStyleSheet(QString("color:%1;font-size:36px;font-weight:700;").arg(C::WARNING));
for (int i = 0; i < 10; ++i) {
m_leds[i]->setState(LedIndicator::Off);
m_results[i]->setText("待检测");
m_results[i]->setStyleSheet(QString("color:%1;font-size:22px;").arg(C::TEXT_SUB));
}
m_status->setText("自检中...");
m_status->setStyleSheet(QString("color:%1;font-size:60px;font-weight:700;").arg(C::WARNING));
resetItems();
ctx()->comm()->sendSelfCheckStart();
}
@@ -163,15 +183,13 @@ void SelfCheckPage::onSelfCheckItem(int index, bool ok)
if (ok) {
m_leds[index]->setState(LedIndicator::Green);
m_results[index]->setText("正常");
m_results[index]->setStyleSheet(QString("color:%1;font-size:22px;").arg(C::SUCCESS));
m_results[index]->setStyleSheet(QString("color:%1;font-size:60px;").arg(C::SUCCESS));
} else {
m_leds[index]->setState(LedIndicator::RedBlink);
m_results[index]->setText("异常");
m_results[index]->setStyleSheet(QString("color:%1;font-size:22px;font-weight:700;").arg(C::DANGER));
m_results[index]->setStyleSheet(QString("color:%1;font-size:60px;font-weight:700;").arg(C::DANGER));
}
int pct = (index + 1) * 10;
m_progress->setValue(pct);
m_progress->setFormat(QString("%p%(%1/10)").arg(index + 1));
m_progress->setValue((index + 1) * 10);
}
void SelfCheckPage::onSelfCheckDone(bool allOk)
@@ -179,19 +197,22 @@ void SelfCheckPage::onSelfCheckDone(bool allOk)
m_done = true;
if (allOk) {
m_status->setText("自检完成");
m_status->setStyleSheet(QString("color:%1;font-size:36px;font-weight:700;").arg(C::SUCCESS));
m_status->setStyleSheet(QString("color:%1;font-size:60px;font-weight:700;").arg(C::SUCCESS));
m_job->setEnabled(true);
m_job->setFocus(); // 自检完成后聚焦到“作业选择”
// 自检完成后停留在本界面,不自动跳转(需进入作业选择请手动点击)
// 【设计建议】自检完成 2s 后自动进入作业选择
QTimer::singleShot(2000, this, [this]() {
if (m_done && isVisible())
emit navigate(PageJob);
});
// QTimer::singleShot(2000, this, [this]() {
// if (m_done && isVisible())
// emit navigate(PageJob);
// });
} else {
m_status->setText("无法完成自检 请检查设备");
m_status->setStyleSheet(QString("color:%1;font-size:36px;font-weight:700;").arg(C::DANGER));
m_status->setStyleSheet(QString("color:%1;font-size:60px;font-weight:700;").arg(C::DANGER));
startBlink(m_status, "blink");
m_ignore->setEnabled(true);
m_job->setEnabled(true);
m_faultQuery->setFocus(); // 出现故障时聚焦“故障查询”
}
}
+3
View File
@@ -31,11 +31,14 @@ private slots:
void onHelp();
private:
void resetItems(); // 复位 10 个自检项(指示灯置灰、结果“待检测”)
TitleBar* m_titleBar = nullptr;
QLabel* m_status = nullptr;
QVector<LedIndicator*> m_leds;
QVector<QLabel*> m_results;
QProgressBar* m_progress = nullptr;
QPushButton* m_faultQuery = nullptr;
QPushButton* m_ignore = nullptr;
QPushButton* m_job = nullptr;
bool m_autoStarted = false;
+14 -2
View File
@@ -1,8 +1,19 @@
#include "ledindicator.h"
#include <QPainter>
#include <QRadialGradient>
#include <QFontMetrics>
#include "global.h"
QSize LedIndicator::sizeHint() const
{
QFont f = font();
f.setPixelSize(m_textPx);
const QFontMetrics fm(f);
// 宽度 = 文字起点(圆点区 + 左侧 10px) + 文字宽度 + 右侧 10px
const int w = textLeft() + fm.horizontalAdvance(m_text) + 10;
return QSize(w, 52); // 高度与构造函数 setFixedHeight(52) 一致
}
LedIndicator::LedIndicator(const QString& text, QWidget* parent)
: QWidget(parent), m_text(text)
{
@@ -35,6 +46,7 @@ void LedIndicator::setState(State s)
void LedIndicator::setText(const QString& t)
{
m_text = t;
updateGeometry(); // 文字变了,重新按新宽度请求布局
update();
}
@@ -84,8 +96,8 @@ void LedIndicator::paintEvent(QPaintEvent*)
// 文字
p.setPen(QColor(C::TEXT));
QFont f = p.font();
f.setPixelSize(24);
f.setPixelSize(m_textPx);
p.setFont(f);
const QRectF textRect(m_radius * 2 + 16, 0, width() - m_radius * 2 - 16, height());
const QRectF textRect(textLeft(), 0, width() - textLeft() - 10, height());
p.drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, m_text);
}
+6 -1
View File
@@ -17,19 +17,24 @@ public:
void setState(State s);
void setText(const QString& t);
void setTextPixelSize(int px) { m_textPx = px; updateGeometry(); update(); } // 文字字号
void setRadius(int r) { m_radius = r; updateGeometry(); update(); } // 圆形指示点半径
State state() const { return m_state; }
QSize sizeHint() const override { return QSize(140, 44); }
QSize sizeHint() const override; // 宽度按文字实际宽度计算,避免文字被裁
protected:
void paintEvent(QPaintEvent*) override;
private:
int textLeft() const { return m_radius * 2 + 18; } // 文字起点:圆点区 + 左侧 10px 留白
State m_state = Off;
QString m_text;
QTimer* m_blink = nullptr;
bool m_on = true;
int m_radius = 16; // 圆形指示点 32×32
int m_textPx = 24; // 文字字号
};
#endif // LEDINDICATOR_H
+36 -19
View File
@@ -18,31 +18,49 @@ TitleBar::TitleBar(AppContext* ctx, QWidget* parent)
setStyleSheet(QString("QWidget#TitleBar{background-color:%1;border-bottom:1px solid %2;}")
.arg(C::PANEL, C::BORDER));
QHBoxLayout* lay = new QHBoxLayout(this);
lay->setContentsMargins(24, 0, 24, 0);
lay->setSpacing(20);
// 通信状态
m_comm = new LedIndicator("通信正常", this);
// 左侧区(通信状态)
QWidget* leftBox = new QWidget(this);
QHBoxLayout* leftLay = new QHBoxLayout(leftBox);
leftLay->setContentsMargins(0, 0, 0, 0);
leftLay->setSpacing(20);
m_comm = new LedIndicator("通信正常", leftBox);
m_comm->setState(LedIndicator::Green);
lay->addWidget(m_comm);
leftLay->addWidget(m_comm);
leftLay->addStretch(1);
// 右侧区(时间 + 软急停)
QWidget* rightBox = new QWidget(this);
QHBoxLayout* rightLay = new QHBoxLayout(rightBox);
rightLay->setContentsMargins(0, 0, 0, 0);
rightLay->setSpacing(20);
m_time = new QLabel("", rightBox);
m_time->setStyleSheet(QString("color:%1;font-size:60px;").arg(C::TEXT_SUB));
m_time->setAlignment(Qt::AlignCenter);
m_estop = new QPushButton("急停", rightBox);
m_estop->setProperty("variant", "estop");
m_estop->setStyleSheet("font-size:60px;");
m_estop->setFixedSize(180, 80);
rightLay->addStretch(1);
rightLay->addWidget(m_time);
rightLay->addWidget(m_estop);
// 左右两侧等宽 → 中间标题恰好居中于屏幕
const int sideW = 380; // 需 >= 较宽一侧所需宽度(右侧:时间 + 急停)
leftBox->setFixedWidth(sideW);
rightBox->setFixedWidth(sideW);
// 标题(居中)
m_title = new QLabel("", this);
m_title->setAlignment(Qt::AlignCenter);
m_title->setStyleSheet(QString("color:%1;font-size:40px;font-weight:700;").arg(C::TEXT));
m_title->setStyleSheet(QString("color:%1;font-size:60px;font-weight:700;").arg(C::TEXT));
QHBoxLayout* lay = new QHBoxLayout(this);
lay->setContentsMargins(24, 6, 24, 6);
lay->setSpacing(0);
lay->addWidget(leftBox);
lay->addWidget(m_title, 1);
lay->addWidget(rightBox);
// 时间
m_time = new QLabel("", this);
m_time->setStyleSheet(QString("color:%1;font-size:26px;").arg(C::TEXT_SUB));
m_time->setAlignment(Qt::AlignCenter);
lay->addWidget(m_time);
// 软急停按钮
m_estop = new QPushButton("急停", this);
m_estop->setProperty("variant", "estop");
m_estop->setFixedSize(130, 64);
connect(m_estop, &QPushButton::clicked, this, [this]() {
if (m_ctx->estopTriggered) {
if (ConfirmDialog::confirm(window(), "急停复位", "确定复位急停并恢复系统?"))
@@ -51,7 +69,6 @@ TitleBar::TitleBar(AppContext* ctx, QWidget* parent)
m_ctx->triggerEstop();
}
});
lay->addWidget(m_estop);
// 通信状态刷新
connect(m_ctx->comm(), &UdpCommunication::commOkChanged, this, [this](bool ok) {
-223
View File
@@ -1,223 +0,0 @@
<html style="margin:0;padding:0;">
<div style="background-color:transparent;box-sizing:border-box;font-family:'PingFang SC','Microsoft YaHei',Arial,sans-serif;color:#1A1B1C;line-height:1.5;">
<!-- 01 页面导航流程 -->
<div style="font-size:15px;font-weight:600;margin:4px 0 10px;">① 10 个界面的导航流程(依据协议③~⑫)</div>
<div style="border:1px solid rgba(0,0,0,0.08);border-radius:12px;padding:14px;background:rgba(0,0,0,0.025);box-sizing:border-box;">
<svg viewBox="0 0 860 340" style="width:100%;height:auto;display:block;" role="img" aria-label="界面导航流程示意">
<!-- 主链 ③④⑤ -->
<rect x="10" y="20" width="120" height="54" rx="8" fill="#3D8BFD" />
<text x="70" y="40" text-anchor="middle" fill="#FFFFFF" font-size="12" font-weight="600">③ 开机密码</text>
<text x="70" y="58" text-anchor="middle" fill="#DCE8FB" font-size="10">密码 6789</text>
<line x1="130" y1="47" x2="178" y2="47" stroke="#3D8BFD" stroke-width="2" marker-end="url(#ar1)"/>
<text x="154" y="40" text-anchor="middle" fill="#6B7280" font-size="9">正确</text>
<rect x="182" y="20" width="120" height="54" rx="8" fill="#242E3A" stroke="#3D8BFD" stroke-width="1.5" />
<text x="242" y="40" text-anchor="middle" fill="#E6EDF3" font-size="12" font-weight="600">④ 自检</text>
<text x="242" y="58" text-anchor="middle" fill="#9AA7B4" font-size="10">10 项 + 进度条</text>
<line x1="302" y1="47" x2="350" y2="47" stroke="#3D8BFD" stroke-width="2" marker-end="url(#ar1)"/>
<text x="326" y="40" text-anchor="middle" fill="#6B7280" font-size="9">完成/忽略</text>
<rect x="354" y="20" width="120" height="54" rx="8" fill="#3D8BFD" />
<text x="414" y="40" text-anchor="middle" fill="#FFFFFF" font-size="12" font-weight="600">⑤ 作业选择</text>
<text x="414" y="58" text-anchor="middle" fill="#DCE8FB" font-size="10">6 个作业入口</text>
<line x1="474" y1="47" x2="522" y2="47" stroke="#3D8BFD" stroke-width="2" marker-end="url(#ar1)"/>
<text x="498" y="40" text-anchor="middle" fill="#6B7280" font-size="9">选择</text>
<rect x="526" y="20" width="120" height="54" rx="8" fill="#242E3A" stroke="#36C75A" stroke-width="1.5" />
<text x="586" y="40" text-anchor="middle" fill="#E6EDF3" font-size="12" font-weight="600">⑥~⑪ 作业界面</text>
<text x="586" y="58" text-anchor="middle" fill="#9AA7B4" font-size="10">底盘/机械臂/检测/洗消</text>
<!-- 错误密码支线 -->
<line x1="70" y1="74" x2="70" y2="110" stroke="#E5484D" stroke-width="1.5" marker-end="url(#ar2)"/>
<text x="78" y="98" fill="#E5484D" font-size="9">密码错误</text>
<rect x="10" y="112" width="120" height="46" rx="8" fill="#3A2530" stroke="#E5484D" stroke-width="1.5" />
<text x="70" y="132" text-anchor="middle" fill="#FFB4B8" font-size="11" font-weight="600">密码警告页</text>
<text x="70" y="148" text-anchor="middle" fill="#E9A6AA" font-size="9">重新输入</text>
<!-- 忘记/修改密码支线 -->
<line x1="10" y1="74" x2="10" y2="190" stroke="#F5A623" stroke-width="1.5" stroke-dasharray="4 3" marker-end="url(#ar2)"/>
<text x="18" y="140" fill="#B9791B" font-size="9">忘记/修改</text>
<rect x="10" y="194" width="120" height="86" rx="8" fill="#2E2A20" stroke="#F5A623" stroke-width="1.5" />
<text x="70" y="216" text-anchor="middle" fill="#FFD9A0" font-size="11" font-weight="600">密码管理</text>
<text x="70" y="234" text-anchor="middle" fill="#C9A25E" font-size="9">登录→勾选重置√</text>
<text x="70" y="252" text-anchor="middle" fill="#C9A25E" font-size="9">输入新密码</text>
<text x="70" y="270" text-anchor="middle" fill="#36C75A" font-size="9">“修改成功”2s</text>
<!-- 故障查询 -->
<rect x="526" y="112" width="120" height="46" rx="8" fill="#242E3A" stroke="#F5A623" stroke-width="1.5" />
<text x="586" y="132" text-anchor="middle" fill="#FFD9A0" font-size="11" font-weight="600">⑫ 故障查询</text>
<text x="586" y="148" text-anchor="middle" fill="#C9A25E" font-size="9">每页 6 条/分类筛选</text>
<line x1="474" y1="40" x2="586" y2="112" stroke="#F5A623" stroke-width="1.5" stroke-dasharray="4 3" marker-end="url(#ar2)"/>
<text x="505" y="78" fill="#B9791B" font-size="9">故障查询</text>
<!-- 急停 -->
<rect x="526" y="194" width="120" height="46" rx="8" fill="#E5484D" />
<text x="586" y="214" text-anchor="middle" fill="#FFFFFF" font-size="11" font-weight="600">急停(全局)</text>
<text x="586" y="230" text-anchor="middle" fill="#FFD9DC" font-size="9">全系统停止</text>
<line x1="586" y1="74" x2="586" y2="192" stroke="#E5484D" stroke-width="1.5" marker-end="url(#ar2)"/>
<text x="600" y="140" fill="#B33B43" font-size="9">任意界面可触发</text>
<!-- 运行中返回规则 -->
<rect x="700" y="20" width="150" height="54" rx="8" fill="#2A3442" stroke="#9AA7B4" stroke-width="1" />
<text x="775" y="40" text-anchor="middle" fill="#E6EDF3" font-size="11" font-weight="600">关键规则</text>
<text x="775" y="58" text-anchor="middle" fill="#9AA7B4" font-size="9">⑨⑩运行中返回无效</text>
<rect x="700" y="112" width="150" height="86" rx="8" fill="#2A3442" stroke="#9AA7B4" stroke-width="1" />
<text x="775" y="132" text-anchor="middle" fill="#E6EDF3" font-size="11" font-weight="600">公共框架</text>
<text x="775" y="150" text-anchor="middle" fill="#9AA7B4" font-size="9">顶条:通信/标题/急停</text>
<text x="775" y="166" text-anchor="middle" fill="#9AA7B4" font-size="9">底条:电量/电压/液位</text>
<text x="775" y="182" text-anchor="middle" fill="#9AA7B4" font-size="9">警示红字 500ms 闪烁</text>
<defs>
<marker id="ar1" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto"><path d="M0,0 L8,4 L0,8 Z" fill="#3D8BFD"/></marker>
<marker id="ar2" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto"><path d="M0,0 L8,4 L0,8 Z" fill="#9AA7B4"/></marker>
</defs>
</svg>
<div style="font-size:11px;color:#6B7280;margin-top:6px;">示意:依据《技术协议(初版)》③~⑫ 及文档【设计建议】绘制的导航关系;⑫可从④自检页与⑤作业选择页进入。</div>
</div>
<!-- 02 配色体系 -->
<div style="font-size:15px;font-weight:600;margin:18px 0 10px;">② 深色工业配色体系(QSS 十六进制,画布 1280×800)</div>
<div style="display:flex;flex-wrap:wrap;gap:8px;box-sizing:border-box;">
<div style="flex:1 1 96px;min-width:0;padding:10px;border-radius:10px;background:#161C23;box-sizing:border-box;">
<div style="width:100%;height:30px;border-radius:6px;background:#161C23;border:1px solid #3D4A59;"></div>
<div style="font-size:10px;color:#C8D3DE;margin-top:6px;">主背景</div>
<div style="font-size:10px;color:#8A96A4;">#161C23</div>
</div>
<div style="flex:1 1 96px;min-width:0;padding:10px;border-radius:10px;background:#161C23;box-sizing:border-box;">
<div style="width:100%;height:30px;border-radius:6px;background:#242E3A;"></div>
<div style="font-size:10px;color:#C8D3DE;margin-top:6px;">面板/弹窗</div>
<div style="font-size:10px;color:#8A96A4;">#242E3A</div>
</div>
<div style="flex:1 1 96px;min-width:0;padding:10px;border-radius:10px;background:#161C23;box-sizing:border-box;">
<div style="width:100%;height:30px;border-radius:6px;background:#2D3947;"></div>
<div style="font-size:10px;color:#C8D3DE;margin-top:6px;">按钮常态</div>
<div style="font-size:10px;color:#8A96A4;">#2D3947</div>
</div>
<div style="flex:1 1 96px;min-width:0;padding:10px;border-radius:10px;background:#161C23;box-sizing:border-box;">
<div style="width:100%;height:30px;border-radius:6px;background:#3D8BFD;"></div>
<div style="font-size:10px;color:#C8D3DE;margin-top:6px;">强调主色</div>
<div style="font-size:10px;color:#8A96A4;">#3D8BFD</div>
</div>
<div style="flex:1 1 96px;min-width:0;padding:10px;border-radius:10px;background:#161C23;box-sizing:border-box;">
<div style="width:100%;height:30px;border-radius:6px;background:#36C75A;"></div>
<div style="font-size:10px;color:#C8D3DE;margin-top:6px;">成功/到位</div>
<div style="font-size:10px;color:#8A96A4;">#36C75A</div>
</div>
<div style="flex:1 1 96px;min-width:0;padding:10px;border-radius:10px;background:#161C23;box-sizing:border-box;">
<div style="width:100%;height:30px;border-radius:6px;background:#F5A623;"></div>
<div style="font-size:10px;color:#C8D3DE;margin-top:6px;">警示</div>
<div style="font-size:10px;color:#8A96A4;">#F5A623</div>
</div>
<div style="flex:1 1 96px;min-width:0;padding:10px;border-radius:10px;background:#161C23;box-sizing:border-box;">
<div style="width:100%;height:30px;border-radius:6px;background:#E5484D;"></div>
<div style="font-size:10px;color:#C8D3DE;margin-top:6px;">危险/急停</div>
<div style="font-size:10px;color:#8A96A4;">#E5484D</div>
</div>
<div style="flex:1 1 96px;min-width:0;padding:10px;border-radius:10px;background:#161C23;box-sizing:border-box;">
<div style="width:100%;height:30px;border-radius:6px;background:#56636F;"></div>
<div style="font-size:10px;color:#C8D3DE;margin-top:6px;">禁用底</div>
<div style="font-size:10px;color:#8A96A4;">#56636F</div>
</div>
<div style="flex:1 1 96px;min-width:0;padding:10px;border-radius:10px;background:#161C23;box-sizing:border-box;">
<div style="width:100%;height:30px;border-radius:6px;background:#E6EDF3;border:1px solid #3D4A59;"></div>
<div style="font-size:10px;color:#C8D3DE;margin-top:6px;">主文字</div>
<div style="font-size:10px;color:#8A96A4;">#E6EDF3</div>
</div>
<div style="flex:1 1 96px;min-width:0;padding:10px;border-radius:10px;background:#161C23;box-sizing:border-box;">
<div style="width:100%;height:30px;border-radius:6px;background:#9AA7B4;"></div>
<div style="font-size:10px;color:#C8D3DE;margin-top:6px;">次文字</div>
<div style="font-size:10px;color:#8A96A4;">#9AA7B4</div>
</div>
</div>
<!-- 03 界面深色效果示意 -->
<div style="font-size:15px;font-weight:600;margin:18px 0 10px;">③ 关键界面深色效果示意(按文档线框还原,非真实截图)</div>
<div style="display:flex;flex-wrap:wrap;gap:12px;box-sizing:border-box;">
<!-- 作业选择界面示意 -->
<div style="flex:1 1 300px;min-width:0;background:#161C23;border-radius:10px;padding:12px;box-sizing:border-box;">
<div style="display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid #3D4A59;padding-bottom:8px;">
<span style="color:#36C75A;font-size:11px;">● 通信正常</span>
<span style="color:#E6EDF3;font-size:13px;font-weight:600;">【作业选择】</span>
<span style="color:#E5484D;background:#E5484D;padding:3px 10px;border-radius:4px;font-size:10px;color:#FFFFFF;font-weight:600;">急停</span>
</div>
<div style="display:flex;gap:8px;margin-top:10px;">
<div style="width:74px;">
<div style="background:#2D3947;border:1px solid #3D8BFD;border-radius:6px;padding:8px 4px;text-align:center;color:#E6EDF3;font-size:11px;margin-bottom:6px;">机器人底盘</div>
<div style="background:#2D3947;border-radius:6px;padding:8px 4px;text-align:center;color:#9AA7B4;font-size:11px;margin-bottom:6px;">机械臂</div>
<div style="background:#2D3947;border-radius:6px;padding:8px 4px;text-align:center;color:#9AA7B4;font-size:11px;margin-bottom:6px;">气体检测仪</div>
<div style="background:#2D3947;border-radius:6px;padding:8px 4px;text-align:center;color:#9AA7B4;font-size:11px;">调试维护</div>
</div>
<div style="flex:1;display:flex;flex-direction:column;gap:6px;">
<div style="background:#242E3A;border-radius:6px;padding:6px;">
<div style="color:#9AA7B4;font-size:10px;">底盘</div>
<div style="color:#E6EDF3;font-size:11px;">电量:85% 电压:360V</div>
<div style="color:#36C75A;font-size:10px;">故障:无</div>
</div>
<div style="background:#242E3A;border-radius:6px;padding:6px;">
<div style="color:#9AA7B4;font-size:10px;">洗消</div>
<div style="color:#E6EDF3;font-size:11px;">A液位:100L 泡沫液位:30L</div>
</div>
<div style="background:#242E3A;border-radius:6px;padding:6px;">
<div style="color:#9AA7B4;font-size:10px;">机械臂</div>
<div style="color:#E6EDF3;font-size:11px;">末端XYZ 姿态RX…</div>
</div>
<div style="background:#242E3A;border-radius:6px;padding:6px;">
<div style="color:#9AA7B4;font-size:10px;">检测仪</div>
<div style="color:#E6EDF3;font-size:11px;">点火S类2级 浓度300ppb</div>
</div>
</div>
<div style="width:64px;display:flex;flex-direction:column;gap:6px;">
<div style="background:#3D8BFD;border-radius:6px;padding:8px 2px;text-align:center;color:#FFFFFF;font-size:11px;">手动消除</div>
<div style="background:#3D8BFD;border-radius:6px;padding:8px 2px;text-align:center;color:#FFFFFF;font-size:11px;">手动消毒</div>
<div style="background:#2D3947;border-radius:6px;padding:8px 2px;text-align:center;color:#9AA7B4;font-size:11px;">返回</div>
</div>
</div>
<div style="border-top:1px solid #3D4A59;margin-top:10px;padding-top:6px;color:#9AA7B4;font-size:10px;">底盘电量:85% 底盘电压:360V 清水液位:100L 泡沫液位:30L 行车模式</div>
</div>
<!-- 手动消毒界面示意 -->
<div style="flex:1 1 300px;min-width:0;background:#161C23;border-radius:10px;padding:12px;box-sizing:border-box;">
<div style="display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid #3D4A59;padding-bottom:8px;">
<span style="color:#36C75A;font-size:11px;">● 通信正常</span>
<span style="color:#E6EDF3;font-size:13px;font-weight:600;">【手动消毒】</span>
<span style="background:#E5484D;padding:3px 10px;border-radius:4px;font-size:10px;color:#FFFFFF;font-weight:600;">急停</span>
</div>
<div style="display:flex;gap:8px;margin-top:10px;">
<div style="width:74px;">
<div style="background:#2D3947;border-radius:6px;padding:7px 4px;text-align:center;color:#E6EDF3;font-size:11px;margin-bottom:6px;">洗消模式</div>
<div style="background:#2D3947;border-radius:6px;padding:7px 4px;text-align:center;color:#9AA7B4;font-size:11px;margin-bottom:6px;">A液位</div>
<div style="background:#2D3947;border-radius:6px;padding:7px 4px;text-align:center;color:#9AA7B4;font-size:11px;">泡沫液位</div>
</div>
<div style="flex:1;background:#242E3A;border-radius:6px;padding:8px;">
<div style="color:#9AA7B4;font-size:10px;">A药剂流量</div>
<div style="color:#E6EDF3;font-size:15px;font-weight:600;">2.0 L/min</div>
<div style="color:#9AA7B4;font-size:10px;margin-top:4px;">空压机压力</div>
<div style="color:#E6EDF3;font-size:15px;font-weight:600;">0.35 MPa</div>
<div style="display:flex;gap:4px;margin-top:6px;">
<span style="background:#2D3947;border-radius:4px;padding:2px 6px;color:#9AA7B4;font-size:9px;">发泡倍数 6</span>
<span style="background:#2D3947;border-radius:4px;padding:2px 6px;color:#9AA7B4;font-size:9px;">泡沫比例 3%</span>
</div>
</div>
<div style="width:64px;display:flex;flex-direction:column;gap:6px;">
<div style="background:#36C75A;border-radius:6px;padding:8px 2px;text-align:center;color:#FFFFFF;font-size:11px;">启动</div>
<div style="background:#2D3947;border-radius:6px;padding:8px 2px;text-align:center;color:#9AA7B4;font-size:11px;">停止</div>
<div style="background:#2D3947;border-radius:6px;padding:8px 2px;text-align:center;color:#9AA7B4;font-size:11px;">保存</div>
<div style="background:#2D3947;border-radius:6px;padding:8px 2px;text-align:center;color:#9AA7B4;font-size:11px;">返回</div>
</div>
</div>
<div style="border-top:1px solid #3D4A59;margin-top:10px;padding-top:6px;color:#9AA7B4;font-size:10px;">
指示灯:<span style="color:#36C75A;">●启停</span> <span style="color:#36C75A;">●柱塞泵</span> <span style="color:#36C75A;">●空压机</span> <span style="color:#E5484D;">●液位低</span> <span style="color:#9AA7B4;">○D1 ○D2 ○系统故障</span>
<div style="color:#E5484D;margin-top:4px;font-size:10px;">⚠ 警告:该模式下无保护功能,操作请谨慎!(红色闪烁)</div>
</div>
</div>
</div>
<div style="font-size:11px;color:#6B7280;margin-top:12px;">注:以上界面效果为深色工业主题示意图,控件坐标、状态机与交互细节以 Word 说明书第 3 章为准;协议原文要求以黑体加粗引用,设计补充均标注【设计建议】。</div>
</div>
</html>