fix: keep report field pool cards fixed height
This commit is contained in:
@@ -5066,7 +5066,7 @@ npm run verify:phase8
|
|||||||
| TC-REPORT-WPS-002 | 分别上传10MB以上且不超过100MB、超过100MB、解压后超过500MB的报备XLSX | 第一类可进入解析;后两类分别在上传层或解包层明确拒绝;Nginx私有站点允许100MB业务文件及multipart开销,不扩大公网单条API边界 |
|
| TC-REPORT-WPS-002 | 分别上传10MB以上且不超过100MB、超过100MB、解压后超过500MB的报备XLSX | 第一类可进入解析;后两类分别在上传层或解包层明确拒绝;Nginx私有站点允许100MB业务文件及multipart开销,不扩大公网单条API边界 |
|
||||||
| TC-REPORT-WPS-003 | 在批次和单条报备导出选择“系统 Excel 文件”或“WPS 单元格图片文件” | 默认保持ExcelJS Drawing格式;WPS选项生成DISPIMG与cellimages关系且图片按对应单元格可回读;两种格式均来自同一真实资料快照,不改变报备状态或短信链路 |
|
| TC-REPORT-WPS-003 | 在批次和单条报备导出选择“系统 Excel 文件”或“WPS 单元格图片文件” | 默认保持ExcelJS Drawing格式;WPS选项生成DISPIMG与cellimages关系且图片按对应单元格可回读;两种格式均来自同一真实资料快照,不改变报备状态或短信链路 |
|
||||||
| TC-REPORT-IMPORT-APPLICATION-001 | 未选择企业应用、选择其他企业的应用、选择当前企业应用后解析导入 | 前两种前后端均阻止导入;合法应用可解析并把applicationId写入导入批次,后续补资料只作用于该企业应用范围 |
|
| TC-REPORT-IMPORT-APPLICATION-001 | 未选择企业应用、选择其他企业的应用、选择当前企业应用后解析导入 | 前两种前后端均阻止导入;合法应用可解析并把applicationId写入导入批次,后续补资料只作用于该企业应用范围 |
|
||||||
| TC-REPORT-FIELD-MODAL-001 | 打开签名或引流字段配置弹窗,添加字段并检查通用字段与移除按钮 | 左侧字段卡片高度不因添加改变;右侧默认包含同资料类型的通用字段;移除按钮为通用宽度、无红色填充,保存仍调用真实通道字段接口 |
|
| TC-REPORT-FIELD-MODAL-001 | 打开签名或引流字段配置弹窗,在左侧字段池数量不同的情况下连续添加字段,并检查通用字段与移除按钮 | 左侧每个字段卡片始终固定为68px,不因可选字段数量或添加操作被Grid拉伸;右侧默认包含同资料类型的通用字段;移除按钮为通用宽度、无红色填充,保存仍调用真实通道字段接口 |
|
||||||
| TC-REPORT-MATERIAL-DETAIL-001 | 查看包含当前图片字段、未删除历史字段及旧图片引用的报备资料 | 当前字段展示名称、代码、导出名及图片预览;未删除历史字段继续展示且同时显示字段名称和代码;图片可内联查看并保留下载入口,缺失内容显示明确占位 |
|
| TC-REPORT-MATERIAL-DETAIL-001 | 查看包含当前图片字段、未删除历史字段及旧图片引用的报备资料 | 当前字段展示名称、代码、导出名及图片预览;未删除历史字段继续展示且同时显示字段名称和代码;图片可内联查看并保留下载入口,缺失内容显示明确占位 |
|
||||||
| TC-REPORT-CHANNEL-IDENTITY-001 | 打开短信通道管理的报备详情 | 页面同时明确展示“通道名称”和“通道编号”,列表、筛选、状态修改和窄屏布局不受影响 |
|
| TC-REPORT-CHANNEL-IDENTITY-001 | 打开短信通道管理的报备详情 | 页面同时明确展示“通道名称”和“通道编号”,列表、筛选、状态修改和窄屏布局不受影响 |
|
||||||
| TC-DASHBOARD-METRIC-ORDER-001 | 打开运营看板并按从左到右、从上到下读取指标 | 顺序为发送总量、消息分片数、总体成功率、到达率、活跃签名、消费金额、返还金额、计收金额、利润、利润率;所有数值继续来自真实API口径 |
|
| TC-DASHBOARD-METRIC-ORDER-001 | 打开运营看板并按从左到右、从上到下读取指标 | 顺序为发送总量、消息分片数、总体成功率、到达率、活跃签名、消费金额、返还金额、计收金额、利润、利润率;所有数值继续来自真实API口径 |
|
||||||
|
|||||||
@@ -4462,3 +4462,9 @@ git diff --check
|
|||||||
- 发布后三条Stream的`last-delivered-id`和`entries-read`与发布前逐项相同:commands为`1787806802603-0 / 130918`,results为`1787806917609-0 / 191696`,protocol logs为`1787806802967-0 / 40472`;全部保持`pending=0 / lag=0`,没有发送、补发、重投、重新入队或手工ACK短信,也没有修改余额、通道、客户或签名业务资料。
|
- 发布后三条Stream的`last-delivered-id`和`entries-read`与发布前逐项相同:commands为`1787806802603-0 / 130918`,results为`1787806917609-0 / 191696`,protocol logs为`1787806802967-0 / 40472`;全部保持`pending=0 / lag=0`,没有发送、补发、重投、重新入队或手工ACK短信,也没有修改余额、通道、客户或签名业务资料。
|
||||||
- 工作站从测试环境实际下载主资源`index-DnhPgg2m.js`和`index-D9xR3Zhi.css`,SHA-256分别为`baa23f0aa62b3a8d1051718cca4a927316b4e2724244e3f39147888e3ea31a36`、`b193f9521c0104d35c645492cdf8c6e71e764349ff6bef59c8da77366e327cb4`,与服务器产物一致。真实浏览器读取到“聆界短信管理平台”运营登录页及用户名、密码、图形验证码和登录按钮;后续截图/控制台采集超时,且未使用平台管理员登录态,因此登录后功能与控制台仍不冒充已完成真实浏览器验收。
|
- 工作站从测试环境实际下载主资源`index-DnhPgg2m.js`和`index-D9xR3Zhi.css`,SHA-256分别为`baa23f0aa62b3a8d1051718cca4a927316b4e2724244e3f39147888e3ea31a36`、`b193f9521c0104d35c645492cdf8c6e71e764349ff6bef59c8da77366e327cb4`,与服务器产物一致。真实浏览器读取到“聆界短信管理平台”运营登录页及用户名、密码、图形验证码和登录按钮;后续截图/控制台采集超时,且未使用平台管理员登录态,因此登录后功能与控制台仍不冒充已完成真实浏览器验收。
|
||||||
- 服务器本轮临时上传包和`/tmp`脚本已在日志归档后清理,完整恢复点及上一运行目录保留。预生产`8.160.169.106`未访问、未部署、未覆盖、未回退或修改。
|
- 服务器本轮临时上传包和`/tmp`脚本已在日志归档后清理,完整恢复点及上一运行目录保留。预生产`8.160.169.106`未访问、未部署、未覆盖、未回退或修改。
|
||||||
|
|
||||||
|
## 2026-09-04 通道字段池单卡片高度补救
|
||||||
|
|
||||||
|
- 重新检查确认上一轮只设置左侧字段按钮`min-height: 68px`,没有阻止父级CSS Grid在字段较少时把自动行拉伸到剩余高度;添加字段导致可选数量变化后,单个字段卡片仍会重新分配高度,原验收结论不成立。
|
||||||
|
- 补救将字段池设为`align-content: start`并固定`grid-auto-rows: 68px`,同时把单个按钮的`height/min-height/max-height`统一为68px,确保签名和引流字段弹窗在任意可选数量下都不改变单卡片高度;不修改字段选择、保存接口或业务数据。
|
||||||
|
- 回归测试直接验证添加前两个卡片及添加后剩余卡片的高度均为68px;定向Vitest 1文件2项、前端TypeScript和`git diff --check`通过。本轮按用户补充要求仅本地提交,不推送、不部署;测试环境继续运行`bb435fb0ac1e7812fcdb59950a4b13757899ab39`,预生产未访问。
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { render, screen } from '@testing-library/react';
|
import { fireEvent, render, screen } from '@testing-library/react';
|
||||||
import { describe, expect, it, vi } from 'vitest';
|
import { describe, expect, it, vi } from 'vitest';
|
||||||
import { ReportFieldMappingModal } from './ReportFieldMappingModal';
|
import { ReportFieldMappingModal } from './ReportFieldMappingModal';
|
||||||
|
|
||||||
@@ -29,4 +29,30 @@ describe('ReportFieldMappingModal', () => {
|
|||||||
const remove = screen.getByRole('button', { name: '移除字段' });
|
const remove = screen.getByRole('button', { name: '移除字段' });
|
||||||
expect(remove).toHaveClass('channel-remove-field-button', 'ui-button--ghost');
|
expect(remove).toHaveClass('channel-remove-field-button', 'ui-button--ghost');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('keeps every field-pool card at a fixed height instead of stretching the grid rows', () => {
|
||||||
|
render(
|
||||||
|
<ReportFieldMappingModal
|
||||||
|
fields={[]}
|
||||||
|
commonFields={[]}
|
||||||
|
libraryFields={[
|
||||||
|
{ id: 'field-1', code: 'field_1', name: '字段一', fieldType: 'string', status: 'active' },
|
||||||
|
{ id: 'field-2', code: 'field_2', name: '字段二', fieldType: 'string', status: 'active' },
|
||||||
|
]}
|
||||||
|
reportType="signature"
|
||||||
|
onClose={vi.fn()}
|
||||||
|
onSave={vi.fn()}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
const pool = document.querySelector<HTMLElement>('.channel-field-pool-list');
|
||||||
|
expect(pool).toHaveStyle({ alignContent: 'start', gridAutoRows: '68px' });
|
||||||
|
const initialCards = document.querySelectorAll<HTMLButtonElement>('.channel-field-pool-list > button');
|
||||||
|
expect(initialCards).toHaveLength(2);
|
||||||
|
expect(initialCards[0]).toHaveStyle({ height: '68px', maxHeight: '68px', minHeight: '68px' });
|
||||||
|
|
||||||
|
fireEvent.click(initialCards[0]);
|
||||||
|
const remainingCards = document.querySelectorAll<HTMLButtonElement>('.channel-field-pool-list > button');
|
||||||
|
expect(remainingCards).toHaveLength(1);
|
||||||
|
expect(remainingCards[0]).toHaveStyle({ height: '68px', maxHeight: '68px', minHeight: '68px' });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -201,9 +201,14 @@ export function ReportFieldMappingModal({
|
|||||||
prefix={<Search size={16} />}
|
prefix={<Search size={16} />}
|
||||||
value={search}
|
value={search}
|
||||||
/>
|
/>
|
||||||
<div className="channel-field-pool-list">
|
<div className="channel-field-pool-list" style={{ alignContent: 'start', gridAutoRows: '68px' }}>
|
||||||
{available.map((field) => (
|
{available.map((field) => (
|
||||||
<button key={String(field.id)} onClick={() => addField(field)} type="button">
|
<button
|
||||||
|
key={String(field.id)}
|
||||||
|
onClick={() => addField(field)}
|
||||||
|
style={{ height: 68, maxHeight: 68, minHeight: 68 }}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
<span>
|
<span>
|
||||||
<strong>{String(field.name ?? field.code)}</strong>
|
<strong>{String(field.name ?? field.code)}</strong>
|
||||||
<Tag tone="neutral">{fieldTypeLabel[String(field.fieldType)] ?? field.fieldType}</Tag>
|
<Tag tone="neutral">{fieldTypeLabel[String(field.fieldType)] ?? field.fieldType}</Tag>
|
||||||
|
|||||||
@@ -6176,6 +6176,11 @@
|
|||||||
padding-right: var(--space-2);
|
padding-right: var(--space-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.channel-field-pool-list {
|
||||||
|
align-content: start;
|
||||||
|
grid-auto-rows: 68px;
|
||||||
|
}
|
||||||
|
|
||||||
.channel-field-pool-list > button {
|
.channel-field-pool-list > button {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: var(--color-surface);
|
background: var(--color-surface);
|
||||||
@@ -6185,10 +6190,12 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
min-height: 58px;
|
box-sizing: border-box;
|
||||||
|
height: 68px;
|
||||||
|
max-height: 68px;
|
||||||
|
min-height: 68px;
|
||||||
padding: var(--space-3) var(--space-4);
|
padding: var(--space-3) var(--space-4);
|
||||||
text-align: left;
|
text-align: left;
|
||||||
min-height: 68px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-remove-field-button {
|
.channel-remove-field-button {
|
||||||
|
|||||||
Reference in New Issue
Block a user