feat(签署工作台): 补齐短信/公众号发送弹窗与 Pad 定位签名位流程

This commit is contained in:
yelan
2026-09-27 16:50:13 +08:00
parent 39d27ae5e7
commit ea5a248a0c
9 changed files with 981 additions and 20 deletions
+113
View File
@@ -1263,6 +1263,119 @@ export function updateSigningTaskMethod(
return Promise.resolve(cloneTask(task))
}
/** 手机号脱敏:与后端 `smsMobileMasked` 同口径(保留前 3 后 4) */
function maskMobile(mobile: string): string {
const digits = mobile.replace(/\D/g, '')
return digits.length === 11 ? `${digits.slice(0, 3)}****${digits.slice(-4)}` : mobile
}
/**
* 演示模式:发送签署短信(原型 `sendSmsFlow`)。
*
* 与「重发短信」的区别:这一步会把任务**切成短信方式**并记下发送号码 ——
* 所以从别的入口点「短信签署」时,方式切换是在这里完成的,
* 不是先把方式改掉再发(原型也是 `sendSmsFlow` 里才 `smsTask.method='sms'`)。
* 号码只留脱敏值,详情里的等待提示直接用它;真实模式后端没有这个接口。
*/
export function sendSigningSms(
id: string,
mobile: string | null,
): Promise<SigningTaskRecord | null> {
if (!useMockData) {
throw new Error('当前后端未提供发送签署短信接口')
}
const task = mockRecords.find((record) => record.id === id)
if (!task) {
return Promise.resolve(null)
}
task.method = 'sms'
// mobile 为 null = 发到登记号码,那就保留原有的脱敏值不动
if (mobile) {
task.smsMobileMasked = maskMobile(mobile)
}
task.updatedAt = formatMockDate()
persistMockRecords()
return Promise.resolve(cloneTask(task))
}
/**
* 演示模式:推送公众号签署消息(原型 `sendWxPush`)。
* 与短信那条同理 —— 方式切换发生在推送这一步。
*/
export function pushSigningWxMessage(id: string): Promise<SigningTaskRecord | null> {
if (!useMockData) {
throw new Error('当前后端未提供公众号签署推送接口')
}
const task = mockRecords.find((record) => record.id === id)
if (!task) {
return Promise.resolve(null)
}
task.method = 'wx'
task.updatedAt = formatMockDate()
persistMockRecords()
return Promise.resolve(cloneTask(task))
}
/**
* 演示模式:重发公众号推送(原型 `wxResend`)。
* 只刷新时间,不改方式 —— 方式在第一次推送时就定了。
*/
export function resendSigningWxMessage(id: string): Promise<SigningTaskRecord | null> {
if (!useMockData) {
throw new Error('当前后端未提供公众号签署推送接口')
}
const task = mockRecords.find((record) => record.id === id)
if (!task) {
return Promise.resolve(null)
}
task.updatedAt = formatMockDate()
persistMockRecords()
return Promise.resolve(cloneTask(task))
}
/**
* 演示模式:模拟患者完成签署(原型 `smsSmsDone` / `wxDone`)。
*
* 演示环境里没人真的去点短信链接 / 打开公众号消息,不给这个入口整条链路走不完。
* 落哪个状态与真实签署同口径(`needConfirm` → `confirming`),
* 签名用演示图 —— 但**必须留痕**,所以走的是与真实签署同一条写库路径。
*/
export function simulatePatientSigning(id: string): Promise<SigningTaskRecord | null> {
if (!useMockData) {
throw new Error('演示入口,真实模式请由患者在签署页完成')
}
const task = mockRecords.find((record) => record.id === id)
if (!task) {
return Promise.resolve(null)
}
if (task.status !== 'pending') {
throw new Error('只有「待签署」的任务可以模拟患者签署')
}
task.status = task.needConfirm ? 'confirming' : 'signed'
task.signatureDataUrl = DEMO_SIGNATURE_DATA_URL
task.signedAt = formatMockDate()
task.updatedAt = task.signedAt
task.fieldAnswers = { ...(task.fieldAnswers ?? {}), signature: DEMO_SIGNATURE_DATA_URL }
persistMockRecords()
return Promise.resolve(cloneTask(task))
}
export function completeSigningTask(
id: string,
signatureDataUrl: string,