feat(documents): 支持全院通用和院区通用归属选择与展示

This commit is contained in:
xy
2026-10-07 19:22:34 +08:00
parent 46bbbfee06
commit 98c94ad3d6
8 changed files with 130 additions and 56 deletions
+7 -1
View File
@@ -107,7 +107,13 @@ function mapDocument(dto: TemplateResponseDto): DocumentRecord {
versionId, versionId,
currentVersionId: dto.currentVersionId ?? undefined, currentVersionId: dto.currentVersionId ?? undefined,
departmentId: dto.departmentId, departmentId: dto.departmentId,
departmentName: dto.departmentId ? undefined : '全院通用', ownershipScope:
dto.ownershipScope ?? (dto.departmentId ? 'DEPARTMENT' : dto.campusId ? 'CAMPUS' : 'GLOBAL'),
departmentName: dto.departmentId
? undefined
: dto.ownershipScope === 'GLOBAL'
? '全院通用'
: '院区通用',
campusId: dto.campusId, campusId: dto.campusId,
description: dto.description ?? '', description: dto.description ?? '',
// 后端补齐这两个字段后卡片会自动显示「检查类型 / 关联项目」; // 后端补齐这两个字段后卡片会自动显示「检查类型 / 关联项目」;
+7 -3
View File
@@ -10,6 +10,7 @@ export interface DocumentQuery extends PageQuery {
} }
export interface DocumentRecord { export interface DocumentRecord {
ownershipScope?: 'GLOBAL' | 'CAMPUS' | 'DEPARTMENT'
id: string id: string
name: string name: string
code?: string code?: string
@@ -75,11 +76,12 @@ export type BackendTemplateStatus =
| string | string
export interface TemplateResponseDto { export interface TemplateResponseDto {
ownershipScope?: 'GLOBAL' | 'CAMPUS' | 'DEPARTMENT'
id: string id: string
templateCode: string templateCode: string
name: string name: string
description?: string | null description?: string | null
campusId: string campusId: string | null
departmentId?: string | null departmentId?: string | null
category?: string | null category?: string | null
/** /**
@@ -131,20 +133,22 @@ export interface TemplateVersionResponseDto {
} }
export interface CreateTemplateRequest { export interface CreateTemplateRequest {
ownershipScope?: 'GLOBAL' | 'CAMPUS' | 'DEPARTMENT'
templateCode: string templateCode: string
name: string name: string
description?: string description?: string
campusId: string campusId: string | null
departmentId?: string | null departmentId?: string | null
category?: string category?: string
} }
export interface UpdateTemplateRequest { export interface UpdateTemplateRequest {
ownershipScope?: 'GLOBAL' | 'CAMPUS' | 'DEPARTMENT'
name: string name: string
description?: string description?: string
category?: string category?: string
/** 修改归属时提供院区;不传则保留原归属。 */ /** 修改归属时提供院区;不传则保留原归属。 */
campusId?: string campusId?: string | null
/** 提供院区时,null 表示该院区通用。 */ /** 提供院区时,null 表示该院区通用。 */
departmentId?: string | null departmentId?: string | null
} }
+6 -2
View File
@@ -780,9 +780,13 @@ function mapAvailableTemplate(dto: AvailableTemplateVersionResponseDto): Signing
name: dto.templateName, name: dto.templateName,
code: dto.templateCode, code: dto.templateCode,
version: dto.versionNo, version: dto.versionNo,
department: dto.departmentId ? '指定科室' : '全院通用', department: dto.departmentId
? '指定科室'
: dto.ownershipScope === 'GLOBAL'
? '全院通用'
: '院区通用',
departmentId: dto.departmentId, departmentId: dto.departmentId,
campusId: dto.campusId, campusId: dto.campusId ?? undefined,
category: dto.category || '未分类', category: dto.category || '未分类',
description: `已发布版本 ${dto.versionNo}`, description: `已发布版本 ${dto.versionNo}`,
// 可用模板接口不返回方式 ACL;四种方式都放行,实际允许范围由后端在创建时校验。 // 可用模板接口不返回方式 ACL;四种方式都放行,实际允许范围由后端在创建时校验。
+2 -1
View File
@@ -477,12 +477,13 @@ export interface VisitResponseDto {
} }
export interface AvailableTemplateVersionResponseDto { export interface AvailableTemplateVersionResponseDto {
ownershipScope?: 'GLOBAL' | 'CAMPUS' | 'DEPARTMENT'
templateId: string templateId: string
templateVersionId: string templateVersionId: string
templateCode: string templateCode: string
templateName: string templateName: string
category: string category: string
campusId: string campusId: string | null
departmentId: string | null departmentId: string | null
versionNo: string versionNo: string
contentSha256: string contentSha256: string
@@ -4,7 +4,14 @@ import { ElMessage } from 'element-plus'
import type { CampusRecord, DepartmentRecord } from '@/api/management/types' import type { CampusRecord, DepartmentRecord } from '@/api/management/types'
import { DEFAULT_DOCUMENT_TYPE, DOCUMENT_TYPES, GENERAL_OWNERSHIP } from '../library' import {
DEFAULT_DOCUMENT_TYPE,
DOCUMENT_TYPES,
GENERAL_OWNERSHIP,
campusOwnership,
isGlobalOwnership,
ownershipCampusId,
} from '../library'
import { DOC_TEMPLATE_PERMISSIONS } from '../permissions' import { DOC_TEMPLATE_PERMISSIONS } from '../permissions'
import type { DocumentPropsForm, DocumentTemplate } from '../types' import type { DocumentPropsForm, DocumentTemplate } from '../types'
@@ -17,7 +24,7 @@ const props = defineProps<{
/** 院区字典,与组织架构页同源;用来给上面的科室分组 */ /** 院区字典,与组织架构页同源;用来给上面的科室分组 */
campuses: CampusRecord[] campuses: CampusRecord[]
/** /**
* 是否可以把文档设为「通用(全院)」。 * 是否可以把文档设为「全院通用」。
* *
* 原型 canSetGeneral() 只放给系统管理员 / 医务管理;这里由页面判定后传进来, * 原型 canSetGeneral() 只放给系统管理员 / 医务管理;这里由页面判定后传进来,
* 弹窗不自己去读角色——弹窗只负责表单。 * 弹窗不自己去读角色——弹窗只负责表单。
@@ -57,7 +64,7 @@ const form = reactive<DocumentPropsForm>({
}) })
interface OwnershipOption { interface OwnershipOption {
/** 落库值:科室取 DepartmentRecord.id,「通用(全院)」取固定哨兵 */ /** 落库值:科室取 DepartmentRecord.id,「全院通用」取固定哨兵 */
value: string value: string
label: string label: string
} }
@@ -74,7 +81,7 @@ interface OwnershipGroup {
* 组织架构里的科室本来就挂在院区下面(同名科室在不同院区是两条记录), * 组织架构里的科室本来就挂在院区下面(同名科室在不同院区是两条记录),
* 只摊平显示名字的话既看不出属于哪个院区、勾了也定位不到唯一的科室 id, * 只摊平显示名字的话既看不出属于哪个院区、勾了也定位不到唯一的科室 id,
* 所以这里按科室的 campusId 归到对应院区下:显示院区名 + 科室名,取值用科室 id。 * 所以这里按科室的 campusId 归到对应院区下:显示院区名 + 科室名,取值用科室 id。
* 「通用(全院)」不是科室、没有院区,单独放最后一组。 * 「全院通用」不是科室、没有院区,单独放最后一组。
*/ */
const ownershipGroups = computed<OwnershipGroup[]>(() => { const ownershipGroups = computed<OwnershipGroup[]>(() => {
const groups: OwnershipGroup[] = [] const groups: OwnershipGroup[] = []
@@ -84,6 +91,8 @@ const ownershipGroups = computed<OwnershipGroup[]>(() => {
.filter((department) => department.campusId === campus.id) .filter((department) => department.campusId === campus.id)
.map((department) => ({ value: department.id, label: department.name })) .map((department) => ({ value: department.id, label: department.name }))
if (props.canSetGeneral)
options.unshift({ value: campusOwnership(campus.id), label: '院区通用' })
if (options.length) { if (options.length) {
groups.push({ key: campus.id, title: campus.name, options }) groups.push({ key: campus.id, title: campus.name, options })
} }
@@ -114,14 +123,18 @@ const generalSelected = computed(() => form.ownership.includes(GENERAL_OWNERSHIP
/** option 是勾选值:科室 id,或 GENERAL_OWNERSHIP */ /** option 是勾选值:科室 id,或 GENERAL_OWNERSHIP */
function toggleOwnership(option: string) { function toggleOwnership(option: string) {
if (option.startsWith('__campus_common__:')) {
form.ownership = form.ownership.includes(option) ? [] : [option]
return
}
if (option === GENERAL_OWNERSHIP) { if (option === GENERAL_OWNERSHIP) {
// 勾上「通用(全院)」就清掉科室勾选,取消则回到空选择—— // 勾上「全院通用」就清掉科室勾选,取消则回到空选择——
// 两种选择混在一起会让「到底归属哪儿」没有唯一答案 // 两种选择混在一起会让「到底归属哪儿」没有唯一答案
form.ownership = generalSelected.value ? [] : [GENERAL_OWNERSHIP] form.ownership = generalSelected.value ? [] : [GENERAL_OWNERSHIP]
return return
} }
if (generalSelected.value) { if (generalSelected.value || ownershipCampusId(form.ownership)) {
form.ownership = [] form.ownership = []
} }
@@ -157,7 +170,9 @@ watch(
? template.departmentId ? template.departmentId
? // 回填主科室用 departmentId 本身:勾选值就是科室 id,不再经名字中转 ? // 回填主科室用 departmentId 本身:勾选值就是科室 id,不再经名字中转
[template.departmentId] [template.departmentId]
: [GENERAL_OWNERSHIP] : isGlobalOwnership(template)
? [GENERAL_OWNERSHIP]
: [campusOwnership(template.campusId ?? '')]
: // 新增时预选当前用户所属科室(对得上就直接用,对不上就空着让科室自己勾) : // 新增时预选当前用户所属科室(对得上就直接用,对不上就空着让科室自己勾)
[], [],
description: template?.description ?? '', description: template?.description ?? '',
@@ -251,11 +266,9 @@ function submit() {
</div> </div>
</div> </div>
<p class="field-tip"> <p class="field-tip">
<template v-if="isMock"> <template v-if="isMock"> 勾选科室设置可见范围,支持多科室与全院通用。 </template>
勾选科室设置可见范围,支持多科室与通用(全院)。
</template>
<template v-else> <template v-else>
选择一个归属科室,或选择「通用(全院)」供文档所属院区使用。归属仍受账号权限限制。 全院通用可供所有院区使用;院区通用仅供对应院区使用;也可选择一个专用科室。查看和维护仍受账号权限限制。
</template> </template>
</p> </p>
</div> </div>
@@ -448,7 +461,7 @@ function submit() {
/* /*
* 文档归属:原型 V10.2 的 .cg-dept —— 卡片式复选框网格。 * 文档归属:原型 V10.2 的 .cg-dept —— 卡片式复选框网格。
* 容器是浅底带框的 3 列网格,每项一张白卡(原生 checkbox + 科室名), * 容器是浅底带框的 3 列网格,每项一张白卡(原生 checkbox + 科室名),
* 「通用(全院)」独占一行并用浅蓝底区分(原型 grid-column:1/-1)。 * 「全院通用」独占一行并用浅蓝底区分(原型 grid-column:1/-1)。
* 科室名过长时截断:原型同一处就是 nowrap + ellipsis。 * 科室名过长时截断:原型同一处就是 nowrap + ellipsis。
* *
* 与原型唯一的差别:这里按院区分成若干个 .ownership(一个院区一个), * 与原型唯一的差别:这里按院区分成若干个 .ownership(一个院区一个),
@@ -49,7 +49,11 @@ const dotColor = computed(() => DOCUMENT_STATUS_DOT[tone.value])
const isGeneral = computed(() => isGeneralOwnership(props.template)) const isGeneral = computed(() => isGeneralOwnership(props.template))
const ownershipLabel = computed(() => const ownershipLabel = computed(() =>
isGeneral.value ? '🌐 全院通用' : `🏥 ${props.template.departmentName ?? '未知科室'}`, isGeneral.value
? props.template.ownershipScope === 'GLOBAL' || !props.template.campusId
? '🌐 全院通用'
: `🏥 ${props.template.campusName ?? '所属院区'} · 院区通用`
: `🏥 ${props.template.departmentName ?? '未知科室'}`,
) )
/** /**
@@ -91,9 +95,7 @@ const toggleAction = computed<TemplateVersionAction | null>(() =>
// 按钮文案与权限码的对应关系集中在模板里,避免多处各写一份 // 按钮文案与权限码的对应关系集中在模板里,避免多处各写一份
const permissions = DOC_TEMPLATE_PERMISSIONS const permissions = DOC_TEMPLATE_PERMISSIONS
const togglePermission = computed(() => const togglePermission = computed(() => workflowPermission(toggleAction.value ?? 'disable'))
workflowPermission(toggleAction.value ?? 'disable'),
)
</script> </script>
<template> <template>
@@ -110,7 +112,8 @@ const togglePermission = computed(() =>
<div class="tpl-tags"> <div class="tpl-tags">
<span class="exam-tag" :class="isGeneral ? 'is-general' : 'is-department'"> <span class="exam-tag" :class="isGeneral ? 'is-general' : 'is-department'">
{{ ownershipLabel }}<template v-if="!isGeneral && sharedCount"> ·+{{ sharedCount }} 科室</template> {{ ownershipLabel
}}<template v-if="!isGeneral && sharedCount"> ·+{{ sharedCount }} 科室</template>
</span> </span>
<span v-if="examType" class="exam-tag is-exam">🔬 检查类型:{{ examType }}</span> <span v-if="examType" class="exam-tag is-exam">🔬 检查类型:{{ examType }}</span>
</div> </div>
@@ -42,6 +42,9 @@ import {
canInitiateSigning, canInitiateSigning,
DOCUMENT_LIBRARY_STATUSES, DOCUMENT_LIBRARY_STATUSES,
GENERAL_OWNERSHIP, GENERAL_OWNERSHIP,
ownershipCampusId,
isGlobalOwnership,
CAMPUS_OWNERSHIP_PREFIX,
readLibraryStatus, readLibraryStatus,
resolveOwnershipDepartmentId, resolveOwnershipDepartmentId,
templateWorkflowAction, templateWorkflowAction,
@@ -79,6 +82,7 @@ const useMockLibrary = mockFlags.documents
/** 没有绑定科室的文书归到这一组(全院通用),不属于任何一个科室页签 */ /** 没有绑定科室的文书归到这一组(全院通用),不属于任何一个科室页签 */
const GENERAL_GROUP_KEY = '__all__' const GENERAL_GROUP_KEY = '__all__'
const CAMPUS_GROUP_KEY = '__campus_common__'
/** /**
* 页面操作的服务端校验兜底。 * 页面操作的服务端校验兜底。
@@ -211,12 +215,16 @@ const departmentTabs = computed<DepartmentTab[]>(() => {
const knownKeys = new Set(campusDepartments.map((department) => department.id)) const knownKeys = new Set(campusDepartments.map((department) => department.id))
const orphans = library.value.filter( const orphans = library.value.filter(
(group) => group.key !== GENERAL_GROUP_KEY && !knownKeys.has(group.key), (group) =>
group.key !== GENERAL_GROUP_KEY &&
group.key !== CAMPUS_GROUP_KEY &&
!knownKeys.has(group.key),
) )
return [ return [
{ key: null, label: '全部', count: allTemplates.value.length }, { key: null, label: '全部', count: allTemplates.value.length },
{ key: GENERAL_GROUP_KEY, label: '全院通用', count: countOf(GENERAL_GROUP_KEY) }, { key: GENERAL_GROUP_KEY, label: '全院通用', count: countOf(GENERAL_GROUP_KEY) },
{ key: CAMPUS_GROUP_KEY, label: '院区通用', count: countOf(CAMPUS_GROUP_KEY) },
...campusDepartments.map((department) => ({ ...campusDepartments.map((department) => ({
key: department.id, key: department.id,
label: allCampusesSelected.value label: allCampusesSelected.value
@@ -282,7 +290,7 @@ function cloneLibrary(source: DocumentDepartment[]): DocumentDepartment[] {
* 把扁平的模板列表组织成页面需要的 科室 → 分类 → 文书 树。 * 把扁平的模板列表组织成页面需要的 科室 → 分类 → 文书 树。
* *
* 分组键使用 departmentId,并用组织接口返回的科室字典补齐名称;没有绑定科室的模板 * 分组键使用 departmentId,并用组织接口返回的科室字典补齐名称;没有绑定科室的模板
* 归入“全院通用”。这样同一科室的模板无论接口返回顺序如何都会落进同一个分组。 * 按明确归属范围分别归入“全院通用”或“院区通用”。同一科室的模板落入同一分组。
*/ */
function groupDocuments( function groupDocuments(
records: DocumentRecord[], records: DocumentRecord[],
@@ -294,10 +302,15 @@ function groupDocuments(
) )
records.forEach((record) => { records.forEach((record) => {
const departmentKey = record.departmentId ?? GENERAL_GROUP_KEY const departmentKey =
record.departmentId ?? (isGlobalOwnership(record) ? GENERAL_GROUP_KEY : CAMPUS_GROUP_KEY)
const departmentName = const departmentName =
record.departmentName ?? record.departmentName ??
(record.departmentId ? (departmentNames.get(record.departmentId) ?? '未知科室') : '全院通用') (record.departmentId
? (departmentNames.get(record.departmentId) ?? '未知科室')
: isGlobalOwnership(record)
? '全院通用'
: '院区通用')
let department = grouped.get(departmentKey) let department = grouped.get(departmentKey)
@@ -314,7 +327,11 @@ function groupDocuments(
department.categories.push(category) department.categories.push(category)
} }
category.documents.push({ ...record, departmentName }) category.documents.push({
...record,
departmentName,
campusName: campuses.value.find((campus) => campus.id === record.campusId)?.name,
})
}) })
// 全院通用的模板排最前,其余按科室名排序,保证每次进页面分组顺序稳定 // 全院通用的模板排最前,其余按科室名排序,保证每次进页面分组顺序稳定
@@ -539,7 +556,12 @@ function generateTemplateCode(name: string) {
*/ */
function sharedDepartmentNames(ownership: string[], primaryDepartmentId: string | null): string[] { function sharedDepartmentNames(ownership: string[], primaryDepartmentId: string | null): string[] {
return ownership return ownership
.filter((value) => value !== GENERAL_OWNERSHIP && value !== primaryDepartmentId) .filter(
(value) =>
value !== GENERAL_OWNERSHIP &&
!value.startsWith(CAMPUS_OWNERSHIP_PREFIX) &&
value !== primaryDepartmentId,
)
.map((id) => departments.value.find((department) => department.id === id)?.name) .map((id) => departments.value.find((department) => department.id === id)?.name)
.filter((name): name is string => Boolean(name)) .filter((name): name is string => Boolean(name))
} }
@@ -567,9 +589,11 @@ function locateLocalDocument(id: string) {
/** 演示模式:把新文书追加进本地文库(分组按科室名匹配已有分组) */ /** 演示模式:把新文书追加进本地文库(分组按科室名匹配已有分组) */
function addLocalTemplate(form: DocumentPropsForm, departmentId: string | null): DocumentTemplate { function addLocalTemplate(form: DocumentPropsForm, departmentId: string | null): DocumentTemplate {
const department = departments.value.find((item) => item.id === departmentId) const department = departments.value.find((item) => item.id === departmentId)
const departmentName = department?.name ?? '全院通用' const global = form.ownership.includes(GENERAL_OWNERSHIP)
const campusId = global ? null : department?.campusId || ownershipCampusId(form.ownership)
const departmentName = department?.name ?? (global ? '全院通用' : '院区通用')
// 真实模式用 departmentId 当分组键,演示模式没有 UUID,用品名保持同样语义 // 真实模式用 departmentId 当分组键,演示模式没有 UUID,用品名保持同样语义
const departmentKey = department?.id ?? GENERAL_GROUP_KEY const departmentKey = department?.id ?? (global ? GENERAL_GROUP_KEY : CAMPUS_GROUP_KEY)
let departmentGroup = library.value.find((item) => item.key === departmentKey) let departmentGroup = library.value.find((item) => item.key === departmentKey)
if (!departmentGroup) { if (!departmentGroup) {
@@ -607,7 +631,9 @@ function addLocalTemplate(form: DocumentPropsForm, departmentId: string | null):
versionId: `local-version-${timestamp}`, versionId: `local-version-${timestamp}`,
departmentId: departmentId, departmentId: departmentId,
departmentName, departmentName,
campusId: campuses.value[0]?.id ?? '', campusId,
ownershipScope: global ? 'GLOBAL' : departmentId ? 'DEPARTMENT' : 'CAMPUS',
campusName: campuses.value.find((campus) => campus.id === campusId)?.name,
contentHtml: '', contentHtml: '',
sharedDepartments: sharedDepartmentNames(form.ownership, departmentId), sharedDepartments: sharedDepartmentNames(form.ownership, departmentId),
} }
@@ -626,9 +652,11 @@ function addLocalTemplate(form: DocumentPropsForm, departmentId: string | null):
*/ */
function updateLocalProps(form: DocumentPropsForm, departmentId: string | null) { function updateLocalProps(form: DocumentPropsForm, departmentId: string | null) {
const target = departments.value.find((item) => item.id === departmentId) const target = departments.value.find((item) => item.id === departmentId)
const targetName = target?.name ?? '全院通用' const global = form.ownership.includes(GENERAL_OWNERSHIP)
const campusId = global ? null : target?.campusId || ownershipCampusId(form.ownership)
const targetName = target?.name ?? (global ? '全院通用' : '院区通用')
// 与 addLocalTemplate 同一套分组键口径:演示模式没有 UUID 时落 GENERAL_GROUP_KEY // 与 addLocalTemplate 同一套分组键口径:演示模式没有 UUID 时落 GENERAL_GROUP_KEY
const targetKey = target?.id ?? GENERAL_GROUP_KEY const targetKey = target?.id ?? (global ? GENERAL_GROUP_KEY : CAMPUS_GROUP_KEY)
const located = locateLocalDocument(form.id ?? '') const located = locateLocalDocument(form.id ?? '')
if (!located) { if (!located) {
@@ -644,6 +672,9 @@ function updateLocalProps(form: DocumentPropsForm, departmentId: string | null)
document.updatedAt = new Date().toISOString() document.updatedAt = new Date().toISOString()
document.departmentId = departmentId document.departmentId = departmentId
document.departmentName = targetName document.departmentName = targetName
document.campusId = campusId
document.campusName = campuses.value.find((campus) => campus.id === campusId)?.name
document.ownershipScope = global ? 'GLOBAL' : departmentId ? 'DEPARTMENT' : 'CAMPUS'
// 主科室进 departmentId,其余勾选科室留在 sharedDepartments(与新建时同一口径) // 主科室进 departmentId,其余勾选科室留在 sharedDepartments(与新建时同一口径)
document.sharedDepartments = sharedDepartmentNames(form.ownership, departmentId) document.sharedDepartments = sharedDepartmentNames(form.ownership, departmentId)
@@ -705,10 +736,10 @@ async function handlePropsSubmit(form: DocumentPropsForm) {
ElMessage.error('所选科室不存在,请刷新后重试') ElMessage.error('所选科室不存在,请刷新后重试')
return return
} }
const campusId = const global = form.ownership.includes(GENERAL_OWNERSHIP)
targetDepartment?.campusId || const campusId = global ? null : targetDepartment?.campusId || ownershipCampusId(form.ownership)
(form.id ? propsTemplate.value?.campusId : appStore.selectedCampusId || campuses.value[0]?.id) const ownershipScope = global ? 'GLOBAL' : departmentId ? 'DEPARTMENT' : 'CAMPUS'
if (!campusId) { if (!global && !campusId) {
ElMessage.error('无法确定文档所属院区,请选择院区后重试') ElMessage.error('无法确定文档所属院区,请选择院区后重试')
return return
} }
@@ -719,6 +750,7 @@ async function handlePropsSubmit(form: DocumentPropsForm) {
category: form.category, category: form.category,
campusId, campusId,
departmentId, departmentId,
ownershipScope,
}) })
closePropsDialog() closePropsDialog()
await loadLibrary() await loadLibrary()
@@ -732,6 +764,7 @@ async function handlePropsSubmit(form: DocumentPropsForm) {
description: form.description, description: form.description,
campusId, campusId,
departmentId, departmentId,
ownershipScope,
category: form.category, category: form.category,
}) })
@@ -131,22 +131,32 @@ export function templateWorkflowLabel(
case 'PUBLISHED': case 'PUBLISHED':
return '停用' return '停用'
default: default:
return record.backendStatus return record.backendStatus ? '' : readLibraryStatus(record) === '停用' ? '启用' : '停用'
? ''
: readLibraryStatus(record) === '停用'
? '启用'
: '停用'
} }
} }
/** /**
* 文档归属:原型把「通用(全院)」当作科室清单里的一个选项一起勾选, * 文档归属:原型把「全院通用」当作科室清单里的一个选项一起勾选,
* 勾中它就等于全院通用,其余科室勾选一并作废(见 docDeptPicks / openDocProps)。 * 勾中它就等于全院通用,其余科室勾选一并作废(见 docDeptPicks / openDocProps)。
*/ */
export const GENERAL_OWNERSHIP = '通用(全院)' export const GENERAL_OWNERSHIP = '全院通用'
export const CAMPUS_OWNERSHIP_PREFIX = '__campus_common__:'
export function campusOwnership(campusId: string): string {
return `${CAMPUS_OWNERSHIP_PREFIX}${campusId}`
}
export function ownershipCampusId(ownership: string[]): string | null {
const value = ownership.find((item) => item.startsWith(CAMPUS_OWNERSHIP_PREFIX))
return value ? value.slice(CAMPUS_OWNERSHIP_PREFIX.length) : null
}
export function isGlobalOwnership(record: DocumentRecord): boolean {
return (
record.ownershipScope === 'GLOBAL' ||
(!record.ownershipScope && !record.campusId && !record.departmentId)
)
}
/** /**
* 归属勾选 → 后端可落库的科室 id(勾了通用(全院)就没有科室 id)。 * 归属勾选 → 后端可落库的科室 id(勾了全院通用就没有科室 id)。
* *
* 勾选值本身就是 DepartmentRecord.id:同名科室在不同院区是两条记录, * 勾选值本身就是 DepartmentRecord.id:同名科室在不同院区是两条记录,
* 这里不再拿名字去反查(反查只能取到第一条,会把院区指错)。 * 这里不再拿名字去反查(反查只能取到第一条,会把院区指错)。
@@ -156,13 +166,19 @@ export function resolveOwnershipDepartmentId(ownership: string[]): string | null
return null return null
} }
return ownership.find((value) => value !== GENERAL_OWNERSHIP) ?? null return (
ownership.find(
(value) => value !== GENERAL_OWNERSHIP && !value.startsWith(CAMPUS_OWNERSHIP_PREFIX),
) ?? null
)
} }
/** 归属徽标文案:全院通用用 🌐,科室用 🏥(与原型 tpl-card 的标签一致) */ /** 归属徽标文案:全院通用用 🌐,科室用 🏥(与原型 tpl-card 的标签一致) */
export function readOwnershipLabel(record: DocumentRecord): string { export function readOwnershipLabel(record: DocumentRecord): string {
if (!record.departmentId) { if (!record.departmentId) {
return '🌐 全院通用' return isGlobalOwnership(record)
? '🌐 全院通用'
: `🏥 ${record.campusName ?? '所属院区'} · 院区通用`
} }
const name = record.departmentName ?? '未知科室' const name = record.departmentName ?? '未知科室'
@@ -180,12 +196,6 @@ export function isGeneralOwnership(record: DocumentRecord): boolean {
* 与原型 docTypes 同一份取值,属性弹窗用下拉而不是自由输入: * 与原型 docTypes 同一份取值,属性弹窗用下拉而不是自由输入:
* 类型是分组的键,自由输入会让「知情同意书 / 知情同意书 」这类写法分成两组。 * 类型是分组的键,自由输入会让「知情同意书 / 知情同意书 」这类写法分成两组。
*/ */
export const DOCUMENT_TYPES = [ export const DOCUMENT_TYPES = ['知情同意书', '风险告知书', '入院告知', '检查预约单', '授权委托']
'知情同意书',
'风险告知书',
'入院告知',
'检查预约单',
'授权委托',
]
export const DEFAULT_DOCUMENT_TYPE = '知情同意书' export const DEFAULT_DOCUMENT_TYPE = '知情同意书'