| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- /**
- * 预警/报警**状态词表**(票 71 返工,维护者 2026-10-29 第 1 条反馈)。
- *
- * ── 为什么必须分族,不能共用 ──
- * 维护者原话:「预警和报警状态是不一样的,不能完全通用(样式可以通用)」。
- * 后端口径逐条核实过,两族是**两套互不相通的生命周期**:
- *
- * 预警(`WarningWorkflow` / `EarlyWarningStatusEnum`,六态,线性推进):
- * DRAFT 草稿 → PENDING 待接收 → RECEIVED 已接收 → PROCESSING 处置中
- * → HANDLED 已处置 → CLOSED 已解除(**唯一终态**)
- * 后端注释原句:「已处置仍需核查,只有『已解除』才是终态」。
- *
- * 报警(`alarm_data.alarm_status` 经后端归一,二态):
- * UNHANDLED 未处理 → HANDLED 已处理(处置手段是工单)
- * 见 `BusinessCockpitEventAdapter` / `CockpitOverviewWarningSettingsService`。
- *
- * 共用一张表的实际后果(返工前就踩了):
- * · `PENDING` 在预警里是「待接收」,旧表却译成「待处理」—— 同一屏两种含义;
- * · 报警的 `UNHANDLED`/`HANDLED` 在旧表里**根本没有词条**,直接漏英文码上大屏;
- * · 预警的 RECEIVED/PROCESSING/CLOSED 同理漏码。
- *
- * ── 共用的是**形状**,不是词条 ──
- * 两个族的词表都走同一个 `statusVocabulary()` 构造函数(同一套字段:label/tone/terminal/
- * unhandled),所以「怎么画一个状态标签」只有一份实现;而「某个码是什么意思」各族自述。
- * 认不出的机器状态显示「状态未知」;协议码仍保留在领域数据中,不编造正常状态。
- */
- /** 状态标签的语义色键(沿用 `statusTones.js` 的四档,不新造色)。 */
- const TONE = { PENDING: 'lv2', ACTIVE: 'lv3', DONE: 'lv4', NEUTRAL: 'neutral' }
- /**
- * 列表状态徽标高亮色(维护者 2026-11-13 指定):
- * 待接收/已接收=黄、处置中=蓝、已处置=紫、已解除=绿。
- *
- * 与语义色键 `tone` 分开:`tone` 服务标签点/图例的中性语义,已被其它面板消费;
- * 这里是「设备详情预警列表」的状态高亮口径,改它不动别处。紫色无既有语义色键,
- * 由 tokens.css 的 --status-handled 单源给出。
- */
- export const STATUS_DISPLAY_TONE = {
- WARNING: {
- PENDING: 'lv2',
- RECEIVED: 'lv2',
- PROCESSING: 'lv3',
- HANDLED: 'handled',
- CLOSED: 'lv4',
- },
- ALARM: {
- UNHANDLED: 'lv2',
- HANDLED: 'lv4',
- },
- }
- /** 某族某状态的高亮色键;认不出回中性(不猜成某个真实态的颜色)。 */
- export function statusDisplayTone(family, status) {
- const key = String(family || '').trim().toUpperCase()
- const code = String(status || '').trim().toUpperCase()
- const table = STATUS_DISPLAY_TONE[key]
- return (table && table[code]) || 'neutral'
- }
- /**
- * 预警六态(`EarlyWarningStatusEnum`,码与中文名逐条照抄后端枚举)。
- *
- * `terminal` 只标 **CLOSED**:HANDLED(已处置)仍需核查,不是终态 ——
- * 这是后端注释明写的口径,也是「处置数」与「已解除数」必须分开算的依据。
- */
- export const WARNING_STATUS = {
- DRAFT: { label: '草稿', tone: TONE.NEUTRAL, terminal: false, unhandled: true },
- PENDING: { label: '待接收', tone: TONE.PENDING, terminal: false, unhandled: true },
- RECEIVED: { label: '已接收', tone: TONE.ACTIVE, terminal: false, unhandled: false },
- PROCESSING: { label: '处置中', tone: TONE.ACTIVE, terminal: false, unhandled: false },
- HANDLED: { label: '已处置', tone: TONE.ACTIVE, terminal: false, unhandled: false },
- CLOSED: { label: '已解除', tone: TONE.DONE, terminal: true, unhandled: false },
- }
- /** 报警二态(后端归一后的取值)。 */
- export const ALARM_STATUS = {
- UNHANDLED: { label: '未处理', tone: TONE.PENDING, terminal: false, unhandled: true },
- HANDLED: { label: '已处理', tone: TONE.DONE, terminal: true, unhandled: false },
- }
- /** 族 → 词表。认不出的族回空表(调用方据此只说原码,不冒充)。 */
- const VOCABULARY_BY_FAMILY = {
- WARNING: WARNING_STATUS,
- ALARM: ALARM_STATUS,
- }
- /**
- * 某一族的**状态词表**(唯一入口;组件与卡片都不直接认码)。
- *
- * @param {string} family `WARNING`/`ALARM`(大小写不敏感)
- * @returns {object} 码 → `{label, tone, terminal, unhandled}`;族认不出回空对象
- */
- export function statusVocabulary(family) {
- const key = String(family || '').trim().toUpperCase()
- // 返回浅拷贝:调用方只读,但也不该拿到能改到这张表内部的原对象。
- return { ...(VOCABULARY_BY_FAMILY[key] || {}) }
- }
- /**
- * 该族里「已了结」的状态码集合(算**处置数**用)。
- *
- * 预警只有 CLOSED;报警只有 HANDLED。用集合而不是单个字符串,
- * 是因为将来任一族加终态时改这一处即可,不用去改算法。
- * @param {string} family
- * @returns {string[]}
- */
- export function terminalStatuses(family) {
- return Object.entries(statusVocabulary(family))
- .filter(([, meta]) => meta.terminal === true)
- .map(([code]) => code)
- }
- /**
- * 状态码 → 展示文本。
- *
- * 三条判定顺序(与 `localizeCodeText` 同一条思路):
- * 1. 本族词表命中 → 中文;
- * 2. 已发布中文保留;未登记机器码显示「状态未知」;空字段留空,不造状态。
- *
- * @param {string} family `WARNING`/`ALARM`
- * @param {string} status 后端状态码
- */
- export function statusText(family, status) {
- const code = typeof status === 'string' ? status.trim() : ''
- if (!code) return ''
- const vocabulary = statusVocabulary(family)
- const meta = Object.hasOwn(vocabulary, code.toUpperCase()) ? vocabulary[code.toUpperCase()] : null
- return meta ? meta.label : /\p{Script=Han}/u.test(code) && !/\p{Script=Latin}/u.test(code) ? code : '状态未知'
- }
- /**
- * 状态码 → 语义色键(标签必须带文字,色只是辅助 —— 票 06 的纪律)。
- * 认不出的码走中性灰,**不猜**成「处理中」。
- */
- export function statusTone(family, status) {
- const code = typeof status === 'string' ? status.trim() : ''
- if (!code) return 'neutral'
- const meta = statusVocabulary(family)[code]
- return meta ? meta.tone : 'neutral'
- }
- /** 该状态是不是本族的「已了结」终态(算处置数用)。 */
- export function isTerminalStatus(family, status) {
- const code = typeof status === 'string' ? status.trim() : ''
- return code !== '' && terminalStatuses(family).includes(code)
- }
- /** 该状态是不是本族的「还没人接手」(未处理/待接收一类)。 */
- export function isUnhandledStatus(family, status) {
- const code = typeof status === 'string' ? status.trim() : ''
- if (!code) return false
- const meta = statusVocabulary(family)[code]
- return !!(meta && meta.unhandled === true)
- }
|