feat(workbench): 扩展签署任务管理功能
This commit is contained in:
@@ -1,48 +1,334 @@
|
||||
import { request } from '@/utils/request'
|
||||
|
||||
import type { SigningTaskListResponse, SigningTaskQuery, SigningTaskRecord } from './types'
|
||||
import type {
|
||||
CreateSigningTaskRequest,
|
||||
PatientProfile,
|
||||
SigningMethod,
|
||||
SigningTaskListResponse,
|
||||
SigningTaskQuery,
|
||||
SigningTaskRecord,
|
||||
SigningTaskStatus,
|
||||
SigningTemplate,
|
||||
VisitType,
|
||||
} from './types'
|
||||
|
||||
const useMockData = import.meta.env.VITE_USE_MOCK !== 'false'
|
||||
|
||||
const mockPatients: PatientProfile[] = [
|
||||
{
|
||||
id: 'P202610001',
|
||||
name: '李某某',
|
||||
sex: '男',
|
||||
age: 46,
|
||||
idCard: '310***********1234',
|
||||
phone: '13800005678',
|
||||
visits: [
|
||||
{
|
||||
id: 'visit-001',
|
||||
type: '住院',
|
||||
visitNo: 'ZY20260827001',
|
||||
department: '消化内科',
|
||||
visitDate: '2026-08-27',
|
||||
isCurrent: true,
|
||||
},
|
||||
{
|
||||
id: 'visit-002',
|
||||
type: '门诊',
|
||||
visitNo: 'MZ20260812018',
|
||||
department: '消化内科',
|
||||
visitDate: '2026-08-12',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'P202610002',
|
||||
name: '王某某',
|
||||
sex: '女',
|
||||
age: 37,
|
||||
idCard: '310***********6721',
|
||||
phone: '13900006789',
|
||||
visits: [
|
||||
{
|
||||
id: 'visit-003',
|
||||
type: '门诊',
|
||||
visitNo: 'JZ20260827018',
|
||||
department: '儿科急诊',
|
||||
visitDate: '2026-08-27',
|
||||
isCurrent: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'P202610003',
|
||||
name: '赵某某',
|
||||
sex: '男',
|
||||
age: 52,
|
||||
idCard: '310***********2846',
|
||||
phone: '13700007890',
|
||||
visits: [
|
||||
{
|
||||
id: 'visit-004',
|
||||
type: '住院',
|
||||
visitNo: 'ZY20260826027',
|
||||
department: '消化内科',
|
||||
visitDate: '2026-08-26',
|
||||
isCurrent: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'P202610004',
|
||||
name: '周雅琴',
|
||||
sex: '女',
|
||||
age: 29,
|
||||
idCard: '310***********9152',
|
||||
phone: '13600008901',
|
||||
visits: [
|
||||
{
|
||||
id: 'visit-005',
|
||||
type: '体检',
|
||||
visitNo: 'TJ20260825006',
|
||||
department: '健康管理中心',
|
||||
visitDate: '2026-08-25',
|
||||
isCurrent: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'P202610005',
|
||||
name: '陈志强',
|
||||
sex: '男',
|
||||
age: 61,
|
||||
idCard: '310***********3488',
|
||||
phone: '13500009012',
|
||||
visits: [
|
||||
{
|
||||
id: 'visit-006',
|
||||
type: '住院',
|
||||
visitNo: 'ZY20260826011',
|
||||
department: '普外科',
|
||||
visitDate: '2026-08-26',
|
||||
isCurrent: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
const mockTemplates: SigningTemplate[] = [
|
||||
{
|
||||
id: 'tpl-001',
|
||||
name: '住院患者知情同意书',
|
||||
code: 'DOC-HOS-001',
|
||||
department: '全院通用',
|
||||
category: '住院告知',
|
||||
description: '住院期间诊疗事项、风险与患者权利告知。',
|
||||
supportedMethods: ['pad', 'sms'],
|
||||
},
|
||||
{
|
||||
id: 'tpl-002',
|
||||
name: '住院须知及告知书',
|
||||
code: 'DOC-HOS-002',
|
||||
department: '全院通用',
|
||||
category: '住院告知',
|
||||
description: '住院流程、陪护要求和患者须知确认。',
|
||||
supportedMethods: ['pad', 'sms'],
|
||||
},
|
||||
{
|
||||
id: 'tpl-003',
|
||||
name: '内镜检查知情同意书',
|
||||
code: 'DOC-DIG-001',
|
||||
department: '消化内科',
|
||||
category: '检查告知',
|
||||
description: '内镜检查适应证、风险及替代方案告知。',
|
||||
supportedMethods: ['pad', 'sms'],
|
||||
},
|
||||
{
|
||||
id: 'tpl-004',
|
||||
name: 'MRI 磁共振检查知情同意书',
|
||||
code: 'DOC-RAD-001',
|
||||
department: '放射科',
|
||||
category: '检查告知',
|
||||
description: '磁共振检查注意事项、禁忌证及风险告知。',
|
||||
supportedMethods: ['pad', 'sms'],
|
||||
},
|
||||
{
|
||||
id: 'tpl-005',
|
||||
name: '心脏介入手术知情同意书',
|
||||
code: 'DOC-CARD-001',
|
||||
department: '心内科',
|
||||
category: '手术告知',
|
||||
description: '介入治疗方案、围术期风险及替代方案告知。',
|
||||
supportedMethods: ['pad'],
|
||||
},
|
||||
{
|
||||
id: 'tpl-006',
|
||||
name: '体检报告发放及知情同意书',
|
||||
code: 'DOC-PE-001',
|
||||
department: '健康管理中心',
|
||||
category: '体检告知',
|
||||
description: '体检报告领取方式、隐私保护和异常结果随访告知。',
|
||||
supportedMethods: ['pad', 'sms'],
|
||||
},
|
||||
{
|
||||
id: 'tpl-007',
|
||||
name: '患者授权委托书',
|
||||
code: 'DOC-GEN-003',
|
||||
department: '医务处',
|
||||
category: '授权文书',
|
||||
description: '患者授权家属或代理人办理相关医疗事项。',
|
||||
supportedMethods: ['pad', 'sms'],
|
||||
},
|
||||
]
|
||||
|
||||
const mockRecords: SigningTaskRecord[] = [
|
||||
{
|
||||
id: 'task-001',
|
||||
campus: '本部院区',
|
||||
patientId: 'P202610001',
|
||||
patientName: '李某某',
|
||||
sex: '男',
|
||||
age: 46,
|
||||
visitNo: 'ZY20260827001',
|
||||
visitType: '住院',
|
||||
visitDate: '2026-08-27',
|
||||
documentId: 'tpl-001',
|
||||
documentName: '住院患者知情同意书',
|
||||
department: '消化内科',
|
||||
status: 'pending',
|
||||
signerName: '李某某',
|
||||
method: 'pad',
|
||||
source: '电子病历',
|
||||
expiresAt: '2026-08-28 09:30',
|
||||
expiresAt: '2026-08-30 09:30',
|
||||
updatedAt: '2026-08-27 09:30',
|
||||
},
|
||||
{
|
||||
id: 'task-002',
|
||||
campus: '东院区',
|
||||
patientId: 'P202610002',
|
||||
patientName: '王某某',
|
||||
sex: '女',
|
||||
age: 37,
|
||||
visitNo: 'JZ20260827018',
|
||||
documentName: '急诊留观知情同意书',
|
||||
department: '儿科急诊',
|
||||
visitType: '门诊',
|
||||
visitDate: '2026-08-27',
|
||||
documentId: 'tpl-004',
|
||||
documentName: 'MRI 磁共振检查知情同意书',
|
||||
department: '放射科',
|
||||
status: 'signed',
|
||||
signerName: '王某某家属',
|
||||
method: 'sms',
|
||||
source: '工作台发起',
|
||||
expiresAt: '2026-08-27 18:00',
|
||||
expiresAt: '2026-08-29 18:00',
|
||||
updatedAt: '2026-08-27 09:12',
|
||||
signedAt: '2026-08-27 09:12',
|
||||
},
|
||||
{
|
||||
id: 'task-003',
|
||||
campus: '本部院区',
|
||||
patientId: 'P202610003',
|
||||
patientName: '赵某某',
|
||||
sex: '男',
|
||||
age: 52,
|
||||
visitNo: 'ZY20260826027',
|
||||
visitType: '住院',
|
||||
visitDate: '2026-08-26',
|
||||
documentId: 'tpl-003',
|
||||
documentName: '内镜检查知情同意书',
|
||||
department: '消化内科',
|
||||
status: 'rejected',
|
||||
status: 'expired',
|
||||
signerName: '赵某某家属',
|
||||
method: 'sms',
|
||||
source: '电子病历',
|
||||
expiresAt: '2026-08-27 16:00',
|
||||
updatedAt: '2026-08-27 08:45',
|
||||
},
|
||||
{
|
||||
id: 'task-004',
|
||||
campus: '本部院区',
|
||||
patientId: 'P202610005',
|
||||
patientName: '陈志强',
|
||||
sex: '男',
|
||||
age: 61,
|
||||
visitNo: 'ZY20260826011',
|
||||
visitType: '住院',
|
||||
visitDate: '2026-08-26',
|
||||
documentId: 'tpl-002',
|
||||
documentName: '住院须知及告知书',
|
||||
department: '普外科',
|
||||
status: 'void',
|
||||
signerName: '陈志强',
|
||||
method: 'pad',
|
||||
source: '电子病历',
|
||||
expiresAt: '2026-08-29 11:00',
|
||||
updatedAt: '2026-08-26 11:20',
|
||||
voidReason: '文档选择错误',
|
||||
},
|
||||
{
|
||||
id: 'task-005',
|
||||
campus: '东院区',
|
||||
patientId: 'P202610004',
|
||||
patientName: '周雅琴',
|
||||
sex: '女',
|
||||
age: 29,
|
||||
visitNo: 'TJ20260825006',
|
||||
visitType: '体检',
|
||||
visitDate: '2026-08-25',
|
||||
documentId: 'tpl-006',
|
||||
documentName: '体检报告发放及知情同意书',
|
||||
department: '健康管理中心',
|
||||
status: 'signing',
|
||||
signerName: '周雅琴',
|
||||
method: 'pad',
|
||||
source: '工作台发起',
|
||||
expiresAt: '2026-08-30 14:20',
|
||||
updatedAt: '2026-08-27 08:20',
|
||||
},
|
||||
]
|
||||
|
||||
function clonePatient(patient: PatientProfile): PatientProfile {
|
||||
return {
|
||||
...patient,
|
||||
visits: patient.visits.map((visit) => ({ ...visit })),
|
||||
}
|
||||
}
|
||||
|
||||
function cloneTask(task: SigningTaskRecord): SigningTaskRecord {
|
||||
return { ...task }
|
||||
}
|
||||
|
||||
function getRangeStart(range: SigningTaskQuery['dateRange']) {
|
||||
if (!range || range === 'all') {
|
||||
return null
|
||||
}
|
||||
|
||||
const date = new Date('2026-08-27T00:00:00')
|
||||
|
||||
if (range === 'yesterday') {
|
||||
date.setDate(date.getDate() - 1)
|
||||
} else if (range === '3d') {
|
||||
date.setDate(date.getDate() - 2)
|
||||
} else if (range === '7d') {
|
||||
date.setDate(date.getDate() - 6)
|
||||
}
|
||||
|
||||
return date
|
||||
}
|
||||
|
||||
function parseMockDate(value: string) {
|
||||
return new Date(value.replace(' ', 'T'))
|
||||
}
|
||||
|
||||
function formatMockDate(date = new Date('2026-08-27T12:00:00')) {
|
||||
const pad = (value: number) => String(value).padStart(2, '0')
|
||||
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`
|
||||
}
|
||||
|
||||
function addHours(value: string, hours: number) {
|
||||
const date = parseMockDate(value)
|
||||
date.setHours(date.getHours() + hours)
|
||||
return formatMockDate(date)
|
||||
}
|
||||
|
||||
export function getSigningTasks(query: SigningTaskQuery): Promise<SigningTaskListResponse> {
|
||||
if (!useMockData) {
|
||||
return request.get<SigningTaskListResponse>('/workbench/signing/tasks', {
|
||||
@@ -51,23 +337,49 @@ export function getSigningTasks(query: SigningTaskQuery): Promise<SigningTaskLis
|
||||
}
|
||||
|
||||
const keyword = query.keyword?.trim().toLowerCase()
|
||||
const filteredRecords = mockRecords.filter((record) => {
|
||||
const matchesKeyword =
|
||||
!keyword ||
|
||||
[record.patientName, record.visitNo, record.documentName]
|
||||
.join(' ')
|
||||
.toLowerCase()
|
||||
.includes(keyword)
|
||||
const matchesStatus = !query.status || query.status === 'all' || record.status === query.status
|
||||
const rangeStart = getRangeStart(query.dateRange)
|
||||
const filteredRecords = mockRecords
|
||||
.filter((record) => {
|
||||
const matchesKeyword =
|
||||
!keyword ||
|
||||
[record.patientName, record.patientId, record.visitNo, record.documentName, record.id]
|
||||
.join(' ')
|
||||
.toLowerCase()
|
||||
.includes(keyword)
|
||||
const matchesStatus =
|
||||
!query.status || query.status === 'all' || record.status === query.status
|
||||
const matchesCampus =
|
||||
!query.campus || query.campus === 'all' || record.campus === query.campus
|
||||
const matchesMethod =
|
||||
!query.method || query.method === 'all' || record.method === query.method
|
||||
const matchesDepartment = !query.department || record.department === query.department
|
||||
const matchesDocument = !query.documentId || record.documentId === query.documentId
|
||||
const matchesVisitType =
|
||||
!query.visitType || query.visitType === 'all' || record.visitType === query.visitType
|
||||
const matchesDate = !rangeStart || parseMockDate(record.updatedAt) >= rangeStart
|
||||
|
||||
return (
|
||||
matchesKeyword &&
|
||||
matchesStatus &&
|
||||
matchesCampus &&
|
||||
matchesMethod &&
|
||||
matchesDepartment &&
|
||||
matchesDocument &&
|
||||
matchesVisitType &&
|
||||
matchesDate
|
||||
)
|
||||
})
|
||||
.sort(
|
||||
(left, right) =>
|
||||
parseMockDate(right.updatedAt).getTime() - parseMockDate(left.updatedAt).getTime(),
|
||||
)
|
||||
|
||||
return matchesKeyword && matchesStatus
|
||||
})
|
||||
const page = Math.max(query.page, 1)
|
||||
const pageSize = Math.max(query.pageSize, 1)
|
||||
const start = (page - 1) * pageSize
|
||||
|
||||
return Promise.resolve({
|
||||
records: filteredRecords.slice(start, start + pageSize),
|
||||
records: filteredRecords.slice(start, start + pageSize).map(cloneTask),
|
||||
total: filteredRecords.length,
|
||||
page,
|
||||
pageSize,
|
||||
@@ -79,5 +391,175 @@ export function getSigningTaskDetail(id: string): Promise<SigningTaskRecord | nu
|
||||
return request.get<SigningTaskRecord>('/workbench/signing/tasks/' + id)
|
||||
}
|
||||
|
||||
return Promise.resolve(mockRecords.find((record) => record.id === id) ?? null)
|
||||
return Promise.resolve(mockRecords.find((record) => record.id === id) ?? null).then((task) =>
|
||||
task ? cloneTask(task) : null,
|
||||
)
|
||||
}
|
||||
|
||||
export function getPatientProfile(keyword: string): Promise<PatientProfile | null> {
|
||||
if (!useMockData) {
|
||||
return request.get<PatientProfile>('/patients/' + encodeURIComponent(keyword))
|
||||
}
|
||||
|
||||
const normalizedKeyword = keyword.trim()
|
||||
const patient = mockPatients.find(
|
||||
(item) =>
|
||||
item.id === normalizedKeyword ||
|
||||
item.visits.some((visit) => visit.visitNo === normalizedKeyword),
|
||||
)
|
||||
|
||||
return Promise.resolve(patient ? clonePatient(patient) : null)
|
||||
}
|
||||
|
||||
export function getSigningTemplates(): Promise<SigningTemplate[]> {
|
||||
if (!useMockData) {
|
||||
return request.get<SigningTemplate[]>('/workbench/signing/templates')
|
||||
}
|
||||
|
||||
return Promise.resolve(mockTemplates.map((template) => ({ ...template })))
|
||||
}
|
||||
|
||||
export function createSigningTask(payload: CreateSigningTaskRequest): Promise<SigningTaskRecord> {
|
||||
if (!useMockData) {
|
||||
return request.post<SigningTaskRecord>('/workbench/signing/tasks', payload)
|
||||
}
|
||||
|
||||
const patient = mockPatients.find((item) => item.id === payload.patientId)
|
||||
const task: SigningTaskRecord = {
|
||||
id: `task-${Date.now()}`,
|
||||
campus: payload.campus,
|
||||
patientId: payload.patientId,
|
||||
patientName: patient?.name ?? '演示患者',
|
||||
sex: patient?.sex ?? '男',
|
||||
age: patient?.age ?? 40,
|
||||
visitNo: payload.visitNo,
|
||||
visitType: payload.visitType,
|
||||
visitDate:
|
||||
patient?.visits.find((visit) => visit.id === payload.visitId)?.visitDate ?? '2026-08-27',
|
||||
documentId: payload.documentId,
|
||||
documentName: payload.documentName,
|
||||
department: payload.department,
|
||||
signerName: patient?.name ?? '演示患者',
|
||||
method: payload.method,
|
||||
status: 'pending',
|
||||
source: '工作台发起',
|
||||
expiresAt: addHours('2026-08-27 12:00', 48),
|
||||
updatedAt: formatMockDate(),
|
||||
}
|
||||
|
||||
mockRecords.unshift(task)
|
||||
return Promise.resolve(cloneTask(task))
|
||||
}
|
||||
|
||||
export function updateSigningTaskMethod(
|
||||
id: string,
|
||||
method: SigningMethod,
|
||||
): Promise<SigningTaskRecord | null> {
|
||||
if (!useMockData) {
|
||||
return request.put<SigningTaskRecord>('/workbench/signing/tasks/' + id + '/method', { method })
|
||||
}
|
||||
|
||||
const task = mockRecords.find((record) => record.id === id)
|
||||
|
||||
if (!task) {
|
||||
return Promise.resolve(null)
|
||||
}
|
||||
|
||||
task.method = method
|
||||
task.updatedAt = formatMockDate()
|
||||
return Promise.resolve(cloneTask(task))
|
||||
}
|
||||
|
||||
export function completeSigningTask(
|
||||
id: string,
|
||||
signatureDataUrl: string,
|
||||
): Promise<SigningTaskRecord | null> {
|
||||
if (!useMockData) {
|
||||
return request.post<SigningTaskRecord>('/workbench/signing/tasks/' + id + '/complete', {
|
||||
signatureDataUrl,
|
||||
})
|
||||
}
|
||||
|
||||
const task = mockRecords.find((record) => record.id === id)
|
||||
|
||||
if (!task) {
|
||||
return Promise.resolve(null)
|
||||
}
|
||||
|
||||
task.status = 'signed'
|
||||
task.signatureDataUrl = signatureDataUrl
|
||||
task.signedAt = formatMockDate()
|
||||
task.updatedAt = task.signedAt
|
||||
return Promise.resolve(cloneTask(task))
|
||||
}
|
||||
|
||||
export function reopenSigningTask(id: string): Promise<SigningTaskRecord | null> {
|
||||
if (!useMockData) {
|
||||
return request.post<SigningTaskRecord>('/workbench/signing/tasks/' + id + '/reopen')
|
||||
}
|
||||
|
||||
const task = mockRecords.find((record) => record.id === id)
|
||||
|
||||
if (!task) {
|
||||
return Promise.resolve(null)
|
||||
}
|
||||
|
||||
task.status = 'pending'
|
||||
task.signatureDataUrl = undefined
|
||||
task.signedAt = undefined
|
||||
task.updatedAt = formatMockDate()
|
||||
return Promise.resolve(cloneTask(task))
|
||||
}
|
||||
|
||||
export function voidSigningTask(id: string, reason: string): Promise<SigningTaskRecord | null> {
|
||||
if (!useMockData) {
|
||||
return request.post<SigningTaskRecord>('/workbench/signing/tasks/' + id + '/void', { reason })
|
||||
}
|
||||
|
||||
const task = mockRecords.find((record) => record.id === id)
|
||||
|
||||
if (!task) {
|
||||
return Promise.resolve(null)
|
||||
}
|
||||
|
||||
task.status = 'void'
|
||||
task.voidReason = reason
|
||||
task.signatureDataUrl = undefined
|
||||
task.updatedAt = formatMockDate()
|
||||
return Promise.resolve(cloneTask(task))
|
||||
}
|
||||
|
||||
export function resendSigningSms(id: string): Promise<SigningTaskRecord | null> {
|
||||
if (!useMockData) {
|
||||
return request.post<SigningTaskRecord>('/workbench/signing/tasks/' + id + '/resend-sms')
|
||||
}
|
||||
|
||||
const task = mockRecords.find((record) => record.id === id)
|
||||
|
||||
if (!task) {
|
||||
return Promise.resolve(null)
|
||||
}
|
||||
|
||||
task.method = 'sms'
|
||||
task.status = 'pending'
|
||||
task.expiresAt = addHours('2026-08-27 12:00', 48)
|
||||
task.updatedAt = formatMockDate()
|
||||
return Promise.resolve(cloneTask(task))
|
||||
}
|
||||
|
||||
export function getSigningStatusLabel(status: SigningTaskStatus) {
|
||||
const labels: Record<SigningTaskStatus, string> = {
|
||||
pending: '待签署',
|
||||
signing: '签署中',
|
||||
signed: '已签署',
|
||||
rejected: '已拒签',
|
||||
expired: '已超时',
|
||||
void: '已作废',
|
||||
}
|
||||
|
||||
return labels[status]
|
||||
}
|
||||
|
||||
export function getVisitTypeLabel(type: VisitType) {
|
||||
return type
|
||||
}
|
||||
|
||||
@@ -9,7 +9,38 @@ export interface WorkbenchOverviewQuery {
|
||||
rankingPeriod: HomeRankingPeriod
|
||||
}
|
||||
|
||||
export type SigningTaskStatus = 'pending' | 'signing' | 'signed' | 'rejected' | 'expired'
|
||||
export type SigningTaskStatus = 'pending' | 'signing' | 'signed' | 'rejected' | 'expired' | 'void'
|
||||
|
||||
export type VisitType = '门诊' | '住院' | '体检'
|
||||
|
||||
export interface PatientVisit {
|
||||
id: string
|
||||
type: VisitType
|
||||
visitNo: string
|
||||
department: string
|
||||
visitDate: string
|
||||
isCurrent?: boolean
|
||||
}
|
||||
|
||||
export interface PatientProfile {
|
||||
id: string
|
||||
name: string
|
||||
sex: '男' | '女'
|
||||
age: number
|
||||
idCard: string
|
||||
phone: string
|
||||
visits: PatientVisit[]
|
||||
}
|
||||
|
||||
export interface SigningTemplate {
|
||||
id: string
|
||||
name: string
|
||||
code: string
|
||||
department: string
|
||||
category: string
|
||||
description: string
|
||||
supportedMethods: SigningMethod[]
|
||||
}
|
||||
|
||||
export interface WorkbenchSummary {
|
||||
todaySigned: number
|
||||
@@ -66,12 +97,44 @@ export interface WorkbenchOverviewResponse {
|
||||
export interface SigningTaskQuery extends PageQuery {
|
||||
keyword?: string
|
||||
status?: SigningTaskStatus | 'all'
|
||||
dateRange?: SigningDateRange
|
||||
campus?: WorkbenchCampus | 'all'
|
||||
method?: SigningMethod | 'all'
|
||||
department?: string
|
||||
documentId?: string
|
||||
visitType?: VisitType | 'all'
|
||||
}
|
||||
|
||||
export type SigningDateRange = 'today' | 'yesterday' | '3d' | '7d' | 'all'
|
||||
|
||||
export interface SigningTaskRecord extends WorkbenchTask {
|
||||
campus: WorkbenchCampus
|
||||
patientId: string
|
||||
sex: '男' | '女'
|
||||
age: number
|
||||
documentId: string
|
||||
signerName: string
|
||||
method: SigningMethod
|
||||
source: string
|
||||
expiresAt: string
|
||||
visitType: VisitType
|
||||
visitDate: string
|
||||
signatureDataUrl?: string
|
||||
signedAt?: string
|
||||
voidReason?: string
|
||||
}
|
||||
|
||||
export type SigningTaskListResponse = PageResult<SigningTaskRecord>
|
||||
|
||||
export interface CreateSigningTaskRequest {
|
||||
campus: WorkbenchCampus
|
||||
patientId: string
|
||||
visitId: string
|
||||
documentId: string
|
||||
documentName: string
|
||||
method: SigningMethod
|
||||
visitType: VisitType
|
||||
visitNo: string
|
||||
department: string
|
||||
phone?: string
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user