Files
xh-medical-sign-web/clinical-web/src/views/management/documents/library.ts
T
2026-09-29 18:49:45 +08:00

192 lines
6.6 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.
/**
* 文档库的展示口径:状态、归属、文档类型。
*
* 状态筛选只有**两组**:启用中 / 停用(2026-09-28 收敛)。卡片可以显示「待发布」等
* 具体版本状态,但不为这些状态增加独立页签。
* 后端仍保留完整版本状态;readLibraryStatus 在这里将它们归入两个筛选组。
*
* 后端模板状态枚举(DRAFT / PENDING_REVIEW / APPROVED / PUBLISHED / DISABLED /
* ARCHIVED)在接口中保留,因此这里提供**折叠**:把原始状态压成两个筛选组。
* 反向映射(口径 → 后端)只保留「按状态过滤」这一处需要,见 toBackendStatusFilter。
*/
import type { DocumentRecord, DocumentStatus } from '@/api/management/types'
import type { TemplateVersionAction } from '@/api/management/documents'
/** 文档库页签与卡片上的状态,取值即显示文案 */
export type DocumentLibraryStatus = '启用中' | '停用'
/** 页签固定顺序:启用中排最前,停用排最后 */
export const DOCUMENT_LIBRARY_STATUSES: DocumentLibraryStatus[] = ['启用中', '停用']
/** 状态色调:决定徽标配色 */
export type DocumentStatusTone = 'enabled' | 'stopped'
const STATUS_TONES: Record<DocumentLibraryStatus, DocumentStatusTone> = {
启用中: 'enabled',
停用: 'stopped',
}
/** 状态徽标前的圆点颜色 */
export const DOCUMENT_STATUS_DOT: Record<DocumentStatusTone, string> = {
enabled: '#0f9d6c',
stopped: '#c0c8cd',
}
/**
* 后端原始状态 → 页面两档口径。
*
* 折叠规则只有一条:**能确定已下线的算「停用」,其余一律「启用中」**。
* - DISABLED / ARCHIVED 都是下线语义(前者可再启用,后者是终态),一并算「停用」;
* - DRAFT / PENDING_REVIEW / REJECTED / APPROVED / PUBLISHED 与未知取值都算「启用中」:
* 审核链路已废弃,新建的文书也直接按「启用中」处理(不再有草稿这一档)。
*
* 兜底取「启用中」而不是「停用」:口径只有两档时,把不认识的状态显示成「停用」
* 会让科室以为文书被下线了,而它其实只是状态取值没对齐——那是更坏的误报。
*/
export function readLibraryStatus(record: {
status: DocumentStatus
backendStatus?: string
}): DocumentLibraryStatus {
switch (record.backendStatus) {
case 'DISABLED':
case 'ARCHIVED':
return '停用'
case 'DRAFT':
case 'PENDING_REVIEW':
case 'REJECTED':
case 'APPROVED':
case 'PUBLISHED':
return '启用中'
default:
break
}
// 没有 backendStatus 的历史数据(演示文库、早期本地缓存)按归一后的状态反推
return record.status === 'archived' ? '停用' : '启用中'
}
export function readStatusTone(status: DocumentLibraryStatus): DocumentStatusTone {
return STATUS_TONES[status]
}
/**
* 状态页签 → 后端查询参数。
*
* 只用于「真实模式按状态向服务端过滤」;页面上默认仍是一次拉全量再本地过滤
* (口径折叠后一个页签对应多个后端状态,服务端做不到一次查全)。
* 后端接口重写后这里的取值要跟着改;改不动就返回 undefined,
* 调用方据此退回本地过滤,而不是拿一个错的状态去查。
*/
export function toBackendStatusFilter(status: DocumentLibraryStatus): string | undefined {
switch (status) {
case '启用中':
return 'PUBLISHED'
case '停用':
return 'DISABLED'
default:
return undefined
}
}
/** 只有「启用中」的文书能发起签署:停用已下线 */
export function canInitiateSigning(status: DocumentLibraryStatus): boolean {
return status === '启用中'
}
/**
* 后端版本状态对应的文书操作。DRAFT 和 DISABLED 使用 enable;APPROVED 使用 publish;
* 已发布版本使用 disable。审核中、驳回和归档状态不提供切换。
*/
export function templateWorkflowAction(
record: Pick<DocumentRecord, 'status' | 'backendStatus'>,
): TemplateVersionAction | null {
switch (record.backendStatus?.toUpperCase()) {
case 'DRAFT':
case 'DISABLED':
return 'enable'
case 'APPROVED':
return 'publish'
case 'PUBLISHED':
return 'disable'
case 'PENDING_REVIEW':
case 'REJECTED':
case 'ARCHIVED':
return null
default:
// 演示文库没有后端状态,仍按启用中 / 停用两档切换。
if (record.backendStatus) return null
return readLibraryStatus(record) === '停用' ? 'enable' : 'disable'
}
}
export function templateWorkflowLabel(
record: Pick<DocumentRecord, 'status' | 'backendStatus'>,
): string {
switch (record.backendStatus?.toUpperCase()) {
case 'DRAFT':
case 'APPROVED':
return '发布'
case 'DISABLED':
return '启用'
case 'PUBLISHED':
return '停用'
default:
return record.backendStatus
? ''
: readLibraryStatus(record) === '停用'
? '启用'
: '停用'
}
}
/**
* 文档归属:原型把「通用(全院)」当作科室清单里的一个选项一起勾选,
* 勾中它就等于全院通用,其余科室勾选一并作废(见 docDeptPicks / openDocProps)。
*/
export const GENERAL_OWNERSHIP = '通用(全院)'
/** 归属选项 → 后端可落库的科室 id(勾了通用(全院)就没有科室 id) */
export function resolveOwnershipDepartmentId(
ownership: string[],
departments: Array<{ id: string; name: string }>,
): string | null {
if (ownership.includes(GENERAL_OWNERSHIP)) {
return null
}
const first = ownership.find((name) => name !== GENERAL_OWNERSHIP)
return first ? (departments.find((department) => department.name === first)?.id ?? null) : null
}
/** 归属徽标文案:全院通用用 🌐,科室用 🏥(与原型 tpl-card 的标签一致) */
export function readOwnershipLabel(record: DocumentRecord): string {
if (!record.departmentId) {
return '🌐 全院通用'
}
const name = record.departmentName ?? '未知科室'
return `🏥 ${name}`
}
/** 归属是否为全院通用:卡片标签配色与归属勾选回填都要用同一个判据 */
export function isGeneralOwnership(record: DocumentRecord): boolean {
return !record.departmentId
}
/**
* 文档类型。
* 与原型 docTypes 同一份取值,属性弹窗用下拉而不是自由输入:
* 类型是分组的键,自由输入会让「知情同意书 / 知情同意书 」这类写法分成两组。
*/
export const DOCUMENT_TYPES = [
'知情同意书',
'风险告知书',
'入院告知',
'检查预约单',
'授权委托',
]
export const DEFAULT_DOCUMENT_TYPE = '知情同意书'