feat(api): 接入医签通业务接口与类型
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
import { request } from '@/utils/request'
|
||||
import { getCampuses } from '@/api/management/organization'
|
||||
|
||||
import { getSigningTasks, getSigningTemplates } from './signing'
|
||||
|
||||
import type {
|
||||
HomeRankingPeriod,
|
||||
@@ -6,6 +8,7 @@ import type {
|
||||
WorkbenchDocumentRanking,
|
||||
WorkbenchOverviewQuery,
|
||||
WorkbenchOverviewResponse,
|
||||
SigningTaskRecord,
|
||||
WorkbenchTodoTask,
|
||||
WorkbenchTrendPoint,
|
||||
} from './types'
|
||||
@@ -243,6 +246,107 @@ function createRanking(
|
||||
.sort((left, right) => right.signedCount - left.signedCount)
|
||||
}
|
||||
|
||||
function isWorkbenchCampus(value: string): value is WorkbenchCampus {
|
||||
return value === '本部院区' || value === '东院区' || value === '西院区'
|
||||
}
|
||||
|
||||
function parseDate(value: string | undefined) {
|
||||
if (!value) {
|
||||
return null
|
||||
}
|
||||
|
||||
const date = new Date(value.includes('T') ? value : value.replace(' ', 'T'))
|
||||
return Number.isNaN(date.getTime()) ? null : date
|
||||
}
|
||||
|
||||
function isSameDay(left: Date | null, right: Date) {
|
||||
return Boolean(
|
||||
left &&
|
||||
left.getFullYear() === right.getFullYear() &&
|
||||
left.getMonth() === right.getMonth() &&
|
||||
left.getDate() === right.getDate(),
|
||||
)
|
||||
}
|
||||
|
||||
function getTaskDate(task: SigningTaskRecord) {
|
||||
return parseDate(task.createdAt) ?? parseDate(task.updatedAt)
|
||||
}
|
||||
|
||||
function isPendingTask(task: SigningTaskRecord) {
|
||||
return task.status === 'pending' || task.status === 'signing'
|
||||
}
|
||||
|
||||
function createLiveOverview(
|
||||
tasks: SigningTaskRecord[],
|
||||
templateCount: number,
|
||||
coveredDepartments: number,
|
||||
rankingPeriod: HomeRankingPeriod,
|
||||
): WorkbenchOverviewResponse {
|
||||
const today = new Date()
|
||||
const signedTasks = tasks.filter((task) => task.status === 'signed')
|
||||
const todaySigned = signedTasks.filter((task) => isSameDay(getTaskDate(task), today)).length
|
||||
const pendingTasks = tasks.filter(isPendingTask)
|
||||
const todayOverdue = tasks.filter(
|
||||
(task) => task.status === 'expired' && isSameDay(getTaskDate(task), today),
|
||||
).length
|
||||
|
||||
const trend = Array.from({ length: rankingPeriod }, (_, index) => {
|
||||
const date = new Date(today)
|
||||
date.setHours(0, 0, 0, 0)
|
||||
date.setDate(today.getDate() - rankingPeriod + index + 1)
|
||||
|
||||
return {
|
||||
label: `${date.getMonth() + 1}/${date.getDate()}`,
|
||||
value: signedTasks.filter((task) => isSameDay(getTaskDate(task), date)).length,
|
||||
}
|
||||
})
|
||||
|
||||
const todos = tasks
|
||||
.filter((task) => isPendingTask(task) || task.status === 'expired')
|
||||
.sort((left, right) => {
|
||||
const leftDate = getTaskDate(left)?.getTime() ?? 0
|
||||
const rightDate = getTaskDate(right)?.getTime() ?? 0
|
||||
return rightDate - leftDate
|
||||
})
|
||||
.slice(0, 8)
|
||||
.map((task) => ({
|
||||
id: task.id,
|
||||
patientId: task.patientId,
|
||||
patientName: task.patientName,
|
||||
documentName: task.documentName,
|
||||
department: task.department,
|
||||
status: task.status === 'expired' ? ('overdue' as const) : ('pending' as const),
|
||||
method: task.method,
|
||||
updatedAt: task.updatedAt,
|
||||
}))
|
||||
|
||||
const rankingMap = new Map<string, WorkbenchDocumentRanking>()
|
||||
signedTasks.forEach((task) => {
|
||||
const current = rankingMap.get(task.documentName)
|
||||
rankingMap.set(task.documentName, {
|
||||
id: current?.id ?? task.documentId,
|
||||
documentName: task.documentName,
|
||||
department: task.department,
|
||||
signedCount: (current?.signedCount ?? 0) + 1,
|
||||
})
|
||||
})
|
||||
|
||||
return {
|
||||
summary: {
|
||||
todaySigned,
|
||||
pendingPatientSigning: pendingTasks.length,
|
||||
todayOverdue,
|
||||
availableTemplates: templateCount,
|
||||
coveredDepartments,
|
||||
},
|
||||
trend,
|
||||
todos,
|
||||
documentRanking: [...rankingMap.values()]
|
||||
.sort((left, right) => right.signedCount - left.signedCount)
|
||||
.slice(0, 10),
|
||||
}
|
||||
}
|
||||
|
||||
export function getWorkbenchOverview(
|
||||
query: WorkbenchOverviewQuery,
|
||||
): Promise<WorkbenchOverviewResponse> {
|
||||
@@ -257,7 +361,38 @@ export function getWorkbenchOverview(
|
||||
})
|
||||
}
|
||||
|
||||
return request.get<WorkbenchOverviewResponse>('/workbench/overview', {
|
||||
params: query,
|
||||
})
|
||||
return Promise.allSettled([getSigningTemplates(), getCampuses()]).then(
|
||||
async ([templatesResult, campusesResult]) => {
|
||||
const templates = templatesResult.status === 'fulfilled' ? templatesResult.value : []
|
||||
const campusNames: Record<string, WorkbenchCampus> =
|
||||
campusesResult.status === 'fulfilled'
|
||||
? (Object.fromEntries(
|
||||
campusesResult.value
|
||||
.filter((campus) => isWorkbenchCampus(campus.name))
|
||||
.map((campus) => [campus.id, campus.name]),
|
||||
) as Record<string, WorkbenchCampus>)
|
||||
: {}
|
||||
const tasksResponse = await getSigningTasks(
|
||||
{
|
||||
page: 1,
|
||||
pageSize: 200,
|
||||
status: 'all',
|
||||
dateRange: 'all',
|
||||
campus: 'all',
|
||||
method: 'all',
|
||||
},
|
||||
{ templates, campusNames },
|
||||
)
|
||||
const scopedTasks = Object.keys(campusNames).length
|
||||
? tasksResponse.records.filter((task) => task.campus === query.campus)
|
||||
: tasksResponse.records
|
||||
|
||||
return createLiveOverview(
|
||||
scopedTasks,
|
||||
templates.length,
|
||||
new Set(templates.map((template) => template.department)).size,
|
||||
query.rankingPeriod,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user