设置(仅管理员) - 可配置是否启用、通知时间(默认 01:00 Asia/Shanghai)、多名通知用户 - 收件人在后端规范化:去空、去重、限长限量,配置持久化到 system_config - 接口不返回通知中心密钥与对象存储密钥,只给是否已配置与脱敏预览 定时任务 - 单实例锁(MySQL GET_LOCK),按配置时间触发,命中后 30 分钟内失败最多补跑 3 次 - 服务端签发 15 分钟短时效 JWT 作为专用身份,令牌只写入浏览器 localStorage - 等数据真正渲染完成(有数据行、无加载中、无错误提示)才截图,展开滚动容器后整页截图 - 对象键形如 daily-inventory/2026-09-25/daily-inventory-20260925-010000.png - 截图上传成功后才逐用户发通知,单人失败不影响他人;正式推送按「业务日期+收件人」幂等 - 立即测试走同一链路但幂等键带随机数,不影响次日正式推送 - 每次执行记录时间、截图地址、通知对象、成功状态与失败原因 测试 - 覆盖收件人去重、通知时间校验、幂等键、业务日期与对象键、重试退避(17 项)
154 lines
2.6 KiB
CSS
154 lines
2.6 KiB
CSS
.daily-inventory-page {
|
|
padding: 16px 20px 24px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
}
|
|
|
|
.daily-inventory-header {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 12px;
|
|
}
|
|
|
|
.daily-inventory-header__title {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
}
|
|
|
|
.daily-inventory-header__help {
|
|
font-size: 13px;
|
|
}
|
|
|
|
.daily-inventory-header__meta {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 16px;
|
|
font-size: 13px;
|
|
color: rgba(0, 0, 0, 0.55);
|
|
}
|
|
|
|
.daily-inventory-th-tip {
|
|
border-bottom: 1px dashed rgba(0, 0, 0, 0.35);
|
|
cursor: help;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.daily-inventory-table .ant-table-thead > tr > th {
|
|
white-space: nowrap;
|
|
font-size: 12px;
|
|
padding: 6px 8px;
|
|
}
|
|
|
|
.daily-inventory-table .ant-table-tbody > tr > td {
|
|
padding: 5px 8px;
|
|
font-size: 13px;
|
|
}
|
|
|
|
/* 运行时取数的列:加淡蓝底纹,与基准值区分 */
|
|
.daily-inventory-table .daily-inventory-col--runtime {
|
|
background: rgba(22, 119, 255, 0.04);
|
|
}
|
|
|
|
/* 暂无单据来源的列:淡灰底纹,提示该列待 DBA 补表 */
|
|
.daily-inventory-table .daily-inventory-col--unavailable {
|
|
background: rgba(0, 0, 0, 0.03);
|
|
}
|
|
|
|
.daily-inventory-cell--na {
|
|
color: rgba(0, 0, 0, 0.25);
|
|
}
|
|
|
|
.daily-inventory-warehouse {
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.daily-inventory-cell--out {
|
|
color: #cf1322;
|
|
}
|
|
|
|
.daily-inventory-cell--in {
|
|
color: rgba(0, 0, 0, 0.85);
|
|
}
|
|
|
|
.daily-inventory-cell--zero {
|
|
color: rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
.daily-inventory-row--total > td {
|
|
font-weight: 600;
|
|
background: rgba(0, 0, 0, 0.03);
|
|
}
|
|
|
|
/* 定时截图通知设置弹窗 */
|
|
.daily-inventory-notify-form {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 10px;
|
|
}
|
|
|
|
.daily-inventory-notify-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.daily-inventory-notify-label {
|
|
width: 120px;
|
|
flex: none;
|
|
color: rgba(0, 0, 0, 0.75);
|
|
}
|
|
|
|
.daily-inventory-notify-recipients {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 6px;
|
|
margin-left: 128px;
|
|
min-height: 24px;
|
|
}
|
|
|
|
.daily-inventory-notify-meta {
|
|
margin-top: 14px;
|
|
padding-top: 12px;
|
|
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.daily-inventory-notify-runs {
|
|
margin-top: 12px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.daily-inventory-notify-run {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
color: rgba(0, 0, 0, 0.6);
|
|
}
|
|
|
|
.daily-inventory-footer {
|
|
font-size: 12px;
|
|
}
|
|
|
|
.daily-inventory-help p {
|
|
margin: 0 0 6px;
|
|
line-height: 1.7;
|
|
font-size: 13px;
|
|
white-space: pre-wrap;
|
|
}
|
|
|
|
.daily-inventory-help p.is-indent {
|
|
padding-left: 16px;
|
|
color: rgba(0, 0, 0, 0.65);
|
|
}
|