refactor(签署工作台): 按原型精简筛选条为日期/状态/搜索并改为输入即筛
This commit is contained in:
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user