feat(signing): 接入工作台任务操作与审计
This commit is contained in:
@@ -6,8 +6,10 @@ import { useRoute } from 'vue-router'
|
||||
import {
|
||||
completeSigningTask,
|
||||
getSigningTaskDetail,
|
||||
getSigningTaskEvents,
|
||||
getSigningTasks,
|
||||
getSigningTemplates,
|
||||
isSigningMockEnabled,
|
||||
reopenSigningTask,
|
||||
resendSigningSms,
|
||||
updateSigningTaskMethod,
|
||||
@@ -16,6 +18,7 @@ import {
|
||||
import type {
|
||||
SigningDateRange,
|
||||
SigningMethod,
|
||||
SigningTaskEvent,
|
||||
SigningTaskRecord,
|
||||
SigningTaskStatus,
|
||||
SigningTemplate,
|
||||
@@ -43,6 +46,7 @@ const STATUS_VALUES: SigningTaskStatus[] = [
|
||||
'rejected',
|
||||
'expired',
|
||||
'void',
|
||||
'failed',
|
||||
]
|
||||
const DATE_RANGE_VALUES: SigningDateRange[] = ['today', 'yesterday', '3d', '7d', 'all']
|
||||
|
||||
@@ -53,6 +57,7 @@ const statusLabels: Record<SigningTaskStatus, string> = {
|
||||
rejected: '已拒签',
|
||||
expired: '已超时',
|
||||
void: '已作废',
|
||||
failed: '处理失败',
|
||||
}
|
||||
|
||||
const filter = reactive<SigningFilterForm>({
|
||||
@@ -70,9 +75,12 @@ const tasks = ref<SigningTaskRecord[]>([])
|
||||
const total = ref(0)
|
||||
const selectedTaskId = ref<string | null>(null)
|
||||
const selectedTask = ref<SigningTaskRecord | null>(null)
|
||||
const taskEvents = ref<SigningTaskEvent[]>([])
|
||||
const templates = ref<SigningTemplate[]>([])
|
||||
const loading = ref(true)
|
||||
const detailLoading = ref(false)
|
||||
const eventsLoading = ref(false)
|
||||
const eventsError = ref(false)
|
||||
const newDialogVisible = ref(false)
|
||||
const signatureDialogVisible = ref(false)
|
||||
const onlineDialogVisible = ref(false)
|
||||
@@ -121,6 +129,11 @@ const documentOptions = computed<SigningFilterOption[]>(() => [
|
||||
...templates.value.map((template) => ({ label: template.name, value: template.id })),
|
||||
])
|
||||
|
||||
const signingApiOptions = computed(() => ({
|
||||
campus: appStore.selectedCampus,
|
||||
templates: templates.value,
|
||||
}))
|
||||
|
||||
function getQueryString(value: unknown) {
|
||||
return typeof value === 'string' ? value : ''
|
||||
}
|
||||
@@ -154,26 +167,47 @@ async function loadTaskDetail(id: string | null) {
|
||||
|
||||
if (!id) {
|
||||
selectedTask.value = null
|
||||
taskEvents.value = []
|
||||
detailLoading.value = false
|
||||
eventsLoading.value = false
|
||||
eventsError.value = false
|
||||
return
|
||||
}
|
||||
|
||||
detailLoading.value = true
|
||||
eventsLoading.value = true
|
||||
eventsError.value = false
|
||||
taskEvents.value = []
|
||||
|
||||
try {
|
||||
const detail = await getSigningTaskDetail(id)
|
||||
const [detailResult, eventsResult] = await Promise.allSettled([
|
||||
getSigningTaskDetail(id, signingApiOptions.value),
|
||||
getSigningTaskEvents(id),
|
||||
])
|
||||
|
||||
if (requestId === detailRequestId) {
|
||||
selectedTask.value = detail
|
||||
if (detailResult.status === 'rejected') {
|
||||
throw detailResult.reason
|
||||
}
|
||||
|
||||
selectedTask.value = detailResult.value
|
||||
|
||||
if (eventsResult.status === 'fulfilled') {
|
||||
taskEvents.value = eventsResult.value
|
||||
} else {
|
||||
eventsError.value = true
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
if (requestId === detailRequestId) {
|
||||
selectedTask.value = null
|
||||
taskEvents.value = []
|
||||
ElMessage.error('签署任务详情加载失败,请稍后重试')
|
||||
}
|
||||
} finally {
|
||||
if (requestId === detailRequestId) {
|
||||
detailLoading.value = false
|
||||
eventsLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,11 +217,14 @@ async function loadTasks(preferredTaskId?: string) {
|
||||
loading.value = true
|
||||
|
||||
try {
|
||||
const response = await getSigningTasks({
|
||||
...filter,
|
||||
page: 1,
|
||||
pageSize: 50,
|
||||
})
|
||||
const response = await getSigningTasks(
|
||||
{
|
||||
...filter,
|
||||
page: 1,
|
||||
pageSize: 50,
|
||||
},
|
||||
signingApiOptions.value,
|
||||
)
|
||||
|
||||
if (requestId !== listRequestId) {
|
||||
return
|
||||
@@ -249,11 +286,21 @@ async function handleTaskAction(action: SigningTaskAction) {
|
||||
}
|
||||
|
||||
if (action === 'pad-sign') {
|
||||
if (!isSigningMockEnabled) {
|
||||
ElMessage.info('手写板设备签署接口待接入')
|
||||
return
|
||||
}
|
||||
|
||||
signatureDialogVisible.value = true
|
||||
return
|
||||
}
|
||||
|
||||
if (action === 'online-sign') {
|
||||
if (!isSigningMockEnabled) {
|
||||
ElMessage.info('线上签署页面接口待接入')
|
||||
return
|
||||
}
|
||||
|
||||
onlineDialogVisible.value = true
|
||||
return
|
||||
}
|
||||
@@ -280,6 +327,11 @@ async function handleTaskAction(action: SigningTaskAction) {
|
||||
|
||||
try {
|
||||
if (action === 'switch-method') {
|
||||
if (!isSigningMockEnabled) {
|
||||
ElMessage.info('当前后端未提供切换签署方式接口,请作废后重新创建任务')
|
||||
return
|
||||
}
|
||||
|
||||
const method: SigningMethod = task.method === 'pad' ? 'sms' : 'pad'
|
||||
await refreshTask(
|
||||
await updateSigningTaskMethod(task.id, method),
|
||||
@@ -289,12 +341,24 @@ async function handleTaskAction(action: SigningTaskAction) {
|
||||
}
|
||||
|
||||
if (action === 'resend-sms') {
|
||||
await refreshTask(await resendSigningSms(task.id), '短信已重新发送')
|
||||
await refreshTask(
|
||||
await resendSigningSms(task.id, {
|
||||
...signingApiOptions.value,
|
||||
expectedRowVersion: task.rowVersion,
|
||||
}),
|
||||
'短信已重新发送',
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if (action === 'reopen') {
|
||||
await refreshTask(await reopenSigningTask(task.id), '签署任务已重新发起')
|
||||
await refreshTask(
|
||||
await reopenSigningTask(task.id, {
|
||||
...signingApiOptions.value,
|
||||
expectedRowVersion: task.rowVersion,
|
||||
}),
|
||||
'签署任务已重新发起',
|
||||
)
|
||||
}
|
||||
} catch {
|
||||
ElMessage.error('任务操作失败,请稍后重试')
|
||||
@@ -339,7 +403,13 @@ async function confirmVoidTask(reason: string) {
|
||||
}
|
||||
|
||||
try {
|
||||
await refreshTask(await voidSigningTask(task.id, reason), '签署任务已作废')
|
||||
await refreshTask(
|
||||
await voidSigningTask(task.id, reason, {
|
||||
...signingApiOptions.value,
|
||||
expectedRowVersion: task.rowVersion,
|
||||
}),
|
||||
'签署任务已作废',
|
||||
)
|
||||
voidDialogVisible.value = false
|
||||
} catch {
|
||||
ElMessage.error('任务作废失败,请稍后重试')
|
||||
@@ -350,6 +420,11 @@ async function handleOnlineResend() {
|
||||
await handleTaskAction('resend-sms')
|
||||
}
|
||||
|
||||
async function initializePage() {
|
||||
await loadTemplates()
|
||||
await loadTasks()
|
||||
}
|
||||
|
||||
async function handleTaskCreated(task: SigningTaskRecord) {
|
||||
await loadTasks(task.id)
|
||||
}
|
||||
@@ -375,7 +450,7 @@ watch(
|
||||
|
||||
onMounted(() => {
|
||||
syncFilterFromRoute()
|
||||
void Promise.all([loadTemplates(), loadTasks()])
|
||||
void initializePage()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -412,7 +487,15 @@ onMounted(() => {
|
||||
:loading="loading"
|
||||
@select="selectTask"
|
||||
/>
|
||||
<SigningTaskDetail :task="selectedTask" :loading="detailLoading" @action="handleTaskAction" />
|
||||
<SigningTaskDetail
|
||||
:task="selectedTask"
|
||||
:loading="detailLoading"
|
||||
:audit-events="taskEvents"
|
||||
:audit-loading="eventsLoading"
|
||||
:audit-error="eventsError"
|
||||
:allow-local-signing="isSigningMockEnabled"
|
||||
@action="handleTaskAction"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<NewSigningTaskDialog
|
||||
|
||||
Reference in New Issue
Block a user