192 lines
6.6 KiB
TypeScript
192 lines
6.6 KiB
TypeScript
/**
|
||
* 文档库的展示口径:状态、归属、文档类型。
|
||
*
|
||
* 状态筛选只有**两组**:启用中 / 停用(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 = '知情同意书'
|