7cf6c18e by 柴进

feat(qml): task #17 任务队列 sidebar 接 taskQueue.model

MainWindow.qml sidebar 改造:
- header: 加 "N 进行中" 计数(绑定 taskQueue.runningCount + pendingCount,0 时隐藏)
- ListView model: 硬编码 ListModel → taskQueue.model(_TaskListModel QAbstractListModel)
- 空态占位: "暂无任务"(visible: count === 0)
- delegate 改造,56px 高 ColumnLayout 三行:
  1. prompt 摘要(>14 字省略)
  2. 状态彩色文字(pending=橙 / running=蓝 / completed=绿 / failed=红) + 耗时
  3. 进行中任务的细进度条(高 2px,绑 progress 0-1)
- delegate 用 required property 声明 6 个 role:taskId / prompt / status / progress / statusText / elapsed
- 右键点击 pending/running 任务 → taskQueue.cancelTask(taskId)

至此 生成 → sidebar → 历史 闭环完整:
- 用户在图片生成 tab 点 "生成图片" → ImageGenBridge.submitTask
- TaskQueueManager 信号 → TaskQueueBridge._on_task_added → upsert 进 model
- sidebar ListView 自动渲染新行,状态文字 + 进度条同步
- 完成后 ImageGenBridge → HistoryBridge.addNew,历史 tab 也会增量

视觉验证:QML_AUTO_LOGIN=1 启动主窗口,空态正确显示"暂无任务",UI 无回归。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 5d893c50
......@@ -146,15 +146,29 @@ Rectangle {
implicitHeight: 48
color: App.Theme.bgSurface
Label {
RowLayout {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: App.Theme.space4
anchors.rightMargin: App.Theme.space4
anchors.verticalCenter: parent.verticalCenter
text: "任务队列"
font.family: App.Theme.fontFamily
font.pointSize: App.Theme.fontBase
font.weight: Font.DemiBold
color: App.Theme.textPrimary
spacing: App.Theme.space2
Label {
text: "任务队列"
font.family: App.Theme.fontFamily
font.pointSize: App.Theme.fontBase
font.weight: Font.DemiBold
color: App.Theme.textPrimary
}
Item { Layout.fillWidth: true }
Label {
visible: taskQueue.runningCount + taskQueue.pendingCount > 0
text: taskQueue.runningCount + taskQueue.pendingCount + " 进行中"
font.family: App.Theme.fontFamily
font.pointSize: App.Theme.fontXs
color: App.Theme.textSecondary
}
}
// 底部分隔线
......@@ -169,32 +183,95 @@ Rectangle {
// 列表
ListView {
id: taskList
Layout.fillWidth: true
Layout.fillHeight: true
Layout.margins: App.Theme.space2
spacing: 4
spacing: 6
clip: true
model: ListModel {
ListElement { status: "执行中"; color: "#ff9500" }
ListElement { status: "等待中"; color: "#0071e3" }
ListElement { status: "已完成"; color: "#34c759" }
model: taskQueue.model
// 空状态占位
Label {
anchors.centerIn: parent
text: "暂无任务"
font.family: App.Theme.fontFamily
font.pointSize: App.Theme.fontSm
color: App.Theme.textTertiary
visible: taskList.count === 0
}
delegate: Rectangle {
required property string taskId
required property string prompt
required property string status
required property real progress
required property string statusText
required property string elapsed
width: ListView.view.width
height: 36
height: 56
radius: App.Theme.radiusSm
color: itemMouse.containsMouse ? App.Theme.bgHover : "transparent"
border.width: 1
border.color: App.Theme.divider
Text {
anchors.left: parent.left
anchors.leftMargin: App.Theme.space3
anchors.verticalCenter: parent.verticalCenter
text: status
color: model.color
font.family: App.Theme.fontFamily
font.pointSize: App.Theme.fontSm
ColumnLayout {
anchors.fill: parent
anchors.margins: App.Theme.space2
spacing: 2
// 第一行: prompt 摘要(最多约 14 字)
Text {
text: prompt.length > 14 ? prompt.substring(0, 14) + "…" : prompt
color: App.Theme.textPrimary
font.family: App.Theme.fontFamily
font.pointSize: App.Theme.fontXs
Layout.fillWidth: true
elide: Text.ElideRight
}
// 第二行: 状态彩色 + elapsed
RowLayout {
Layout.fillWidth: true
spacing: 4
Text {
text: statusText
color: status === "completed" ? App.Theme.success
: status === "failed" ? App.Theme.danger
: status === "running" ? App.Theme.accent
: App.Theme.warning // pending
font.family: App.Theme.fontFamily
font.pointSize: App.Theme.fontXs
Layout.fillWidth: true
elide: Text.ElideRight
}
Text {
visible: elapsed.length > 0
text: elapsed
color: App.Theme.textTertiary
font.family: App.Theme.fontFamily
font.pointSize: App.Theme.fontXs
}
}
// 第三行: running 时显示细进度条
Rectangle {
visible: status === "running"
Layout.fillWidth: true
Layout.preferredHeight: 2
color: App.Theme.bgSubtle
radius: 1
Rectangle {
width: parent.width * Math.max(0.05, Math.min(progress, 1.0))
height: parent.height
color: App.Theme.accent
radius: 1
}
}
}
MouseArea {
......@@ -202,6 +279,13 @@ Rectangle {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: function(mouse) {
if (mouse.button === Qt.RightButton
&& (status === "pending" || status === "running")) {
taskQueue.cancelTask(taskId)
}
}
}
}
}
......