feat: 第6布局改为左品右聊(聊天通高整列,chatFullHeight 几何)

This commit is contained in:
Aisland
2026-08-17 11:37:46 +08:00
parent 9afcc91e25
commit 9731c9b7f0
5 changed files with 37 additions and 18 deletions
+13 -9
View File
@@ -66,12 +66,12 @@ const OVER_SIDE_PX = 80
/** 拓扑预设(聊天窗恒贴右,PRD §13.2 硬约束):左右/三栏/上一下二/井字 */
const PRESET_DEFS = [
{ id: '2h', leftCount: 0, topCount: 0, contentCount: 1 },
{ id: '3h', leftCount: 0, topCount: 0, contentCount: 2 },
{ id: 'l2', leftCount: 1, topCount: 1, contentCount: 0 },
{ id: 't2', leftCount: 0, topCount: 1, contentCount: 1 },
{ id: 'grid', leftCount: 0, topCount: 2, contentCount: 1 },
{ id: 't3', leftCount: 0, topCount: 1, contentCount: 2 },
{ id: '2h', leftCount: 0, topCount: 0, contentCount: 1, chatFull: false },
{ id: '3h', leftCount: 0, topCount: 0, contentCount: 2, chatFull: false },
{ id: 'l2', leftCount: 1, topCount: 1, contentCount: 0, chatFull: false },
{ id: 't2', leftCount: 0, topCount: 1, contentCount: 1, chatFull: false },
{ id: 'grid', leftCount: 0, topCount: 2, contentCount: 1, chatFull: false },
{ id: 't3', leftCount: 0, topCount: 1, contentCount: 2, chatFull: true },
] as const
function buildLayout(presetId: string, name: string): LayoutSpec {
@@ -95,6 +95,7 @@ function buildLayout(presetId: string, name: string): LayoutSpec {
chatWidth: { default: 360, min: 240, max: 600 },
topHeight: { default: 200, min: 120, max: 480 },
chatSide: 'right',
chatFullHeight: def.chatFull === true,
}
}
@@ -137,9 +138,12 @@ function presetThumb(defId: string) {
)
}
return (
<span className="dsh-wt_thumb">
<span className="dsh-wt_thumbRow">{cell(false, 'a')}</span>
<span className="dsh-wt_thumbRow">{cell(false, 'b')}{cell(false, 'c')}{cell(true, 'd')}</span>
<span className="dsh-wt_thumb dsh-wt_thumbCols">
<span className="dsh-wt_thumbCol">
<span className="dsh-wt_thumbRow">{cell(false, 'a')}</span>
<span className="dsh-wt_thumbRow">{cell(false, 'b')}{cell(false, 'c')}</span>
</span>
<span className="dsh-wt_thumbCol">{cell(true, 'd')}</span>
</span>
)
}
+2 -2
View File
@@ -50,7 +50,7 @@ export const zh = {
'preset.l2': '左一右二',
'preset.t2': '上一下二',
'preset.grid': '井字四栏',
'preset.t3': '上一下三',
'preset.t3': '左品右聊',
'manage.deleteLayout': '删除布局',
'pane.browser': '浏览器',
'pane.explorer': '资源管理器',
@@ -115,7 +115,7 @@ export const en = {
'preset.l2': 'Left + stacked',
'preset.t2': 'Top + two',
'preset.grid': '2×2 grid',
'preset.t3': 'Top + three',
'preset.t3': 'Pin + chat',
'manage.deleteLayout': 'Delete layout',
'pane.browser': 'Browser',
'pane.explorer': 'Explorer',
+10 -6
View File
@@ -30,6 +30,8 @@ export type LayoutSpec = {
topHeight?: { default: number; min: number; max: number }
/** 聊天窗贴边位置:'right'(右列/右下,默认)| 'left'(左列/左下) */
chatSide?: 'left' | 'right'
/** 聊天窗通高(整列):为 true 时聊天占整条右/左列,内容区(含 top 行)全部排在其另一侧 */
chatFullHeight?: boolean
}
type Geom = { left: number; top: number; right: number; bottom: number }
@@ -310,8 +312,9 @@ export const splitStore: SplitState = {
const leftW = hasLeft
? clamp(this.leftW, spec.leftWidth?.min ?? 160, Math.max(spec.leftWidth?.min ?? 160, colW - 260))
: 0
const chatFull = spec.chatFullHeight === true
const gap = Math.max(0, colW - chatW) + 'px'
const mt = (BAR_H + topH) + 'px'
const mt = (BAR_H + (hasTop && !chatFull ? topH : 0)) + 'px'
const chatLeft = !hasLeft && spec.chatSide === 'left'
this.lastMarginLeft = hasLeft ? leftW + 'px' : (chatLeft ? '' : gap)
this.lastMarginRight = hasLeft ? '' : (chatLeft ? gap : '')
@@ -691,10 +694,11 @@ function SplitWorkspace() {
const leftW = hasLeft
? clamp(snap.leftW, spec.leftWidth?.min ?? 160, Math.max(spec.leftWidth?.min ?? 160, colW - 260))
: 0
const chatFull = spec.chatFullHeight === true
const contentW = Math.max(0, colW - chatW)
const contentX = hasLeft ? g.left + leftW : (chatLeft ? g.left + chatW : g.left)
const topRowX = hasLeft ? g.left + leftW : g.left
const topRowW = hasLeft ? Math.max(0, colW - leftW) : colW
const topRowX = hasLeft ? g.left + leftW : contentX
const topRowW = hasLeft ? Math.max(0, colW - leftW) : (chatFull ? contentW : colW)
const topItems = allocate(top, snap.topWs, topRowW)
const mainItems = allocate(main, snap.paneWs, contentW)
@@ -731,7 +735,7 @@ function SplitWorkspace() {
return (
<>
{/* 标题栏 */}
<div className="dsh-wt_splitBar" style={{ position: 'fixed', left: g.left, top: barTop, width: hasLeft ? colW : (hasTop ? colW : contentW), zIndex: 70 }}>
<div className="dsh-wt_splitBar" style={{ position: 'fixed', left: g.left, top: barTop, width: hasLeft || chatFull ? contentW : (hasTop ? colW : contentW), zIndex: 70 }}>
<span className="dsh-wt_splitTitle">{spec.title}</span>
{!hasLeft && (
<button
@@ -789,9 +793,9 @@ function SplitWorkspace() {
style={{
position: 'fixed',
left: (hasLeft ? g.left + leftW : (chatLeft ? g.left + chatW : g.right - chatW)) - DIVIDER / 2,
top: hasLeft ? barTop + BAR_H : bodyTop,
top: hasLeft || chatFull ? barTop + BAR_H : bodyTop,
width: DIVIDER,
height: hasLeft ? g.bottom - barTop - BAR_H : mainH,
height: hasLeft || chatFull ? g.bottom - barTop - BAR_H : mainH,
zIndex: 72,
}}
onPointerDown={makeDividerHandler(hasLeft ? 'left' : 'chat')}
+3 -1
View File
@@ -335,8 +335,10 @@ type SplitPane = {
视口内钳制;透明遮罩点击关闭),不再使用侧边栏内展开式下拉;面板内容仅「选择布局 + 填名称」
(快捷方式表单暂移除,存量快捷方式条目仍保留展示/删除);
- **拓扑预设六个**(2 行 × 3 列缩略图网格,聊天窗蓝色 💬 标注):
左右两栏 / 三栏横排 / 左一右二 / 上一下二 / 井字四栏 / 上一下三(2026-08-16 定案);
左右两栏 / 三栏横排 / 左一右二 / 上一下二 / 井字四栏 / 左品右聊(2026-08-16 定案);
左一右二 = 左列整高内容窗 + 右列「上内容 + 下聊天」(左列布局聊天固定右下,无 ⇄ 翻转);
左品右聊 = 左侧品字形(上一个、下两个内容窗)+ 右侧聊天通高整列(chatFullHeight 几何,
聊天可 ⇄ 翻转贴左);
- 保存的布局以「布局条目」形式出现在项目区(布局 = 一种工作台项目),点击打开 tiling 工作区,
再次点击 / ✕ / Esc 关闭。
@@ -324,3 +324,12 @@
(removeShortcut 保留);词典新增 preset.l2/preset.t3。
- 验证:构建 + node --check 通过;服务端实时下发(含 preset.l2/leftWidth/setLeftW);
待用户刷新实测。
## 补记(第 6 个布局改为「左品右聊」)
- 用户定案:上一下三 改为——左侧品字形(上一个、下两个内容窗)+ 右侧聊天窗通高整列。
- 引擎:LayoutSpec 新增 chatFullHeight(聊天通高:marginTop 不再被 top 行下推、
top 行排入内容区一侧、聊天分隔线全高、工具栏宽度取内容区宽);
该布局支持 ⇄ 翻转(聊天通高贴左时内容区在右)。
- 预设:t3 的 chatFull=true;缩略图改为左品字 + 右通高聊天;词典 preset.t3 改名「左品右聊 / Pin + chat」。
- 验证:构建 + node --check 通过;服务端实时下发(含 chatFullHeight);待用户刷新实测。