移除退役策划界面样式
删除旧 GDD 审批卡与策划窄条的孤儿 CSS 更新聊天布局测试以覆盖现役 DirectCodex 选择器 保留设计 Agent 和通用项目工作台表现
This commit is contained in:
@@ -818,7 +818,6 @@ export const AGENT_RUNTIME_PLAN_SUBMIT_GDD_TOOL = 'plan.submit_gdd';
|
||||
// 屏障处按信封原文构造这个 pending(`ensure_static_delegate_user_input_wait_at_locked`),
|
||||
// 同一份问题再投影成 `userInputRequest`,交互面是问答卡。
|
||||
// - `plan.submit_gdd`:策划子 Agent 提交 Fast GDD 后,`planning/pending.json` 的
|
||||
// `submission.pendingActionId` 指向的正是这个 pending,交互面是 `GddApprovalCard`
|
||||
// 的批准 / 修改 / 退回。
|
||||
//
|
||||
// 两者都没有「确认 / 拒绝」语义:`user.input_request` 从来不在
|
||||
|
||||
@@ -9269,115 +9269,6 @@ iframe.preview-frame {
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
立项策划前端样式(PlanGddSurface / 阶段进度 / GDD 审批卡 / 交付行 /
|
||||
planning-lane-runtime-strip)。
|
||||
这一段曾在 #193「Codex/agent chat layout fix」重写聊天样式时被整体误删:
|
||||
组件(TSX)原样保留、选择器全数消失,策划界面裸奔、正文弹层失去 fixed 定位
|
||||
变成内联平铺。从 5802048c3^ 原样恢复。聊天区样式重构时请勿顺手清理本段——
|
||||
这些选择器的使用方在 features/project-workspace/GddApprovalCard.tsx 与
|
||||
PlanningLaneRuntimeStrip.tsx。
|
||||
============================================================ */
|
||||
|
||||
/* 策划区是一个面:阶段进度是标题栏,审批卡是正文。边框和圆角只画在外壳上,里面两块
|
||||
不再各自带框。 */
|
||||
.plan-gdd-surface {
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
border: 1px solid #cfd7e6;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.gdd-approval-card {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
padding: 16px 18px 18px;
|
||||
background: #f8fbff;
|
||||
}
|
||||
|
||||
.plan-gdd-surface--with-card .plan-gdd-stage-progress {
|
||||
border-bottom: 1px solid #dbe4f1;
|
||||
}
|
||||
|
||||
.plan-gdd-stage-progress {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
padding: 10px 12px;
|
||||
background: #fff;
|
||||
color: #526173;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.plan-gdd-stage-progress__header,
|
||||
.plan-gdd-stage-progress__meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px 14px;
|
||||
}
|
||||
|
||||
/* 批准后的交付行。它是策划阶段唯一的产物出口,所以给一条分隔线把它和上面的状态
|
||||
区分开,而不是混成第三行元信息。 */
|
||||
.plan-gdd-stage-progress__delivery {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
margin-top: 4px;
|
||||
padding-top: 9px;
|
||||
border-top: 1px solid #e6ecf5;
|
||||
}
|
||||
|
||||
.plan-gdd-stage-progress__delivery code {
|
||||
min-width: 0;
|
||||
color: #3c4a5c;
|
||||
font-size: 11px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.plan-gdd-stage-progress__delivery-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.plan-gdd-stage-progress__delivery-actions button {
|
||||
min-height: 30px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid #cfd7e6;
|
||||
border-radius: 6px;
|
||||
color: #27364a;
|
||||
background: #fff;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.plan-gdd-stage-progress__delivery-actions button:hover:not(:disabled),
|
||||
.plan-gdd-stage-progress__delivery-actions button:focus-visible {
|
||||
border-color: #1f6feb;
|
||||
color: #1f6feb;
|
||||
}
|
||||
|
||||
.plan-gdd-stage-progress__delivery-actions button:disabled {
|
||||
opacity: 0.58;
|
||||
}
|
||||
|
||||
.plan-gdd-stage-progress__delivery-error {
|
||||
color: #b42323;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.plan-gdd-stage-progress__header strong {
|
||||
color: #27364a;
|
||||
}
|
||||
|
||||
.plan-gdd-stage-progress__header span {
|
||||
padding: 3px 8px;
|
||||
border-radius: 999px;
|
||||
background: #eef6ff;
|
||||
color: #1f6feb;
|
||||
}
|
||||
|
||||
.design-agent-approval,
|
||||
.design-agent-clarify {
|
||||
display: flex;
|
||||
@@ -9910,283 +9801,6 @@ button.design-workspace-tree__entry:hover,
|
||||
}
|
||||
}
|
||||
|
||||
.gdd-approval-card__header {
|
||||
display: grid;
|
||||
gap: 5px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.gdd-approval-card h2,
|
||||
.gdd-approval-card h3,
|
||||
.gdd-approval-card p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.gdd-approval-card h2 {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.gdd-approval-card__header p {
|
||||
color: #526173;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.gdd-approval-card__details-trace {
|
||||
color: #6b7a8c;
|
||||
font-size: 11px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.gdd-approval-card__details-trigger {
|
||||
justify-self: start;
|
||||
min-height: 30px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #cfd7e6;
|
||||
border-radius: 6px;
|
||||
color: #27364a;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.gdd-approval-card__decisions {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.gdd-approval-card__decisions article {
|
||||
display: grid;
|
||||
gap: 3px;
|
||||
padding: 9px 10px;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 7px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.gdd-approval-card__decisions article span {
|
||||
color: #1f6feb;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.gdd-approval-card__decisions article small {
|
||||
color: #526173;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.gdd-approval-card__actions,
|
||||
.gdd-approval-card__dialog-actions,
|
||||
.gdd-approval-card__recovery {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.gdd-approval-card__actions button,
|
||||
.gdd-approval-card__dialog-actions button,
|
||||
.gdd-approval-card__recovery button {
|
||||
min-height: 32px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid #cfd7e6;
|
||||
border-radius: 6px;
|
||||
color: #fff;
|
||||
background: #1f6feb;
|
||||
}
|
||||
|
||||
.gdd-approval-card__actions button:nth-child(n + 2),
|
||||
.gdd-approval-card__dialog-actions button:first-child {
|
||||
color: #27364a;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.gdd-approval-card button:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
.gdd-approval-card__recovery {
|
||||
justify-content: space-between;
|
||||
padding: 9px 10px;
|
||||
border-radius: 7px;
|
||||
color: #854d0e;
|
||||
background: #fff7df;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.gdd-approval-card__error {
|
||||
padding: 9px 10px;
|
||||
border-radius: 7px;
|
||||
color: #991b1b;
|
||||
background: #fff1f2;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.gdd-approval-card__dialog-backdrop {
|
||||
position: fixed;
|
||||
top: var(--window-chrome-height);
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 220;
|
||||
display: grid;
|
||||
padding: 24px;
|
||||
background: rgb(0 0 0 / 56%);
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
.gdd-approval-card__dialog {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
width: min(520px, 100%);
|
||||
padding: 20px;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
box-shadow: 0 18px 52px rgb(0 0 0 / 18%);
|
||||
}
|
||||
|
||||
.gdd-approval-card__details {
|
||||
max-height: min(760px, calc(100vh - 32px));
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.gdd-approval-card__details header,
|
||||
.gdd-approval-card__details article {
|
||||
display: grid;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.gdd-approval-card__details article {
|
||||
padding-top: 10px;
|
||||
border-top: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.gdd-approval-card__details p {
|
||||
white-space: pre-line;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.gdd-approval-card__dialog textarea {
|
||||
width: 100%;
|
||||
min-height: 110px;
|
||||
padding: 9px;
|
||||
border: 1px solid #cfd7e6;
|
||||
border-radius: 6px;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.gdd-approval-card__dialog-hint {
|
||||
padding: 9px 10px;
|
||||
border-radius: 7px;
|
||||
color: #854d0e;
|
||||
background: #fff7df;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* 审批卡是这一列里唯一没有天花板的成员:Fast GDD 的决定项越多它越高,能把消息列表和运行
|
||||
时面板一起挤出可视区。和 `.agent-runtime-status` 一样给它自己的上限加内部滚动,而不是
|
||||
让它去挤别人。 */
|
||||
/* 策划链路的会话列比另外两条多一个成员:策划面(阶段进度 + 审批卡)。#193(5802048c3
|
||||
「Codex/agent chat layout fix」)把这个容器从基础规则继承来的 `display: grid` 改成
|
||||
`display: block`、并把消息列表从 `flex: 1 1 auto` 改成 `height: 100%`,于是列表独吞
|
||||
整列高度,排在它后面的策划窄条、待确认命令、输入框和状态行全部被 `overflow: hidden`
|
||||
静默裁掉——组件照常渲染、DOM 里查得到,只是位置落在裁剪线外,屏幕上什么都没有。
|
||||
实测:窄条 top=858 而容器 bottom=788,超出 384px;scrollHeight 1235 vs clientHeight 734。
|
||||
|
||||
同一批改动还删掉了 `.game-workbench-chat .project-supervisor-composer` 的 4 条规则,
|
||||
所以列表上那个 `padding-bottom: 196px`(本意是给「浮起来的输入框」留位)从来没有对应
|
||||
的定位规则,那个模型压根没成立过。
|
||||
|
||||
命中判据是两个类的并集,两个都只属于策划链路,做游戏与做素材保持 master 的 block
|
||||
列原样不动。为什么不能只认策划面:`PlanGddSurface` 在 `planGddState === null` 时整个
|
||||
返回 null,而 `planGddState` 初值就是 null、要靠一次独立的 IPC 才填上。首帧竞态、以及
|
||||
hydrate 持续失败时,策划 run 照跑、澄清卡照渲染,只认策划面就会漏掉这一格,裁剪原样
|
||||
复发。窄条自己在场就等价于「有东西要用户动手」,把它并进来之后,「卡片存在」和「列
|
||||
布局生效」才是同一件事。
|
||||
|
||||
用 flex 列而不是 grid:子元素个数随待确认命令的有无浮动,固定行模板会错位;而且下面
|
||||
那条 `.plan-gdd-surface { flex: 0 0 auto }` 本来就是照 flex 写的,容器变成 flex 之后它
|
||||
才真正生效——在此之前它一直是死声明。 */
|
||||
.game-workbench-chat
|
||||
.project-supervisor-conversation:has(
|
||||
.plan-gdd-surface,
|
||||
.planning-lane-runtime-strip
|
||||
) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
/* 兜底:正常情况下上面的行分配已经让整列放得下,这条不会产生滚动条。但审批卡展开
|
||||
到 52dvh 且窄条同时在场时仍可能超出,届时给滚动而不是继承 `overflow: hidden`
|
||||
的裁剪——这个 bug 的全部代价就来自「悄悄裁掉」,宁可多一根滚动条。 */
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* 整列里只有消息列表可收缩:其余成员各自有天花板(策划面按内容、窄条 52dvh 且内滚、
|
||||
输入框定高),由列表吸收剩余空间。`height: 100%` 必须撤掉,否则它照旧独吞整列;
|
||||
`padding-bottom` 也一并收回,输入框已经回到文档流里,不再需要给它留空。 */
|
||||
.game-workbench-chat
|
||||
.project-supervisor-conversation:has(
|
||||
.plan-gdd-surface,
|
||||
.planning-lane-runtime-strip
|
||||
)
|
||||
.project-supervisor-message-list {
|
||||
flex: 1 1 auto;
|
||||
height: auto;
|
||||
min-height: 96px;
|
||||
padding-bottom: 12px;
|
||||
scroll-padding-bottom: 12px;
|
||||
}
|
||||
|
||||
/* 这三个成员不参与压缩:消息列表变长时不能把它们挤没——它们正是用户唯一需要动手的
|
||||
地方(澄清卡、输入框)。 */
|
||||
.game-workbench-chat
|
||||
.project-supervisor-conversation:has(
|
||||
.plan-gdd-surface,
|
||||
.planning-lane-runtime-strip
|
||||
)
|
||||
.planning-lane-runtime-strip,
|
||||
.game-workbench-chat
|
||||
.project-supervisor-conversation:has(
|
||||
.plan-gdd-surface,
|
||||
.planning-lane-runtime-strip
|
||||
)
|
||||
.project-supervisor-composer,
|
||||
.game-workbench-chat
|
||||
.project-supervisor-conversation:has(
|
||||
.plan-gdd-surface,
|
||||
.planning-lane-runtime-strip
|
||||
)
|
||||
.project-supervisor-workspace-status {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
/* 这个面不参与 flex 压缩。它自己不会长高:标题栏是固定几行,审批卡下面有自己的
|
||||
max-height 和内滚,所以高度天然有界。让它可压缩的话,`overflow: hidden`(画圆角
|
||||
要的)会把底部切掉——批准后交付行正好在那儿,表现是路径和两个按钮凭空消失。 */
|
||||
.game-workbench-chat .plan-gdd-surface {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
/* 只有审批卡在场时才需要「标题栏定高 + 正文占余下」的两行轨道。批准后卡片收掉,
|
||||
面里只剩标题栏,这条声明会给它套上一个不存在的第二行。 */
|
||||
.game-workbench-chat .plan-gdd-surface--with-card {
|
||||
min-height: 0;
|
||||
grid-template-rows: auto minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.game-workbench-chat .gdd-approval-card {
|
||||
min-height: 0;
|
||||
max-height: clamp(240px, 52dvh, 640px);
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
|
||||
/* 上面 24dvh/240px 的天花板是给做游戏链路常驻的调试面板设的。策划链路的窄条只在
|
||||
需要用户动手时出现(澄清卡 / 失败恢复),内容是要读完再回答的题面,给它和审批
|
||||
卡同级的空间。 */
|
||||
.game-workbench-chat .planning-lane-runtime-strip {
|
||||
max-height: clamp(240px, 52dvh, 640px);
|
||||
}
|
||||
|
||||
/* 做方案在拿到第一个已登记资源之前,左边的资源画布是空的;工作台此时收成单栏,
|
||||
对话铺满。类名由 view/project-development/index.tsx 的 conversationOnlyWorkbench
|
||||
拼上(planningStartMode && resources.length === 0),画布是 display: none 不是
|
||||
@@ -10675,11 +10289,8 @@ button.design-workspace-tree__entry:hover,
|
||||
color: var(--platform-button-primary-text);
|
||||
}
|
||||
|
||||
/* 对话框盒子的最终几何,故意放在文件靠后的位置:它与上面那条同选择器同权重
|
||||
(`.game-workbench-chat .project-supervisor-surface.is-direct-codex
|
||||
.project-supervisor-message-list`),按"后写胜出"把两处会顶掉它的规则压回去——
|
||||
一是 `:has(.plan-gdd-surface, .planning-lane-runtime-strip)` 给列表留的
|
||||
`padding-bottom: 12px`,二是下面窄屏块之前可能出现的任何底边偏移。
|
||||
/* 对话框盒子的最终几何,故意放在文件靠后的位置:它与上面的同选择器同权重,按
|
||||
"后写胜出"把窄屏块之前可能出现的任何底边偏移压回去。
|
||||
这里曾经是一条 `bottom: 156px`("列表在上、输入区在下"那版两盒布局的残留:给下面那只
|
||||
浮起来的输入区预留高度),它把上面那条 `bottom: 0` 悄悄顶掉,外框底边落在输入区腰上、
|
||||
输入区下半截露在框外——用户看到的就是"外框底边与输入区压在一起、没把输入区包住"。
|
||||
|
||||
@@ -112,10 +112,6 @@ const COMPOSER_EDITOR = `${COMPOSER_PLAIN} .resource-reference-input-editor`;
|
||||
const COMPOSER_CONTROLS = `${COMPOSER} .project-supervisor-composer-controls`;
|
||||
const COMPOSER_SUBMIT = `${COMPOSER_CONTROLS} .project-supervisor-submit-button`;
|
||||
const INPUT_ACTIONS = `${COMPOSER} .resource-reference-input-actions`;
|
||||
// 策划链在会话列里额外挂了一条规划面/窄条时,列表会命中这条 `:has(...)` 规则——
|
||||
// 它同样声明了 `padding-bottom`,正是上一轮把留白改回 12px 的那种隐患。
|
||||
const LIST_WITH_PLAN_SURFACE = `.game-workbench-chat .project-supervisor-conversation:has(.plan-gdd-surface, .planning-lane-runtime-strip) .project-supervisor-message-list`;
|
||||
|
||||
const DESKTOP = 1440;
|
||||
const MOBILE = 390;
|
||||
|
||||
@@ -186,7 +182,7 @@ function composerMaxHeight() {
|
||||
|
||||
describe('陶泥儿对话区:外框完整包住输入区', () => {
|
||||
it('外框四边贴会话区,输入区四边都在外框之内且不重合(宽屏)', () => {
|
||||
const list = desktopDeclarations(MESSAGE_LIST, LIST_WITH_PLAN_SURFACE);
|
||||
const list = desktopDeclarations(MESSAGE_LIST);
|
||||
const composer = desktopDeclarations(COMPOSER, COMPOSER_PLAIN);
|
||||
|
||||
// 先看不重合关系再钉绝对位移:底边必须"外框在外、输入区在内",留白 > 0。
|
||||
@@ -238,7 +234,7 @@ describe('陶泥儿对话区:外框完整包住输入区', () => {
|
||||
});
|
||||
|
||||
it('消息列表底部留白 = 输入区内缩 + 输入区最高高度 + 间距,且与 scroll-padding 同值', () => {
|
||||
const list = desktopDeclarations(MESSAGE_LIST, LIST_WITH_PLAN_SURFACE);
|
||||
const list = desktopDeclarations(MESSAGE_LIST);
|
||||
const composer = desktopDeclarations(COMPOSER, COMPOSER_PLAIN);
|
||||
const { total, actionsRowHeight } = composerMaxHeight();
|
||||
|
||||
@@ -260,7 +256,7 @@ describe('陶泥儿对话区:外框完整包住输入区', () => {
|
||||
|
||||
it('窄屏把外框交给会话列,输入区回到文档流,四周仍有一圈边距(390px)', () => {
|
||||
const conversation = mobileDeclarations(CONVERSATION);
|
||||
const list = mobileDeclarations(MESSAGE_LIST, LIST_WITH_PLAN_SURFACE);
|
||||
const list = mobileDeclarations(MESSAGE_LIST);
|
||||
const composer = mobileDeclarations(
|
||||
COMPOSER,
|
||||
COMPOSER_PLAIN,
|
||||
|
||||
Reference in New Issue
Block a user