refactor(签署工作台): 按原型精简筛选条为日期/状态/搜索并改为输入即筛

This commit is contained in:
yelan
2026-09-27 09:27:26 +08:00
parent 3cb174ce0c
commit cc1ef72320
3 changed files with 126 additions and 143 deletions
@@ -33,19 +33,13 @@ import type {
SigningTaskRecord,
SigningTaskStatus,
SigningTemplate,
VisitType,
WorkbenchCampus,
} from '@/api/workbench/types'
import NewSigningTaskDialog from '@/components/signing/NewSigningTaskDialog.vue'
import { useAppStore } from '@/stores/app'
import { useLoginStore } from '@/stores/login'
import type { SigningFieldProgress, SigningSignatureRequest } from '@/utils/signing-document'
import {
formatSigningMethodTitle,
readSigningMethod,
toggleSigningMethod,
WORKBENCH_METHOD_FILTERS,
} from '@/utils/signing-method'
import { formatSigningMethodTitle, readSigningMethod, toggleSigningMethod } from '@/utils/signing-method'
import { downloadSigningPdf } from '@/utils/signing-pdf'
import OnlineSigningDialog from './components/OnlineSigningDialog.vue'
@@ -61,15 +55,6 @@ const route = useRoute()
const appStore = useAppStore()
const loginStore = useLoginStore()
const STATUS_VALUES: SigningTaskStatus[] = [
'pending',
'signing',
'confirming',
'signed',
'expired',
'void',
'failed',
]
const DATE_RANGE_VALUES: SigningDateRange[] = ['today', 'yesterday', '3d', '7d', 'all']
const statusLabels: Record<SigningTaskStatus, string> = {
@@ -86,11 +71,6 @@ const filter = reactive<SigningFilterForm>({
keyword: '',
status: 'all',
dateRange: 'all',
campus: 'all',
method: 'all',
department: '',
documentId: '',
visitType: 'all',
})
const tasks = ref<SigningTaskRecord[]>([])
@@ -162,46 +142,27 @@ const canViewEvents = computed(() => canRead('sign:task:event:query'))
const canViewArtifacts = computed(() => canRead('sign:artifact:query'))
const canDownloadArtifacts = computed(() => canRead('sign:artifact:download'))
const campusOptions = computed<SigningFilterOption<WorkbenchCampus | 'all'>[]>(() => [
{ label: '全部院区', value: 'all' },
...appStore.campuses.map((campus) => ({ label: campus, value: campus })),
])
/**
* 状态筛选的取值:原型 `#fStat` 只有 6 项
* (全部 / 待签署 / 待科室确认 / 已签署 / 已超时 / 已作废)。
*
* 仓库另有 `signing`(签署中)与 `failed`(处理失败)两个状态 —— 它们仍会正常渲染徽标,
* 只是原型没有对应筛选项,所以不进下拉;路由 query 里出现这两个值也按「全部」处理,
* 否则下拉会选中一个不存在的 option、显示成空白。
*/
const STATUS_FILTER_VALUES: SigningTaskStatus[] = [
'pending',
'confirming',
'signed',
'expired',
'void',
]
const statusOptions: SigningFilterOption<SigningFilterForm['status']>[] = [
{ label: '全部状态', value: 'all' },
...STATUS_VALUES.map((status) => ({ label: statusLabels[status], value: status })),
{ label: '全部', value: 'all' },
...STATUS_FILTER_VALUES.map((status) => ({ label: statusLabels[status], value: status })),
]
/** 原型 #qMethod 只有 3 项(手写板 / 短信线上 / Pad),没有公众号 */
const methodOptions: SigningFilterOption<SigningFilterForm['method']>[] = [
{ label: '全部方式', value: 'all' },
...WORKBENCH_METHOD_FILTERS.map((option) => ({ label: option.label, value: option.value })),
]
const visitTypeOptions: SigningFilterOption<VisitType | 'all'>[] = [
{ label: '全部类型', value: 'all' },
{ label: '门诊', value: '门诊' },
{ label: '住院', value: '住院' },
{ label: '体检', value: '体检' },
]
const departmentOptions = computed<SigningFilterOption[]>(() => {
const departments = new Set([
...templates.value.map((template) => template.department),
...tasks.value.map((task) => task.department),
])
return [
{ label: '全部科室', value: '' },
...[...departments].sort().map((department) => ({ label: department, value: department })),
]
})
const documentOptions = computed<SigningFilterOption[]>(() => [
{ label: '全部文档', value: '' },
...templates.value.map((template) => ({ label: template.name, value: template.id })),
])
const signingApiOptions = computed(() => ({
campus: appStore.selectedCampus,
campusId: campusIds.value[appStore.selectedCampus],
@@ -216,25 +177,25 @@ function getQueryString(value: unknown) {
}
function isSigningStatus(value: string): value is SigningTaskStatus {
return STATUS_VALUES.includes(value as SigningTaskStatus)
return STATUS_FILTER_VALUES.includes(value as SigningTaskStatus)
}
function isSigningDateRange(value: string): value is SigningDateRange {
return DATE_RANGE_VALUES.includes(value as SigningDateRange)
}
function isWorkbenchCampus(value: string): value is WorkbenchCampus {
return appStore.campuses.includes(value)
}
/**
* 路由 query → 搜索条件。
*
* 只认 `status` 与 `range`:原型工作台顶部就这两个条件,
* `campus` 由右上角的全局院区选择器统一约束(见 `signingApiOptions`),不再从 query 取。
*/
function syncFilterFromRoute() {
const status = getQueryString(route.query.status)
const range = getQueryString(route.query.range)
const campus = getQueryString(route.query.campus)
filter.status = status === 'all' || isSigningStatus(status) ? status : 'all'
filter.dateRange = isSigningDateRange(range) ? range : 'all'
filter.campus = isWorkbenchCampus(campus) ? campus : 'all'
}
async function loadTemplates() {
@@ -919,7 +880,7 @@ async function handleTaskCreated(task: SigningTaskRecord) {
}
watch(
() => [route.query.status, route.query.range, route.query.campus, route.query.taskId],
() => [route.query.status, route.query.range, route.query.taskId],
() => {
syncFilterFromRoute()
page.value = 1
@@ -928,12 +889,10 @@ watch(
},
)
/** 切换全局院区:列表跟着换(院区不再是筛选条里的一个下拉,见 syncFilterFromRoute) */
watch(
() => appStore.selectedCampus,
(campus) => {
if (filter.campus !== 'all') {
filter.campus = campus
}
() => {
page.value = 1
void loadTasks()
},
@@ -959,12 +918,7 @@ onMounted(() => {
<SigningFilterBar
:filter="filter"
:campuses="campusOptions"
:statuses="statusOptions"
:methods="methodOptions"
:departments="departmentOptions"
:documents="documentOptions"
:visit-types="visitTypeOptions"
:can-create="canCreateTask"
@add="newDialogVisible = true"
@search="handleSearch"