feat(签署工作台): 补齐短信/公众号发送弹窗与 Pad 定位签名位流程
This commit is contained in:
@@ -8,7 +8,12 @@ import type {
|
||||
SigningTaskEvent,
|
||||
SigningTaskRecord,
|
||||
} from '@/api/workbench/types'
|
||||
import type { SigningFieldProgress, SigningSignatureRequest } from '@/utils/signing-document'
|
||||
import {
|
||||
SIGN_FIELD_LOCATE_CLASS,
|
||||
SIGN_FIELD_LOCATE_MS,
|
||||
type SigningFieldProgress,
|
||||
type SigningSignatureRequest,
|
||||
} from '@/utils/signing-document'
|
||||
import { formatSigningMethodTitle, readSigningMethod } from '@/utils/signing-method'
|
||||
|
||||
import SigningDocumentInteractive from '@/components/signing/SigningDocumentInteractive.vue'
|
||||
@@ -81,6 +86,30 @@ function alternateMethods(current: SigningMethod): SigningMethod[] {
|
||||
return ALTERNATE_METHODS.filter((item) => item !== current)
|
||||
}
|
||||
|
||||
/**
|
||||
* 「其余三种方式」按钮各自打开哪个流程(原型 wbActs 里四个按钮的 onclick)。
|
||||
*
|
||||
* 原型这四个按钮**互为入口**:点「短信签署」是弹「发送签署短信」、
|
||||
* 点「公众号签署」是弹「消息推送」、点「Pad 签署」是切换方式并把文书滚到签名位 ——
|
||||
* 都不是「只把方式改一下」。
|
||||
*/
|
||||
function entryActionFor(target: SigningMethod): SigningTaskAction {
|
||||
if (target === 'pad') {
|
||||
return 'pad-sign'
|
||||
}
|
||||
|
||||
if (target === 'ipad') {
|
||||
return 'switch-to-ipad'
|
||||
}
|
||||
|
||||
return target === 'wx' ? 'send-wx-push' : 'send-sms'
|
||||
}
|
||||
|
||||
/** 「查看患者签署页」的按钮文案:原型两处写法不同(短信写 H5、公众号写患者签署页),照抄 */
|
||||
function viewPatientPageLabel(method: SigningMethod): string {
|
||||
return method === 'wx' ? '查看患者签署页(公众号)' : '查看线上签署(H5)'
|
||||
}
|
||||
|
||||
/**
|
||||
* 现场设备签署(手写板 / Pad)走本地采集入口;线上(短信 / 公众号)走患者端页面。
|
||||
* 这只是**入口形态**的分组,不是取值归并 —— 按钮文案、状态标签仍按具体取值区分。
|
||||
@@ -113,7 +142,34 @@ function getDocumentElement() {
|
||||
return documentRef.value?.getDocumentElement() ?? null
|
||||
}
|
||||
|
||||
defineExpose({ getDocumentElement })
|
||||
/**
|
||||
* 「📲 Pad 签署」:把文书滚到第一个签名位并高亮(原型 `openIpad`)。
|
||||
*
|
||||
* 原型这一步**不弹签名板** —— 它只把签名位滚到眼前、闪一下、提示「点击签名框弹出签名板」,
|
||||
* 由操作人自己在文书上点那个签名位。这样「Pad 签署」与「手写板签署」的差别才看得出来:
|
||||
* 前者是在文书上定位后现场签,后者是直接开签名板。
|
||||
*
|
||||
* 返回是否找到了签名位(没找到由父级提示,原型也是 toast 报错)。
|
||||
*/
|
||||
function locateSignatureSlot(): boolean {
|
||||
const root = documentRef.value?.getDocumentElement()
|
||||
const slot = root?.querySelector<HTMLElement>('[data-sign-kind="signature"]')
|
||||
|
||||
if (!slot) {
|
||||
return false
|
||||
}
|
||||
|
||||
slot.scrollIntoView({ behavior: 'smooth', block: 'center' })
|
||||
// 重放动画:先摘类、强制 reflow、再加回去(原型用同一手法)
|
||||
slot.classList.remove(SIGN_FIELD_LOCATE_CLASS)
|
||||
void slot.offsetWidth
|
||||
slot.classList.add(SIGN_FIELD_LOCATE_CLASS)
|
||||
window.setTimeout(() => slot.classList.remove(SIGN_FIELD_LOCATE_CLASS), SIGN_FIELD_LOCATE_MS)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
defineExpose({ getDocumentElement, locateSignatureSlot })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -128,7 +184,9 @@ defineExpose({ getDocumentElement })
|
||||
<span class="task-action-meta">任务 {{ task.id }} · {{ task.patientName }}</span>
|
||||
|
||||
<template v-if="task.status === 'pending'">
|
||||
<!-- 主按钮 = 当前方式的签署入口(原型:手写板/Pad 走现场设备,短信/公众号走线上页面) -->
|
||||
<!-- 主按钮 = 当前方式的签署入口(原型 wbActs 的四个分支):
|
||||
手写板 → 直接开签名板;Pad → 把文书滚到签名位等高亮;短信 → 开「发送签署短信」;
|
||||
公众号 → 开「消息推送」 -->
|
||||
<template v-if="isOnsiteMethod(task.method)">
|
||||
<template v-if="allowLocalSigning">
|
||||
<button type="button" class="action-button" @click="emit('action', 'pad-sign')">
|
||||
@@ -152,8 +210,12 @@ defineExpose({ getDocumentElement })
|
||||
<span v-else class="action-hint">创建会话后仍需接入厂商设备适配器完成签名采集</span>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<!-- 线上方式:消息已经发出去了,此刻等的是患者(原型 `.tg-wait`)。
|
||||
所以主按钮不是「再发一次」,而是「查看患者那一页」;
|
||||
再加一个演示用的「模拟患者完成签署」——
|
||||
演示环境里没人真的去点短信链接,不给这个入口整条链路就走不完 -->
|
||||
<template v-else>
|
||||
<!-- 线上方式先给等待态:这条任务此刻等的是患者,不是操作人 -->
|
||||
<span class="action-wait">{{ waitingHint(task) }}</span>
|
||||
<button
|
||||
v-if="allowLocalSigning"
|
||||
@@ -161,31 +223,40 @@ defineExpose({ getDocumentElement })
|
||||
class="action-button"
|
||||
@click="emit('action', 'online-sign')"
|
||||
>
|
||||
查看{{ readSigningMethod(task.method).short }}签署
|
||||
{{ viewPatientPageLabel(task.method) }}
|
||||
</button>
|
||||
<span v-else class="action-hint">线上签署页面接口待接入</span>
|
||||
<button
|
||||
v-if="allowLocalSigning"
|
||||
type="button"
|
||||
class="action-button action-button--ghost"
|
||||
@click="emit('action', 'simulate-patient-sign')"
|
||||
>
|
||||
✓ 模拟患者完成签署(演示)
|
||||
</button>
|
||||
<button
|
||||
v-if="canDeliveryWrite"
|
||||
type="button"
|
||||
class="action-button action-button--ghost"
|
||||
@click="emit('action', task.method === 'wx' ? 'resend-wx-push' : 'resend-sms')"
|
||||
>
|
||||
{{ task.method === 'wx' ? '重发推送' : '重发短信' }}
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<!-- 其余三种方式:一键转换(原型四种方式互为切换入口) -->
|
||||
<!-- 其余三种方式:**直接打开各自的流程**(原型四个按钮互为入口,不是「只切方式」)。
|
||||
短信按钮先弹「发送签署短信」、公众号按钮先弹「消息推送」,
|
||||
发送/推送成功后才把任务切成那个方式 —— 与原型 openSmsFlow / openWxPush 一致;
|
||||
Pad 按钮 = 切换方式 + 把文书滚到签名位(原型 switchToIpad) -->
|
||||
<button
|
||||
v-for="target in alternateMethods(task.method)"
|
||||
:key="target"
|
||||
type="button"
|
||||
class="action-button action-button--ghost"
|
||||
@click="emit('action', 'switch-method', target)"
|
||||
@click="emit('action', entryActionFor(target))"
|
||||
>
|
||||
{{ readSigningMethod(target).short }}签署
|
||||
{{ readSigningMethod(target).buttonLabel }}
|
||||
</button>
|
||||
|
||||
<button
|
||||
v-if="canDeliveryWrite && task.method === 'sms'"
|
||||
type="button"
|
||||
class="action-button action-button--ghost"
|
||||
@click="emit('action', 'resend-sms')"
|
||||
>
|
||||
重发短信
|
||||
</button>
|
||||
<span v-else-if="task.method === 'wx'" class="action-hint">公众号推送接口待接入</span>
|
||||
</template>
|
||||
|
||||
<!-- 待科室确认:患者已签完,此刻要动的是科室那一道章(原型 confirmDept 的动作组)。
|
||||
|
||||
Reference in New Issue
Block a user