feat(签署方式): 扩展为手写板/短信/Pad/公众号四种并集中口径
This commit is contained in:
@@ -310,7 +310,8 @@ export interface OrganizationResponseDto {
|
||||
export type ReportBackendTaskStatus =
|
||||
'CREATED' | 'WAITING_SIGN' | 'SIGNED' | 'EXPIRED' | 'VOIDED' | 'GENERATING' | 'FAILED'
|
||||
|
||||
export type ReportBackendSignMethod = 'PAD' | 'SMS'
|
||||
/** 与 workbench 的 BackendSigningMethod 同口径:四种方式平铺,无通道归并 */
|
||||
export type ReportBackendSignMethod = 'PAD' | 'SMS' | 'IPAD' | 'WX'
|
||||
|
||||
export type ReportTimeDimension = 'CREATED' | 'SIGNED' | 'EXPIRED'
|
||||
|
||||
|
||||
@@ -79,6 +79,27 @@ const mockCampusOverviews: Record<WorkbenchCampus, MockCampusOverview> = {
|
||||
method: 'sms',
|
||||
updatedAt: '2026-08-27 09:40',
|
||||
},
|
||||
{
|
||||
// Pad 移动端:待办里要四种方式都有样本,徽标配色才看得出区别
|
||||
id: 'T0818004',
|
||||
patientId: 'P202610003',
|
||||
patientName: '赵某某',
|
||||
documentName: '住院须知及告知书',
|
||||
department: '消化内科',
|
||||
status: 'pending',
|
||||
method: 'ipad',
|
||||
updatedAt: '2026-08-27 09:05',
|
||||
},
|
||||
{
|
||||
id: 'T0818005',
|
||||
patientId: 'P202610007',
|
||||
patientName: '孙浩然',
|
||||
documentName: '内镜检查知情同意书',
|
||||
department: '普外科',
|
||||
status: 'pending',
|
||||
method: 'wx',
|
||||
updatedAt: '2026-08-27 08:50',
|
||||
},
|
||||
],
|
||||
ranking: [
|
||||
{ id: 'doc-001', documentName: '住院患者知情同意书', department: '全院通用', baseCount: 58 },
|
||||
@@ -137,6 +158,26 @@ const mockCampusOverviews: Record<WorkbenchCampus, MockCampusOverview> = {
|
||||
method: 'sms',
|
||||
updatedAt: '2026-08-27 08:30',
|
||||
},
|
||||
{
|
||||
id: 'T0818012',
|
||||
patientId: 'P202610003',
|
||||
patientName: '赵某某',
|
||||
documentName: '住院须知及告知书',
|
||||
department: '消化内科',
|
||||
status: 'pending',
|
||||
method: 'ipad',
|
||||
updatedAt: '2026-08-27 09:05',
|
||||
},
|
||||
{
|
||||
id: 'T0818013',
|
||||
patientId: 'P202610007',
|
||||
patientName: '孙浩然',
|
||||
documentName: '内镜检查知情同意书',
|
||||
department: '普外科',
|
||||
status: 'pending',
|
||||
method: 'wx',
|
||||
updatedAt: '2026-08-27 08:50',
|
||||
},
|
||||
],
|
||||
ranking: [
|
||||
{
|
||||
@@ -215,6 +256,26 @@ const mockCampusOverviews: Record<WorkbenchCampus, MockCampusOverview> = {
|
||||
method: 'pad',
|
||||
updatedAt: '2026-08-27 08:05',
|
||||
},
|
||||
{
|
||||
id: 'T0818024',
|
||||
patientId: 'P202610003',
|
||||
patientName: '赵某某',
|
||||
documentName: '住院须知及告知书',
|
||||
department: '消化内科',
|
||||
status: 'pending',
|
||||
method: 'ipad',
|
||||
updatedAt: '2026-08-27 09:05',
|
||||
},
|
||||
{
|
||||
id: 'T0818025',
|
||||
patientId: 'P202610007',
|
||||
patientName: '孙浩然',
|
||||
documentName: '内镜检查知情同意书',
|
||||
department: '普外科',
|
||||
status: 'pending',
|
||||
method: 'wx',
|
||||
updatedAt: '2026-08-27 08:50',
|
||||
},
|
||||
],
|
||||
ranking: [
|
||||
{
|
||||
@@ -281,8 +342,16 @@ function mapTodoStatus(status: BackendSigningTaskStatus): WorkbenchTodoStatus {
|
||||
}
|
||||
}
|
||||
|
||||
const METHOD_BY_BACKEND: Record<BackendSigningMethod, SigningMethod> = {
|
||||
PAD: 'pad',
|
||||
SMS: 'sms',
|
||||
IPAD: 'ipad',
|
||||
WX: 'wx',
|
||||
}
|
||||
|
||||
function mapSigningMethod(method: BackendSigningMethod): SigningMethod {
|
||||
return method === 'SMS' ? 'sms' : 'pad'
|
||||
// 后端理论上只回这四个;未知取值按手写板兜底,避免整行渲染不出来
|
||||
return METHOD_BY_BACKEND[method] ?? 'pad'
|
||||
}
|
||||
|
||||
function mapWorkbenchOverview(dto: WorkbenchOverviewResponseDto): WorkbenchOverviewResponse {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
import { DEMO_SIGNATURE_DATA_URL } from '@/utils/demo-signature'
|
||||
import { mockFlags } from '@/utils/mock-flags'
|
||||
import { buildFieldSpanHtml } from '@/utils/signing-fields'
|
||||
import { formatSigningMethod, toBackendSigningMethod } from '@/utils/signing-method'
|
||||
|
||||
import {
|
||||
campusOfDepartment,
|
||||
@@ -128,10 +129,13 @@ const MOCK_RECORD_SEEDS: MockRecordSeed[] = [
|
||||
{ patient: '赵美英', sex: '女', age: 58, visitType: '住院', doc: 'mock-doc-cardiac', status: 'signed', method: 'pad', days: 0, at: '09:12', minutes: 7 },
|
||||
{ patient: '李淑芬', sex: '女', age: 67, visitType: '门诊', doc: 'mock-doc-mri', status: 'signed', method: 'sms', days: 0, at: '10:05', minutes: 4 },
|
||||
{ patient: '周雅琴', sex: '女', age: 29, visitType: '门诊', doc: 'mock-doc-endoscopy', status: 'pending', method: 'sms', days: 0, at: '11:20' },
|
||||
{ patient: '赵某某', sex: '男', age: 52, visitType: '住院', doc: 'mock-doc-admission', status: 'pending', method: 'ipad', days: 0, at: '09:05', source: '工作台发起' },
|
||||
{ patient: '孙浩然', sex: '男', age: 54, visitType: '住院', doc: 'mock-doc-endoscopy', status: 'pending', method: 'wx', days: 0, at: '08:50' },
|
||||
// 昨天
|
||||
{ patient: '孙浩然', sex: '男', age: 54, visitType: '住院', doc: 'mock-doc-narcotic', status: 'signed', method: 'pad', days: 1, at: '08:40', minutes: 6, source: '工作台发起' },
|
||||
{ patient: '王建国', sex: '男', age: 71, visitType: '住院', doc: 'mock-doc-blood', status: 'signed', method: 'sms', days: 1, at: '14:15', minutes: 9 },
|
||||
{ patient: '陈志强', sex: '男', age: 61, visitType: '住院', doc: 'mock-doc-admission', status: 'void', method: 'pad', days: 1, at: '16:02', source: '工作台发起', voidReason: '文书选择错误,已重新发起' },
|
||||
{ patient: '罗文静', sex: '女', age: 44, visitType: '住院', doc: 'mock-doc-mri', status: 'signed', method: 'ipad', days: 1, at: '11:35', minutes: 5 },
|
||||
// 近 3 天
|
||||
{ patient: '吴桂芳', sex: '女', age: 73, visitType: '住院', doc: 'mock-doc-surgery', status: 'signed', method: 'pad', days: 2, at: '09:35', minutes: 5 },
|
||||
{ patient: '刘伟', sex: '男', age: 45, visitType: '门诊', doc: 'mock-doc-cardiac', status: 'signed', method: 'sms', days: 2, at: '15:48', minutes: 3, source: '工作台发起' },
|
||||
@@ -142,6 +146,7 @@ const MOCK_RECORD_SEEDS: MockRecordSeed[] = [
|
||||
{ patient: '马晓东', sex: '男', age: 33, visitType: '其他', doc: 'mock-doc-emergency', status: 'failed', method: 'pad', days: 5, at: '20:18', source: '工作台发起' },
|
||||
{ patient: '何秀英', sex: '女', age: 79, visitType: '住院', doc: 'mock-doc-surgery', status: 'signed', method: 'sms', days: 6, at: '09:05', minutes: 12 },
|
||||
{ patient: '林俊杰', sex: '男', age: 41, visitType: '门诊', doc: 'mock-doc-narcotic', status: 'signing', method: 'pad', days: 6, at: '14:52' },
|
||||
{ patient: '梁俊豪', sex: '男', age: 35, visitType: '住院', doc: 'mock-doc-surgery', status: 'signed', method: 'wx', days: 6, at: '10:28', minutes: 4 },
|
||||
// 近 30 天
|
||||
{ patient: '罗美玲', sex: '女', age: 62, visitType: '门诊', doc: 'mock-doc-admission', status: 'expired', method: 'sms', days: 11, at: '17:30' },
|
||||
{ patient: '高文斌', sex: '男', age: 57, visitType: '住院', doc: 'mock-doc-cardiac', status: 'signed', method: 'pad', days: 14, at: '10:10', minutes: 7 },
|
||||
@@ -447,25 +452,30 @@ export async function getSigningRecordDetail(
|
||||
* 如果每次刷新都在变,就没法用来核对签署链路了。
|
||||
*/
|
||||
function buildMockEvents(record: SigningRecord): SigningTaskEvent[] {
|
||||
const channel = record.method === 'pad' ? '手写板' : '短信'
|
||||
const backendChannel = toBackendSigningMethod(record.method)
|
||||
// 线上方式(短信 / 公众号)才有一条「已发送」留痕,现场方式是设备上直接采集
|
||||
const isOnline = record.method === 'sms' || record.method === 'wx'
|
||||
const createdAt = record.createdAt ?? record.updatedAt
|
||||
const events: SigningTaskEvent[] = [
|
||||
{
|
||||
id: `${record.id}-created`,
|
||||
time: createdAt,
|
||||
text: `张文静创建签署任务(${channel})`,
|
||||
text: `张文静创建签署任务(${formatSigningMethod(record.method)})`,
|
||||
eventType: 'TASK_CREATED',
|
||||
channel: record.method === 'pad' ? 'PAD' : 'SMS',
|
||||
channel: backendChannel,
|
||||
},
|
||||
]
|
||||
|
||||
if (record.method === 'sms') {
|
||||
if (isOnline) {
|
||||
events.push({
|
||||
id: `${record.id}-sent`,
|
||||
time: createdAt,
|
||||
text: `已向 ${record.patientName} 预留手机号发送签署短信`,
|
||||
text:
|
||||
record.method === 'wx'
|
||||
? `已向 ${record.patientName} 推送公众号签署通知`
|
||||
: `已向 ${record.patientName} 预留手机号发送签署短信`,
|
||||
eventType: 'SEND_PREPARED',
|
||||
channel: 'SMS',
|
||||
channel: backendChannel,
|
||||
attemptNo: 1,
|
||||
})
|
||||
}
|
||||
@@ -476,7 +486,7 @@ function buildMockEvents(record: SigningRecord): SigningTaskEvent[] {
|
||||
time: record.updatedAt,
|
||||
text: '已打开签名采集,等待患者完成签名',
|
||||
eventType: 'SIGNING_STARTED',
|
||||
channel: 'PAD',
|
||||
channel: backendChannel,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -486,7 +496,7 @@ function buildMockEvents(record: SigningRecord): SigningTaskEvent[] {
|
||||
time: record.signedAt,
|
||||
text: `患者 ${record.signerName} 完成签名,系统已合成文书并双留存`,
|
||||
eventType: 'SIGNED',
|
||||
channel: record.method === 'pad' ? 'PAD' : 'SMS',
|
||||
channel: backendChannel,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -182,6 +182,36 @@ function pickStatus(random: () => number): SigningTaskStatus {
|
||||
return 'signed'
|
||||
}
|
||||
|
||||
/**
|
||||
* 四种签署方式的抽样权重。
|
||||
*
|
||||
* 现场两种(手写板 / Pad)占比高,线上两种(短信 / 公众号)略低 —— 四种都要出现,
|
||||
* 否则「签署方式分布」这个报表维度会缺行,演示时看不到新方式。
|
||||
* 权重和不必是 100,`pickMethod` 会自己算总和。
|
||||
*/
|
||||
const METHOD_WEIGHTS: readonly { method: SigningMethod; weight: number }[] = [
|
||||
{ method: 'pad', weight: 38 },
|
||||
{ method: 'ipad', weight: 24 },
|
||||
{ method: 'sms', weight: 26 },
|
||||
{ method: 'wx', weight: 12 },
|
||||
]
|
||||
|
||||
const METHOD_TOTAL_WEIGHT = METHOD_WEIGHTS.reduce((sum, item) => sum + item.weight, 0)
|
||||
|
||||
function pickMethod(random: () => number): SigningMethod {
|
||||
let roll = random() * METHOD_TOTAL_WEIGHT
|
||||
|
||||
for (const item of METHOD_WEIGHTS) {
|
||||
roll -= item.weight
|
||||
|
||||
if (roll <= 0) {
|
||||
return item.method
|
||||
}
|
||||
}
|
||||
|
||||
return 'pad'
|
||||
}
|
||||
|
||||
function pad(value: number): string {
|
||||
return String(value).padStart(2, '0')
|
||||
}
|
||||
@@ -219,7 +249,8 @@ function buildTasks(): ReportTaskRow[] {
|
||||
const patient = pick(random, DEMO_PATIENTS)
|
||||
const document = pick(random, mockDocumentCatalog)
|
||||
const status = pickStatus(random)
|
||||
const method: SigningMethod = random() < 0.45 ? 'pad' : 'sms'
|
||||
// 四种方式按现场/线上偏重的权重抽,保证「签署方式分布」四个维度都有量
|
||||
const method = pickMethod(random)
|
||||
|
||||
// 越靠近今天的任务越少:真实签署量不会是均匀分布,均匀分布的趋势图一眼假
|
||||
const daysAgo = Math.floor(DEMO_SPAN_DAYS * Math.pow(random(), 1.35))
|
||||
|
||||
@@ -10,6 +10,7 @@ import { mockFlags } from '@/utils/mock-flags'
|
||||
import { readLocalSigningTemplates } from '@/utils/mock-document-library'
|
||||
import { MOCK_STORAGE_KEYS, readMockState, writeMockState } from '@/utils/mock-storage'
|
||||
import { request } from '@/utils/request'
|
||||
import { ALL_SIGNING_METHODS, formatSigningMethod, toBackendSigningMethod } from '@/utils/signing-method'
|
||||
import { resendSigningSms as resendSigningSmsDelivery } from './deliveries'
|
||||
|
||||
import type {
|
||||
@@ -51,7 +52,8 @@ const mockPatients: PatientProfile[] = [
|
||||
sex: '男',
|
||||
age: 46,
|
||||
idCard: '310***********1234',
|
||||
phone: '13800005678',
|
||||
phone: '138****5678',
|
||||
phoneFull: '13800005678',
|
||||
visits: [
|
||||
{
|
||||
id: 'visit-001',
|
||||
@@ -76,7 +78,8 @@ const mockPatients: PatientProfile[] = [
|
||||
sex: '女',
|
||||
age: 37,
|
||||
idCard: '310***********6721',
|
||||
phone: '13900006789',
|
||||
phone: '139****6789',
|
||||
phoneFull: '13900006789',
|
||||
visits: [
|
||||
{
|
||||
id: 'visit-003',
|
||||
@@ -94,7 +97,8 @@ const mockPatients: PatientProfile[] = [
|
||||
sex: '男',
|
||||
age: 52,
|
||||
idCard: '310***********2846',
|
||||
phone: '13700007890',
|
||||
phone: '137****7890',
|
||||
phoneFull: '13700007890',
|
||||
visits: [
|
||||
{
|
||||
id: 'visit-004',
|
||||
@@ -112,7 +116,8 @@ const mockPatients: PatientProfile[] = [
|
||||
sex: '女',
|
||||
age: 29,
|
||||
idCard: '310***********9152',
|
||||
phone: '13600008901',
|
||||
phone: '136****8901',
|
||||
phoneFull: '13600008901',
|
||||
visits: [
|
||||
{
|
||||
id: 'visit-005',
|
||||
@@ -130,7 +135,8 @@ const mockPatients: PatientProfile[] = [
|
||||
sex: '男',
|
||||
age: 61,
|
||||
idCard: '310***********3488',
|
||||
phone: '13500009012',
|
||||
phone: '135****9012',
|
||||
phoneFull: '13500009012',
|
||||
visits: [
|
||||
{
|
||||
id: 'visit-006',
|
||||
@@ -252,6 +258,73 @@ const defaultMockRecords: SigningTaskRecord[] = [
|
||||
expiresAt: '2026-08-30 14:20',
|
||||
updatedAt: '2026-08-27 08:20',
|
||||
},
|
||||
{
|
||||
// Pad 移动端(床旁/诊间):原型种子里就有这一条,待签署,用来验证 Pad 方式的状态徽标与详情动作
|
||||
id: 'task-006',
|
||||
templateVersionId: 'tpl-002-v1',
|
||||
campus: '本部院区',
|
||||
patientId: 'P202610003',
|
||||
patientName: '赵某某',
|
||||
sex: '男',
|
||||
age: 52,
|
||||
visitNo: 'ZY20260826027',
|
||||
visitType: '住院',
|
||||
visitDate: '2026-08-26',
|
||||
documentId: 'tpl-002',
|
||||
documentName: '住院须知及告知书',
|
||||
department: '消化内科',
|
||||
status: 'pending',
|
||||
signerName: '赵某某',
|
||||
method: 'ipad',
|
||||
source: '工作台发起',
|
||||
expiresAt: '2026-08-30 18:00',
|
||||
updatedAt: '2026-08-27 09:05',
|
||||
},
|
||||
{
|
||||
// 微信公众号:四种方式里最晚加的一条,演示数据里必须有一条,
|
||||
// 否则「公众号」的筛选项与状态徽标永远没有样本可看
|
||||
id: 'task-007',
|
||||
templateVersionId: 'tpl-003-v3',
|
||||
campus: '西院区',
|
||||
patientId: 'P202610005',
|
||||
patientName: '陈志强',
|
||||
sex: '男',
|
||||
age: 61,
|
||||
visitNo: 'ZY20260826011',
|
||||
visitType: '住院',
|
||||
visitDate: '2026-08-26',
|
||||
documentId: 'tpl-003',
|
||||
documentName: '内镜检查知情同意书',
|
||||
department: '普外科',
|
||||
status: 'pending',
|
||||
signerName: '陈志强',
|
||||
method: 'wx',
|
||||
source: '电子病历',
|
||||
expiresAt: '2026-08-31 10:00',
|
||||
updatedAt: '2026-08-27 09:40',
|
||||
},
|
||||
{
|
||||
// 短信线上:待签署的四种方式各要一条,列表徽标的四种配色才都能看到
|
||||
id: 'task-008',
|
||||
templateVersionId: 'tpl-004-v1',
|
||||
campus: '东院区',
|
||||
patientId: 'P202610002',
|
||||
patientName: '王某某',
|
||||
sex: '女',
|
||||
age: 37,
|
||||
visitNo: 'JZ20260827018',
|
||||
visitType: '门诊',
|
||||
visitDate: '2026-08-27',
|
||||
documentId: 'tpl-004',
|
||||
documentName: 'MRI 磁共振检查知情同意书',
|
||||
department: '放射科',
|
||||
status: 'pending',
|
||||
signerName: '王某某',
|
||||
method: 'sms',
|
||||
source: '工作台发起',
|
||||
expiresAt: '2026-08-31 18:00',
|
||||
updatedAt: '2026-08-27 09:50',
|
||||
},
|
||||
]
|
||||
|
||||
/**
|
||||
@@ -405,9 +478,15 @@ export function getMockSigningTask(taskId: string): SigningTaskRecord | null {
|
||||
return task ? cloneTask(task) : null
|
||||
}
|
||||
|
||||
/** 演示患者清单(仅 Mock 模式):给签署弹窗做“点一下就能定位”的输入提示 */
|
||||
export function getMockPatientHints(): { id: string; name: string }[] {
|
||||
return useMockData ? mockPatients.map((item) => ({ id: item.id, name: item.name })) : []
|
||||
/**
|
||||
* 演示患者清单(仅 Mock 模式)。
|
||||
*
|
||||
* 给发起签署弹窗做「候选患者」下拉:原型允许按 患者ID / 姓名 / 证件号 / 就诊号
|
||||
* 模糊匹配,因此这里返回完整档案(克隆一份,避免调用方就地改动演示数据),
|
||||
* 而不是只给 id + 姓名。真实模式返回空数组,候选下拉自然不出现。
|
||||
*/
|
||||
export function getMockPatients(): PatientProfile[] {
|
||||
return useMockData ? mockPatients.map(clonePatient) : []
|
||||
}
|
||||
|
||||
function isNotFoundError(error: unknown) {
|
||||
@@ -467,8 +546,16 @@ function normalizeVisitType(value: string): VisitType {
|
||||
return '其他'
|
||||
}
|
||||
|
||||
const METHOD_BY_BACKEND: Record<BackendSigningMethod, SigningMethod> = {
|
||||
PAD: 'pad',
|
||||
SMS: 'sms',
|
||||
IPAD: 'ipad',
|
||||
WX: 'wx',
|
||||
}
|
||||
|
||||
function normalizeSigningMethod(value: BackendSigningMethod): SigningMethod {
|
||||
return value === 'SMS' ? 'sms' : 'pad'
|
||||
// 后端理论上只回这四个;出现未知取值时按手写板兜底,避免整行渲染不出来
|
||||
return METHOD_BY_BACKEND[value] ?? 'pad'
|
||||
}
|
||||
|
||||
function normalizeTaskStatus(value: BackendSigningTaskStatus): SigningTaskStatus {
|
||||
@@ -531,8 +618,8 @@ function mapAvailableTemplate(dto: AvailableTemplateVersionResponseDto): Signing
|
||||
campusId: dto.campusId,
|
||||
category: dto.category || '未分类',
|
||||
description: `已发布版本 ${dto.versionNo}`,
|
||||
// 可用模板接口没有返回通道 ACL;具体通道仍由后端在创建时校验。
|
||||
supportedMethods: ['pad', 'sms'],
|
||||
// 可用模板接口不返回方式 ACL;四种方式都放行,实际允许范围由后端在创建时校验。
|
||||
supportedMethods: [...ALL_SIGNING_METHODS],
|
||||
// 接口不返回正文,只能带出哈希;正文由 hydrateTemplateContents 按需补回
|
||||
contentSha256: dto.contentSha256,
|
||||
contentHtml: cachedContent || undefined,
|
||||
@@ -677,7 +764,7 @@ function createTemplateFromInput(input: CreateSigningTaskInput): SigningTemplate
|
||||
department: input.department,
|
||||
category: '—',
|
||||
description: '',
|
||||
supportedMethods: ['pad', 'sms'],
|
||||
supportedMethods: [...ALL_SIGNING_METHODS],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -708,7 +795,7 @@ function toBackendTaskQuery(query: SigningTaskQuery, options: SigningApiOptions
|
||||
}
|
||||
|
||||
if (query.method && query.method !== 'all') {
|
||||
params.signMethod = query.method === 'sms' ? 'SMS' : 'PAD'
|
||||
params.signMethod = toBackendSigningMethod(query.method)
|
||||
}
|
||||
|
||||
if (query.visitType && query.visitType !== 'all') {
|
||||
@@ -1041,7 +1128,7 @@ export async function createSigningTask(input: CreateSigningTaskInput): Promise<
|
||||
patientId: input.patientId,
|
||||
visitId: input.visitId,
|
||||
templateVersionId: input.templateVersionId,
|
||||
signMethod: input.method === 'sms' ? 'SMS' : 'PAD',
|
||||
signMethod: toBackendSigningMethod(input.method),
|
||||
idempotencyKey: createIdempotencyKey(),
|
||||
}
|
||||
const response = await request.post<ApiResponseOf<SignTaskResponseDto>>(
|
||||
@@ -1244,7 +1331,7 @@ export async function getSigningTaskEvents(id: string): Promise<SigningTaskEvent
|
||||
{
|
||||
id: `${task.id}-created`,
|
||||
time: task.updatedAt,
|
||||
text: `张文静发起签署任务(${task.method === 'pad' ? '手写板' : '线上短信'})`,
|
||||
text: `张文静发起签署任务(${formatSigningMethod(task.method)})`,
|
||||
eventType: 'TASK_CREATED',
|
||||
},
|
||||
]
|
||||
|
||||
@@ -44,7 +44,14 @@ export interface PatientProfile {
|
||||
sex: PatientSex
|
||||
age: number
|
||||
idCard: string
|
||||
/** 展示用手机号。真实接口只返回脱敏值,演示数据同样存脱敏值,两边口径一致。 */
|
||||
phone: string
|
||||
/**
|
||||
* 完整手机号,仅演示数据提供。
|
||||
* 「显示明文」与短信投递预填需要完整号码,而患者接口按合规要求只回脱敏值,
|
||||
* 真实模式拿不到时保持 undefined,页面据此隐藏入口——不拿脱敏值冒充明文。
|
||||
*/
|
||||
phoneFull?: string
|
||||
visits: PatientVisit[]
|
||||
}
|
||||
|
||||
@@ -92,7 +99,15 @@ export interface WorkbenchTask {
|
||||
export type WorkbenchTodoStatus =
|
||||
'created' | 'pending' | 'generating' | 'overdue' | 'signed' | 'voided' | 'failed'
|
||||
|
||||
export type SigningMethod = 'pad' | 'sms'
|
||||
/**
|
||||
* 签署方式(原型 V10.2 的四种,四个平铺取值)。
|
||||
*
|
||||
* 现场两种(手写板原笔迹 / Pad 移动端)与线上两种(短信链接 / 微信公众号)。
|
||||
* **原型里没有「通道」这一层** —— 状态标签、筛选项、详情动作都按具体取值精确分支,
|
||||
* 所以这里也不做任何归并;文案与取值口径集中在 utils/signing-method,
|
||||
* 各页面不要再自己写 `method === 'pad' ? … : …`。
|
||||
*/
|
||||
export type SigningMethod = 'pad' | 'sms' | 'ipad' | 'wx'
|
||||
|
||||
export interface WorkbenchTodoTask {
|
||||
id: string
|
||||
@@ -330,7 +345,11 @@ export interface SigningTaskActionOptions extends SigningApiOptions {
|
||||
export type BackendSigningTaskStatus =
|
||||
'CREATED' | 'WAITING_SIGN' | 'SIGNED' | 'EXPIRED' | 'VOIDED' | 'GENERATING' | 'FAILED'
|
||||
|
||||
export type BackendSigningMethod = 'PAD' | 'SMS'
|
||||
/**
|
||||
* 后端签署方式,与前端 SigningMethod 一一对应(大小写之差)。
|
||||
* 原型 V10.2 就是四个平铺取值,没有「通道」归并,这里保持一致。
|
||||
*/
|
||||
export type BackendSigningMethod = 'PAD' | 'SMS' | 'IPAD' | 'WX'
|
||||
|
||||
export type BackendVisitType = 'OUTPATIENT' | 'INPATIENT' | 'CHECKUP' | string
|
||||
|
||||
|
||||
Reference in New Issue
Block a user