feat(workbench): 接入签署投递与产物管理
This commit is contained in:
@@ -3,6 +3,9 @@ import { computed, onMounted, reactive, ref, watch } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import { getCampuses, getDepartments } from '@/api/management/organization'
|
||||
import { downloadSigningArtifact, getSigningArtifacts } from '@/api/workbench/artifacts'
|
||||
import { createPadSigningSession } from '@/api/workbench/deliveries'
|
||||
import {
|
||||
completeSigningTask,
|
||||
getSigningTaskDetail,
|
||||
@@ -18,6 +21,8 @@ import {
|
||||
import type {
|
||||
SigningDateRange,
|
||||
SigningMethod,
|
||||
SigningArtifact,
|
||||
SignDeliveryResponseDto,
|
||||
SigningTaskEvent,
|
||||
SigningTaskRecord,
|
||||
SigningTaskStatus,
|
||||
@@ -76,11 +81,19 @@ const total = ref(0)
|
||||
const selectedTaskId = ref<string | null>(null)
|
||||
const selectedTask = ref<SigningTaskRecord | null>(null)
|
||||
const taskEvents = ref<SigningTaskEvent[]>([])
|
||||
const artifacts = ref<SigningArtifact[]>([])
|
||||
const templates = ref<SigningTemplate[]>([])
|
||||
const loading = ref(true)
|
||||
const detailLoading = ref(false)
|
||||
const eventsLoading = ref(false)
|
||||
const eventsError = ref(false)
|
||||
const artifactsLoading = ref(false)
|
||||
const artifactsError = ref(false)
|
||||
const padSessionStatus = ref<string | null>(null)
|
||||
const padSessionLoading = ref(false)
|
||||
const campusIds = ref<Record<string, string>>({})
|
||||
const campusNames = ref<Record<string, WorkbenchCampus>>({})
|
||||
const departmentIds = ref<Record<string, string>>({})
|
||||
const newDialogVisible = ref(false)
|
||||
const signatureDialogVisible = ref(false)
|
||||
const onlineDialogVisible = ref(false)
|
||||
@@ -131,6 +144,9 @@ const documentOptions = computed<SigningFilterOption[]>(() => [
|
||||
|
||||
const signingApiOptions = computed(() => ({
|
||||
campus: appStore.selectedCampus,
|
||||
campusId: campusIds.value[appStore.selectedCampus],
|
||||
campusNames: campusNames.value,
|
||||
departmentIds: departmentIds.value,
|
||||
templates: templates.value,
|
||||
}))
|
||||
|
||||
@@ -162,27 +178,67 @@ async function loadTemplates() {
|
||||
}
|
||||
}
|
||||
|
||||
async function loadOrganizationOptions() {
|
||||
if (isSigningMockEnabled) {
|
||||
return
|
||||
}
|
||||
|
||||
const [campusesResult, departmentsResult] = await Promise.allSettled([
|
||||
getCampuses(),
|
||||
getDepartments(),
|
||||
])
|
||||
|
||||
if (campusesResult.status === 'fulfilled') {
|
||||
campusIds.value = Object.fromEntries(
|
||||
campusesResult.value.map((campus) => [campus.name, campus.id]),
|
||||
)
|
||||
campusNames.value = Object.fromEntries(
|
||||
campusesResult.value
|
||||
.filter(
|
||||
(campus): campus is typeof campus & { name: WorkbenchCampus } =>
|
||||
campus.name === '本部院区' || campus.name === '东院区' || campus.name === '西院区',
|
||||
)
|
||||
.map((campus) => [campus.id, campus.name]),
|
||||
)
|
||||
}
|
||||
|
||||
if (departmentsResult.status === 'fulfilled') {
|
||||
departmentIds.value = Object.fromEntries(
|
||||
departmentsResult.value.map((department) => [department.name, department.id]),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
async function loadTaskDetail(id: string | null) {
|
||||
const requestId = ++detailRequestId
|
||||
|
||||
if (!id) {
|
||||
selectedTask.value = null
|
||||
taskEvents.value = []
|
||||
artifacts.value = []
|
||||
detailLoading.value = false
|
||||
eventsLoading.value = false
|
||||
eventsError.value = false
|
||||
artifactsLoading.value = false
|
||||
artifactsError.value = false
|
||||
padSessionStatus.value = null
|
||||
return
|
||||
}
|
||||
|
||||
detailLoading.value = true
|
||||
eventsLoading.value = true
|
||||
eventsError.value = false
|
||||
artifactsLoading.value = true
|
||||
artifactsError.value = false
|
||||
taskEvents.value = []
|
||||
artifacts.value = []
|
||||
padSessionStatus.value = null
|
||||
|
||||
try {
|
||||
const [detailResult, eventsResult] = await Promise.allSettled([
|
||||
const [detailResult, eventsResult, artifactsResult] = await Promise.allSettled([
|
||||
getSigningTaskDetail(id, signingApiOptions.value),
|
||||
getSigningTaskEvents(id),
|
||||
getSigningArtifacts(id),
|
||||
])
|
||||
|
||||
if (requestId === detailRequestId) {
|
||||
@@ -197,6 +253,12 @@ async function loadTaskDetail(id: string | null) {
|
||||
} else {
|
||||
eventsError.value = true
|
||||
}
|
||||
|
||||
if (artifactsResult.status === 'fulfilled') {
|
||||
artifacts.value = artifactsResult.value
|
||||
} else {
|
||||
artifactsError.value = true
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
if (requestId === detailRequestId) {
|
||||
@@ -208,6 +270,7 @@ async function loadTaskDetail(id: string | null) {
|
||||
if (requestId === detailRequestId) {
|
||||
detailLoading.value = false
|
||||
eventsLoading.value = false
|
||||
artifactsLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -295,6 +358,22 @@ async function handleTaskAction(action: SigningTaskAction) {
|
||||
return
|
||||
}
|
||||
|
||||
if (action === 'create-pad-session') {
|
||||
padSessionLoading.value = true
|
||||
|
||||
try {
|
||||
const session: SignDeliveryResponseDto = await createPadSigningSession(task.id)
|
||||
padSessionStatus.value = session.status
|
||||
ElMessage.success('手写板签署会话已创建,请由设备适配器继续采集签名')
|
||||
} catch {
|
||||
ElMessage.error('手写板签署会话创建失败,请稍后重试')
|
||||
} finally {
|
||||
padSessionLoading.value = false
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (action === 'online-sign') {
|
||||
if (!isSigningMockEnabled) {
|
||||
ElMessage.info('线上签署页面接口待接入')
|
||||
@@ -311,12 +390,26 @@ async function handleTaskAction(action: SigningTaskAction) {
|
||||
}
|
||||
|
||||
if (action === 'download-pdf') {
|
||||
ElMessage.info('原型演示:PDF 原件下载接口待接入')
|
||||
const artifact =
|
||||
artifacts.value.find((item) => item.artifactType === 'SIGNED_PDF') ??
|
||||
artifacts.value.find((item) => item.artifactType === 'ORIGINAL_PDF')
|
||||
|
||||
if (artifact) {
|
||||
await downloadArtifact(artifact)
|
||||
} else {
|
||||
ElMessage.info('当前任务暂无 PDF 文件')
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (action === 'download-signature') {
|
||||
ElMessage.info('原型演示:签名原图下载接口待接入')
|
||||
const artifact = artifacts.value.find((item) => item.artifactType === 'SIGNATURE_IMAGE')
|
||||
|
||||
if (artifact) {
|
||||
await downloadArtifact(artifact)
|
||||
} else {
|
||||
ElMessage.info('当前任务暂无签名原图')
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -365,6 +458,21 @@ async function handleTaskAction(action: SigningTaskAction) {
|
||||
}
|
||||
}
|
||||
|
||||
async function downloadArtifact(artifact: SigningArtifact) {
|
||||
try {
|
||||
const blob = await downloadSigningArtifact(artifact.id)
|
||||
const url = URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = artifact.fileName
|
||||
link.click()
|
||||
window.setTimeout(() => URL.revokeObjectURL(url), 0)
|
||||
ElMessage.success(`${artifact.label}下载已开始`)
|
||||
} catch {
|
||||
ElMessage.error(`${artifact.label}下载失败,请稍后重试`)
|
||||
}
|
||||
}
|
||||
|
||||
async function confirmPadSignature(signatureDataUrl: string) {
|
||||
const task = selectedTask.value
|
||||
|
||||
@@ -421,6 +529,7 @@ async function handleOnlineResend() {
|
||||
}
|
||||
|
||||
async function initializePage() {
|
||||
await loadOrganizationOptions()
|
||||
await loadTemplates()
|
||||
await loadTasks()
|
||||
}
|
||||
@@ -494,7 +603,13 @@ onMounted(() => {
|
||||
:audit-loading="eventsLoading"
|
||||
:audit-error="eventsError"
|
||||
:allow-local-signing="isSigningMockEnabled"
|
||||
:artifacts="artifacts"
|
||||
:artifacts-loading="artifactsLoading"
|
||||
:artifacts-error="artifactsError"
|
||||
:pad-session-status="padSessionStatus"
|
||||
:pad-session-loading="padSessionLoading"
|
||||
@action="handleTaskAction"
|
||||
@download-artifact="downloadArtifact"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user