Files
AgentLab/frontend/src/typesSource.ts
T
ThearchyHelios aa3bd65cfc W4-d 前端:数据目录页的「变化」视图、表详情「结构与取值变化」一节、后台任务条、数据源的角标和定时维护
第 3 波的结构变化、取值观察、变化记录、定时维护都只有接口,这一提交给它们界面,能走通(收口):

- 数据目录页左栏加第三个视图「变化」(view=changes):按要处理 / 提醒 / 说明分组(组内照服务端排好的先后),能按开着的 /
  处理过的、结构变化 / 取值变化筛,筛选和打开的那一条记在地址里;视图标签上写几条要处理。点开一条,右栏写服务端的一句说法、
  依据(谁、经什么测到的;取值变化写观察口径,结构变化写比对的两版结构)、前后各是什么、影响面(说到这些列的目录项和它们
  现在的状态、写死了这张表的已发布模板、「这条 SQL 现在会报列不存在」、有效记录条件)、能做的处理。动作和做不了的原因都照
  服务端给的 actions 画;清理目录项先确认,加入码值可以先填含义,误报必须写理由(写之前按钮不能点,服务端也会拒)。处理完
  照实写结果:谁、什么时候、目录第几版、建了的任务(点得进起草、剖析的进度)。
- 表详情加「结构与取值变化」一节:这张表的变化(点「去处理」到「变化」视图里那一条)、撤销过的「已列全」、最近几次取值观察
  (行数、码值分布、最新业务日期、按日行数)和各自的口径,口径换过的说一句不互相比较;按日行数的小柱图只给眼睛看,数字写在
  字里和读屏名称里。
- 后台任务条(05 (g)):页头的「起草」「数据剖析」改回纯入口(进行中转圈、排队中时钟,读屏名称写状态、不写数字);DraftStrip
  换成 JobStrip,按服务端给的同源队先后列出探查、起草、剖析,每项一行加进度条和提醒(剖析的「最近查询多数超时」也挪到这里,
  窄屏、触屏看得见全文),「查看」打开对应的对话框,探查的到数据源卡片上(#source-<id> 滚过去)。
- 数据源卡片:要处理的变化条数的角标(读屏写全,点开到「变化」视图);「定时维护」对话框(和「探查范围」一样是卡片上的
  独立对话框,不塞进编辑表单:两个保存混在一起出错时说不清哪一样没存上):开关缺省关、开启时提示选低峰时段,选步骤(PUT
  /maintenance),频率用 components/FreqPicker,保存成一条 target_kind=source_maintenance 的定时任务(新建 ScheduleTargetCreate,
  改频率、开关 SchedulePatch 带版本);照实写下一次什么时候、最近一次建了哪些任务、哪几步没执行和原因(触发记录的 inputs),
  剖析没开、调度没开时说到点会怎样。上传表格、记录表不给这一节。开着的维护在卡片上带一个标签写频率。
- 地址里带 pjob / djob 时打开那个剖析、起草任务的进度(定时维护的「最近一次」从数据源页链过来)。

新文件:typesSource.ts(接口约定)、api/sourceChanges.ts、lib/termsSource.ts(terms.ts 末尾转出)、pages/catalog/changes.ts、
ChangesQueue.tsx、ChangeDetail.tsx、TableChanges.tsx、JobStrip.tsx、pages/SourceMaintenanceDialog.tsx。变化的叫法和服务端逐字
一致,tests/test_source_change_terms.py 守着(维护步骤的叫法同样)。观察的按日行数服务端补上窗口里没数据的日子(不然小柱图
看不出断档)。
2026-10-16 19:46:14 +08:00

233 lines
7.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 数据源的变化、取值观察、定时维护、后台任务条的接口约定(docs/design/next-round/03-数据接入与目录维护.md B2–B4、05 (g))。
* 和后端 app/api/source_changes.py、app/data/source_changes.py(agentlab-change/1)、app/data/catalog_profile_observe.py 一一对应。
*
* 能不能做、依据什么、现在怎样都由服务端给(actions、basis_text、affects.catalog[*].now),界面只照写,不自己判。
*/
import type { Schedule, ScheduleFire } from './types'
// ---------------------------------------------------------------- 变化记录 agentlab-change/1
export type SourceChangeSeverity = 'info' | 'warning' | 'action'
export type SourceChangeStatus = 'open' | 'acknowledged' | 'resolved' | 'dismissed'
/** 结构变化 / 取值变化(叫法分开,和已有的「目录有变化」也分开,总方案 X10) */
export type SourceChangeCategory = 'struct' | 'value'
/** 清理目录项、加入码值、重新起草、重新剖析、知道了、误报(必须写理由) */
export type SourceChangeAction = 'clean_catalog' | 'add_codes' | 'redraft' | 'reprofile' | 'acknowledge' | 'dismiss'
/** 列表的状态筛选:开着的(含知道了还没处理的)、处理过的(解决了的、标为误报的) */
export type SourceChangeStatusFilter = 'pending' | 'handled'
/** 影响面里说到这些列的一个目录项(测到时的状态),now 是它现在的状态:清理过、不在目录里了为 null */
export interface SourceChangeCatalogRef {
table: string
path: string
label: string
status: string | null
source: string | null
/** 人工确认过的项还说着被删的列 */
needs_action?: boolean
now: { status: string | null; source: string | null } | null
}
export interface SourceChangeTemplateNode {
node_id: string
label: string | null
type: string
impact: 'direct' | 'possible'
/** 这条写死的 SQL 现在会报列不存在 */
breaks: boolean
unknown_columns?: string[]
}
/** 已发布模板里用到这张表的一个 */
export interface SourceChangeTemplate {
workflow_id: string
name: string
version: number
level: string
impact: 'direct' | 'possible'
nodes: SourceChangeTemplateNode[]
}
export interface SourceChangeAffects {
catalog: SourceChangeCatalogRef[]
templates: SourceChangeTemplate[]
/** 有效记录条件用到了这一列 */
rules_touched: boolean
}
/** 现在能做的一个处理动作;ok 为假时 reason 写为什么做不了 */
export interface SourceChangeActionOption {
action: SourceChangeAction
ok: boolean
reason: string | null
}
export interface SourceChangeResolution {
by: string | null
at: string
action: SourceChangeAction
note: string | null
catalog_version?: number
/** 别的表(指向它的关联关系)也动了的,各表的目录版本 */
catalog_versions?: Record<string, number>
job_id?: string
}
/** 谁、经什么测到的 */
export interface SourceChangeDetected {
job_kind: 'introspect' | 'profile' | 'on_demand' | string
job_id: string | null
task_seq: number | null
trigger: 'manual' | 'schedule' | 'on_demand' | string
actor: string | null
fire_at?: string
}
export interface SourceChange {
schema: string
seq: number
id: string
source_id: string
source_name: string
table: string | null
column: string | null
kind: string
category: SourceChangeCategory
severity: SourceChangeSeverity
/** 服务端给人看的一句(「orders.amount:删除了列」) */
summary: string
detected_at: string
last_seen_at: string
seen_count: number
detected_by: SourceChangeDetected
basis: { method?: string; key?: string; query_refs?: number[] } | null
/** 取值变化依据的口径(整表 / 窗口 / 块采样 / 前 N 行……);结构变化为 null(依据是前后两版结构) */
basis_text: string | null
before: any
after: any
affects: SourceChangeAffects
struct_version_before: number | null
struct_version_after: number | null
status: SourceChangeStatus
resolution: SourceChangeResolution | null
/** 现在能做的处理动作(处理过的为空) */
actions: SourceChangeActionOption[]
/** 处理时建的任务(重新起草、重新剖析) */
job: { kind: 'draft' | 'profile'; id: string } | null
}
export interface SourceChangeCounts {
/** 开着的和知道了还没处理的 */
pending: number
open: number
by_severity: Record<SourceChangeSeverity, number>
}
export interface SourceChangeList {
items: SourceChange[]
total: number
counts: SourceChangeCounts
}
export interface SourceChangeQuery {
status?: SourceChangeStatusFilter
category?: SourceChangeCategory | null
table?: string | null
limit?: number
offset?: number
}
export interface SourceChangeResolveBody {
action: SourceChangeAction
/** 误报必须写 */
note?: string
/** 加入码值:{码值: 含义},含义可以空 */
codes?: Record<string, string>
}
export interface SourceChangeResolveOut {
change: SourceChange
catalog_version?: number
catalog_versions?: Record<string, number>
job?: { kind: 'draft' | 'profile'; id: string }
}
// ---------------------------------------------------------------- 取值观察
export type ObservationKind = 'rows' | 'codes_observe' | 'freshness' | 'daily_volume'
/** 一次观察。data 的形状按种类:rows {rows, at_least, method}、codes_observe {values: [码值, 行数, 占比][], rows, truncated}、
* freshness {max}、daily_volume {since, until, days: [日期, 行数][], total, days_with_data} */
export interface ObservationPoint {
at: string | null
basis_key: string
/** 口径的说法(整表、业务日期 x 最近 35 天、块采样约 1%、按存储顺序取前 N 行……) */
basis_text: string
data: any
}
export interface ObservationSeries {
kind: ObservationKind
/** 行数是空串 */
column: string
/** 新的在前 */
points: ObservationPoint[]
/** 这几次的口径不全相同:口径不同不比 */
basis_changed: boolean
}
export interface TableObservations {
table: string
series: ObservationSeries[]
}
// ---------------------------------------------------------------- 定时维护
export type MaintenanceStep = 'introspect' | 'profile_needed' | 'observe'
/** 一次维护触发的 inputs:建了哪些任务、哪几步没执行和原因 */
export interface MaintenanceFireInputs {
steps?: MaintenanceStep[]
jobs?: { step: string; kind: 'introspect' | 'profile'; id: string; tables?: number; scope?: string }[]
skipped?: { step: MaintenanceStep; reason: string }[]
}
export interface MaintenanceSchedule extends Omit<Schedule, 'last_fire'> {
last_fire: (ScheduleFire & { inputs?: MaintenanceFireInputs }) | null
}
export interface SourceMaintenance {
steps: MaintenanceStep[]
profile_enabled: boolean
/** 上传表格、记录表不维护 */
maintained: boolean
/** 调度循环开着没有:关着时到点不会触发 */
scheduler_on: boolean
schedules: MaintenanceSchedule[]
}
/** 数据源列表一次取齐的:要处理的变化条数(角标)、指向它的维护定时 */
export interface SourceUpkeep {
source_id: string
changes: SourceChangeCounts
maintenance: { id: string; enabled: boolean; cron: string; timezone: string; description_text: string; next_run_at: string | null }[]
}
// ---------------------------------------------------------------- 后台任务条
export type SourceJobKind = 'introspect' | 'draft' | 'profile'
/** 这个源进行中和排队的一个后台任务,按同源队的先后排好 */
export interface SourceBackgroundJob {
kind: SourceJobKind
id: string
status: string
total: number
done: number
/** 排在谁后面(draft / profile / introspect / import / sync_draft) */
waiting_for: string | null
/** 在同源队里的位置(0 是正在做的);还没排进队为 null */
position: number | null
}