diff --git a/components/task/AttachmentFileUploader.vue b/components/task/AttachmentFileUploader.vue new file mode 100644 index 0000000..6a8ed74 --- /dev/null +++ b/components/task/AttachmentFileUploader.vue @@ -0,0 +1,456 @@ + + + + + + diff --git a/components/task/AttachmentImageUploader.vue b/components/task/AttachmentImageUploader.vue new file mode 100644 index 0000000..926d368 --- /dev/null +++ b/components/task/AttachmentImageUploader.vue @@ -0,0 +1,175 @@ + + + + + + diff --git a/pages/task/add/index.vue b/pages/task/add/index.vue index b4c3b03..d9f0d3c 100644 --- a/pages/task/add/index.vue +++ b/pages/task/add/index.vue @@ -69,46 +69,8 @@ 附件 请上传不超过200MB的文件,支持常见图片、Office、PDF、压缩包等格式。 - - - 🏔️ - 添加照片 - - - - - - - - - - - - - 📄 - 添加文件 - - - - - - {{ getFileIcon(file.name) }} - - {{ file.name }} - {{ formatFileSize(file.size) }} - - - - + + @@ -209,12 +171,11 @@ import { ref, computed } from 'vue'; import { onLoad } from '@dcloudio/uni-app'; import { createTask, getProjectListAll, getUserList } from '@/api'; import { useDictStore } from '@/store/dict'; -import { chooseAndUploadImages, batchUploadFilesToQiniu } from '@/utils/qiniu.js'; +import AttachmentImageUploader from '@/components/task/AttachmentImageUploader.vue'; +import AttachmentFileUploader from '@/components/task/AttachmentFileUploader.vue'; const dictStore = useDictStore(); -const ATTACHMENT_LIMIT = 9; - const formData = ref({ projectId: '', projectName: '', @@ -245,28 +206,6 @@ const projectPicker=ref(null); const expirePickerRef = ref(null); const expirePickerValue = ref(Date.now()); -const getFileIcon = (fileName) => { - if (!fileName) return '📄'; - const ext = fileName.split('.').pop().toLowerCase(); - const iconMap = { - 'pdf': '📕', - 'doc': '📘', - 'docx': '📘', - 'xls': '📗', - 'xlsx': '📗', - 'ppt': '📙', - 'pptx': '📙', - 'txt': '📄', - 'zip': '📦', - 'rar': '📦', - 'jpg': '🖼️', - 'jpeg': '🖼️', - 'png': '🖼️', - 'gif': '🖼️' - }; - return iconMap[ext] || '📄'; -}; - const typeOptions = computed(() => { return dictStore.getDictByType('task_type').map(item => ({ label: item.dictLabel, @@ -418,371 +357,6 @@ const onExpireTimeConfirm = (event) => { } }; -const handleAddAttachment = () => { - const remaining = ATTACHMENT_LIMIT - formData.value.attachments.length; - if (remaining <= 0) { - uni.showToast({ - title: `最多上传${ATTACHMENT_LIMIT}个附件`, - icon: 'none' - }); - return; - } - - uni.showActionSheet({ - itemList: ['上传图片', '上传文件'], - success: ({ tapIndex }) => { - if (tapIndex === 0) { - chooseImages(); - } else if (tapIndex === 1) { - chooseFiles(); - } - } - }); -}; - -// 选择图片并自动上传到七牛云 -const chooseImages = async () => { - try { - const remainingCount = 9 - formData.value.images.length; - if (remainingCount <= 0) { - uni.showToast({ - title: '最多只能添加9张图片', - icon: 'none' - }); - return; - } - - // 使用封装好的选择并上传功能 - const urls = await chooseAndUploadImages({ - count: remainingCount, - sizeType: ['original', 'compressed'], - sourceType: ['album', 'camera'] - }); - - // 将上传后的URL添加到图片列表 - formData.value.images = [...formData.value.images, ...urls]; - } catch (err) { - console.error('选择或上传图片失败:', err); - uni.showToast({ - title: err.message || '选择图片失败', - icon: 'none' - }); - } -}; - -// 预览图片 -const previewImage = (index) => { - uni.previewImage({ - urls: formData.value.images, - current: index - }); -}; - -// 删除图片 -const removeImage = (index) => { - formData.value.images.splice(index, 1); -}; -const chooseFiles = async () => { - const remainingCount = 5 - formData.value.files.length; - if (remainingCount <= 0) { - uni.showToast({ - title: '最多只能添加5个文件', - icon: 'none' - }); - return; - } - - // 优先使用 uni.chooseFile(H5和部分平台支持) - // #ifdef H5 || MP-WEIXIN || APP-PLUS - try { - uni.chooseFile({ - count: remainingCount, - extension: ['.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.txt', '.zip', '.rar','.jpg','.png'], - success: async (res) => { - try { - uni.showLoading({ - title: '上传中...', - mask: true - }); - - // 批量上传文件到七牛云 - const uploadResults = await batchUploadFilesToQiniu( - res.tempFiles.map(file => ({ - path: file.path, - name: file.name - })) - ); - - // 将上传结果添加到文件列表 - const newFiles = uploadResults.map(result => ({ - name: result.name, - path: result.url, // 保存七牛云URL - size: result.size - })); - - formData.value.files = [...formData.value.files, ...newFiles]; - - uni.hideLoading(); - uni.showToast({ - title: `成功添加${newFiles.length}个文件`, - icon: 'success' - }); - } catch (error) { - uni.hideLoading(); - console.error('上传文件失败:', error); - uni.showToast({ - title: error.message || '上传文件失败', - icon: 'none' - }); - } - }, - fail: (err) => { - console.error('选择文件失败:', err); - // 如果uni.chooseFile不支持,尝试使用原生方法 - chooseFilesNative(); - } - }); - } catch (error) { - // 如果不支持uni.chooseFile,使用原生方法 - chooseFilesNative(); - } - // #endif - - // #ifndef H5 || MP-WEIXIN || APP-PLUS - // 其他平台使用原生方法 - chooseFilesNative(); - // #endif -}; - -// 原生文件选择方法(安卓平台) -const chooseFilesNative = async () => { - const remainingCount = 5 - formData.value.files.length; - - // 安卓平台使用 plus API 调用原生文件选择器 - if (typeof plus !== 'undefined') { - try { - const Intent = plus.android.importClass('android.content.Intent'); - const main = plus.android.runtimeMainActivity(); - - // 创建文件选择 Intent - const intent = new Intent(Intent.ACTION_GET_CONTENT); - intent.setType('*/*'); - intent.addCategory(Intent.CATEGORY_OPENABLE); - intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); // 允许多选 - - // 启动文件选择器 - main.startActivityForResult(intent, 1001); - - // 监听文件选择结果 - const originalOnActivityResult = main.onActivityResult; - main.onActivityResult = async (requestCode, resultCode, data) => { - if (requestCode === 1001) { - if (resultCode === -1 && data) { // RESULT_OK = -1 - try { - const clipData = data.getClipData(); - const files = []; - - // 获取文件名的方法 - const getFileName = (uri) => { - try { - const cursor = main.getContentResolver().query(uri, null, null, null, null); - if (cursor && cursor.moveToFirst()) { - const nameIndex = cursor.getColumnIndex('_display_name'); - if (nameIndex !== -1) { - const fileName = cursor.getString(nameIndex); - cursor.close(); - return fileName; - } - cursor.close(); - } - } catch (e) { - console.error('获取文件名失败:', e); - } - return null; - }; - - if (clipData) { - // 多选文件 - const count = clipData.getItemCount(); - for (let i = 0; i < count && files.length < remainingCount; i++) { - const item = clipData.getItemAt(i); - const uri = item.getUri(); - const uriString = uri.toString(); - - // 获取文件名 - let fileName = getFileName(uri) || `file_${Date.now()}_${i}`; - - files.push({ - name: fileName, - path: uriString, // 保存 URI 字符串 - size: 0 - }); - } - } else { - // 单选文件 - const uri = data.getData(); - if (uri) { - const uriString = uri.toString(); - let fileName = getFileName(uri) || `file_${Date.now()}`; - - files.push({ - name: fileName, - path: uriString, // 保存 URI 字符串 - size: 0 - }); - } - } - - if (files.length > 0) { - // 显示上传中提示 - uni.showLoading({ - title: '上传中...', - mask: true - }); - - try { - // 批量上传文件到七牛云 - const uploadResults = await batchUploadFilesToQiniu(files); - - // 将上传结果添加到文件列表 - const newFiles = uploadResults.map(result => ({ - name: result.name, - path: result.url, // 保存七牛云URL - size: result.size - })); - - formData.value.files = [...formData.value.files, ...newFiles]; - - uni.hideLoading(); - uni.showToast({ - title: `成功添加${newFiles.length}个文件`, - icon: 'success' - }); - } catch (uploadError) { - uni.hideLoading(); - console.error('上传文件失败:', uploadError); - uni.showToast({ - title: uploadError.message || '上传文件失败', - icon: 'none' - }); - } - } - - // 恢复原始的 onActivityResult - if (originalOnActivityResult) { - main.onActivityResult = originalOnActivityResult; - } - } catch (error) { - uni.hideLoading(); - console.error('处理文件选择结果失败:', error); - uni.showToast({ - title: '处理文件失败', - icon: 'none' - }); - } - } - } else { - // 调用原始的 onActivityResult - if (originalOnActivityResult) { - originalOnActivityResult(requestCode, resultCode, data); - } - } - }; - } catch (error) { - console.error('打开文件选择器失败:', error); - uni.showToast({ - title: '文件选择功能暂不可用', - icon: 'none' - }); - } - } else { - uni.showToast({ - title: '当前环境不支持文件选择', - icon: 'none' - }); - } -}; - -// 删除文件 -const removeFile = (index) => { - formData.value.files.splice(index, 1); -}; - -// 格式化文件大小 -const formatFileSize = (bytes) => { - if (!bytes || bytes === 0) return ''; - const k = 1024; - const sizes = ['B', 'KB', 'MB', 'GB']; - const i = Math.floor(Math.log(bytes) / Math.log(k)); - return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i]; -}; - -// 预览/下载文件 -const previewFile = (file) => { - if (!file.path) { - uni.showToast({ - title: '文件路径不存在', - icon: 'none' - }); - return; - } - - // 如果是图片,使用预览图片功能 - const imageExts = ['jpg', 'jpeg', 'png', 'gif', 'webp']; - const ext = file.name.split('.').pop().toLowerCase(); - - if (imageExts.includes(ext)) { - uni.previewImage({ - urls: [file.path], - current: file.path - }); - } else { - // 其他文件类型,尝试打开或下载 - // #ifdef H5 - window.open(file.path, '_blank'); - // #endif - - // #ifdef APP-PLUS - plus.runtime.openURL(file.path); - // #endif - - // #ifndef H5 || APP-PLUS - uni.showToast({ - title: '点击下载文件', - icon: 'none' - }); - // 可以调用下载API - uni.downloadFile({ - url: file.path, - success: (res) => { - if (res.statusCode === 200) { - uni.openDocument({ - filePath: res.tempFilePath, - success: () => { - console.log('打开文档成功'); - }, - fail: (err) => { - console.error('打开文档失败:', err); - uni.showToast({ - title: '无法打开此文件', - icon: 'none' - }); - } - }); - } - }, - fail: (err) => { - console.error('下载文件失败:', err); - uni.showToast({ - title: '下载文件失败', - icon: 'none' - }); - } - }); - // #endif - } -}; - @@ -1060,6 +634,7 @@ onLoad(async (options) => { line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; + line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } diff --git a/pages/task/submit/index.vue b/pages/task/submit/index.vue index 471bc9a..bc5d204 100644 --- a/pages/task/submit/index.vue +++ b/pages/task/submit/index.vue @@ -24,82 +24,11 @@ - - - 🏔️ - 添加照片 - - - - - - - - - - - - - 📄 - 添加文件 - - - - - - {{ getFileIcon(file.name) }} - - {{ file.name }} - {{ formatFileSize(file.size) }} - - - - + + - - - - 选择任务进度 - - - - - {{ progress }}% - - - - - 取消 - 确定 - - - -