Files
taskq/ui/styles.css
hupeh 1f9f1cab53 feat: 添加监控仪表盘
- 新增 Lit.js 组件化 UI (ui/ 目录)
  - tasks-chart: 带十字准星和拖拽选择的图表
  - queue-table: 队列列表,支持暂停/恢复
  - queue-modal: 队列详情弹窗,支持任务重试
  - time-range-picker: Prometheus 风格时间选择器
  - help-tooltip: 可复用的提示组件

- HTTPHandler 功能
  - SSE 实时推送 (stats + queues)
  - 队列暂停/恢复 API
  - 任务重试 API
  - 时间范围查询 API

- Inspector 改进
  - Prometheus 风格单表存储
  - 集成到 Start/Stop 生命周期
  - 新增 PauseQueue/UnpauseQueue/RunTask 方法

- 代码重构
  - Start 函数拆分为小函数
  - 优雅关闭流程优化

- 其他
  - 忽略 SQLite 数据库文件
  - example 添加延迟/定点任务示例
2025-12-09 19:58:18 +08:00

407 lines
6.4 KiB
CSS

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background-color: #424242;
color: #e0e0e0;
min-height: 100vh;
padding: 20px;
}
/* Chart Card */
.chart-card {
background: #515151;
border-radius: 4px;
padding: 20px;
border: 1px solid #616161;
margin-bottom: 20px;
}
.chart-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.chart-title {
font-size: 1.1em;
font-weight: 500;
}
.chart-container {
height: 280px;
position: relative;
}
/* Time Range Picker */
.time-range-picker {
display: flex;
gap: 10px;
align-items: center;
}
.time-control {
display: flex;
align-items: center;
background: #424242;
border: 1px solid #616161;
border-radius: 4px;
overflow: hidden;
}
.time-control button {
background: transparent;
border: none;
color: #9e9e9e;
padding: 6px 10px;
cursor: pointer;
font-size: 1em;
}
.time-control button:hover {
background: #515151;
color: #e0e0e0;
}
.time-control .value {
padding: 6px 12px;
color: #e0e0e0;
font-size: 0.85em;
min-width: 40px;
text-align: center;
}
.time-control .end-value {
cursor: pointer;
}
.time-control .end-value:hover {
background: #515151;
}
.time-control .reset-btn:hover {
color: #ef5350;
}
/* Table Card */
.table-card {
background: #515151;
border-radius: 4px;
border: 1px solid #616161;
overflow: hidden;
}
.queues-table {
width: 100%;
border-collapse: collapse;
}
.queues-table th {
background: #424242;
padding: 14px 16px;
text-align: left;
font-weight: 500;
color: #bdbdbd;
font-size: 0.9em;
border-bottom: 1px solid #616161;
}
.queues-table td {
padding: 14px 16px;
border-bottom: 1px solid #616161;
}
.queues-table tr:last-child td {
border-bottom: none;
}
.queues-table tbody tr:hover {
background: #5a5a5a;
}
.queue-name {
font-weight: 500;
color: #4fc3f7;
cursor: pointer;
}
.queue-name:hover {
text-decoration: underline;
}
.state-badge {
display: inline-block;
padding: 4px 10px;
border-radius: 4px;
font-size: 0.8em;
font-weight: 500;
background: #66bb6a;
color: #1b5e20;
}
.state-badge.paused {
background: #ffb74d;
color: #e65100;
}
.memory-bar {
width: 120px;
height: 6px;
background: #424242;
border-radius: 3px;
overflow: hidden;
}
.memory-bar-fill {
height: 100%;
background: #42a5f5;
border-radius: 3px;
}
.latency-value {
color: #bdbdbd;
}
.action-btn {
background: transparent;
border: 1px solid #757575;
color: #bdbdbd;
padding: 4px 8px;
border-radius: 4px;
cursor: pointer;
font-size: 0.8em;
}
.action-btn:hover {
background: #616161;
color: #e0e0e0;
}
/* Loading & Empty State */
.loading {
text-align: center;
padding: 60px;
color: #9e9e9e;
}
.loading-spinner {
width: 40px;
height: 40px;
border: 3px solid #616161;
border-top-color: #42a5f5;
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto 15px;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.empty-state {
text-align: center;
padding: 60px;
color: #9e9e9e;
}
/* Modal */
.modal {
display: none;
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: #424242;
}
.modal.open {
display: block;
}
.modal-content {
background-color: #424242;
width: 100%;
height: 100%;
overflow: hidden;
}
.modal-header {
background: #515151;
padding: 16px 20px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #616161;
}
.modal-header h2 {
font-size: 1.1em;
font-weight: 500;
}
.close-btn {
color: #9e9e9e;
font-size: 24px;
cursor: pointer;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
background: transparent;
border: none;
}
.close-btn:hover {
background: #616161;
color: #e0e0e0;
}
.modal-body {
padding: 20px;
height: calc(100vh - 60px);
overflow-y: auto;
}
/* Task Tabs */
.task-tabs {
display: flex;
gap: 5px;
margin-bottom: 20px;
background: #424242;
padding: 5px;
border-radius: 4px;
}
.task-tab {
padding: 8px 16px;
cursor: pointer;
border: none;
background: transparent;
color: #9e9e9e;
border-radius: 4px;
font-size: 0.85em;
}
.task-tab:hover {
color: #e0e0e0;
}
.task-tab.active {
background: #42a5f5;
color: #fff;
}
/* Task List */
.task-list {
max-height: 400px;
overflow-y: auto;
}
.task-item {
background: #5a5a5a;
border: 1px solid #616161;
border-radius: 4px;
padding: 12px;
margin-bottom: 8px;
}
.task-item:hover {
border-color: #42a5f5;
}
.task-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 8px;
}
.task-id {
font-family: monospace;
font-size: 0.8em;
color: #9e9e9e;
}
.task-type {
font-weight: 500;
color: #42a5f5;
}
.task-payload {
font-family: monospace;
font-size: 0.75em;
color: #9e9e9e;
background: #424242;
padding: 8px;
border-radius: 4px;
margin-top: 8px;
word-break: break-all;
}
.task-meta {
display: flex;
gap: 12px;
margin-top: 8px;
font-size: 0.8em;
color: #9e9e9e;
}
.task-error {
color: #ef5350;
background: rgba(239, 83, 80, 0.1);
padding: 6px 8px;
border-radius: 4px;
margin-top: 8px;
font-size: 0.8em;
}
/* Pagination */
.pagination {
display: flex;
justify-content: center;
gap: 6px;
margin-top: 16px;
}
.pagination button {
padding: 6px 12px;
border: 1px solid #616161;
background: #424242;
color: #e0e0e0;
cursor: pointer;
border-radius: 4px;
font-size: 0.85em;
}
.pagination button:hover {
background: #5a5a5a;
}
.pagination button.active {
background: #42a5f5;
border-color: #42a5f5;
}
.pagination button:disabled {
opacity: 0.4;
cursor: not-allowed;
}
/* Queue Detail Chart */
.queue-chart-container {
height: 200px;
margin-bottom: 15px;
background: #424242;
border-radius: 4px;
padding: 10px;
}