|
|
@@ -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>
|