Merge branch 'master' of https://gitea.xinyuxi.com/zhanggaoming/xh-medical-sign-web
This commit is contained in:
@@ -5,6 +5,7 @@ defineProps<{
|
||||
artifacts: SigningArtifact[]
|
||||
loading: boolean
|
||||
error: boolean
|
||||
canDownload: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -51,7 +52,12 @@ function formatFileSize(size: number) {
|
||||
<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)">
|
||||
<button
|
||||
v-if="canDownload"
|
||||
type="button"
|
||||
class="artifact-download"
|
||||
@click="emit('download', artifact)"
|
||||
>
|
||||
下载
|
||||
</button>
|
||||
</li>
|
||||
|
||||
@@ -13,6 +13,7 @@ const props = defineProps<{
|
||||
departments: SigningFilterOption[]
|
||||
documents: SigningFilterOption[]
|
||||
visitTypes: SigningFilterOption<VisitType | 'all'>[]
|
||||
canCreate: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -109,7 +110,9 @@ function submit() {
|
||||
|
||||
<span class="filter-spacer" />
|
||||
<button type="submit" class="action-button action-button--ghost">查询</button>
|
||||
<button type="button" class="action-button" @click="emit('add')">+ 新增签署任务</button>
|
||||
<button v-if="canCreate" type="button" class="action-button" @click="emit('add')">
|
||||
+ 新增签署任务
|
||||
</button>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -27,6 +27,12 @@ defineProps<{
|
||||
artifactsError: boolean
|
||||
padSessionStatus: string | null
|
||||
padSessionLoading: boolean
|
||||
canDeliveryWrite: boolean
|
||||
canReopen: boolean
|
||||
canVoid: boolean
|
||||
canViewAudit: boolean
|
||||
canViewArtifacts: boolean
|
||||
canDownloadArtifact: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -70,7 +76,7 @@ defineExpose({ getDocumentElement })
|
||||
转为短信发送
|
||||
</button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<template v-else-if="canDeliveryWrite">
|
||||
<button
|
||||
type="button"
|
||||
class="action-button"
|
||||
@@ -105,6 +111,7 @@ defineExpose({ getDocumentElement })
|
||||
转手写板签署
|
||||
</button>
|
||||
<button
|
||||
v-if="canDeliveryWrite"
|
||||
type="button"
|
||||
class="action-button action-button--ghost"
|
||||
@click="emit('action', 'resend-sms')"
|
||||
@@ -113,15 +120,13 @@ defineExpose({ getDocumentElement })
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<!-- 处理失败与已超时都需要「重新发起」这条出路:只给「作废」的话,
|
||||
一次偶发的后端处理失败就得把整个任务废掉重来 -->
|
||||
<template v-else-if="task.status === 'expired' || task.status === 'failed'">
|
||||
<template v-else-if="task.status === 'expired' && canReopen">
|
||||
<button type="button" class="action-button" @click="emit('action', 'reopen')">
|
||||
↻ 重新发起
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<template v-else-if="task.status === 'signed'">
|
||||
<template v-else-if="task.status === 'signed' && canDownloadArtifact">
|
||||
<button
|
||||
type="button"
|
||||
class="action-button action-button--ghost"
|
||||
@@ -147,10 +152,11 @@ defineExpose({ getDocumentElement })
|
||||
|
||||
<button
|
||||
v-if="
|
||||
task.status === 'pending' ||
|
||||
task.status === 'expired' ||
|
||||
task.status === 'signing' ||
|
||||
task.status === 'failed'
|
||||
canVoid &&
|
||||
(task.status === 'pending' ||
|
||||
task.status === 'expired' ||
|
||||
task.status === 'signing' ||
|
||||
task.status === 'failed')
|
||||
"
|
||||
type="button"
|
||||
class="action-button action-button--danger"
|
||||
@@ -171,11 +177,18 @@ defineExpose({ getDocumentElement })
|
||||
@field-change="(answers, progress) => emit('fieldChange', answers, progress)"
|
||||
/>
|
||||
<SigningDocumentPreview v-else :task="task" />
|
||||
<TaskAuditTimeline :events="auditEvents" :loading="auditLoading" :error="auditError" />
|
||||
<TaskAuditTimeline
|
||||
v-if="canViewAudit"
|
||||
:events="auditEvents"
|
||||
:loading="auditLoading"
|
||||
:error="auditError"
|
||||
/>
|
||||
<SigningArtifactList
|
||||
v-if="canViewArtifacts"
|
||||
:artifacts="artifacts"
|
||||
:loading="artifactsLoading"
|
||||
:error="artifactsError"
|
||||
:can-download="canDownloadArtifact"
|
||||
@download="emit('downloadArtifact', $event)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -37,6 +37,7 @@ import type {
|
||||
} from '@/api/workbench/types'
|
||||
import NewSigningTaskDialog from '@/components/signing/NewSigningTaskDialog.vue'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
import { useLoginStore } from '@/stores/login'
|
||||
import type { SigningFieldProgress } from '@/utils/signing-document'
|
||||
import { downloadSigningPdf } from '@/utils/signing-pdf'
|
||||
|
||||
@@ -50,6 +51,7 @@ import type { SigningFilterForm, SigningFilterOption, SigningTaskAction } from '
|
||||
|
||||
const route = useRoute()
|
||||
const appStore = useAppStore()
|
||||
const loginStore = useLoginStore()
|
||||
|
||||
const STATUS_VALUES: SigningTaskStatus[] = [
|
||||
'pending',
|
||||
@@ -117,6 +119,24 @@ const pdfExporting = ref(false)
|
||||
let listRequestId = 0
|
||||
let detailRequestId = 0
|
||||
|
||||
function canWrite(permission: string) {
|
||||
return (
|
||||
!loginStore.isReadOnly && (isSigningMockEnabled || loginStore.hasWritePermission(permission))
|
||||
)
|
||||
}
|
||||
|
||||
function canRead(permission: string) {
|
||||
return isSigningMockEnabled || loginStore.hasPermission(permission)
|
||||
}
|
||||
|
||||
const canCreateTask = computed(() => canWrite('sign:task:create'))
|
||||
const canDeliveryWrite = computed(() => canWrite('sign:delivery:write'))
|
||||
const canReopenTask = computed(() => canWrite('sign:task:reopen'))
|
||||
const canVoidTask = computed(() => canWrite('sign:task:void'))
|
||||
const canViewEvents = computed(() => canRead('sign:task:event:query'))
|
||||
const canViewArtifacts = computed(() => canRead('sign:artifact:query'))
|
||||
const canDownloadArtifacts = computed(() => canRead('sign:artifact:download'))
|
||||
|
||||
const campusOptions = computed<SigningFilterOption<WorkbenchCampus | 'all'>[]>(() => [
|
||||
{ label: '全部院区', value: 'all' },
|
||||
...appStore.campuses.map((campus) => ({ label: campus, value: campus })),
|
||||
@@ -248,9 +268,9 @@ async function loadTaskDetail(id: string | null) {
|
||||
}
|
||||
|
||||
detailLoading.value = true
|
||||
eventsLoading.value = true
|
||||
eventsLoading.value = canViewEvents.value
|
||||
eventsError.value = false
|
||||
artifactsLoading.value = true
|
||||
artifactsLoading.value = canViewArtifacts.value
|
||||
artifactsError.value = false
|
||||
taskEvents.value = []
|
||||
artifacts.value = []
|
||||
@@ -259,8 +279,8 @@ async function loadTaskDetail(id: string | null) {
|
||||
try {
|
||||
const [detailResult, eventsResult, artifactsResult] = await Promise.allSettled([
|
||||
getSigningTaskDetail(id, signingApiOptions.value),
|
||||
getSigningTaskEvents(id),
|
||||
getSigningArtifacts(id),
|
||||
canViewEvents.value ? getSigningTaskEvents(id) : Promise.resolve([]),
|
||||
canViewArtifacts.value ? getSigningArtifacts(id) : Promise.resolve([]),
|
||||
])
|
||||
|
||||
if (requestId === detailRequestId) {
|
||||
@@ -431,6 +451,20 @@ async function handleTaskAction(action: SigningTaskAction) {
|
||||
return
|
||||
}
|
||||
|
||||
const allowed =
|
||||
isSigningMockEnabled ||
|
||||
(action === 'create-pad-session' && canDeliveryWrite.value) ||
|
||||
(action === 'resend-sms' && canDeliveryWrite.value) ||
|
||||
(action === 'reopen' && canReopenTask.value) ||
|
||||
(action === 'void' && canVoidTask.value) ||
|
||||
((action === 'download-pdf' || action === 'download-signature' || action === 'print') &&
|
||||
canDownloadArtifacts.value)
|
||||
|
||||
if (!allowed) {
|
||||
ElMessage.warning('当前账号没有执行此操作的权限')
|
||||
return
|
||||
}
|
||||
|
||||
if (action === 'pad-sign') {
|
||||
if (!isSigningMockEnabled) {
|
||||
ElMessage.info('手写板设备签署接口待接入')
|
||||
@@ -585,6 +619,11 @@ async function exportSignedPdf() {
|
||||
}
|
||||
|
||||
async function downloadArtifact(artifact: SigningArtifact) {
|
||||
if (!canDownloadArtifacts.value) {
|
||||
ElMessage.warning('当前账号没有下载签署文件的权限')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const blob = await downloadSigningArtifact(artifact.id)
|
||||
const url = URL.createObjectURL(blob)
|
||||
@@ -729,6 +768,7 @@ onMounted(() => {
|
||||
:departments="departmentOptions"
|
||||
:documents="documentOptions"
|
||||
:visit-types="visitTypeOptions"
|
||||
:can-create="canCreateTask"
|
||||
@add="newDialogVisible = true"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
@@ -757,6 +797,12 @@ onMounted(() => {
|
||||
:artifacts-error="artifactsError"
|
||||
:pad-session-status="padSessionStatus"
|
||||
:pad-session-loading="padSessionLoading"
|
||||
:can-delivery-write="canDeliveryWrite"
|
||||
:can-reopen="canReopenTask"
|
||||
:can-void="canVoidTask"
|
||||
:can-view-audit="canViewEvents"
|
||||
:can-view-artifacts="canViewArtifacts"
|
||||
:can-download-artifact="canDownloadArtifacts"
|
||||
@action="handleTaskAction"
|
||||
@download-artifact="downloadArtifact"
|
||||
@selection-change="handleSelectionChange"
|
||||
|
||||
Reference in New Issue
Block a user