Browse Source

上传附件

xiaohaizhao 2 months ago
parent
commit
9917deae83
1 changed files with 298 additions and 0 deletions
  1. 298 0
      components/My_upload/My_upload.vue

+ 298 - 0
components/My_upload/My_upload.vue

@@ -0,0 +1,298 @@
+<template>
+    <up-upload :fileList="fileList" @after-read="afterRead" @delete="deletePic" :max-count="maxCount" :accept="accept"
+        multiple />
+</template>
+
+<script setup>
+import { ref, reactive, defineProps, defineEmits, getCurrentInstance, onUnmounted } from 'vue'
+// 4. 删除文件 临时附件直接删除 绑定过的放到待删除列表中,保存时清空
+// 5. 上传和清空附件返回列表,和单个附件 用于表单校验
+
+const emit = defineEmits(['uploadCallback'])
+const props = defineProps({
+    accept: {
+        type: String,
+        default: "image"
+    },
+    maxCount: {
+        type: [String, Number],
+        default: 99
+    },
+    uploadCallback: {
+        type: Function
+    },
+    fileList: {
+        type: Array,
+        default: reactive([])
+    },
+    usetype: {
+        type: String,
+        default: 'default'
+    },
+    ownertable: {
+        type: String,
+        default: 'temporary'
+    },
+    ownerid: {
+        type: [String, Number],
+        default: 1
+    }
+})
+const { $Http } = getCurrentInstance().proxy;
+const deleteList = reactive([]); // 用于存储待删除的文件列表
+
+// 文件读取后处理
+const afterRead = ({ file }) => {
+    file.forEach(v => {
+        // #ifdef H5
+        getArrayBuffer(v).then(data => {
+            data.data.url = v.url;
+            handleUploadFile(requestType(v), data.data)
+            props.fileList.push({
+                ...v,
+                status: 'uploading',
+                message: '上传中',
+            });
+
+        })
+        // #endif
+
+        // #ifndef H5
+        uni.getFileSystemManager().readFile({
+            filePath: v.url,
+            success: data => {
+                data.data.url = v.url;
+                handleUploadFile(requestType(v), data.data)
+                props.fileList.push({
+                    ...v,
+                    status: 'uploading',
+                    message: '上传中',
+                });
+            },
+            fail: console.error
+        })
+        // #endif
+    })
+}
+
+// 获取文件类型信息
+const requestType = (file) => {
+    let ext = ''
+
+    // #ifdef H5
+    ext = file.name.substring(file.name.lastIndexOf(".") + 1)
+    // #endif
+
+    // #ifndef H5
+    ext = file.type?.split("/")[1] ||
+        file.url.substring(file.url.lastIndexOf(".") + 1) ||
+        file.name.substring(file.name.lastIndexOf(".") + 1)
+    // #endif
+
+    return {
+        "classname": "system.attachment.huawei.OBS",
+        "method": "getFileName",
+        "content": {
+            "filename": `${Date.now() + file.size}.${ext}`,
+            "filetype": ext,
+            "parentid": uni.getStorageSync('siteP').appfolderid
+        }
+    }
+}
+
+// 处理文件上传
+const handleUploadFile = (file, data) => {
+    $Http.basic(file).then(res => {
+        console.log("上传文件成功", res)
+        if (res.msg == "成功") {
+            uploadFile(res.data, data)
+        } else {
+            uni.showToast({
+                title: `${file.content.filename}上传失败`,
+                icon: "none"
+            })
+        }
+    })
+}
+
+// 获取ArrayBuffer (H5专用)
+const getArrayBuffer = (file) => {
+    return new Promise((resolve, reject) => {
+        const xhr = new XMLHttpRequest()
+        xhr.open('GET', file.url, true)
+        xhr.responseType = 'blob'
+        xhr.onload = function () {
+            if (this.status === 200) {
+                const myBlob = this.response
+                const files = new File(
+                    [myBlob],
+                    file.name,
+                    { type: file.type }
+                )
+                const reader = new FileReader()
+                reader.readAsArrayBuffer(files)
+                reader.onload = () => resolve(reader.result)
+                reader.onerror = error => reject(error)
+            } else {
+                reject(`文件加载失败: ${this.status}`)
+            }
+        }
+        xhr.onerror = () => reject('网络请求失败')
+        xhr.send()
+    })
+}
+
+// 上传文件到服务器
+const uploadFile = (res, data) => {
+    uni.request({
+        url: res.uploadurl,
+        method: "PUT",
+        data,
+        header: { 'Content-Type': 'application/octet-stream' },
+        success: () => {
+            $Http.basic({
+                "classname": "system.attachment.huawei.OBS",
+                "method": "uploadSuccess",
+                "content": { "serialfilename": res.serialfilename }
+            }).then(s => {
+                console.log("文件上传反馈", s)
+                handleFileLink([{
+                    attachmentid: s.data.attachmentids[0],
+                    url: data.url
+                }], "temporary", 1, props.usetype)
+            }).catch(console.error)
+        },
+        fail: console.error
+    })
+}
+
+function handleFileLink(list, ownertable = "temporary", ownerid = 1, usetype = 'default') {
+    return new Promise((resolve, reject) => {
+        if (list.length == 0) return resolve(true);
+        let content = {
+            ownertable,
+            ownerid,
+            usetype,
+            attachmentids: list.map(v => v.attachmentid),
+            siteid: uni.getStorageSync("userMsg").siteid
+        }
+        $Http.basic({
+            "classname": "system.attachment.Attachment",
+            "method": "createFileLink",
+            content
+        }).then(res => {
+            console.log('跟进记录绑定附件', res)
+            resolve(res.code == '1')
+            if (res.code != '1') return uni.showToast({
+                title: res.msg,
+                icon: "none"
+            })
+            list.forEach(v => {
+                let index = props.fileList.findIndex(s => v.url == s.url)
+                props.fileList[index] = res.data.find(s => s.attachmentid == v.attachmentid)
+                console.log("props.fileList[index]", props.fileList[index])
+            })
+            emit('uploadCallback', { fileList: props.fileList, attachmentids: content.attachmentids })
+        })
+    });
+}
+
+// 保存所有的附件绑定到表上,有在上传的文件不能保存
+const isUploading = (showToast = true) => {
+    let res = props.fileList.some(file => file.status === 'uploading');
+    if (res && showToast) uni.showToast({
+        title: '文件正在上传中,请稍后再试',
+        icon: 'none'
+    });
+    return res
+}
+
+// 保存接口 接受数据调用handleFileLink
+const saveFileLinks = (ownertable, ownerid, usetype = 'default') => {
+    return new Promise((resolve, reject) => {
+        if (isUploading(false)) return resolve(false);
+        const list = props.fileList;
+        if (list.length) {
+            return handleFileLink(list, ownertable, ownerid, usetype);
+        } else {
+            resolve(true)
+        }
+    })
+}
+
+function deletePic({ file, index, name }) {
+    console.log("index", index)
+    uni.showModal({
+        cancelText: '取消',
+        confirmText: '删除',
+        content: '是否确定删除该文件?',
+        title: '提示',
+        success: ({ confirm }) => {
+            if (confirm) {
+                console.log("删除文件", file);
+                if (file.ownertable == 'temporary') {
+                    // 临时文件直接删除
+                    deleteFile([file]).then(res => {
+                        if (res) {
+                            props.fileList.splice(index, 1);
+                            emit('uploadCallback', { fileList: props.fileList });
+                        }
+                    })
+                } else {
+                    deleteList.push(file)
+                    props.fileList.splice(index, 1);
+                    emit('uploadCallback', { fileList: props.fileList })
+                }
+            }
+        },
+    })
+}
+
+// 直接删除文件
+const deleteFile = (arr) => {
+    return new Promise((resolve, reject) => {
+        let list = arr.filter(file => file.linksid);
+        if (list.length) {
+            $Http.basic({
+                "classname": "system.attachment.Attachment",
+                "method": "deleteFileLink",
+                "content": {
+                    linksids: list.map(v => v.linksid),
+                }
+            }).then(res => {
+                console.log("删除文件", res);
+                resolve(res.code == 1)
+                if (res.code != 1) uni.showToast({
+                    title: res.msg,
+                    icon: "none"
+                })
+            })
+        } else {
+            resolve(true)
+        }
+    })
+
+}
+
+// 清空临时文件 ownertable == 'temporary'
+const clearTemporaryFiles = (arr = props.fileList) => {
+    let list = arr.filter(file => file.ownertable == 'temporary' && file.linksid);
+    if (list.length) $Http.basic({
+        "classname": "system.attachment.Attachment",
+        "method": "deleteFileLink",
+        "content": {
+            linksids: list.map(v => v.linksid),
+        }
+    }).then(res => {
+        console.log("清空临时文件", res);
+    })
+}
+
+// 在页面销毁的时候 自动清空所有的临时文件
+onUnmounted(() => {
+    console.log("组件销毁,清空临时文件");
+    clearTemporaryFiles();
+})
+
+defineExpose({ isUploading, saveFileLinks, clearTemporaryFiles, handleFileLink })
+</script>