功能:支持设备身份自动登录并直达桌面列表

变更详情:开机直进桌面列表——设备身份自动登录,移除登录页与退出登录入口

- 构造时以设备 SN 走演示认证,kConfig->kAuthenticating->kDesktopList 同步完成,开机不再显示登录页
- 列表页移除"退出登录"按钮(无登录概念无去向);管理菜单"退出终端"保留
- 登录页与认证代码保留,接平台正式认证后由 DesktopService 驱动恢复登录流程
- 已部署盒子并抓屏验证;文档与 MEMORY 同步
This commit is contained in:
宋一鸣 2026-10-30 09:19:17 +08:00
parent 7fdcb53dd9
commit 85f64df1a5
6 changed files with 31 additions and 26 deletions

View File

@ -9,7 +9,8 @@
- Proxmox:9.2.2 节点 `starhe`。VM 100 win10-test `192.168.1.70`(Sunshine/Moonlight 云桌面);
VM 101 kylin-test `192.168.1.71`(test1)、VM 102 ubuntu-test `192.168.1.72`(test2),
密码均 `yx66668888`,SSH 可登、图形会话在跑,**尚未装 Sunshine**,暂不能串流
- `kiosk-shell`(Qt/C++):登录页 → 桌面列表 → Moonlight 会话;**RDP 代码已于 2026-10-29
- `kiosk-shell`(Qt/C++):**开机直进桌面列表**(2026-10-30 起,设备 SN 即用户自动登录,
登录页代码保留待平台正式认证接入)→ 选择桌面 → Moonlight 会话;**RDP 代码已于 2026-10-29
全部删除**(git 历史可查),Moonlight 是唯一会话通道,无 freerdp 构建依赖
- 新增退出三层与会话过场层:`Ctrl+Alt+Shift+Q` 退串流回列表;列表页"退出登录";
登录页无退出按钮(退出终端只在管理菜单);点连接有全屏过场层,首帧后淡出。

View File

@ -250,3 +250,17 @@ Desktop Duplication 的脏帧节奏,叠加 QEMU 显示栈),不是编码器
两台均未装 Sunshine(47989 等端口关闭),还不能被 Moonlight 连接。
接入桌面列表的步骤:装 Sunshine(Linux 版)→ 配对 → 在盒子"桌面连接设置"里
把 Ubuntu/麒麟卡片的地址填上即可(kiosk 代码已支持,无需改代码)。
---
# 2026-10-30 追加:开机直进桌面列表
按产品决定,盒子开机不再显示 kiosk 登录页,直接进入"选择云桌面"列表页:
- 构造时以设备身份(SN)自动走 DesktopService 演示认证(SN 即当前用户展示),
状态链 `kConfig -> kAuthenticating -> kDesktopList` 同步完成,无登录页闪烁;
- 列表页右上角"退出登录"按钮移除(无登录概念后无去向),管理菜单"退出终端"保留;
- **登录页与 DesktopService 认证代码全部保留**:接入管理平台正式认证
(/api/v1/terminal/session/login)后,由 DesktopService 决定是否回到登录流程,
页面代码无需重写;git 历史含完整"登录页 -> 桌面列表"产品流程版本。
- 已编译部署盒子并抓屏验证:开机落在桌面列表,Windows 可连接、Ubuntu/麒麟待分配。

View File

@ -35,11 +35,10 @@ DesktopListPage::DesktopListPage(QWidget* parent) : QWidget(parent) {
auto* infoRow = new QHBoxLayout();
labelUser_ = new QLabel(this);
labelUser_->setStyleSheet(QStringLiteral("color: #8a94a6;"));
buttonLogout_ = new QPushButton(QStringLiteral("退出登录"), this);
buttonLogout_->setMinimumSize(110, 38);
// 无登录页演示模式下不设"退出登录"(用户身份由设备/平台承担,
// 正式认证接入后由 DesktopService 驱动恢复登录流程)
infoRow->addWidget(labelUser_);
addStretchToRow(infoRow);
infoRow->addWidget(buttonLogout_);
root->addLayout(infoRow);
// ---- 卡片区 ----
@ -62,12 +61,6 @@ DesktopListPage::DesktopListPage(QWidget* parent) : QWidget(parent) {
labelStatus_->setAlignment(Qt::AlignCenter);
labelStatus_->setStyleSheet(QStringLiteral("color: #8a94a6;"));
root->addWidget(labelStatus_);
connect(buttonLogout_, &QPushButton::clicked, this, [this]() {
if (!busy_) {
emit logoutRequested();
}
});
}
void DesktopListPage::setDesktops(const std::vector<DesktopInfo>& desktops) {
@ -175,7 +168,6 @@ void DesktopListPage::setStatus(const QString& text, bool error) {
void DesktopListPage::setBusy(bool busy) {
busy_ = busy;
buttonLogout_->setEnabled(!busy);
// 连接按钮在 rebuildCards 时根据 busy_ 生成;这里统一刷新点击行为由 busy_ 拦截
}

View File

@ -38,8 +38,6 @@ signals:
void desktopSelected(const QString& desktopId);
// 用户点击某张卡片的“设置”按钮
void editRequested(const QString& desktopId);
// 用户点击退出登录
void logoutRequested();
private:
void rebuildCards();
@ -50,7 +48,6 @@ private:
QLabel* labelUser_ = nullptr;
QLabel* labelStatus_ = nullptr;
QVBoxLayout* cardsLayout_ = nullptr;
QPushButton* buttonLogout_ = nullptr;
bool busy_ = false;
};

View File

@ -36,9 +36,19 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) {
config_ = loadConfig();
// 开机永远进入登录页;会话只能由用户在桌面列表选择后启动。
fsm_.transitionTo(State::kConfig, QStringLiteral("等待登录"));
showLogin();
// 开机直进桌面列表:当前无正式账号体系,设备身份(SN)即用户,自动登录。
// 登录页代码保留——接入管理平台认证后,由 DesktopService 决定是否回到登录流程;
// 会话只能由用户在桌面列表选择后启动。
fsm_.transitionTo(State::kConfig, QStringLiteral("就绪"));
const QString deviceUser = QString::fromStdString(config_.sn).trimmed();
desktopService_.login(deviceUser.isEmpty() ? QStringLiteral("terminal") : deviceUser,
QStringLiteral("kiosk"), [this](const AuthResult& result) {
if (result.ok) {
currentUser_ = result.displayName;
}
fsm_.transitionTo(State::kAuthenticating, QStringLiteral("自动登录"));
fsm_.transitionTo(State::kDesktopList, QStringLiteral("请选择要进入的云桌面"));
});
}
MainWindow::~MainWindow() {
@ -81,7 +91,6 @@ void MainWindow::setupUi() {
connect(list, &DesktopListPage::desktopSelected, this, &MainWindow::onDesktopSelected);
connect(list, &DesktopListPage::editRequested, this, &MainWindow::onEditDesktopRequested);
connect(list, &DesktopListPage::logoutRequested, this, &MainWindow::onLogoutRequested);
// 过场层:独立置顶窗口,盖住 moonlight-qt 启动期的小窗口闪烁与分辨率切换,
// 首帧检测到后淡出。不属于 stack_(串流期间整个 kiosk 都被 moonlight 覆盖)。
@ -268,13 +277,6 @@ void MainWindow::onEditDesktopRequested(const QString& desktopId) {
}
}
void MainWindow::onLogoutRequested() {
stopSessions();
desktopService_.logout();
currentUser_.clear();
fsm_.transitionTo(State::kConfig, QStringLiteral("已退出登录"));
}
void MainWindow::startMoonlightSession(const ConnectionTicket& ticket) {
if (!fsm_.transitionTo(State::kConnecting, ticket.endpoint)) {
return;

View File

@ -47,7 +47,6 @@ private slots:
void onLoginRequested(const QString& username, const QString& password);
void onDesktopSelected(const QString& desktopId);
void onEditDesktopRequested(const QString& desktopId);
void onLogoutRequested();
void onQuitRequested();
void onMoonlightState(bool running, const QString& message);
void onMenuAction(int action);