fix(documents): 保存文档归属并支持所有院区筛选
This commit is contained in:
@@ -218,7 +218,7 @@ API 模块与页面按业务域对应。工作台页面使用 `api/workbench`
|
|||||||
- `GET /api/v1/sign-artifacts/{artifactId}/download`:原始 PDF、签署后 PDF、签名原图下载;
|
- `GET /api/v1/sign-artifacts/{artifactId}/download`:原始 PDF、签署后 PDF、签名原图下载;
|
||||||
- `POST /api/v1/sign-deliveries/{taskId}/sms/resend`:短信重发,自动携带幂等键;
|
- `POST /api/v1/sign-deliveries/{taskId}/sms/resend`:短信重发,自动携带幂等键;
|
||||||
- `GET/POST /api/v1/templates`、`GET /api/v1/templates/{id}`:模板列表、详情;
|
- `GET/POST /api/v1/templates`、`GET /api/v1/templates/{id}`:模板列表、详情;
|
||||||
- `PUT /api/v1/templates/{id}`:更新模板元数据;
|
- `PUT /api/v1/templates/{id}`:更新模板名称、说明、分类及归属。修改归属时提交 `campusId` 与 `departmentId`;科室为空表示该院区通用,不提交院区则保留原归属。真实模式只支持一个归属科室,选择科室时使用该科室的院区;编辑为通用时保留文档原院区。后端校验目标组织状态、院区匹配及数据权限,记录归属变更审计,保留历史签署快照;
|
||||||
- `GET/POST /api/v1/templates/{id}/versions`、`GET /api/v1/templates/{id}/versions/{versionId}`:版本列表、创建与版本详情(**正文 `contentHtml` 只在这个详情接口里返回**);
|
- `GET/POST /api/v1/templates/{id}/versions`、`GET /api/v1/templates/{id}/versions/{versionId}`:版本列表、创建与版本详情(**正文 `contentHtml` 只在这个详情接口里返回**);
|
||||||
- `POST /api/v1/templates/{id}/versions/{versionId}/{action}`(submit-review / reject / approve / publish / disable / archive):版本工作流,模板「删除」即走 archive;
|
- `POST /api/v1/templates/{id}/versions/{versionId}/{action}`(submit-review / reject / approve / publish / disable / archive):版本工作流,模板「删除」即走 archive;
|
||||||
- `GET /api/v1/users`、`POST /api/v1/users`、`GET/PUT /api/v1/users/{id}`:员工列表、资料创建和资料更新;
|
- `GET /api/v1/users`、`POST /api/v1/users`、`GET/PUT /api/v1/users/{id}`:员工列表、资料创建和资料更新;
|
||||||
@@ -243,6 +243,8 @@ API 模块与页面按业务域对应。工作台页面使用 `api/workbench`
|
|||||||
|
|
||||||
## 签署记录查询
|
## 签署记录查询
|
||||||
|
|
||||||
|
文档库院区筛选支持「所有院区」:列表查询省略 `campusId`,由后端按当前账号的角色数据范围过滤;科室标签显示院区和科室名称。此选项只影响文档库查询,全局院区及新增通用文档的目标院区仍使用具体院区,编辑通用文档仍保留原院区。
|
||||||
|
|
||||||
`views/workbench/records` 是「工作台 → 签署记录查询」(`/sign/records`,菜单资源 `sign/record/index`)的实现:工作台只保留当天的签署操作,历史记录的检索、核对与导出统一放在这里。页面只读——已签署的正式文书不可直接修改,需要追加内容时回签署工作台新建签署任务。
|
`views/workbench/records` 是「工作台 → 签署记录查询」(`/sign/records`,菜单资源 `sign/record/index`)的实现:工作台只保留当天的签署操作,历史记录的检索、核对与导出统一放在这里。页面只读——已签署的正式文书不可直接修改,需要追加内容时回签署工作台新建签署任务。
|
||||||
|
|
||||||
**接口现状与边界**(后端还没有「按条件检索历史签署记录」的专用接口):
|
**接口现状与边界**(后端还没有「按条件检索历史签署记录」的专用接口):
|
||||||
|
|||||||
@@ -143,6 +143,10 @@ export interface UpdateTemplateRequest {
|
|||||||
name: string
|
name: string
|
||||||
description?: string
|
description?: string
|
||||||
category?: string
|
category?: string
|
||||||
|
/** 修改归属时提供院区;不传则保留原归属。 */
|
||||||
|
campusId?: string
|
||||||
|
/** 提供院区时,null 表示该院区通用。 */
|
||||||
|
departmentId?: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CreateTemplateVersionRequest {
|
export interface CreateTemplateVersionRequest {
|
||||||
|
|||||||
@@ -4,8 +4,7 @@
|
|||||||
*
|
*
|
||||||
* 原型 V10.2 只有「科室 + 状态」两行(#libTabs / #libStatus)。这里把科室那一级按
|
* 原型 V10.2 只有「科室 + 状态」两行(#libTabs / #libStatus)。这里把科室那一级按
|
||||||
* 「组织架构」的口径拆成两级:先选院区(同一份院区字典、同一个 sortNo 顺序,
|
* 「组织架构」的口径拆成两级:先选院区(同一份院区字典、同一个 sortNo 顺序,
|
||||||
* 与架构树的院区顺序一致),再在该院区的科室里筛。院区不做「全部院区」——
|
* 与架构树的院区顺序一致),再按科室筛选。「所有院区」跨院区查询,科室显示院区名。
|
||||||
* 架构树里也始终落在某一个院区上,两处口径保持一致。
|
|
||||||
*
|
*
|
||||||
* 类名沿用原型的 lib-tabs / lib-tab / lib-status / lib-st:这套样式是文档库页面独有的
|
* 类名沿用原型的 lib-tabs / lib-tab / lib-status / lib-st:这套样式是文档库页面独有的
|
||||||
* 筛选语言(胶囊 + 虚线分隔),与通用 Tabs 组件的观感不同,换成通用组件会把
|
* 筛选语言(胶囊 + 虚线分隔),与通用 Tabs 组件的观感不同,换成通用组件会把
|
||||||
@@ -16,7 +15,7 @@
|
|||||||
import type { CampusTab, DepartmentTab, DocumentFilterStatus, StatusTab } from '../types'
|
import type { CampusTab, DepartmentTab, DocumentFilterStatus, StatusTab } from '../types'
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
/** 当前院区 id。院区是页面级的取数口径,由页面持有(见 index.vue) */
|
/** 当前院区 id;空字符串表示所有院区,由页面持有查询状态。 */
|
||||||
campus: string
|
campus: string
|
||||||
department: string | null
|
department: string | null
|
||||||
status: DocumentFilterStatus
|
status: DocumentFilterStatus
|
||||||
|
|||||||
@@ -125,6 +125,11 @@ function toggleOwnership(option: string) {
|
|||||||
form.ownership = []
|
form.ownership = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!props.isMock) {
|
||||||
|
form.ownership = form.ownership.includes(option) ? [] : [option]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const index = form.ownership.indexOf(option)
|
const index = form.ownership.indexOf(option)
|
||||||
|
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
@@ -205,7 +210,11 @@ function submit() {
|
|||||||
<div class="form-grid">
|
<div class="form-grid">
|
||||||
<label class="form-field span-2">
|
<label class="form-field span-2">
|
||||||
<span>文书名称 <i>*</i></span>
|
<span>文书名称 <i>*</i></span>
|
||||||
<input v-model="form.name" type="text" placeholder="例:麻醉药品、精神药品知情同意书" />
|
<input
|
||||||
|
v-model="form.name"
|
||||||
|
type="text"
|
||||||
|
placeholder="例:麻醉药品、精神药品知情同意书"
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="form-field">
|
<label class="form-field">
|
||||||
@@ -242,17 +251,18 @@ function submit() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="field-tip">
|
<p class="field-tip">
|
||||||
勾选科室设置可见范围,支持多科室与通用(全院)。勾选「通用(全院)」后各科室均可见。
|
<template v-if="isMock">
|
||||||
|
勾选科室设置可见范围,支持多科室与通用(全院)。
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
选择一个归属科室,或选择「通用(全院)」供文档所属院区使用。归属仍受账号权限限制。
|
||||||
|
</template>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label class="form-field span-2">
|
<label class="form-field span-2">
|
||||||
<span>文书说明</span>
|
<span>文书说明</span>
|
||||||
<textarea
|
<textarea v-model="form.description" rows="2" placeholder="显示在文书卡片上的简介" />
|
||||||
v-model="form.description"
|
|
||||||
rows="2"
|
|
||||||
placeholder="显示在文书卡片上的简介"
|
|
||||||
/>
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -265,11 +275,11 @@ function submit() {
|
|||||||
: '属性与正文分开维护:此处只修改文档基本信息与归属;正文请在文档卡片点「编辑正文」。'
|
: '属性与正文分开维护:此处只修改文档基本信息与归属;正文请在文档卡片点「编辑正文」。'
|
||||||
}}
|
}}
|
||||||
</p>
|
</p>
|
||||||
<button type="button" class="footer-button secondary" @click="emit('close')">
|
<button type="button" class="footer-button secondary" @click="emit('close')">取消</button>
|
||||||
取消
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
v-permission.disable="isCreate ? DOC_TEMPLATE_PERMISSIONS.create : DOC_TEMPLATE_PERMISSIONS.props"
|
v-permission.disable="
|
||||||
|
isCreate ? DOC_TEMPLATE_PERMISSIONS.create : DOC_TEMPLATE_PERMISSIONS.props
|
||||||
|
"
|
||||||
type="button"
|
type="button"
|
||||||
class="footer-button primary"
|
class="footer-button primary"
|
||||||
:disabled="saving"
|
:disabled="saving"
|
||||||
|
|||||||
@@ -111,6 +111,8 @@ const libraryError = ref('')
|
|||||||
const library = ref<DocumentDepartment[]>([])
|
const library = ref<DocumentDepartment[]>([])
|
||||||
const campuses = ref<CampusRecord[]>([])
|
const campuses = ref<CampusRecord[]>([])
|
||||||
const departments = ref<DepartmentRecord[]>([])
|
const departments = ref<DepartmentRecord[]>([])
|
||||||
|
const allCampusesSelected = ref(false)
|
||||||
|
const libraryCampusId = computed(() => (allCampusesSelected.value ? '' : appStore.selectedCampusId))
|
||||||
|
|
||||||
const filters = reactive<DocumentFilterForm>({
|
const filters = reactive<DocumentFilterForm>({
|
||||||
keyword: '',
|
keyword: '',
|
||||||
@@ -169,13 +171,16 @@ const allTemplates = computed<DocumentTemplate[]>(() =>
|
|||||||
const campusTabs = computed<CampusTab[]>(() =>
|
const campusTabs = computed<CampusTab[]>(() =>
|
||||||
useMockLibrary
|
useMockLibrary
|
||||||
? []
|
? []
|
||||||
: [...campuses.value]
|
: [
|
||||||
|
{ key: '', label: '所有院区' },
|
||||||
|
...[...campuses.value]
|
||||||
.filter((campus) => campus.status !== 'DISABLED')
|
.filter((campus) => campus.status !== 'DISABLED')
|
||||||
.sort(
|
.sort(
|
||||||
(left, right) =>
|
(left, right) =>
|
||||||
left.sortNo - right.sortNo || left.name.localeCompare(right.name, 'zh-CN'),
|
left.sortNo - right.sortNo || left.name.localeCompare(right.name, 'zh-CN'),
|
||||||
)
|
)
|
||||||
.map((campus) => ({ key: campus.id, label: campus.name })),
|
.map((campus) => ({ key: campus.id, label: campus.name })),
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -195,7 +200,7 @@ const departmentTabs = computed<DepartmentTab[]>(() => {
|
|||||||
const countOf = (key: string) =>
|
const countOf = (key: string) =>
|
||||||
allTemplates.value.filter((template) => template.departmentKey === key).length
|
allTemplates.value.filter((template) => template.departmentKey === key).length
|
||||||
|
|
||||||
const campusId = appStore.selectedCampusId
|
const campusId = libraryCampusId.value
|
||||||
const campusDepartments = [...departments.value]
|
const campusDepartments = [...departments.value]
|
||||||
.filter((department) => department.status !== 'DISABLED')
|
.filter((department) => department.status !== 'DISABLED')
|
||||||
// 演示文库没有院区维度(科室字典的 campusId 是演示值,与全局院区对不上),不按院区过滤
|
// 演示文库没有院区维度(科室字典的 campusId 是演示值,与全局院区对不上),不按院区过滤
|
||||||
@@ -214,7 +219,9 @@ const departmentTabs = computed<DepartmentTab[]>(() => {
|
|||||||
{ key: GENERAL_GROUP_KEY, label: '全院通用', count: countOf(GENERAL_GROUP_KEY) },
|
{ key: GENERAL_GROUP_KEY, label: '全院通用', count: countOf(GENERAL_GROUP_KEY) },
|
||||||
...campusDepartments.map((department) => ({
|
...campusDepartments.map((department) => ({
|
||||||
key: department.id,
|
key: department.id,
|
||||||
label: department.name,
|
label: allCampusesSelected.value
|
||||||
|
? `${campuses.value.find((campus) => campus.id === department.campusId)?.name ?? '未知院区'} · ${department.name}`
|
||||||
|
: department.name,
|
||||||
count: countOf(department.id),
|
count: countOf(department.id),
|
||||||
})),
|
})),
|
||||||
...orphans.map((group) => ({ key: group.key, label: group.name, count: countOf(group.key) })),
|
...orphans.map((group) => ({ key: group.key, label: group.name, count: countOf(group.key) })),
|
||||||
@@ -307,7 +314,7 @@ function groupDocuments(
|
|||||||
department.categories.push(category)
|
department.categories.push(category)
|
||||||
}
|
}
|
||||||
|
|
||||||
category.documents.push(record)
|
category.documents.push({ ...record, departmentName })
|
||||||
})
|
})
|
||||||
|
|
||||||
// 全院通用的模板排最前,其余按科室名排序,保证每次进页面分组顺序稳定
|
// 全院通用的模板排最前,其余按科室名排序,保证每次进页面分组顺序稳定
|
||||||
@@ -330,12 +337,13 @@ function groupDocuments(
|
|||||||
* 表现为"文档库里少了几份文书",很难排查。
|
* 表现为"文档库里少了几份文书",很难排查。
|
||||||
*/
|
*/
|
||||||
async function fetchAllDocuments(): Promise<DocumentRecord[]> {
|
async function fetchAllDocuments(): Promise<DocumentRecord[]> {
|
||||||
|
const campusId = libraryCampusId.value || undefined
|
||||||
const pageSize = 200
|
const pageSize = 200
|
||||||
const firstPage = await getDocuments({
|
const firstPage = await getDocuments({
|
||||||
page: 1,
|
page: 1,
|
||||||
pageSize,
|
pageSize,
|
||||||
status: 'all',
|
status: 'all',
|
||||||
campusId: appStore.selectedCampusId || undefined,
|
campusId,
|
||||||
})
|
})
|
||||||
const effectivePageSize = Math.max(firstPage.pageSize, 1)
|
const effectivePageSize = Math.max(firstPage.pageSize, 1)
|
||||||
const pageCount = Math.ceil(firstPage.total / effectivePageSize)
|
const pageCount = Math.ceil(firstPage.total / effectivePageSize)
|
||||||
@@ -350,7 +358,7 @@ async function fetchAllDocuments(): Promise<DocumentRecord[]> {
|
|||||||
page: index + 2,
|
page: index + 2,
|
||||||
pageSize: effectivePageSize,
|
pageSize: effectivePageSize,
|
||||||
status: 'all',
|
status: 'all',
|
||||||
campusId: appStore.selectedCampusId || undefined,
|
campusId,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -358,6 +366,8 @@ async function fetchAllDocuments(): Promise<DocumentRecord[]> {
|
|||||||
return [firstPage, ...remaining].flatMap((page) => page.records)
|
return [firstPage, ...remaining].flatMap((page) => page.records)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let libraryRequestId = 0
|
||||||
|
|
||||||
async function loadLibrary() {
|
async function loadLibrary() {
|
||||||
if (useMockLibrary) {
|
if (useMockLibrary) {
|
||||||
libraryError.value = ''
|
libraryError.value = ''
|
||||||
@@ -367,15 +377,18 @@ async function loadLibrary() {
|
|||||||
|
|
||||||
libraryLoading.value = true
|
libraryLoading.value = true
|
||||||
libraryError.value = ''
|
libraryError.value = ''
|
||||||
|
const requestId = ++libraryRequestId
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const records = await fetchAllDocuments()
|
const records = await fetchAllDocuments()
|
||||||
|
if (requestId !== libraryRequestId) return
|
||||||
library.value = groupDocuments(records, departments.value)
|
library.value = groupDocuments(records, departments.value)
|
||||||
} catch {
|
} catch {
|
||||||
|
if (requestId !== libraryRequestId) return
|
||||||
library.value = []
|
library.value = []
|
||||||
libraryError.value = '文书库加载失败,请确认后端模板接口可访问后重试'
|
libraryError.value = '文书库加载失败,请确认后端模板接口可访问后重试'
|
||||||
} finally {
|
} finally {
|
||||||
libraryLoading.value = false
|
if (requestId === libraryRequestId) libraryLoading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -687,11 +700,25 @@ async function handlePropsSubmit(form: DocumentPropsForm) {
|
|||||||
propsSaving.value = true
|
propsSaving.value = true
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const targetDepartment = departments.value.find((item) => item.id === departmentId)
|
||||||
|
if (departmentId && !targetDepartment) {
|
||||||
|
ElMessage.error('所选科室不存在,请刷新后重试')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const campusId =
|
||||||
|
targetDepartment?.campusId ||
|
||||||
|
(form.id ? propsTemplate.value?.campusId : appStore.selectedCampusId || campuses.value[0]?.id)
|
||||||
|
if (!campusId) {
|
||||||
|
ElMessage.error('无法确定文档所属院区,请选择院区后重试')
|
||||||
|
return
|
||||||
|
}
|
||||||
if (form.id) {
|
if (form.id) {
|
||||||
await updateTemplate(form.id, {
|
await updateTemplate(form.id, {
|
||||||
name: form.name,
|
name: form.name,
|
||||||
description: form.description,
|
description: form.description,
|
||||||
category: form.category,
|
category: form.category,
|
||||||
|
campusId,
|
||||||
|
departmentId,
|
||||||
})
|
})
|
||||||
closePropsDialog()
|
closePropsDialog()
|
||||||
await loadLibrary()
|
await loadLibrary()
|
||||||
@@ -703,7 +730,7 @@ async function handlePropsSubmit(form: DocumentPropsForm) {
|
|||||||
templateCode: generateTemplateCode(form.name),
|
templateCode: generateTemplateCode(form.name),
|
||||||
name: form.name,
|
name: form.name,
|
||||||
description: form.description,
|
description: form.description,
|
||||||
campusId: appStore.selectedCampusId || campuses.value[0]?.id || '',
|
campusId,
|
||||||
departmentId,
|
departmentId,
|
||||||
category: form.category,
|
category: form.category,
|
||||||
})
|
})
|
||||||
@@ -894,9 +921,8 @@ async function handleToggleStatus(template: DocumentTemplate) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const versionId = action === 'disable'
|
const versionId =
|
||||||
? template.currentVersionId ?? template.versionId
|
action === 'disable' ? (template.currentVersionId ?? template.versionId) : template.versionId
|
||||||
: template.versionId
|
|
||||||
if (!versionId) {
|
if (!versionId) {
|
||||||
ElMessage.error('该文书没有可操作的版本,请刷新后重试')
|
ElMessage.error('该文书没有可操作的版本,请刷新后重试')
|
||||||
return
|
return
|
||||||
@@ -1140,15 +1166,16 @@ function clearFilters() {
|
|||||||
/**
|
/**
|
||||||
* 切换院区。
|
* 切换院区。
|
||||||
*
|
*
|
||||||
* 走全局院区状态而不是页面自己存一份:右上角的院区选择器读的就是这个值,
|
* 所有院区仅用于文档库查询;具体院区仍与全局选择器同步。
|
||||||
* 两处共用一份状态,就不会出现「右上角写着本部院区、筛选条却选中东院区」。
|
* 重新取数由下面的 watch 负责。
|
||||||
* 重新取数由下面的 watch 负责,这里只改状态。
|
|
||||||
*/
|
*/
|
||||||
function handleCampusSelect(campusId: string) {
|
function handleCampusSelect(campusId: string) {
|
||||||
if (campusId === appStore.selectedCampusId) {
|
if (!campusId) {
|
||||||
|
allCampusesSelected.value = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allCampusesSelected.value = false
|
||||||
appStore.selectCampus(campusId)
|
appStore.selectCampus(campusId)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1156,6 +1183,8 @@ function useTemplate(template: DocumentTemplate) {
|
|||||||
void openSigningDialog(template)
|
void openSigningDialog(template)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let libraryInitialized = false
|
||||||
|
|
||||||
async function initializePage() {
|
async function initializePage() {
|
||||||
if (useMockLibrary) {
|
if (useMockLibrary) {
|
||||||
await loadOrganizationOptions()
|
await loadOrganizationOptions()
|
||||||
@@ -1164,28 +1193,25 @@ async function initializePage() {
|
|||||||
await loadOrganizationOptions()
|
await loadOrganizationOptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
libraryInitialized = true
|
||||||
await loadLibrary()
|
await loadLibrary()
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(libraryCampusId, (campusId, previousCampusId) => {
|
||||||
() => appStore.selectedCampusId,
|
if (campusId === previousCampusId) {
|
||||||
(campusId, previousCampusId) => {
|
|
||||||
if (!campusId || campusId === previousCampusId) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 院区变了,原先选中的科室不一定属于新院区,清掉以免筛出一片空结果
|
// 院区变了,原先选中的科室不一定属于新院区,清掉以免筛出一片空结果
|
||||||
filters.department = null
|
filters.department = null
|
||||||
|
|
||||||
// 演示模式没有院区维度;首次进页面时院区从空值变成第一个院区,
|
// 初始化由 initializePage 取数,演示文库没有院区维度。
|
||||||
// 那一次由 initializePage 负责取数,这里跳过,避免重复拉一遍文库
|
if (useMockLibrary || !libraryInitialized) {
|
||||||
if (useMockLibrary || !previousCampusId) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadLibrary()
|
void loadLibrary()
|
||||||
},
|
})
|
||||||
)
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
void initializePage()
|
void initializePage()
|
||||||
@@ -1206,7 +1232,7 @@ onMounted(() => {
|
|||||||
<DocumentFilterTabs
|
<DocumentFilterTabs
|
||||||
v-model:department="filters.department"
|
v-model:department="filters.department"
|
||||||
v-model:status="filters.status"
|
v-model:status="filters.status"
|
||||||
:campus="appStore.selectedCampusId"
|
:campus="libraryCampusId"
|
||||||
:campuses="campusTabs"
|
:campuses="campusTabs"
|
||||||
:departments="departmentTabs"
|
:departments="departmentTabs"
|
||||||
:statuses="statusTabs"
|
:statuses="statusTabs"
|
||||||
|
|||||||
Reference in New Issue
Block a user