chore: rebuild CentOS 7 release package
This commit is contained in:
@@ -291,6 +291,23 @@ class FakeElement {
|
||||
}
|
||||
|
||||
getBoundingClientRect() {
|
||||
const wallColumn = this.closest('.ccweb-task-board__wall-column');
|
||||
if (wallColumn) {
|
||||
const wallGrid = wallColumn.parentNode;
|
||||
const cells = wallGrid?.children?.filter((node) => (
|
||||
node.classList.contains('ccweb-task-board__clock')
|
||||
|| node.classList.contains('ccweb-task-board__wall-column')
|
||||
)) || [];
|
||||
const cellIndex = Math.max(0, cells.indexOf(wallColumn));
|
||||
const columnCount = Number(wallGrid?.style?.getPropertyValue('--task-board-wall-columns')) || 1;
|
||||
const wallCards = this.parentNode?.children?.filter((node) => node.classList.contains('ccweb-task-board__wall-card')) || [];
|
||||
const wallCardIndex = Math.max(0, wallCards.indexOf(this));
|
||||
const left = 8 + ((cellIndex % columnCount) * 288);
|
||||
const top = 8 + (Math.floor(cellIndex / columnCount) * 210) + 42 + (wallCardIndex * 78);
|
||||
const width = 270;
|
||||
const height = 70;
|
||||
return { x: left, y: top, left, top, right: left + width, bottom: top + height, width, height };
|
||||
}
|
||||
const column = this.closest('.ccweb-task-board__column');
|
||||
const lanes = column?.parentNode;
|
||||
const columns = lanes?.children?.filter((node) => node.classList.contains('ccweb-task-board__column')) || [];
|
||||
@@ -440,6 +457,10 @@ async function flush() {
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
}
|
||||
|
||||
async function wait(ms) {
|
||||
await new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const source = fs.readFileSync(SCRIPT_PATH, 'utf8');
|
||||
const css = fs.readFileSync(STYLE_PATH, 'utf8');
|
||||
@@ -464,6 +485,77 @@ async function main() {
|
||||
assert(css.includes('.ccweb-task-board__lanes'), 'CSS 应包含横向看板工作区');
|
||||
assert(/overflow-x:\s*auto/.test(css), '看板应允许横向滚动');
|
||||
assert(/grid-auto-columns:/.test(css), '看板列数和宽度应动态生成');
|
||||
assert(source.includes("'--task-board-column-count'"), '看板应把服务端动态列数暴露给响应式布局');
|
||||
assert(css.includes('@media (orientation: landscape) and (max-height: 768px)'), 'CSS 应覆盖桌面模式浏览器下的手机横屏高度');
|
||||
assert(
|
||||
/@media \(orientation: landscape\) and \(max-height: 768px\)[\s\S]*?\.task-board-panel\s*\{[^}]*position:\s*fixed;[^}]*inset:\s*0;/.test(css),
|
||||
'横屏看板必须覆盖整个网页视口而不是留在聊天内容区',
|
||||
);
|
||||
assert(
|
||||
/@media \(orientation: landscape\) and \(max-height: 768px\)[\s\S]*?\.task-board-panel\s*\{[^}]*height:\s*100vh;[^}]*height:\s*100dvh;/.test(css),
|
||||
'横屏看板必须为旧浏览器提供 100vh 回退并优先使用动态视口高度',
|
||||
);
|
||||
assert(
|
||||
/@media \(orientation: landscape\) and \(max-height: 768px\)[\s\S]*?\.task-board-panel__root\s*\{[^}]*height:\s*100vh;[^}]*height:\s*100dvh;/.test(css),
|
||||
'横屏挂载根必须把完整视口高度继续传给看板矩阵',
|
||||
);
|
||||
assert(
|
||||
/@media \(orientation: landscape\) and \(max-height: 768px\)[\s\S]*?\.ccweb-task-board\s*\{[^}]*grid-template-rows:\s*minmax\(0,\s*1fr\);/.test(css),
|
||||
'横屏隐藏工具栏后根网格必须只保留一行,不能留下空白的第二轨道',
|
||||
);
|
||||
assert(
|
||||
/@media \(orientation: landscape\) and \(max-height: 768px\)[\s\S]*?\.task-board-panel__header\s*\{[^}]*position:\s*absolute;/.test(css),
|
||||
'横屏返回按钮必须叠入看板顶带而不是单占一行',
|
||||
);
|
||||
assert(
|
||||
/@media \(orientation: landscape\) and \(max-height: 768px\)[\s\S]*?\.ccweb-task-board__toolbar\s*\{[^}]*display:\s*none;/.test(css),
|
||||
'横屏只读看板不得保留任务看板工具条',
|
||||
);
|
||||
assert(
|
||||
css.includes('.ccweb-task-board__clock-time') && css.includes('.ccweb-task-board__clock-date'),
|
||||
'数字时钟应具有明确的时间与日期层级',
|
||||
);
|
||||
assert(
|
||||
/@media \(orientation: landscape\) and \(max-height: 768px\)[\s\S]*?\.ccweb-task-board__lanes\s*\{[^}]*display:\s*none;/.test(css),
|
||||
'横屏展示不得暴露可操作的传统看板列',
|
||||
);
|
||||
assert(
|
||||
/@media \(orientation: landscape\) and \(max-height: 768px\)[\s\S]*?\.ccweb-task-board__wall-grid\s*\{[^}]*display:\s*grid;[^}]*grid-template-columns:\s*repeat\(var\(--task-board-wall-columns\),\s*minmax\(0,\s*1fr\)\);[^}]*grid-template-rows:\s*repeat\(var\(--task-board-wall-rows\),\s*minmax\(0,\s*1fr\)\);/.test(css),
|
||||
'横屏看板应把时钟格与状态格排成动态矩阵',
|
||||
);
|
||||
assert(
|
||||
css.includes('.ccweb-task-board__wall-column')
|
||||
&& css.includes('.ccweb-task-board__wall-card-title')
|
||||
&& css.includes('.ccweb-task-board__wall-card-summary'),
|
||||
'横屏看板应具有动态状态格和多任务卡层级',
|
||||
);
|
||||
assert(source.includes('wallRotationMs') && source.includes('wallUpdateHoldMs'), '状态格应提供列内轮换与更新延长停留时长');
|
||||
assert(!source.includes('ccweb-task-board__wall-focus'), '横屏看板不得再渲染单任务聚焦舞台');
|
||||
assert(!source.includes('ccweb-task-board__wall-stage'), '横屏看板不得再保留巨幅单任务舞台');
|
||||
for (const animationId of [
|
||||
'ccweb-task-board-wall-card-page-leave',
|
||||
'ccweb-task-board-wall-card-page-enter',
|
||||
'ccweb-task-board-wall-card-move',
|
||||
'ccweb-task-board-wall-card-update',
|
||||
]) {
|
||||
assert(source.includes(animationId), `横屏看板缺少卡片动效 ${animationId}`);
|
||||
}
|
||||
assert(
|
||||
/\.ccweb-task-board__wall-card-summary\s*\{[^}]*white-space:\s*normal;[^}]*\}/.test(css),
|
||||
'横屏任务摘要应在卡片内自然换行',
|
||||
);
|
||||
assert(
|
||||
!/\.ccweb-task-board__wall-card-(?:title|summary)\s*\{[^}]*-webkit-line-clamp:/.test(css),
|
||||
'横屏任务标题和摘要不得使用行数截断',
|
||||
);
|
||||
assert(
|
||||
/\.ccweb-task-board__clock\s*\{[^}]*background:\s*var\(--bg-secondary\);/.test(css),
|
||||
'时钟应作为矩阵中的普通主题格而不是巨型侧栏',
|
||||
);
|
||||
assert(
|
||||
/body:has\(\.task-board-panel:not\(\[hidden\]\)\)\s+\.menu-btn\s*\{[^}]*display:\s*none/.test(css),
|
||||
'横屏看板打开时应隐藏宿主侧栏浮动菜单按钮',
|
||||
);
|
||||
assert(css.includes(':focus-visible'), 'CSS 应提供键盘焦点样式');
|
||||
assert(css.includes('@media (prefers-reduced-motion: reduce)'), 'CSS 应尊重减少动态效果偏好');
|
||||
assert(
|
||||
@@ -639,6 +731,35 @@ async function main() {
|
||||
'状态列应按服务端 order 排序',
|
||||
);
|
||||
const lanesNode = byClass(root, 'ccweb-task-board__lanes')[0];
|
||||
assert.strictEqual(lanesNode.style.getPropertyValue('--task-board-column-count'), '4', '横屏布局列数应跟随服务端定义');
|
||||
assert.strictEqual(lanesNode.style.getPropertyValue('--task-board-grid-columns'), '', '看板不得再计算宫格列数');
|
||||
assert.strictEqual(lanesNode.dataset.columnCount, '4', 'CSS 应能读取真实泳道数量');
|
||||
assert.strictEqual(lanesNode.dataset.columnLayout, 'fit', '常规动态列数应使用整屏均分布局');
|
||||
const wall = byClass(root, 'ccweb-task-board__wall')[0];
|
||||
assert(wall, '独立看板应同时提供横屏只读看板');
|
||||
const wallGrid = byClass(wall, 'ccweb-task-board__wall-grid')[0];
|
||||
assert(wallGrid, '横屏看板应提供时钟与状态格共用的矩阵');
|
||||
const clock = byClass(root, 'ccweb-task-board__clock')[0];
|
||||
assert(clock, '横屏看板应提供数字时钟');
|
||||
assert.strictEqual(clock.parentNode, wallGrid, '数字时钟应直接占据矩阵中的一格');
|
||||
assert(/^\d{2}:\d{2}$/.test(byClass(clock, 'ccweb-task-board__clock-time')[0].textContent), '时钟应显示 24 小时制时分');
|
||||
assert(/\d{1,2}月\d{1,2}日/.test(byClass(clock, 'ccweb-task-board__clock-date')[0].textContent), '时钟应显示月日');
|
||||
assert.strictEqual(byClass(wall, 'ccweb-task-board__wall-column').length, definitions.length, '状态格必须由服务端定义动态生成');
|
||||
assert.strictEqual(wallGrid.style.getPropertyValue('--task-board-wall-columns'), '3', '五个矩阵格应排成三列两行');
|
||||
assert.strictEqual(wallGrid.style.getPropertyValue('--task-board-wall-rows'), '2', '五个矩阵格应排成三列两行');
|
||||
assert.strictEqual(byClass(wall, 'ccweb-task-board__wall-card').length, 3, '横屏看板应同时显示多个状态中的任务卡');
|
||||
assert.strictEqual(
|
||||
walk(wall).filter((node) => ['BUTTON', 'INPUT', 'SELECT', 'TEXTAREA'].includes(node.tagName)).length,
|
||||
0,
|
||||
'横屏看板必须完全只读',
|
||||
);
|
||||
const runningWallCard = byClass(wall, 'ccweb-task-board__wall-card')
|
||||
.find((card) => card.dataset.sessionId === 'session-one');
|
||||
assert(runningWallCard, '运行任务应与其他任务一起出现在所属状态格');
|
||||
assert.strictEqual(runningWallCard.closest('.ccweb-task-board__wall-column').dataset.statusId, 'queue-x');
|
||||
assert(byClass(runningWallCard, 'ccweb-task-board__wall-card-title')[0].textContent.includes('定位协议边界'), '任务格应显示完整任务标题文本');
|
||||
assert.strictEqual(walk(runningWallCard).some((node) => node.tagName === 'IMG'), false, '横屏看板也不得把任务标题解析成 HTML');
|
||||
assert.strictEqual(byClass(wall, 'ccweb-task-board__wall-focus').length, 0, '横屏看板不得退化成单任务聚焦屏');
|
||||
const originalColumns = new Map(
|
||||
byClass(root, 'ccweb-task-board__column').map((column) => [column.dataset.statusId, column]),
|
||||
);
|
||||
@@ -666,7 +787,9 @@ async function main() {
|
||||
assert.strictEqual(firstCard.textContent.includes('42%'), false, '任务卡不得把历史百分比渲染为文案');
|
||||
assert.strictEqual(firstCard.textContent.includes('任务:入口'), false, '卡片不得重复显示只读业务状态');
|
||||
assert.strictEqual(byClass(firstCard, 'ccweb-task-board__business-state').length, 0, '卡片不得渲染业务状态胶囊');
|
||||
assert.strictEqual(byAction(firstCard, 'set-status')[0].value, 'queue-x', '状态选择器应作为业务状态的唯一卡片入口');
|
||||
assert.strictEqual(byAction(firstCard, 'set-status')[0].value, '', '移动控件不得重复显示当前所在列');
|
||||
assert.strictEqual(byAction(firstCard, 'set-status')[0].textContent.includes('入口'), false, '移动选项不得再次列出当前状态');
|
||||
assert(byAction(firstCard, 'set-status')[0].textContent.includes('移动到…'), '状态入口应明确表达移动动作');
|
||||
assert(firstCard.textContent.includes('运行:运行中'), '卡片应独立显示运行态');
|
||||
assert.strictEqual(firstTaskState.isRunning, true, '前端公开任务状态应保留服务端明确下发的运行布尔值');
|
||||
assert.strictEqual(firstCard.dataset.runtimeState, 'running', '运行卡片应暴露稳定的 data-runtime-state 契约');
|
||||
@@ -689,7 +812,7 @@ async function main() {
|
||||
board.setFilters({ archived: true });
|
||||
assert.strictEqual(byClass(root, 'ccweb-task-board__card').length, 1, '归档视图应只显示软归档任务');
|
||||
const archivedCard = byClass(root, 'ccweb-task-board__card')[0];
|
||||
assert.strictEqual(byAction(archivedCard, 'set-status')[0].value, 'queue-x', '归档不应改写任务业务状态');
|
||||
assert.strictEqual(byAction(archivedCard, 'set-status')[0].value, '', '归档任务的移动控件也不得重复当前状态');
|
||||
board.setFilters({ archived: false, search: '' });
|
||||
|
||||
const activeFirstCard = byClass(root, 'ccweb-task-board__card').find((card) => card.dataset.sessionId === 'session-one');
|
||||
@@ -707,6 +830,7 @@ async function main() {
|
||||
assert.strictEqual(Object.prototype.hasOwnProperty.call(statusRequest, 'progress'), false, '状态写请求不得发送百分比进度');
|
||||
assert.strictEqual(statusRequest.expectedVersion, 5, '写请求应携带期望任务版本');
|
||||
assert(statusRequest.requestId, '写请求应携带 requestId');
|
||||
assert.strictEqual(statusSelect.value, '', '提交移动后应恢复为紧凑动作提示');
|
||||
|
||||
const archiveButton = byAction(activeFirstCard, 'set-archive')[0];
|
||||
emit(archiveButton, 'click');
|
||||
@@ -747,6 +871,9 @@ async function main() {
|
||||
assert.strictEqual(byClass(root, 'ccweb-task-board__toolbar')[0].hasAttribute('inert'), false, '关闭后应解除 inert');
|
||||
|
||||
const moveAnimationCount = activeFirstCard.animations.length;
|
||||
const activeWallCard = byClass(root, 'ccweb-task-board__wall-card')
|
||||
.find((card) => card.dataset.sessionId === 'session-one');
|
||||
const wallMoveAnimationCount = activeWallCard.animations.length;
|
||||
statusSelect.focus();
|
||||
board.handleMessage({
|
||||
type: 'task_board_event',
|
||||
@@ -776,6 +903,15 @@ async function main() {
|
||||
const movedStatusSelect = byAction(movedFirstCard, 'set-status')[0];
|
||||
assert.strictEqual(movedFirstCard, activeFirstCard, '跨列更新必须移动原卡片节点,而非销毁后新建');
|
||||
assert.strictEqual(movedFirstCard.parentNode.parentNode.dataset.statusId, 'review-custom', '卡片应进入服务端指定状态列');
|
||||
const movedWallCard = byClass(root, 'ccweb-task-board__wall-card')
|
||||
.find((card) => card.dataset.sessionId === 'session-one');
|
||||
assert.strictEqual(movedWallCard, activeWallCard, '横屏看板也必须复用并移动原只读任务卡');
|
||||
assert.strictEqual(movedWallCard.closest('.ccweb-task-board__wall-column').dataset.statusId, 'review-custom');
|
||||
assert(
|
||||
movedWallCard.animations.slice(wallMoveAnimationCount)
|
||||
.some((animation) => animation.options.id === 'ccweb-task-board-wall-card-move'),
|
||||
'横屏任务卡跨状态格时应触发可见的 FLIP 位移动画',
|
||||
);
|
||||
assert.strictEqual(document.activeElement, movedStatusSelect, '卡片内容更新后应把键盘焦点恢复到状态控件');
|
||||
assert.strictEqual(byClass(root, 'ccweb-task-board__lanes')[0], lanesNode, '数据事件不得替换看板滚动节点');
|
||||
for (const [statusId, originalColumn] of originalColumns) {
|
||||
@@ -891,20 +1027,139 @@ async function main() {
|
||||
});
|
||||
assert.strictEqual(board.getState().tasks.length, 1, '最新查询结果应替换当前快照');
|
||||
|
||||
const rotatingRoot = document.createElement('div');
|
||||
document.body.appendChild(rotatingRoot);
|
||||
const rotatingBoard = api.mount(rotatingRoot, {
|
||||
document,
|
||||
autoLoad: false,
|
||||
wallRotationMs: 50,
|
||||
wallUpdateHoldMs: 140,
|
||||
wallCardsPerPage: 2,
|
||||
initialData: {
|
||||
statusDefinitions: definitions,
|
||||
tasks: [
|
||||
{
|
||||
sessionId: 'wall-running',
|
||||
title: '正在执行的任务',
|
||||
summary: '这是一段应在状态格内完整换行展示的任务摘要。',
|
||||
isRunning: true,
|
||||
runtimeState: '运行中',
|
||||
updatedAt: '2026-08-11T06:00:00.000Z',
|
||||
taskTracking: { enabled: true, statusId: 'doing-z', version: 1 },
|
||||
},
|
||||
{
|
||||
sessionId: 'wall-newer',
|
||||
title: '同列最近更新的任务',
|
||||
updatedAt: '2026-08-11T07:00:00.000Z',
|
||||
taskTracking: { enabled: true, statusId: 'doing-z', version: 1 },
|
||||
},
|
||||
{
|
||||
sessionId: 'wall-old',
|
||||
title: '同列较早任务',
|
||||
updatedAt: '2026-08-11T05:00:00.000Z',
|
||||
taskTracking: { enabled: true, statusId: 'doing-z', version: 1 },
|
||||
},
|
||||
{
|
||||
sessionId: 'wall-review',
|
||||
title: '另一状态中的任务',
|
||||
updatedAt: '2026-08-11T04:00:00.000Z',
|
||||
taskTracking: { enabled: true, statusId: 'review-custom', version: 1 },
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
const rotatingWall = byClass(rotatingRoot, 'ccweb-task-board__wall')[0];
|
||||
const doingWallColumn = byClass(rotatingWall, 'ccweb-task-board__wall-column')
|
||||
.find((column) => column.dataset.statusId === 'doing-z');
|
||||
const reviewWallColumn = byClass(rotatingWall, 'ccweb-task-board__wall-column')
|
||||
.find((column) => column.dataset.statusId === 'review-custom');
|
||||
const initialDoingCards = byClass(doingWallColumn, 'ccweb-task-board__wall-card');
|
||||
assert.deepStrictEqual(
|
||||
initialDoingCards.map((card) => card.dataset.sessionId),
|
||||
['wall-running', 'wall-newer'],
|
||||
'状态格第一页应同时显示多张任务卡,并优先显示运行与最近更新任务',
|
||||
);
|
||||
assert.strictEqual(
|
||||
byClass(initialDoingCards[0], 'ccweb-task-board__wall-card-summary')[0].textContent,
|
||||
'这是一段应在状态格内完整换行展示的任务摘要。',
|
||||
'横屏任务卡必须保留完整摘要文本',
|
||||
);
|
||||
const stableReviewCard = byClass(reviewWallColumn, 'ccweb-task-board__wall-card')[0];
|
||||
await wait(70);
|
||||
const rotatedDoingCards = byClass(doingWallColumn, 'ccweb-task-board__wall-card');
|
||||
assert.deepStrictEqual(
|
||||
rotatedDoingCards.map((card) => card.dataset.sessionId),
|
||||
['wall-old'],
|
||||
'溢出时只应轮换当前状态格内的下一页任务',
|
||||
);
|
||||
assert.strictEqual(byClass(reviewWallColumn, 'ccweb-task-board__wall-card')[0], stableReviewCard, '列内轮换不得替换其他状态格的任务');
|
||||
assert(
|
||||
initialDoingCards.some((card) => card.animations.some((animation) => animation.options.id === 'ccweb-task-board-wall-card-page-leave')),
|
||||
'列内换页应让旧页卡片收缩离场',
|
||||
);
|
||||
assert(
|
||||
rotatedDoingCards[0].animations.some((animation) => animation.options.id === 'ccweb-task-board-wall-card-page-enter'),
|
||||
'列内换页应让新页卡片展开进入',
|
||||
);
|
||||
assert.strictEqual(byClass(doingWallColumn, 'ccweb-task-board__wall-column-page')[0].textContent, '2 / 2', '溢出状态格应显示当前页码');
|
||||
rotatingBoard.handleMessage({
|
||||
type: 'task_board_event',
|
||||
task: {
|
||||
sessionId: 'wall-running',
|
||||
title: '刚刚更新的任务',
|
||||
isRunning: true,
|
||||
runtimeState: '运行中',
|
||||
updatedAt: '2026-08-11T08:00:00.000Z',
|
||||
statusId: 'doing-z',
|
||||
trackingEnabled: true,
|
||||
version: 2,
|
||||
},
|
||||
});
|
||||
const updatedWallCard = byClass(doingWallColumn, 'ccweb-task-board__wall-card')
|
||||
.find((card) => card.dataset.sessionId === 'wall-running');
|
||||
assert(updatedWallCard, '任务更新后必须立即切回并显示该任务所在页');
|
||||
assert.strictEqual(byClass(updatedWallCard, 'ccweb-task-board__wall-card-title')[0].textContent, '刚刚更新的任务');
|
||||
assert(
|
||||
updatedWallCard.animations.some((animation) => animation.options.id === 'ccweb-task-board-wall-card-update'),
|
||||
'更新任务应只在所属状态格内触发强调动画',
|
||||
);
|
||||
await wait(80);
|
||||
assert(byClass(doingWallColumn, 'ccweb-task-board__wall-card').some((card) => card.dataset.sessionId === 'wall-running'), '更新任务所在页应获得更长停留时间');
|
||||
await wait(85);
|
||||
assert.deepStrictEqual(
|
||||
byClass(doingWallColumn, 'ccweb-task-board__wall-card').map((card) => card.dataset.sessionId),
|
||||
['wall-old'],
|
||||
'延长停留结束后应恢复该状态格的列内轮换',
|
||||
);
|
||||
rotatingBoard.destroy();
|
||||
|
||||
const reducedEnvironment = loadTaskBoard(source, { reducedMotion: true });
|
||||
const reducedRoot = reducedEnvironment.document.createElement('div');
|
||||
reducedEnvironment.document.body.appendChild(reducedRoot);
|
||||
const reducedBoard = reducedEnvironment.api.mount(reducedRoot, {
|
||||
document: reducedEnvironment.document,
|
||||
autoLoad: false,
|
||||
initialData: { statusDefinitions: definitions, tasks: [tasks[0]] },
|
||||
wallRotationMs: 30,
|
||||
wallCardsPerPage: 1,
|
||||
initialData: { statusDefinitions: definitions, tasks: [tasks[0], tasks[1], tasks[2]] },
|
||||
});
|
||||
const reducedCard = byClass(reducedRoot, 'ccweb-task-board__card')[0];
|
||||
const reducedWallColumn = byClass(reducedRoot, 'ccweb-task-board__wall-column')
|
||||
.find((column) => column.dataset.statusId === 'queue-x');
|
||||
const reducedWallSessionId = byClass(reducedWallColumn, 'ccweb-task-board__wall-card')[0]?.dataset.sessionId;
|
||||
await wait(45);
|
||||
assert.strictEqual(
|
||||
byClass(reducedWallColumn, 'ccweb-task-board__wall-card')[0]?.dataset.sessionId,
|
||||
reducedWallSessionId,
|
||||
'减少动态偏好下应停止状态格自动换页',
|
||||
);
|
||||
const reducedCard = byClass(reducedRoot, 'ccweb-task-board__card')
|
||||
.find((card) => card.dataset.sessionId === 'session-one');
|
||||
reducedBoard.handleMessage({
|
||||
type: 'task_board_event',
|
||||
task: { sessionId: 'session-one', statusId: 'review-custom', trackingEnabled: true, version: 6 },
|
||||
});
|
||||
const reducedMovedCard = byClass(reducedRoot, 'ccweb-task-board__card')[0];
|
||||
const reducedMovedCard = byClass(reducedRoot, 'ccweb-task-board__card')
|
||||
.find((card) => card.dataset.sessionId === 'session-one');
|
||||
assert.strictEqual(reducedMovedCard, reducedCard, '减少动态效果时仍应复用并移动原卡片节点');
|
||||
assert.strictEqual(reducedMovedCard.parentNode.parentNode.dataset.statusId, 'review-custom');
|
||||
assert.strictEqual(reducedMovedCard.animations.length, 0, '减少动态效果偏好下不得启动脚本动画');
|
||||
@@ -918,8 +1173,39 @@ async function main() {
|
||||
initialData: { statusDefinitions: definitions.slice(0, 1), tasks: [] },
|
||||
});
|
||||
assert.strictEqual(secondBoard.getState().statusDefinitions.length, 1, '不同挂载实例应保持状态隔离');
|
||||
assert.strictEqual(
|
||||
byClass(secondRoot, 'ccweb-task-board__lanes')[0].style.getPropertyValue('--task-board-column-count'),
|
||||
'1',
|
||||
'不同挂载实例应独立维护响应式列数',
|
||||
);
|
||||
secondBoard.destroy();
|
||||
|
||||
const crowdedRoot = document.createElement('div');
|
||||
document.body.appendChild(crowdedRoot);
|
||||
const crowdedDefinitions = Array.from({ length: 7 }, (_, index) => ({
|
||||
id: `crowded-${index}`,
|
||||
label: `状态 ${index + 1}`,
|
||||
prompt: `归入状态 ${index + 1} 的任务。`,
|
||||
order: index,
|
||||
enabled: true,
|
||||
}));
|
||||
const crowdedBoard = api.mount(crowdedRoot, {
|
||||
document,
|
||||
autoLoad: false,
|
||||
initialData: { statusDefinitions: crowdedDefinitions, tasks: [] },
|
||||
});
|
||||
assert.strictEqual(
|
||||
byClass(crowdedRoot, 'ccweb-task-board__lanes')[0].dataset.columnLayout,
|
||||
'scroll',
|
||||
'超过六列时应降级为可读的横向滚动布局',
|
||||
);
|
||||
assert.strictEqual(
|
||||
byClass(crowdedRoot, 'ccweb-task-board__lanes')[0].style.getPropertyValue('--task-board-grid-columns'),
|
||||
'',
|
||||
'七列降级布局仍不得拆成上下两排',
|
||||
);
|
||||
crowdedBoard.destroy();
|
||||
|
||||
const openedBeforeDestroy = opened.length;
|
||||
board.destroy();
|
||||
emit(openButton, 'click');
|
||||
|
||||
Reference in New Issue
Block a user