提交
This commit is contained in:
1 parent
f90726927e
commit
6eea13370c
103 files changed
+38401
-32231
No files matched your search
@@ -44,11 +44,12 @@
|
||||
<div class="section-title">
|
||||
<div class="section-title-left"><h3>一键导入</h3></div>
|
||||
</div>
|
||||
<el-form-item label="标准信息">
|
||||
<el-form-item label="标准信息" class="import-textarea-item">
|
||||
<el-input
|
||||
v-model="standardImportText"
|
||||
type="textarea"
|
||||
:rows="12"
|
||||
:rows="28"
|
||||
class="import-standard-textarea"
|
||||
placeholder="请粘贴标准格式信息,点击「一键导入」填充各 Tab 字段"
|
||||
/>
|
||||
</el-form-item>
|
||||
@@ -198,6 +199,164 @@
|
||||
</div>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="form-grid form-grid--attachment">
|
||||
<el-form-item label="知情同意书">
|
||||
<div
|
||||
class="attachment-upload"
|
||||
:class="{ 'is-dragover': isConsentAttachDragover }"
|
||||
v-bind="consentAttachDropHandlers"
|
||||
>
|
||||
<div class="attachment-list">
|
||||
<el-upload
|
||||
ref="consentAttachmentUploadRef"
|
||||
:auto-upload="false"
|
||||
:show-file-list="false"
|
||||
:multiple="true"
|
||||
accept="image/*,video/*,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.zip,.rar"
|
||||
@change="handleConsentAttachmentChange"
|
||||
>
|
||||
<div class="upload-card">
|
||||
<el-icon :size="28" color="#047857"><Plus /></el-icon>
|
||||
<span class="upload-card-text">上传附件</span>
|
||||
</div>
|
||||
</el-upload>
|
||||
<div
|
||||
v-for="(file, index) in formData.consentAttachments"
|
||||
:key="file.id || index"
|
||||
class="attachment-item"
|
||||
:class="{ 'is-uploading': file._uploading }"
|
||||
>
|
||||
<div
|
||||
class="attachment-preview"
|
||||
@click="
|
||||
isImageFile(file) && file.fileUrl
|
||||
? handlePreviewAttachment(file)
|
||||
: undefined
|
||||
"
|
||||
>
|
||||
<template v-if="isImageFile(file) && file.fileUrl">
|
||||
<img :src="fullFileUrl(file.fileUrl)" :alt="file.fileName" />
|
||||
</template>
|
||||
<template v-else-if="isImageFile(file) && !file.fileUrl">
|
||||
<el-icon :size="24" color="#94a3b8"><Loading /></el-icon>
|
||||
</template>
|
||||
<template v-else-if="isVideoFile(file)">
|
||||
<div class="attachment-preview__icon attachment-preview__icon--video">
|
||||
<el-icon :size="28"><VideoPlay /></el-icon>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="attachment-preview__icon attachment-preview__icon--doc">
|
||||
<el-icon :size="28"><Document /></el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="attachment-footer">
|
||||
<span class="attachment-name" :title="file.fileName">{{
|
||||
file.fileName
|
||||
}}</span>
|
||||
<div class="attachment-actions">
|
||||
<el-icon
|
||||
class="action-btn"
|
||||
title="下载"
|
||||
@click="handleDownloadAttachment(file)"
|
||||
><Download
|
||||
/></el-icon>
|
||||
<el-icon
|
||||
class="action-btn action-btn--danger"
|
||||
title="删除"
|
||||
@click="removeConsentAttachment(index)"
|
||||
><Delete
|
||||
/></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="upload-hint"
|
||||
>支持拖拽或点击上传图片、视频、PDF、Word、Excel等文件,单文件不超过 20MB</span
|
||||
>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="form-grid form-grid--attachment">
|
||||
<el-form-item label="孕妇健康调查表">
|
||||
<div
|
||||
class="attachment-upload"
|
||||
:class="{ 'is-dragover': isHealthSurveyAttachDragover }"
|
||||
v-bind="healthSurveyAttachDropHandlers"
|
||||
>
|
||||
<div class="attachment-list">
|
||||
<el-upload
|
||||
ref="healthSurveyAttachmentUploadRef"
|
||||
:auto-upload="false"
|
||||
:show-file-list="false"
|
||||
:multiple="true"
|
||||
accept="image/*,video/*,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.zip,.rar"
|
||||
@change="handleHealthSurveyAttachmentChange"
|
||||
>
|
||||
<div class="upload-card">
|
||||
<el-icon :size="28" color="#047857"><Plus /></el-icon>
|
||||
<span class="upload-card-text">上传附件</span>
|
||||
</div>
|
||||
</el-upload>
|
||||
<div
|
||||
v-for="(file, index) in formData.healthSurveyAttachments"
|
||||
:key="file.id || index"
|
||||
class="attachment-item"
|
||||
:class="{ 'is-uploading': file._uploading }"
|
||||
>
|
||||
<div
|
||||
class="attachment-preview"
|
||||
@click="
|
||||
isImageFile(file) && file.fileUrl
|
||||
? handlePreviewAttachment(file)
|
||||
: undefined
|
||||
"
|
||||
>
|
||||
<template v-if="isImageFile(file) && file.fileUrl">
|
||||
<img :src="fullFileUrl(file.fileUrl)" :alt="file.fileName" />
|
||||
</template>
|
||||
<template v-else-if="isImageFile(file) && !file.fileUrl">
|
||||
<el-icon :size="24" color="#94a3b8"><Loading /></el-icon>
|
||||
</template>
|
||||
<template v-else-if="isVideoFile(file)">
|
||||
<div class="attachment-preview__icon attachment-preview__icon--video">
|
||||
<el-icon :size="28"><VideoPlay /></el-icon>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="attachment-preview__icon attachment-preview__icon--doc">
|
||||
<el-icon :size="28"><Document /></el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="attachment-footer">
|
||||
<span class="attachment-name" :title="file.fileName">{{
|
||||
file.fileName
|
||||
}}</span>
|
||||
<div class="attachment-actions">
|
||||
<el-icon
|
||||
class="action-btn"
|
||||
title="下载"
|
||||
@click="handleDownloadAttachment(file)"
|
||||
><Download
|
||||
/></el-icon>
|
||||
<el-icon
|
||||
class="action-btn action-btn--danger"
|
||||
title="删除"
|
||||
@click="removeHealthSurveyAttachment(index)"
|
||||
><Delete
|
||||
/></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="upload-hint"
|
||||
>支持拖拽或点击上传图片、视频、PDF、Word、Excel等文件,单文件不超过 20MB</span
|
||||
>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1218,6 +1377,8 @@
|
||||
registerDate: '',
|
||||
collectorUserId: '',
|
||||
protocolAttachments: '',
|
||||
consentFormUrls: '',
|
||||
healthSurveyFormUrls: '',
|
||||
remark: '',
|
||||
attachments: [] as Array<{
|
||||
id?: string
|
||||
@@ -1228,6 +1389,24 @@
|
||||
fileType?: string
|
||||
_uploading?: boolean
|
||||
}>,
|
||||
consentAttachments: [] as Array<{
|
||||
id?: string
|
||||
fileName: string
|
||||
fileUrl: string
|
||||
fileSize: number
|
||||
fileSizeDisplay?: string
|
||||
fileType?: string
|
||||
_uploading?: boolean
|
||||
}>,
|
||||
healthSurveyAttachments: [] as Array<{
|
||||
id?: string
|
||||
fileName: string
|
||||
fileUrl: string
|
||||
fileSize: number
|
||||
fileSizeDisplay?: string
|
||||
fileType?: string
|
||||
_uploading?: boolean
|
||||
}>,
|
||||
// Party Customer
|
||||
customerId: '' as string,
|
||||
motherName: '',
|
||||
@@ -1284,7 +1463,11 @@
|
||||
registerDate: '',
|
||||
collectorUserId: '',
|
||||
protocolAttachments: '',
|
||||
consentFormUrls: '',
|
||||
healthSurveyFormUrls: '',
|
||||
attachments: [],
|
||||
consentAttachments: [],
|
||||
healthSurveyAttachments: [],
|
||||
remark: '',
|
||||
customerId: '',
|
||||
motherName: '',
|
||||
@@ -1875,6 +2058,16 @@
|
||||
if (att && att.length) {
|
||||
formData.attachments = att.map((a) => ({ ...a })) as any
|
||||
}
|
||||
const consentAtt = (bundle as any).consentAttachmentFiles as Array<Record<string, any>> | null
|
||||
if (consentAtt && consentAtt.length) {
|
||||
formData.consentAttachments = consentAtt.map((a) => ({ ...a })) as any
|
||||
}
|
||||
const healthSurveyAtt = (bundle as any).healthSurveyAttachmentFiles as
|
||||
| Array<Record<string, any>>
|
||||
| null
|
||||
if (healthSurveyAtt && healthSurveyAtt.length) {
|
||||
formData.healthSurveyAttachments = healthSurveyAtt.map((a) => ({ ...a })) as any
|
||||
}
|
||||
}
|
||||
|
||||
async function handleOpenForEdit() {
|
||||
@@ -1891,6 +2084,8 @@
|
||||
formData.registerDate = String(row.registerDate || '')
|
||||
formData.collectorUserId = String(row.collectorUserId || '')
|
||||
formData.protocolAttachments = String((row as any).protocolAttachments || '')
|
||||
formData.consentFormUrls = String((row as any).consentFormUrls || '')
|
||||
formData.healthSurveyFormUrls = String((row as any).healthSurveyFormUrls || '')
|
||||
formData.remark = String(row.remark || '')
|
||||
|
||||
dialogFormLoading.value = true
|
||||
@@ -1979,11 +2174,22 @@
|
||||
.map((a) => a.fileUrl)
|
||||
.filter(Boolean)
|
||||
.join(',')
|
||||
const consentAttachmentUrls = formData.consentAttachments
|
||||
.map((a) => a.fileUrl)
|
||||
.filter(Boolean)
|
||||
.join(',')
|
||||
const healthSurveyAttachmentUrls = formData.healthSurveyAttachments
|
||||
.map((a) => a.fileUrl)
|
||||
.filter(Boolean)
|
||||
.join(',')
|
||||
const payload: Record<string, unknown> = {
|
||||
protocolStatus: formData.protocolStatus,
|
||||
registerDate: formData.registerDate || undefined,
|
||||
collectorUserId: formData.collectorUserId || undefined,
|
||||
protocolAttachments: protocolAttachmentUrls || formData.protocolAttachments || undefined,
|
||||
consentFormUrls: consentAttachmentUrls || formData.consentFormUrls || undefined,
|
||||
healthSurveyFormUrls:
|
||||
healthSurveyAttachmentUrls || formData.healthSurveyFormUrls || undefined,
|
||||
attachments: formData.attachments.map((a) => ({
|
||||
id: a.id,
|
||||
fileName: a.fileName,
|
||||
@@ -1992,6 +2198,22 @@
|
||||
fileSizeDisplay: a.fileSizeDisplay,
|
||||
fileType: a.fileType
|
||||
})),
|
||||
consentAttachments: formData.consentAttachments.map((a) => ({
|
||||
id: a.id,
|
||||
fileName: a.fileName,
|
||||
fileUrl: a.fileUrl,
|
||||
fileSize: a.fileSize,
|
||||
fileSizeDisplay: a.fileSizeDisplay,
|
||||
fileType: a.fileType
|
||||
})),
|
||||
healthSurveyAttachments: formData.healthSurveyAttachments.map((a) => ({
|
||||
id: a.id,
|
||||
fileName: a.fileName,
|
||||
fileUrl: a.fileUrl,
|
||||
fileSize: a.fileSize,
|
||||
fileSizeDisplay: a.fileSizeDisplay,
|
||||
fileType: a.fileType
|
||||
})),
|
||||
remark: formData.remark || undefined,
|
||||
partyCustomer: {
|
||||
customerId: formData.customerId || undefined,
|
||||
@@ -3294,6 +3516,62 @@
|
||||
|
||||
/* ====== 附件上传 ====== */
|
||||
const attachmentUploadRef = ref()
|
||||
const consentAttachmentUploadRef = ref()
|
||||
const healthSurveyAttachmentUploadRef = ref()
|
||||
|
||||
type ProtocolAttachmentItem = {
|
||||
id?: string
|
||||
fileName: string
|
||||
fileUrl: string
|
||||
fileSize: number
|
||||
fileSizeDisplay?: string
|
||||
fileType?: string
|
||||
_uploading?: boolean
|
||||
}
|
||||
|
||||
async function uploadProtocolAttachmentFile(
|
||||
uploadFile: any,
|
||||
list: ProtocolAttachmentItem[],
|
||||
folder: string,
|
||||
uploadRef: { value?: { clearFiles?: () => void } | null }
|
||||
) {
|
||||
const file = uploadFile.raw || uploadFile
|
||||
if (!file) return
|
||||
|
||||
const tempId = `temp_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`
|
||||
list.push({
|
||||
id: tempId,
|
||||
fileName: file.name,
|
||||
fileUrl: '',
|
||||
fileSize: file.size,
|
||||
fileSizeDisplay: `${(file.size / 1024).toFixed(1)} KB`,
|
||||
fileType: file.type || '',
|
||||
_uploading: true
|
||||
})
|
||||
const idx = list.length - 1
|
||||
|
||||
try {
|
||||
const fd = new FormData()
|
||||
fd.append('folder', folder)
|
||||
fd.append('file', file)
|
||||
const res = await fetchUploadAttachment(fd)
|
||||
list[idx] = {
|
||||
...list[idx],
|
||||
id: res.id || tempId,
|
||||
fileName: file.name || res.fileName,
|
||||
fileUrl: res.fileUrl,
|
||||
fileSize: res.fileSize || file.size,
|
||||
fileSizeDisplay: res.fileSizeDisplay || `${(file.size / 1024).toFixed(1)} KB`,
|
||||
fileType: res.fileType || file.type || '',
|
||||
_uploading: false
|
||||
}
|
||||
} catch {
|
||||
ElMessage.error('文件上传失败')
|
||||
list.splice(idx, 1)
|
||||
} finally {
|
||||
nextTick(() => uploadRef.value?.clearFiles())
|
||||
}
|
||||
}
|
||||
|
||||
function isImageFile(file: any) {
|
||||
const url = (file.fileUrl || '').toLowerCase()
|
||||
@@ -3316,48 +3594,44 @@
|
||||
}
|
||||
|
||||
async function handleAttachmentChange(uploadFile: any) {
|
||||
const file = uploadFile.raw || uploadFile
|
||||
if (!file) return
|
||||
|
||||
const tempId = `temp_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`
|
||||
formData.attachments.push({
|
||||
id: tempId,
|
||||
fileName: file.name,
|
||||
fileUrl: '',
|
||||
fileSize: file.size,
|
||||
fileSizeDisplay: `${(file.size / 1024).toFixed(1)} KB`,
|
||||
fileType: file.type || '',
|
||||
_uploading: true
|
||||
})
|
||||
const idx = formData.attachments.length - 1
|
||||
|
||||
try {
|
||||
const fd = new FormData()
|
||||
fd.append('folder', 'protocol')
|
||||
fd.append('file', file)
|
||||
const res = await fetchUploadAttachment(fd)
|
||||
formData.attachments[idx] = {
|
||||
...formData.attachments[idx],
|
||||
id: res.id || tempId,
|
||||
fileName: file.name || res.fileName,
|
||||
fileUrl: res.fileUrl,
|
||||
fileSize: res.fileSize || file.size,
|
||||
fileSizeDisplay: res.fileSizeDisplay || `${(file.size / 1024).toFixed(1)} KB`,
|
||||
fileType: res.fileType || file.type || '',
|
||||
_uploading: false
|
||||
}
|
||||
} catch {
|
||||
ElMessage.error('文件上传失败')
|
||||
formData.attachments.splice(idx, 1)
|
||||
} finally {
|
||||
nextTick(() => attachmentUploadRef.value?.clearFiles())
|
||||
}
|
||||
await uploadProtocolAttachmentFile(
|
||||
uploadFile,
|
||||
formData.attachments,
|
||||
'protocol',
|
||||
attachmentUploadRef
|
||||
)
|
||||
}
|
||||
|
||||
function removeAttachment(index: number) {
|
||||
formData.attachments.splice(index, 1)
|
||||
}
|
||||
|
||||
async function handleConsentAttachmentChange(uploadFile: any) {
|
||||
await uploadProtocolAttachmentFile(
|
||||
uploadFile,
|
||||
formData.consentAttachments,
|
||||
'protocol-consent',
|
||||
consentAttachmentUploadRef
|
||||
)
|
||||
}
|
||||
|
||||
function removeConsentAttachment(index: number) {
|
||||
formData.consentAttachments.splice(index, 1)
|
||||
}
|
||||
|
||||
async function handleHealthSurveyAttachmentChange(uploadFile: any) {
|
||||
await uploadProtocolAttachmentFile(
|
||||
uploadFile,
|
||||
formData.healthSurveyAttachments,
|
||||
'protocol-health-survey',
|
||||
healthSurveyAttachmentUploadRef
|
||||
)
|
||||
}
|
||||
|
||||
function removeHealthSurveyAttachment(index: number) {
|
||||
formData.healthSurveyAttachments.splice(index, 1)
|
||||
}
|
||||
|
||||
const { isDragover: isProtocolAttachDragover, dropZoneHandlers: protocolAttachDropHandlers } =
|
||||
useAttachmentDropZone({
|
||||
onFiles: (files) => {
|
||||
@@ -3367,6 +3641,26 @@
|
||||
}
|
||||
})
|
||||
|
||||
const { isDragover: isConsentAttachDragover, dropZoneHandlers: consentAttachDropHandlers } =
|
||||
useAttachmentDropZone({
|
||||
onFiles: (files) => {
|
||||
for (const file of files) {
|
||||
void handleConsentAttachmentChange({ raw: file })
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const {
|
||||
isDragover: isHealthSurveyAttachDragover,
|
||||
dropZoneHandlers: healthSurveyAttachDropHandlers
|
||||
} = useAttachmentDropZone({
|
||||
onFiles: (files) => {
|
||||
for (const file of files) {
|
||||
void handleHealthSurveyAttachmentChange({ raw: file })
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const { isDragover: isPaymentDetailDragover, handlersFor: paymentDetailDropHandlers } =
|
||||
useIndexedAttachmentDropZone({
|
||||
onFiles: (detailIndex, files) => {
|
||||
@@ -3507,11 +3801,20 @@
|
||||
|
||||
&--import {
|
||||
margin-bottom: 0;
|
||||
|
||||
.import-textarea-item {
|
||||
margin-bottom: 12px;
|
||||
|
||||
:deep(.el-textarea__inner) {
|
||||
min-height: 560px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.import-actions {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
justify-content: flex-end;
|
||||
padding: 0 0 8px;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user