feat: 增加文件上传功能

- 新增 useFileUploadHooks , 保存文件上传的状态
- 删除无用的 rate 引用组件
- 对文件内容可增加限制
This commit is contained in:
Huangzhe
2025-03-23 10:59:12 +08:00
parent cf9a237e36
commit c1e31f096b
3 changed files with 70 additions and 62 deletions

View File

@@ -1,59 +1,61 @@
<script setup lang="ts">
import { toRefs } from 'vue';
import { Toast } from 'vant';
import { fileLimit, answer } from './hooks/useFileUploadHooks';
const isPreview = defineModel('isPreview', { default: false, type: Boolean, required: false });
const props = defineProps<{
element: any;
index: number;
active: boolean;
isPreview: {
type: Boolean;
default: false;
};
}>();
const { element } = toRefs(props);
/**
* 文件大小限制
* @property {number} max - 最大文件大小
* @property {number} min - 最小文件大小
*/
// const fileLimit = {
// // 默认3MB
// max: 1024 * 1024 * 4,
// min: 0
// };
/**
* 上传文件
* @description 上传文件
*/
// function handleFileUpload() {
// const fileInput = document.createElement('input');
// fileInput.type = 'file';
// // fileInput.accept = '.jpg,.jpeg,.png,.gif';
// // fileInput.multiple = true;
// fileInput.click();
//
// fileInput.addEventListener('change', handleFileChange);
//
// function handleFileChange(event: Event) {
// const files = (event.target as HTMLInputElement).files;
// if (files) {
// for (let i = 0; i < files.length; i++) {
// const file = files[i];
// // console.log(file.size);
//
// if (file.size > fileLimit.max) {
// Toast.fail(`文件太大,超过${fileLimit.max / 1024 / 1024}MB`);
// return;
// } else if (file.size < fileLimit.min) {
// Toast.fail(`文件太小,小于${fileLimit.min / 1024 / 1024}MB`);
// return;
// }
// }
// }
// }
// }
function handleFileUpload () {
const fileInput = document.createElement('input');
fileInput.type = 'file';
// 文件类型限制
fileInput.accept = fileLimit.value.format.join(',');
// 是否限制多选
// fileInput.multiple = true;
fileInput.click();
fileInput.addEventListener('change', handleFileChange);
function handleFileChange (event: Event) {
const files = (event.target as HTMLInputElement).files;
if (files) {
// 检测文件数量
if (files.length > 1) {
Toast.fail('一次只能上传一个文件');
return;
}
for (let i = 0; i < files.length; i++) {
const file = files[i];
// console.log(file.size);
// 文件限制
if (file.size > fileLimit.value.maxFileSize) {
Toast.fail(`文件太大,超过${fileLimit.value.maxFileSize / 1024 / 1024}MB`);
return;
} else if (file.size < fileLimit.value.minFileSize) {
Toast.fail(`文件太小,小于${fileLimit.value.minFileSize / 1024 / 1024}MB`);
return;
}
}
// 上传文件
// 生成答案
answer.value = files;
}
}
}
const errorMessage = defineModel('errorMessage', {
type: String,
@@ -68,30 +70,19 @@ const emitValue = () => {
<template>
<van-cell-group>
<van-field
v-model="element.stem"
:label="element.stem"
:required="element.config.is_required === 1"
label-align="top"
input-align="center"
class="contenteditable-question-title"
>
<template #left-icon> {{ isPreview ? element.title : index + 1 }} {{ index + 1 }} </template>
<van-field v-model="element.stem" :label="element.stem" :required="element.config.is_required === 1"
label-align="top" input-align="center" class="contenteditable-question-title">
<template #left-icon> {{ isPreview ? element.title : index + 1 }}</template>
<!-- 使用 title 插槽来自定义标题 -->
<template #label>
<contenteditable
v-model="element.stem"
:active="active"
@blur="emitValue"
className="contenteditable-label"
:errorMessage="errorMessage"
></contenteditable>
<contenteditable v-model="element.stem" :active="active" @blur="emitValue" className="contenteditable-label"
:errorMessage="errorMessage"></contenteditable>
</template>
<template #input>
<div class="file-upload-label">
<van-icon class-prefix="mobilefont" name="upload " />
<span>文件上传</span>
<div class="file-upload-label" @click="handleFileUpload">
<van-icon class-prefix="mobilefont" name="upload" />
<span>{{ answer?.length > 0 ? '文件已上传' : '文件上传' }}</span>
</div>
</template>
</van-field>

View File

@@ -0,0 +1,18 @@
import { ref } from 'vue';
const answer = ref<FileList>();
/**
* 文件限制
* @property {number} max - 最大文件大小
* @property {number} min - 最小文件大小
*/
const fileLimit = ref({
// 默认4MB
maxFileSize: 1024 * 1024 * 4,
minFileSize: 0,
minFileCount: 0,
maxFileCount: 1,
format: [] // ['jpg', 'jpeg', 'png', 'gif']
});
export { answer, fileLimit };

View File

@@ -1,6 +1,5 @@
<script setup lang="ts">
import FileUpload from '@/views/Design/components/Questions/FileUpload.vue';
import Rate from '@/views/Design/components/Questions/Rate.vue';
const questionIndex = defineModel<number>('questionIndex', { default: NaN });
const answerIndex = defineModel<number>('answerIndex', { default: NaN });
const question = defineModel<question>('question', { default: () => {} });