二七王:修复出牌操作条/亮牌历史布局越界,补主牌统计条改名遗漏
- I1:Layers.js 群组 206 改名遗漏一处注释(亮牌信息条 → 主牌统计条),全仓复查确认无第二处 - I2:出牌操作条补「提示」项后 anchor:center 导致已有两项挤偏,改用 anchor:left 并反推 anchorX=446,令「出牌」按钮回到参考图实测 x≈556(求解器验证:446/556/748) - I3:HIST_FAN/MING_FAN 的 maxWidth 反推算错(旧注释「488」有误,实际总宽恒等于 maxWidth=500),导致 RIGHT 座位整排超出画布 5px;收窄为 490 使三座位求解结果落在 0-1280 内,订正注释与清单 §6.9c 对应文字 - M3:同步修正计划文档里遗留的旧名「亮牌信息条/亮牌条」 - M6:test_constants.js 补 items[].key 的三命名空间解析守卫(此前完全无守卫) - M5/M7:订正 ACC_ROW_TEXT_GRID 与扣底按钮宽度的估值依据说明 - M1/M2:清单 §6.9 子节重新排序为 6.9a→6.9b→6.9c 并统一标题层级,修正脚注星号误渲染 client/tests/run.js 与 server/games/erqiwang/test/run.js 均全绿,精灵总数(380)/ 布局节点数(83) 两个钉死断言未变。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
// 均落在框架保留段,与下列不冲突。
|
||||
var EQW_Layers = EQW_Layers || {
|
||||
|
||||
TABLE_STATIC: 101, // 牌桌常驻:顶部信息条、玩家位附加标记、亮牌信息条、底栏(局数 + 功能钮)
|
||||
TABLE_STATIC: 101, // 牌桌常驻:顶部信息条、玩家位附加标记、主牌统计条、底栏(局数 + 功能钮)
|
||||
HAND: 102, // 自己手牌区(单排 / 埋牌双排)
|
||||
TABLE_CARDS: 103, // 桌面牌:底牌区、三家已出牌区、埋牌底牌展示区
|
||||
ACTION: 104, // 阶段操作区:叫分面板、选主/投降面板、埋牌/出牌操作条、倒计时
|
||||
|
||||
@@ -89,9 +89,23 @@ EQW_Layout.BURY_OPERATION_BAR = {
|
||||
//埋牌条 items 首项(同一个提示按钮)也取 180,故沿用 180,待设计稿复核。
|
||||
//⚠ 本条 itemHeight 为 55(对齐出牌按钮 BTN_PLAY 157×55),而 BTN_TIP 原生高 63——
|
||||
// 求解结果里提示项的 height 会是 55,实际显示高度以精灵自身资源为准;此高度差同样待设计稿裁定
|
||||
//
|
||||
//2026-08-27 修订:补「提示」项后原先仍用 anchor:'center',导致整排重新居中、把已有的
|
||||
//CD_SELF / PLAY_BTN_SUBMIT 两项相对原先(仅 2 项时)左移了 107.5px——「出牌」按钮的位置在
|
||||
//参考图 `出牌.png` 是有实测依据的(556–711,宽约 156×57),不该因为插入第 3 项而漂移。
|
||||
//改为 anchor:'left',把 anchorX 定成【首项 CD_SELF 的起点】,让先前已有的两项固定不动、只是
|
||||
//在其后追加「提示」——与 FOOTER_FUNC_BUTTONS 用 anchor:'right' 固定住最右项「底牌」是同一思路
|
||||
//(那边插入更早的项,这边追加更晚的项,对称地选左/右锚点)。
|
||||
//反推 anchorX:_solveLineItems 在 anchor:'left' 下 start = anchorX,故
|
||||
// PLAY_BTN_SUBMIT.x = anchorX + CD_SELF.width(75) + spacing(35) = anchorX + 110
|
||||
//要 PLAY_BTN_SUBMIT.x ≈ 556(参考图实测),故 anchorX = 556 - 110 = 446。
|
||||
//实际调用求解器验证(count=3,spacing=35):
|
||||
// CD_SELF x=446 width=75 (参考图目测约 444,估值层面 2px 差可接受)
|
||||
// PLAY_BTN_SUBMIT x=556 width=157 (与参考图 556–711 实测吻合)
|
||||
// PLAY_BTN_TIP x=748 width=180
|
||||
EQW_Layout.PLAY_OPERATION_BAR = {
|
||||
kind: 'line', direction: 'horizontal', anchorX: 640, anchorY: 345,
|
||||
itemHeight: 55, spacing: 35, anchor: 'center',
|
||||
kind: 'line', direction: 'horizontal', anchorX: 446, anchorY: 345,
|
||||
itemHeight: 55, spacing: 35, anchor: 'left',
|
||||
items: [
|
||||
{ key: 'CD_SELF', width: 75 },
|
||||
{ key: 'PLAY_BTN_SUBMIT', width: 157 },
|
||||
|
||||
@@ -145,6 +145,9 @@ EQW_Layout.ACC_TPL_AVATAR = {
|
||||
// 列4: 傍王分{n}
|
||||
// 第 2 行只有前两列有文字,第 3/4 列留空(求解仍返回 8 个槽位,调用方按数据取前 6 个)。
|
||||
// anchorX 相对容器(= 参考图列1 绝对 x272 − 容器 x80);anchorY 随所在行浮动 → 运行时注入
|
||||
// 【估值精度说明】本节点用等距列模型(itemWidth:176 spacingX:0 → 相对容器 192/368/544/720),
|
||||
// 而参考图「大局结算.png」目视实测的列 x 约为 272/455/634/800(列距 183/179/166,并不等距)——
|
||||
// 与等距模型偏差约 10px,比本文件头部通用声明的「±5px」更大,待设计稿复核(本次未改数值,仅订正估值说明)
|
||||
EQW_Layout.ACC_ROW_TEXT_GRID = {
|
||||
kind: 'grid', anchorX: 192, cols: 4, rows: 2,
|
||||
itemWidth: 176, itemHeight: 34, spacingX: 0, spacingY: 10,
|
||||
@@ -181,9 +184,21 @@ EQW_Layout.ACC_FUNC_BUTTONS = {
|
||||
// 三者【同一种版式】(半透黑遮罩 + 每家一排重叠大牌),参考图同为
|
||||
// docs_dev/uiref/冲关牌型显示.png;故以下节点照 CHONGGUAN_FAN / CG_MASK 同构给出,
|
||||
// 三家落点沿用清单 §6.7 的冲关牌锚点(LEFT 260,120 / RIGHT 1035,120 / SELF 640,400)。
|
||||
// 与冲关牌的唯一差别是【张数上限】:出牌历史摊平后可达 28 张以上,420 的 maxWidth 装不下,
|
||||
// 故放宽到 500、spacingMin 收到 -96(每张露 14px,28 张总宽 110+27×14=488 ≤ 500)。
|
||||
// 这两个数是【估值,待设计稿复核】——清单未给本 View 的排布参数。
|
||||
// 与冲关牌的唯一差别是【张数上限】:出牌历史摊平后可达 28 张以上,420 的 maxWidth 装不下。
|
||||
// 2026-08-27 订正:原估值 maxWidth:500 是算错的——_solveFan 的间距公式是
|
||||
// spacing = max(spacingMin, min(spacingMax, (maxWidth-itemWidth)/(count-1) - itemWidth))
|
||||
// 代入 maxWidth 500 / itemWidth 110(CARD_SIZE.L.w)/ count 28:
|
||||
// (500-110)/27 - 110 = -95.56,没有触到 spacingMin:-96 的下限,故实际 spacing 是 -95.56,
|
||||
// 而 fan 的总宽恒等于 maxWidth(AlignmentUtils.distributeHorizontally 的 totalWidth 公式代入后
|
||||
// 可化简为 maxWidth,只要 spacing 没被下限截断)——不是旧注释算的「488」。
|
||||
// RIGHT 锚点 anchorX:1035、anchor:center 时,总宽 500 使整排右边缘落在 1035+250=1285,
|
||||
// 超出 1280 设计画布 5px(LEFT/SELF 因锚点更靠左,仍在画布内,故此前没暴露)。
|
||||
// 故收窄 maxWidth 500 → 490:总宽=490(同样未触及 spacingMin 下限,spacingMin 因此仍是【死参数】,
|
||||
// 28 张时永远用不到 -96 这个下限,留着仅为将来张数/尺寸变化时兜底),RIGHT 边缘 1035+245=1280,
|
||||
// 恰好落在画布内;每张仍露约 14px(itemWidth+spacing=110-95.93≈14.07),与旧估值视觉上接近。
|
||||
// maxWidth:490 与 spacingMin:-96 仍是【估值,待设计稿复核】——清单未给本 View 的排布参数。
|
||||
// 【已知限制,留给后来者】每张仅露约 14px、视觉偏窄,待设计稿复核是否改为分两排显示,
|
||||
// 或改用 CARD_SIZE.M(更小的牌面)——这是本次估值阶段接受的限制,不是本次要解决的问题。
|
||||
//
|
||||
// 【牌用精灵复制】求解结果直接作为 SpriteCopyUtils.create 的 x/y(相对容器),
|
||||
// 与 §5.6a 冲关牌同一用法:三个容器精灵摆在原点、尺寸铺满屏,故容器内坐标 = 屏幕坐标。
|
||||
@@ -199,7 +214,7 @@ EQW_Layout.HIST_BOX = { kind: 'point', x: 0, y: 0, w: 1280, h: 720 };
|
||||
EQW_Layout.HIST_FAN = {
|
||||
kind: 'fan', direction: 'horizontal', anchor: 'center',
|
||||
itemWidth: EQW_Layout.CARD_SIZE.L.w, itemHeight: EQW_Layout.CARD_SIZE.L.h,
|
||||
maxWidth: 500, spacingMax: -40, spacingMin: -96,
|
||||
maxWidth: 490, spacingMax: -40, spacingMin: -96,
|
||||
bySeat: {
|
||||
LEFT: { anchorX: 260, anchorY: 120 },
|
||||
RIGHT: { anchorX: 1035, anchorY: 120 },
|
||||
@@ -231,7 +246,7 @@ EQW_Layout.MING_BOX = { kind: 'point', x: 0, y: 0, w: 1280, h: 720 };
|
||||
EQW_Layout.MING_FAN = {
|
||||
kind: 'fan', direction: 'horizontal', anchor: 'center',
|
||||
itemWidth: EQW_Layout.CARD_SIZE.L.w, itemHeight: EQW_Layout.CARD_SIZE.L.h,
|
||||
maxWidth: 500, spacingMax: -40, spacingMin: -96,
|
||||
maxWidth: 490, spacingMax: -40, spacingMin: -96,
|
||||
bySeat: {
|
||||
LEFT: { anchorX: 260, anchorY: 120 },
|
||||
RIGHT: { anchorX: 1035, anchorY: 120 }
|
||||
|
||||
@@ -51,8 +51,10 @@ EQW_Layout.FOOTER_ASET_TEXT = {
|
||||
//底栏 · 功能钮组(明牌/已出牌/上一轮/扣底/底牌):逐项不等宽(清单 §6.1 T-25)。
|
||||
//2026-08-27 补上「扣底」项(清单 §2.6 列的是 5 个按钮,此处原只排了 4 个)——
|
||||
//排序按 §2.6 表:扣底紧邻底牌(两者分别看埋牌底牌 / 底牌,成对但不同批,勿写反)。
|
||||
//【估值】扣底 78:清单未给该项宽度;同为两字按钮的「底牌」实测 78、「明牌」74,
|
||||
//故取同类两字按钮的 78,待设计稿复核(其余四项 74/87/93/78 为清单 §6.5 实测值)
|
||||
//【估值】扣底 78:清单未给该项宽度,参考图(等待叫分.png)底栏也只画出「底牌」一项
|
||||
//(当时还没有「扣底」按钮,§2.6 后补)。依据取自【底牌】按钮实测的 78——不能笼统地说
|
||||
//「两字按钮 = 78」:同为两字的「明牌」实测只有 74,两者并不相同,不可一概而论。
|
||||
//故本项沿用「底牌」实测值 78,待设计稿复核(其余四项 74/87/93/78 为清单 §6.5 实测值)
|
||||
EQW_Layout.FOOTER_FUNC_BUTTONS = {
|
||||
kind: 'line', direction: 'horizontal', anchorX: 1250, anchorY: 672,
|
||||
itemHeight: 30, spacing: 15, anchor: 'right',
|
||||
|
||||
@@ -135,6 +135,21 @@ allNodes.forEach(entry => {
|
||||
if (missing.length) { console.log('无法解析的 attach.target:\n ' + missing.join('\n ')); }
|
||||
t.eq('attach.target 在其 targetKind 命名空间内可解析', missing, []);
|
||||
|
||||
// line + items 节点:每项 key 同样是"指向另一个命名空间对象"的标识(多为精灵键),
|
||||
// 与 attach.target 同一职责,此前完全没有守卫——写错 key 不会报错,只会在渲染时摆错精灵。
|
||||
// items 没有 targetKind 字段,按 attach.target 同样的三命名空间并集解析
|
||||
const missingItemKeys = [];
|
||||
allNodes.forEach(entry => {
|
||||
if (!entry.node.items) { return; }
|
||||
entry.node.items.forEach((it, i) => {
|
||||
if (!resolvable[it.key]) {
|
||||
missingItemKeys.push(entry.path + '.items[' + i + '] -> key 不存在: ' + it.key);
|
||||
}
|
||||
});
|
||||
});
|
||||
if (missingItemKeys.length) { console.log('无法解析的 items[].key:\n ' + missingItemKeys.join('\n ')); }
|
||||
t.eq('items[].key 在三命名空间并集内可解析', missingItemKeys, []);
|
||||
|
||||
// ---- 求解冒烟:每个布局节点都真的能被求解器算出来 ----
|
||||
// 这是配置与求解器之间契约的最强守卫——字段名写错、缺 w/h、kind 不认识、
|
||||
// bySeat 缺座位,全都会在这里当场抛错,而不是等到界面上静默摆歪。
|
||||
|
||||
Reference in New Issue
Block a user