fix(signing): align workbench with MEDISIGN contract
This commit is contained in:
@@ -226,7 +226,7 @@ function mapReportTask(task: SigningTaskRecord, templates: SigningTemplate[]): R
|
||||
? 'signed'
|
||||
: task.status === 'expired'
|
||||
? 'expired'
|
||||
: task.status === 'void' || task.status === 'failed' || task.status === 'rejected'
|
||||
: task.status === 'void' || task.status === 'failed'
|
||||
? 'void'
|
||||
: 'pending'
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ function formatFileSize(size: number) {
|
||||
</div>
|
||||
<div class="artifact-info">
|
||||
<strong>{{ artifact.label }}</strong>
|
||||
<span>{{ artifact.fileName }} · {{ formatFileSize(artifact.size) }}</span>
|
||||
<span>{{ artifact.fileName }} · {{ formatFileSize(artifact.sizeBytes) }}</span>
|
||||
<small v-if="artifact.createdAt">生成于 {{ artifact.createdAt }}</small>
|
||||
</div>
|
||||
<button type="button" class="artifact-download" @click="emit('download', artifact)">
|
||||
|
||||
@@ -93,7 +93,7 @@ const emit = defineEmits<{
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<template v-else-if="task.status === 'expired' || task.status === 'failed'">
|
||||
<template v-else-if="task.status === 'expired'">
|
||||
<button type="button" class="action-button" @click="emit('action', 'reopen')">
|
||||
↻ 重新发起
|
||||
</button>
|
||||
@@ -105,7 +105,7 @@ const emit = defineEmits<{
|
||||
class="action-button action-button--ghost"
|
||||
@click="emit('action', 'download-pdf')"
|
||||
>
|
||||
下载 PDF 原件
|
||||
下载签署后 PDF
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
|
||||
import type { SigningTaskRecord } from '@/api/workbench/types'
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
tasks: SigningTaskRecord[]
|
||||
selectedId: string | null
|
||||
total: number
|
||||
page: number
|
||||
pageSize: number
|
||||
loading: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
select: [id: string]
|
||||
pageChange: [page: number]
|
||||
}>()
|
||||
|
||||
const pageCount = computed(() => Math.max(Math.ceil(props.total / props.pageSize), 1))
|
||||
|
||||
const statusLabels: Record<SigningTaskRecord['status'], string> = {
|
||||
pending: '待签署',
|
||||
signing: '签署中',
|
||||
signed: '已签署',
|
||||
rejected: '已拒签',
|
||||
expired: '已超时',
|
||||
void: '已作废',
|
||||
failed: '处理失败',
|
||||
@@ -100,6 +106,21 @@ function getVisitClass(type: SigningTaskRecord['visitType']) {
|
||||
<span aria-hidden="true">🔍</span>
|
||||
<p>没有符合条件的任务</p>
|
||||
</div>
|
||||
|
||||
<footer v-if="total > pageSize" class="task-pagination">
|
||||
<span>第 {{ page }} / {{ pageCount }} 页</span>
|
||||
<span class="task-pagination__total">共 {{ total }} 条</span>
|
||||
<button type="button" :disabled="page <= 1 || loading" @click="emit('pageChange', page - 1)">
|
||||
上一页
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
:disabled="page >= pageCount || loading"
|
||||
@click="emit('pageChange', page + 1)"
|
||||
>
|
||||
下一页
|
||||
</button>
|
||||
</footer>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
@@ -212,7 +233,6 @@ function getVisitClass(type: SigningTaskRecord['visitType']) {
|
||||
background: var(--ok-l);
|
||||
}
|
||||
|
||||
.task-status--rejected,
|
||||
.task-status--expired {
|
||||
color: var(--err);
|
||||
background: var(--err-l);
|
||||
@@ -292,6 +312,42 @@ function getVisitClass(type: SigningTaskRecord['visitType']) {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.task-pagination {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
padding: 9px 10px;
|
||||
margin-top: 10px;
|
||||
color: var(--mut);
|
||||
font-size: 11.5px;
|
||||
background: var(--card);
|
||||
border-radius: var(--r);
|
||||
box-shadow: var(--sh);
|
||||
}
|
||||
|
||||
.task-pagination__total {
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.task-pagination button {
|
||||
padding: 4px 8px;
|
||||
color: var(--brand);
|
||||
font-size: 11.5px;
|
||||
background: #fff;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.task-pagination button:hover:not(:disabled) {
|
||||
border-color: var(--brand);
|
||||
background: var(--brand-l);
|
||||
}
|
||||
|
||||
.task-pagination button:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
.task-items--loading {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -48,7 +48,6 @@ const STATUS_VALUES: SigningTaskStatus[] = [
|
||||
'pending',
|
||||
'signing',
|
||||
'signed',
|
||||
'rejected',
|
||||
'expired',
|
||||
'void',
|
||||
'failed',
|
||||
@@ -59,7 +58,6 @@ const statusLabels: Record<SigningTaskStatus, string> = {
|
||||
pending: '待签署',
|
||||
signing: '签署中',
|
||||
signed: '已签署',
|
||||
rejected: '已拒签',
|
||||
expired: '已超时',
|
||||
void: '已作废',
|
||||
failed: '处理失败',
|
||||
@@ -78,6 +76,8 @@ const filter = reactive<SigningFilterForm>({
|
||||
|
||||
const tasks = ref<SigningTaskRecord[]>([])
|
||||
const total = ref(0)
|
||||
const page = ref(1)
|
||||
const pageSize = ref(20)
|
||||
const selectedTaskId = ref<string | null>(null)
|
||||
const selectedTask = ref<SigningTaskRecord | null>(null)
|
||||
const taskEvents = ref<SigningTaskEvent[]>([])
|
||||
@@ -145,6 +145,7 @@ const documentOptions = computed<SigningFilterOption[]>(() => [
|
||||
const signingApiOptions = computed(() => ({
|
||||
campus: appStore.selectedCampus,
|
||||
campusId: campusIds.value[appStore.selectedCampus],
|
||||
campusIds: campusIds.value,
|
||||
campusNames: campusNames.value,
|
||||
departmentIds: departmentIds.value,
|
||||
templates: templates.value,
|
||||
@@ -275,7 +276,11 @@ async function loadTaskDetail(id: string | null) {
|
||||
}
|
||||
}
|
||||
|
||||
async function loadTasks(preferredTaskId?: string) {
|
||||
async function loadTasks(preferredTaskId?: string, resetPage = false) {
|
||||
if (resetPage) {
|
||||
page.value = 1
|
||||
}
|
||||
|
||||
const requestId = ++listRequestId
|
||||
loading.value = true
|
||||
|
||||
@@ -283,8 +288,8 @@ async function loadTasks(preferredTaskId?: string) {
|
||||
const response = await getSigningTasks(
|
||||
{
|
||||
...filter,
|
||||
page: 1,
|
||||
pageSize: 50,
|
||||
page: page.value,
|
||||
pageSize: pageSize.value,
|
||||
},
|
||||
signingApiOptions.value,
|
||||
)
|
||||
@@ -295,6 +300,8 @@ async function loadTasks(preferredTaskId?: string) {
|
||||
|
||||
tasks.value = response.records
|
||||
total.value = response.total
|
||||
page.value = response.page
|
||||
pageSize.value = response.pageSize
|
||||
|
||||
const taskIds = new Set(response.records.map((task) => task.id))
|
||||
const routeTaskId = getQueryString(route.query.taskId)
|
||||
@@ -323,7 +330,7 @@ async function loadTasks(preferredTaskId?: string) {
|
||||
function handleSearch(nextFilter: SigningFilterForm) {
|
||||
Object.assign(filter, nextFilter)
|
||||
selectedTaskId.value = null
|
||||
void loadTasks()
|
||||
void loadTasks(undefined, true)
|
||||
}
|
||||
|
||||
function selectTask(id: string) {
|
||||
@@ -331,13 +338,25 @@ function selectTask(id: string) {
|
||||
void loadTaskDetail(id)
|
||||
}
|
||||
|
||||
function handlePageChange(nextPage: number) {
|
||||
const pageCount = Math.max(Math.ceil(total.value / pageSize.value), 1)
|
||||
|
||||
if (nextPage < 1 || nextPage > pageCount || nextPage === page.value) {
|
||||
return
|
||||
}
|
||||
|
||||
page.value = nextPage
|
||||
selectedTaskId.value = null
|
||||
void loadTasks()
|
||||
}
|
||||
|
||||
async function refreshTask(updatedTask: SigningTaskRecord | null, successMessage: string) {
|
||||
if (!updatedTask) {
|
||||
ElMessage.error('签署任务不存在或已被删除')
|
||||
return
|
||||
}
|
||||
|
||||
await loadTasks(updatedTask.id)
|
||||
await loadTasks(updatedTask.id, true)
|
||||
ElMessage.success(successMessage)
|
||||
}
|
||||
|
||||
@@ -389,15 +408,18 @@ async function handleTaskAction(action: SigningTaskAction) {
|
||||
return
|
||||
}
|
||||
|
||||
if (action === 'reopen' && task.status !== 'expired') {
|
||||
ElMessage.info('只有已超时任务可以重新发起')
|
||||
return
|
||||
}
|
||||
|
||||
if (action === 'download-pdf') {
|
||||
const artifact =
|
||||
artifacts.value.find((item) => item.artifactType === 'SIGNED_PDF') ??
|
||||
artifacts.value.find((item) => item.artifactType === 'ORIGINAL_PDF')
|
||||
const artifact = artifacts.value.find((item) => item.artifactType === 'SIGNED_PDF')
|
||||
|
||||
if (artifact) {
|
||||
await downloadArtifact(artifact)
|
||||
} else {
|
||||
ElMessage.info('当前任务暂无 PDF 文件')
|
||||
ElMessage.info('当前任务暂无签署后 PDF')
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -535,13 +557,14 @@ async function initializePage() {
|
||||
}
|
||||
|
||||
async function handleTaskCreated(task: SigningTaskRecord) {
|
||||
await loadTasks(task.id)
|
||||
await loadTasks(task.id, true)
|
||||
}
|
||||
|
||||
watch(
|
||||
() => [route.query.status, route.query.range, route.query.taskId],
|
||||
() => {
|
||||
syncFilterFromRoute()
|
||||
page.value = 1
|
||||
selectedTaskId.value = null
|
||||
void loadTasks()
|
||||
},
|
||||
@@ -553,6 +576,7 @@ watch(
|
||||
if (filter.campus !== 'all') {
|
||||
filter.campus = campus
|
||||
}
|
||||
page.value = 1
|
||||
void loadTasks()
|
||||
},
|
||||
)
|
||||
@@ -593,8 +617,11 @@ onMounted(() => {
|
||||
:tasks="tasks"
|
||||
:selected-id="selectedTaskId"
|
||||
:total="total"
|
||||
:page="page"
|
||||
:page-size="pageSize"
|
||||
:loading="loading"
|
||||
@select="selectTask"
|
||||
@page-change="handlePageChange"
|
||||
/>
|
||||
<SigningTaskDetail
|
||||
:task="selectedTask"
|
||||
|
||||
Reference in New Issue
Block a user