feat(documents): 文档归属按院区分组并改用科室 id 落库
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
import { computed, reactive, watch } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
import type { DepartmentRecord } from '@/api/management/types'
|
||||
import type { CampusRecord, DepartmentRecord } from '@/api/management/types'
|
||||
|
||||
import { DEFAULT_DOCUMENT_TYPE, DOCUMENT_TYPES, GENERAL_OWNERSHIP } from '../library'
|
||||
import { DOC_TEMPLATE_PERMISSIONS } from '../permissions'
|
||||
@@ -14,6 +14,8 @@ const props = defineProps<{
|
||||
template: DocumentTemplate | null
|
||||
/** 可归属的科室(真实模式取组织接口,演示模式取演示字典) */
|
||||
departments: DepartmentRecord[]
|
||||
/** 院区字典,与组织架构页同源;用来给上面的科室分组 */
|
||||
campuses: CampusRecord[]
|
||||
/**
|
||||
* 是否可以把文档设为「通用(全院)」。
|
||||
*
|
||||
@@ -54,19 +56,63 @@ const form = reactive<DocumentPropsForm>({
|
||||
description: '',
|
||||
})
|
||||
|
||||
/**
|
||||
* 归属勾选列表。
|
||||
* 顺序与原型 docDeptOpts 一致:科室名在前、「通用(全院)」在最后,
|
||||
* 勾了通用(全院)就等于全院可见,其余科室勾选不再参与落库。
|
||||
*/
|
||||
const ownershipOptions = computed(() => {
|
||||
const names = props.departments.map((department) => department.name)
|
||||
interface OwnershipOption {
|
||||
/** 落库值:科室取 DepartmentRecord.id,「通用(全院)」取固定哨兵 */
|
||||
value: string
|
||||
label: string
|
||||
}
|
||||
|
||||
return props.canSetGeneral ? [...names, GENERAL_OWNERSHIP] : names
|
||||
interface OwnershipGroup {
|
||||
key: string
|
||||
title: string
|
||||
options: OwnershipOption[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 归属勾选列表:**按院区分组**,一个院区一个 .ownership 容器。
|
||||
*
|
||||
* 组织架构里的科室本来就挂在院区下面(同名科室在不同院区是两条记录),
|
||||
* 只摊平显示名字的话既看不出属于哪个院区、勾了也定位不到唯一的科室 id,
|
||||
* 所以这里按科室的 campusId 归到对应院区下:显示院区名 + 科室名,取值用科室 id。
|
||||
* 「通用(全院)」不是科室、没有院区,单独放最后一组。
|
||||
*/
|
||||
const ownershipGroups = computed<OwnershipGroup[]>(() => {
|
||||
const groups: OwnershipGroup[] = []
|
||||
|
||||
for (const campus of props.campuses) {
|
||||
const options = props.departments
|
||||
.filter((department) => department.campusId === campus.id)
|
||||
.map((department) => ({ value: department.id, label: department.name }))
|
||||
|
||||
if (options.length) {
|
||||
groups.push({ key: campus.id, title: campus.name, options })
|
||||
}
|
||||
}
|
||||
|
||||
// 院区字典里没有的科室单独兜底成一组,否则这些科室在弹窗里直接没得勾
|
||||
const campusIds = new Set(props.campuses.map((campus) => campus.id))
|
||||
const unassigned = props.departments
|
||||
.filter((department) => !campusIds.has(department.campusId))
|
||||
.map((department) => ({ value: department.id, label: department.name }))
|
||||
|
||||
if (unassigned.length) {
|
||||
groups.push({ key: '__unassigned__', title: '未指定院区', options: unassigned })
|
||||
}
|
||||
|
||||
if (props.canSetGeneral) {
|
||||
groups.push({
|
||||
key: '__general__',
|
||||
title: '全院',
|
||||
options: [{ value: GENERAL_OWNERSHIP, label: GENERAL_OWNERSHIP }],
|
||||
})
|
||||
}
|
||||
|
||||
return groups
|
||||
})
|
||||
|
||||
const generalSelected = computed(() => form.ownership.includes(GENERAL_OWNERSHIP))
|
||||
|
||||
/** option 是勾选值:科室 id,或 GENERAL_OWNERSHIP */
|
||||
function toggleOwnership(option: string) {
|
||||
if (option === GENERAL_OWNERSHIP) {
|
||||
// 勾上「通用(全院)」就清掉科室勾选,取消则回到空选择——
|
||||
@@ -104,7 +150,8 @@ watch(
|
||||
versionNo: template?.version ?? 'v1.0.0',
|
||||
ownership: template
|
||||
? template.departmentId
|
||||
? [template.departmentName ?? ''].filter(Boolean)
|
||||
? // 回填主科室用 departmentId 本身:勾选值就是科室 id,不再经名字中转
|
||||
[template.departmentId]
|
||||
: [GENERAL_OWNERSHIP]
|
||||
: // 新增时预选当前用户所属科室(对得上就直接用,对不上就空着让科室自己勾)
|
||||
[],
|
||||
@@ -176,20 +223,23 @@ function submit() {
|
||||
|
||||
<div class="form-field span-2">
|
||||
<span>文档归属 <i>*</i></span>
|
||||
<div class="ownership">
|
||||
<label
|
||||
v-for="option in ownershipOptions"
|
||||
:key="option"
|
||||
class="ownership-option"
|
||||
:class="{ 'is-general': option === GENERAL_OWNERSHIP }"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
:checked="form.ownership.includes(option)"
|
||||
@change="toggleOwnership(option)"
|
||||
/>
|
||||
<span>{{ option }}</span>
|
||||
</label>
|
||||
<div v-for="group in ownershipGroups" :key="group.key" class="ownership-group">
|
||||
<p class="ownership-group-title">{{ group.title }}</p>
|
||||
<div class="ownership">
|
||||
<label
|
||||
v-for="option in group.options"
|
||||
:key="option.value"
|
||||
class="ownership-option"
|
||||
:class="{ 'is-general': option.value === GENERAL_OWNERSHIP }"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
:checked="form.ownership.includes(option.value)"
|
||||
@change="toggleOwnership(option.value)"
|
||||
/>
|
||||
<span>{{ option.label }}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<p class="field-tip">
|
||||
勾选科室设置可见范围,支持多科室与通用(全院)。勾选「通用(全院)」后各科室均可见。
|
||||
@@ -390,7 +440,21 @@ function submit() {
|
||||
* 容器是浅底带框的 3 列网格,每项一张白卡(原生 checkbox + 科室名),
|
||||
* 「通用(全院)」独占一行并用浅蓝底区分(原型 grid-column:1/-1)。
|
||||
* 科室名过长时截断:原型同一处就是 nowrap + ellipsis。
|
||||
*
|
||||
* 与原型唯一的差别:这里按院区分成若干个 .ownership(一个院区一个),
|
||||
* 每组上面带院区标题 —— 科室字典是多院区的,摊平成一列会分不出同名科室属于谁。
|
||||
*/
|
||||
.ownership-group + .ownership-group {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.ownership-group-title {
|
||||
margin: 0 0 6px;
|
||||
color: var(--brand-d);
|
||||
font-size: 11.5px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.ownership {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
|
||||
Reference in New Issue
Block a user