更新
This commit is contained in:
@ -443,6 +443,18 @@ export function upImage(data) {
|
||||
})
|
||||
}
|
||||
|
||||
// 单个文件上传
|
||||
export function uploadFile(file) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
return service({
|
||||
url: '/common/upload',
|
||||
method: 'post',
|
||||
data: formData,
|
||||
headers: { 'Content-Type': 'multipart/form-data' }
|
||||
})
|
||||
}
|
||||
|
||||
//根据身份证号查询涉疫登记信息
|
||||
export function getRySydjInfo(data) {
|
||||
return service({
|
||||
|
||||
141
src/components/FileUploader.vue
Normal file
141
src/components/FileUploader.vue
Normal file
@ -0,0 +1,141 @@
|
||||
<template>
|
||||
<div class="file-uploader">
|
||||
<van-uploader
|
||||
:max-count="1"
|
||||
:after-read="handleAfterRead"
|
||||
:preview-size="previewSize"
|
||||
:show-upload="!modelValue"
|
||||
:disabled="uploading"
|
||||
>
|
||||
<slot v-if="!modelValue">
|
||||
<div class="upload-placeholder" :style="{ width: previewSize + 'px', height: previewSize + 'px' }">
|
||||
<van-icon name="photograph" class="upload-icon" />
|
||||
<div class="upload-text">{{ uploading ? '上传中...' : placeholder }}</div>
|
||||
</div>
|
||||
</slot>
|
||||
</van-uploader>
|
||||
<div v-if="modelValue" class="preview-wrapper">
|
||||
<van-image
|
||||
:src="modelValue"
|
||||
:preview-src-list="[modelValue]"
|
||||
class="preview-image"
|
||||
:width="previewSize"
|
||||
:height="previewSize"
|
||||
fit="cover"
|
||||
radius="6"
|
||||
preview
|
||||
/>
|
||||
<van-icon v-if="showDelete" name="cross" class="delete-btn" @click.stop="handleDelete" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { Toast } from 'vant'
|
||||
import { uploadFile } from '@/api/common'
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: { type: String, default: '' },
|
||||
previewSize: { type: [Number, String], default: 100 },
|
||||
placeholder: { type: String, default: '点击上传' },
|
||||
showDelete: { type: Boolean, default: true }
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'success', 'error', 'delete'])
|
||||
|
||||
const uploading = ref(false)
|
||||
|
||||
async function handleAfterRead(file) {
|
||||
uploading.value = true
|
||||
try {
|
||||
const fileObj = file.file
|
||||
const res = await uploadFile(fileObj)
|
||||
// 根据响应结构获取 URL,请根据实际返回调整
|
||||
const url = res? res.fileName : ''
|
||||
if (url) {
|
||||
emit('update:modelValue', url)
|
||||
emit('success', url)
|
||||
} else {
|
||||
throw new Error('上传失败')
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('上传失败:', err)
|
||||
Toast('上传失败,请重试')
|
||||
emit('error', err)
|
||||
} finally {
|
||||
uploading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleDelete() {
|
||||
emit('update:modelValue', '')
|
||||
emit('delete')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.file-uploader {
|
||||
display: inline-block;
|
||||
|
||||
:deep(.van-uploader) {
|
||||
display: block;
|
||||
}
|
||||
|
||||
:deep(.van-uploader__wrapper) {
|
||||
display: block;
|
||||
}
|
||||
|
||||
:deep(.van-uploader__preview) {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .upload-placeholder {
|
||||
background: #fff;
|
||||
border: 1px dashed #d1d5db;
|
||||
border-radius: 6px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
width: 135px !important;
|
||||
height: 135px !important;
|
||||
|
||||
.upload-icon {
|
||||
font-size: 28px;
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.upload-text {
|
||||
font-size: 12px;
|
||||
color: #6b7280;
|
||||
}
|
||||
}
|
||||
|
||||
.preview-wrapper {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
|
||||
.preview-image {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
right: -6px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
border-radius: 50%;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -89,15 +89,13 @@
|
||||
<div class="photo-upload-list">
|
||||
<div class="photo-upload-item" v-for="(photo, index) in photoList" :key="index">
|
||||
<div style="text-align: left;">照片{{ index + 1 }}</div>
|
||||
<van-uploader :max-count="1" :after-read="(file) => onPhotoRead(file, index)" :preview-size="200"
|
||||
:show-upload="!photo.url">
|
||||
<div class="photo-upload-content" v-if="!photo.url">
|
||||
<van-icon name="photograph" class="photo-icon" />
|
||||
<div class="photo-text">点击拍照/上传</div>
|
||||
</div>
|
||||
</van-uploader>
|
||||
<van-image v-if="photo.url" :src="photo.url" :preview-src-list="[photo.url]" class="photo-preview-img" width="100" height="100" fit="cover" radius="6" preview/>
|
||||
<van-icon v-if="photo.url" @click.stop="deletePhoto(index)" name="cross" class="photo-delete" />
|
||||
<FileUploader
|
||||
v-model="photo.url"
|
||||
:preview-size="200"
|
||||
placeholder="点击拍照/上传"
|
||||
@success="(url) => onPhotoUploaded(url, index)"
|
||||
@delete="onPhotoDelete(index)"
|
||||
/>
|
||||
<van-field v-model="photo.url" label="图片链接" placeholder="请输入图片链接" class="photo-link-field" />
|
||||
</div>
|
||||
</div>
|
||||
@ -141,10 +139,10 @@
|
||||
|
||||
<script setup>
|
||||
import PopupView from '@/components/popupView.vue'
|
||||
import FileUploader from '@/components/FileUploader.vue'
|
||||
import { ref, reactive, onMounted } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { Toast } from "vant";
|
||||
import { upImage } from "@/api/common";
|
||||
import { addSsPai } from "@/api/traffic";
|
||||
const isLoading = ref(false);
|
||||
const router = useRouter();
|
||||
@ -297,18 +295,18 @@ function toggleSection(key) {
|
||||
openSections[key] = !openSections[key];
|
||||
}
|
||||
|
||||
// 删除照片
|
||||
function deletePhoto(index) {
|
||||
photoList.value[index].url = "";
|
||||
const uploadedCount = photoList.value.filter(p => p.url).length;
|
||||
formData.zpsl = uploadedCount.toString();
|
||||
// 照片上传成功回调
|
||||
function onPhotoUploaded(url, index) {
|
||||
photoList.value[index].url = url
|
||||
const uploadedCount = photoList.value.filter(p => p.url).length
|
||||
formData.zpsl = uploadedCount.toString()
|
||||
}
|
||||
|
||||
// vant upload上传后处理
|
||||
function onPhotoRead(file, index) {
|
||||
photoList.value[index].url = file.content;
|
||||
const uploadedCount = photoList.value.filter(p => p.url).length;
|
||||
formData.zpsl = uploadedCount.toString();
|
||||
// 照片删除回调
|
||||
function onPhotoDelete(index) {
|
||||
photoList.value[index].url = ""
|
||||
const uploadedCount = photoList.value.filter(p => p.url).length
|
||||
formData.zpsl = uploadedCount.toString()
|
||||
}
|
||||
|
||||
// 返回上一页
|
||||
@ -564,98 +562,6 @@ onMounted(() => {
|
||||
border-radius: 8px;
|
||||
border: 1px solid #e5e7eb;
|
||||
|
||||
:deep(.van-uploader) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.van-uploader__wrapper) {
|
||||
display: block;
|
||||
}
|
||||
|
||||
:deep(.van-uploader__preview) {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
:deep(.van-uploader__preview-image) {
|
||||
width: 100%;
|
||||
aspect-ratio: 3/1;
|
||||
border-radius: 6px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
:deep(.van-uploader__preview-delete) {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
border-radius: 50%;
|
||||
top: -6px;
|
||||
right: -6px;
|
||||
}
|
||||
|
||||
:deep(.van-uploader__upload) {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
aspect-ratio: 3/1;
|
||||
background: #fff;
|
||||
border: 1px dashed #d1d5db;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
:deep(.van-uploader__upload-icon) {
|
||||
font-size: 28px;
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
:deep(.van-uploader__upload-text) {
|
||||
font-size: 12px;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.photo-upload-content {
|
||||
width: 100%;
|
||||
aspect-ratio: 3/1;
|
||||
background: #fff;
|
||||
border: 1px dashed #d1d5db;
|
||||
border-radius: 6px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
|
||||
.photo-icon {
|
||||
font-size: 32px;
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.photo-text {
|
||||
font-size: 12px;
|
||||
color: #6b7280;
|
||||
}
|
||||
}
|
||||
|
||||
.photo-preview-img {
|
||||
width: 100px;
|
||||
border-radius: 6px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.photo-delete {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
border-radius: 50%;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.photo-label {
|
||||
font-size: 13px;
|
||||
color: #374151;
|
||||
|
||||
Reference in New Issue
Block a user