123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 |
- <template>
- <view v-if="custom">
- <up-upload @after-read="afterRead" :deletable="!disabled" @delete="deletePic"
- :max-count="disabled ? fileList.length : maxCount" :accept="accept" multiple @clickPreview="clickPreview">
- <slot />
- </up-upload>
- </view>
- <up-upload v-else :fileList="fileList" @after-read="afterRead" :deletable="!disabled" @delete="deletePic"
- :max-count="disabled ? fileList.length : maxCount" :accept="accept" multiple @clickPreview="clickPreview" />
- </template>
- <script setup>
- import { ref, reactive, defineProps, defineEmits, getCurrentInstance, onUnmounted } from 'vue'
- const emit = defineEmits(['uploadCallback', 'startUploading'])
- const props = defineProps({
- accept: {
- type: String,
- default: "image"
- },
- maxCount: {
- type: [String, Number],
- default: 99
- },
- uploadCallback: {
- type: Function
- },
- startUploading: {
- type: Function
- },
- fileList: {
- type: Array,
- default: reactive([])
- },
- usetype: {
- type: String,
- default: 'default'
- },
- ownertable: {
- type: String,
- default: 'temporary'
- },
- ownerid: {
- type: [String, Number],
- default: 1
- },
- disabled: {
- type: Boolean,
- default: false
- },
- custom: {
- type: Boolean,
- default: false
- }
- })
- const { $Http } = getCurrentInstance().proxy;
- const deleteList = reactive([]); // 用于存储待删除的文件列表
- const clickPreview = (e) => {
- uni.previewImage({
- urls: props.fileList.map(v => v.url),
- current: e.url,
- loop: true,
- })
- }
- // 文件读取后处理
- const afterRead = ({ file }) => {
- emit('startUploading', file);
- file.forEach(v => {
- // #ifdef H5
- getArrayBuffer(v).then(data => {
- data.data.url = v.url;
- console.log("data.data", data.data)
- 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({
- data: 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', resolve = () => { }) {
- 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 => {
- const file = props.fileList.find(s => v.url === s.url);
- delete file.status;
- delete file.message;
- if (file) {
- Object.assign(file, res.data.find(s => s.attachmentid === v.attachmentid));
- }
- });
- 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') => {
- // 如果有待删除的文件,先删除
- deleteList.length && deleteFile(deleteList);
- return new Promise((resolve, reject) => {
- const list = props.fileList;
- console.log("list", list)
- if (list.length) {
- return handleFileLink(list, ownertable, ownerid, usetype, resolve);
- } else {
- resolve(true)
- }
- })
- }
- function deletePic({ file, index, name }) {
- 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(() => {
- clearTemporaryFiles();
- })
- defineExpose({ isUploading, handleFileLink, saveFileLinks, deleteFile })
- </script>
|