123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 |
- import {
- NButton,
- NModal,
- NUpload,
- UploadCustomRequestOptions,
- UploadFileInfo,
- useMessage
- } from 'naive-ui';
- import { defineComponent, watch, PropType, reactive, ref } from 'vue';
- import { policy } from './api';
- import Copper from './copper';
- import axios from 'axios';
- import {
- getUploadSign,
- onFileUpload,
- onOnlyFileUpload
- } from '/src/helpers/oss-file-upload';
- export default defineComponent({
- name: 'upload-file',
- props: {
- fileList: {
- type: String,
- default: ''
- },
- imageList: {
- type: Array,
- default: () => []
- },
- accept: {
- // 支持类型
- type: String,
- default: '.jpg,.png,.jpeg,.gif'
- },
- listType: {
- type: String as PropType<'image' | 'image-card'>,
- default: 'image-card'
- },
- showType: {
- type: String as PropType<'default' | 'custom'>,
- default: 'default'
- },
- showFileList: {
- type: Boolean,
- default: true
- },
- // width: {
- // type: Number,
- // default: 96
- // },
- // height: {
- // type: Number,
- // default: 96
- // },
- text: {
- type: String as PropType<string>,
- default: '上传文件'
- },
- size: {
- // 文件大小
- type: Number as PropType<number>,
- default: 5
- },
- max: {
- type: Number as PropType<number>,
- default: 1
- },
- multiple: {
- type: Boolean as PropType<boolean>,
- default: false
- },
- disabled: {
- type: Boolean as PropType<boolean>,
- default: false
- },
- tips: {
- type: String as PropType<string>,
- default: ''
- },
- bucketName: {
- type: String,
- default: 'gyt'
- },
- path: {
- type: String,
- default: ''
- },
- fileName: {
- type: String,
- default: ''
- },
- cropper: {
- // 是否裁切, 只有图片才支持
- type: Boolean as PropType<boolean>,
- default: false
- },
- options: {
- type: Object,
- default: () => {
- return {
- viewMode: 0,
- autoCrop: true, //是否默认生成截图框
- enlarge: 1, // 图片放大倍数
- autoCropWidth: 200, //默认生成截图框宽度
- autoCropHeight: 200, //默认生成截图框高度
- fixedBox: false, //是否固定截图框大小 不允许改变
- previewsCircle: true, //预览图是否是原图形
- title: '上传图片'
- };
- }
- }
- },
- // readFileInputEventAsArrayBuffer 只会在文件的时间回调
- emits: [
- 'update:fileList',
- 'close',
- 'readFileInputEventAsArrayBuffer',
- 'remove'
- ],
- setup(props, { emit, expose, slots }) {
- const ossUploadUrl = `https://${props.bucketName}.ks3-cn-beijing.ksyuncs.com/`;
- const message = useMessage();
- const visiable = ref<boolean>(false);
- const btnLoading = ref<boolean>(false);
- const tempFiileBuffer = ref();
- const uploadRef = ref();
- // const state = reactive({
- // policy: '',
- // signature: '',
- // key: '',
- // KSSAccessKeyId: '',
- // acl: 'public-read',
- // name: ''
- // }) as any;
- const state = reactive([]) as any;
- const fileListRef = ref<UploadFileInfo[]>([]);
- const initFileList = () => {
- if (props.fileList) {
- const splitName = props.fileList.split('/');
- fileListRef.value = [
- {
- id: new Date().getTime().toString(),
- name: splitName[splitName.length - 1],
- status: 'finished',
- url: props.fileList
- }
- ];
- } else if (Array.isArray(props.imageList)) {
- const list: any = [];
- props.imageList.forEach((n: any) => {
- const splitName = n.split('/');
- list.push({
- id: Date.now().toString(),
- name: splitName[splitName.length - 1],
- status: 'finished',
- url: n
- });
- });
- fileListRef.value = list;
- } else {
- fileListRef.value = [];
- }
- };
- initFileList();
- watch(
- () => props.imageList,
- () => {
- initFileList();
- }
- );
- watch(
- () => props.fileList,
- () => {
- console.log('list');
- initFileList();
- }
- );
- const handleClearFile = () => {
- uploadRef.value?.clear();
- console.log('清空', uploadRef.value);
- };
- expose({
- handleClearFile
- });
- const CropperModal = ref();
- const onBeforeUpload = async (options: any) => {
- const file = options.file;
- // 文件大小
- let isLt2M = true;
- if (props.size) {
- isLt2M = file.file.size / 1024 / 1024 < props.size;
- if (!isLt2M) {
- message.error(`文件大小不能超过${props.size}M`);
- return false;
- }
- }
- if (!isLt2M) {
- return isLt2M;
- }
- // 是否裁切
- if (props.cropper) {
- getBase64(file.file, (imageUrl: any) => {
- const target = Object.assign({}, props.options, {
- img: imageUrl,
- name: file.file.name // 上传文件名
- });
- visiable.value = true;
- setTimeout(() => {
- CropperModal.value?.edit(target);
- console.log(CropperModal.value, 'cropper');
- }, 100);
- });
- return false;
- }
- try {
- btnLoading.value = true;
- console.log(props.path, file.file);
- const name = file.file.name;
- const suffix = name.slice(name.lastIndexOf('.'));
- // const months = dayjs().format('MM')
- const fileName = `${props.path}${
- props.fileName || Date.now() + suffix
- }`;
- const obj = {
- filename: fileName,
- bucketName: props.bucketName,
- postData: {
- filename: fileName,
- acl: 'public-read',
- key: fileName,
- unknowValueField: []
- }
- };
- // const { data } = await policy(obj);
- // state.policy = data.policy;
- // state.signature = data.signature;
- // state.key = fileName;
- // state.KSSAccessKeyId = data.kssAccessKeyId;
- // state.name = fileName;
- // tempFiileBuffer.value = file.file;
- const { data } = await getUploadSign(obj);
- state.push({
- id: file.id,
- tempFiileBuffer: file.file,
- policy: data.policy,
- signature: data.signature,
- acl: 'public-read',
- key: fileName,
- KSSAccessKeyId: data.kssAccessKeyId,
- name: fileName
- });
- } catch {
- //
- // message.error('上传失败')
- btnLoading.value = false;
- return false;
- }
- return true;
- };
- const getBase64 = async (img: any, callback: any) => {
- const reader = new FileReader();
- reader.addEventListener('load', () => callback(reader.result));
- reader.readAsDataURL(img);
- };
- const onFinish = (options: any) => {
- const item = state.find((c: any) => c.id == options.file.id);
- // const url = ossUploadUrl + state.key;
- emit('update:fileList', options.file.url);
- emit('readFileInputEventAsArrayBuffer', item.tempFiileBuffer);
- // options.file.url = url;
- visiable.value = false;
- btnLoading.value = false;
- };
- const onRemove = async (options: any) => {
- console.log('🚀 ~ options', options);
- emit('update:fileList', '');
- emit('remove');
- btnLoading.value = false;
- };
- const onCustomRequest = ({
- file,
- // data,
- // headers,
- // withCredentials,
- action,
- onFinish,
- onError,
- onProgress
- }: UploadCustomRequestOptions) => {
- const item = state.find((c: any) => {
- return c.id == file.id;
- });
- item.file = file;
- onFileUpload({ file, action, data: item, onProgress, onFinish, onError });
- };
- // 裁切失败
- // const cropperNo = () => {}
- // 裁切成功
- const cropperOk = async (blob: any) => {
- try {
- // const months = dayjs().format('MM')
- const fileName = `${props.path}${
- props.fileName || new Date().getTime() + '.png'
- }`;
- const obj = {
- filename: fileName,
- bucketName: props.bucketName,
- postData: {
- filename: fileName,
- acl: 'public-read',
- key: fileName,
- unknowValueField: []
- }
- };
- // const { data } = await policy(obj);
- const { data } = await getUploadSign(obj);
- const formData = {
- policy: data.policy,
- signature: data.signature,
- acl: 'public-read',
- key: fileName,
- KSSAccessKeyId: data.kssAccessKeyId,
- name: fileName,
- file: blob
- };
- const res = await onOnlyFileUpload(ossUploadUrl, formData);
- console.log(res, 'upload');
- emit('update:fileList', res);
- visiable.value = false;
- } catch {
- //
- // message.error('上传失败');
- return false;
- }
- };
- return () => (
- <div>
- <NUpload
- ref={uploadRef}
- action={ossUploadUrl}
- // data={state}
- customRequest={onCustomRequest}
- v-model:fileList={fileListRef.value}
- listType={props.listType}
- accept={props.accept}
- multiple={props.multiple}
- max={props.max}
- disabled={props.disabled}
- showFileList={props.showFileList}
- showPreviewButton
- onBeforeUpload={(options: any) => onBeforeUpload(options)}
- onFinish={(options: any) => onFinish(options)}
- onRemove={(options: any) => onRemove(options)}>
- {props.showType === 'default' && props.listType === 'image' && (
- <NButton loading={btnLoading.value} type="primary">
- {props.text}
- </NButton>
- )}
- {props.showType === 'custom' && slots.custom && slots.custom()}
- </NUpload>
- {props.tips && (
- <p style="font-size: 13px; color: #666; padding-top: 4px;">
- {props.tips}
- </p>
- )}
- <NModal
- v-model:show={visiable.value}
- preset="dialog"
- showIcon={false}
- class={['modalTitle background']}
- title="上传图片"
- style={{ width: '800px' }}>
- {/* @cropper-no="error" @cropper-ok="success" */}
- <Copper
- // ref="CropperModal"
- ref={CropperModal}
- onClose={() => (visiable.value = false)}
- onCropperOk={cropperOk}
- />
- </NModal>
- </div>
- );
- }
- });
|