style(web): 渠道卡片改并排省纵向空间 + bump 0.27.4

接 0.27.3:两张渠道镜像对话卡片(微信/企业微信)从竖排改并排
(#channel-cards flex row,各 flex:1);窄栏内图标左、名称 + 条数·时间
堆两行(新增 .cc-body 列容器)。绑定弹框(左下角「微信」rail 按钮)保留
不动 —— 它是绑定/解绑/测试推送唯一入口,与卡片职责互补不重复。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
caoqianming 2026-06-25 12:39:25 +08:00
parent 7dfdf4c73b
commit 133e350428
4 changed files with 20 additions and 9 deletions

View File

@ -21,6 +21,12 @@
## 已完成关键能力 ## 已完成关键能力
### 2026-06-25 / 渠道卡片改并排(bump 0.27.4)
- 接 0.27.3:两张渠道卡片从竖排改并排(`#channel-cards` flex row,各 `flex:1`),省左栏纵向空间;窄栏内图标左、名称 + 条数·时间堆两行(新增 `.cc-body` 列容器)。
- 确认渠道绑定弹框(左下角「微信」rail 按钮)**保留不动** —— 它是绑定/解绑/测试推送的唯一入口,与卡片(只读对话入口)职责互补不重复(方案②)。
- 文件:`web/static/dev.html`(CSS row + cc-body)、`web/static/js/chat.js`(卡片 markup 加 cc-body)。
### 2026-06-25 / 渠道镜像对话改成左栏固定卡片 + 企业微信也只读(bump 0.27.3) ### 2026-06-25 / 渠道镜像对话改成左栏固定卡片 + 企业微信也只读(bump 0.27.3)
- 把微信 / 企业微信常驻对话从「任务列表里置顶 + 绿徽章 + 绿边的行」改成「『新建任务』下方两张固定卡片」(`#channel-cards`):它们是每用户每渠道唯一的常驻只读镜像,从可滚动任务列表抽出更清爽、常驻可见。 - 把微信 / 企业微信常驻对话从「任务列表里置顶 + 绿徽章 + 绿边的行」改成「『新建任务』下方两张固定卡片」(`#channel-cards`):它们是每用户每渠道唯一的常驻只读镜像,从可滚动任务列表抽出更清爽、常驻可见。

View File

@ -1,3 +1,3 @@
# zcbot 版本号单一事实源:web/app.py 的 FastAPI version、/healthz 返回、前端展示都引这里。 # zcbot 版本号单一事实源:web/app.py 的 FastAPI version、/healthz 返回、前端展示都引这里。
# 改版本只动这一行。 # 改版本只动这一行。
__version__ = "0.27.3" __version__ = "0.27.4"

View File

@ -557,19 +557,22 @@
.badge.wx { background: #07C160; color: #fff; display: inline-flex; align-items: center; .badge.wx { background: #07C160; color: #fff; display: inline-flex; align-items: center;
gap: 3px; vertical-align: 1px; } gap: 3px; vertical-align: 1px; }
.badge.wx svg { width: 11px; height: 11px; fill: currentColor; display: block; } .badge.wx svg { width: 11px; height: 11px; fill: currentColor; display: block; }
/* 渠道镜像对话卡片(微信 / 企业微信):固定在「新建任务」下,绿调入口,与普通任务列表分离 */ /* 渠道镜像对话卡片(微信 / 企业微信):固定在「新建任务」下,绿调入口,与普通任务列表分离。
#channel-cards { padding: 6px 12px 2px; display: flex; flex-direction: column; gap: 6px; } 并排放(flex row,各 flex:1)省纵向空间;窄栏内图标左、名称/条数时间堆两行 */
#channel-cards { padding: 6px 12px 2px; display: flex; gap: 6px; }
#channel-cards:empty { display: none; } #channel-cards:empty { display: none; }
.channel-card { display: flex; align-items: center; gap: 7px; padding: 7px 9px; border-radius: 8px; .channel-card { flex: 1; min-width: 0; display: flex; align-items: center; gap: 7px; padding: 7px 9px;
border: 1px solid rgba(7,193,96,.35); background: rgba(7,193,96,.06); cursor: pointer; } border-radius: 8px; border: 1px solid rgba(7,193,96,.35); background: rgba(7,193,96,.06); cursor: pointer; }
.channel-card:hover { background: rgba(7,193,96,.12); } .channel-card:hover { background: rgba(7,193,96,.12); }
.channel-card.active { border-color: #07C160; background: var(--accent-soft); } .channel-card.active { border-color: #07C160; background: var(--accent-soft); }
.channel-card .cc-icon { width: 18px; height: 18px; border-radius: 5px; background: #07C160; color: #fff; .channel-card .cc-icon { width: 18px; height: 18px; border-radius: 5px; background: #07C160; color: #fff;
display: inline-flex; align-items: center; justify-content: center; flex: none; } display: inline-flex; align-items: center; justify-content: center; flex: none; }
.channel-card .cc-icon svg { width: 12px; height: 12px; fill: currentColor; display: block; } .channel-card .cc-icon svg { width: 12px; height: 12px; fill: currentColor; display: block; }
.channel-card .cc-name { font-weight: 600; font-size: 13px; flex: 1; min-width: 0; .channel-card .cc-body { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.channel-card .cc-name { font-weight: 600; font-size: 13px; min-width: 0;
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.channel-card .cc-meta { color: var(--muted); font-size: 11px;
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.channel-card .cc-meta { color: var(--muted); font-size: 11px; flex: none; }
.empty { padding: 24px; color: var(--muted); text-align: center; font-size: 13px; } .empty { padding: 24px; color: var(--muted); text-align: center; font-size: 13px; }
/* ───── chat ───── */ /* ───── chat ───── */

View File

@ -210,8 +210,10 @@ export async function loadChannelCards() {
return ` return `
<div class="channel-card${active}" data-tid="${t.task_id}" title="${escapeHtml(cfg.title)}"> <div class="channel-card${active}" data-tid="${t.task_id}" title="${escapeHtml(cfg.title)}">
<span class="cc-icon">${WECHAT_ICON}</span> <span class="cc-icon">${WECHAT_ICON}</span>
<span class="cc-body">
<span class="cc-name">${escapeHtml(name)}</span> <span class="cc-name">${escapeHtml(name)}</span>
<span class="cc-meta">${meta}</span> <span class="cc-meta">${meta}</span>
</span>
</div>`; </div>`;
}).join(""); }).join("");
box.querySelectorAll(".channel-card").forEach((el) => { box.querySelectorAll(".channel-card").forEach((el) => {