OfficeSystem/pages/task/submit/index.vue

1022 lines
26 KiB
Vue
Raw Normal View History

2025-11-05 15:23:52 +08:00
<template>
2025-11-05 15:52:46 +08:00
2025-11-05 15:23:52 +08:00
<view class="submit-task-page">
<!-- 自定义导航栏 -->
2025-11-05 15:52:46 +08:00
2025-11-05 15:23:52 +08:00
<!-- 内容区域 -->
<scroll-view class="content-scroll" scroll-y>
2025-11-05 15:52:46 +08:00
<view style="padding: 16px">
2025-11-05 15:23:52 +08:00
<!-- 输入提交说明 -->
<view class="form-item">
2025-11-05 15:52:46 +08:00
<view class="form-icon"></view>
2025-11-05 15:23:52 +08:00
<textarea
2025-11-05 15:56:46 +08:00
v-model="formData.description"
2025-11-05 15:23:52 +08:00
class="description-input"
placeholder="输入提交说明"
placeholder-style="color: #999;"
:maxlength="500"
auto-height
/>
</view>
<!-- 输入任务进度 -->
<view class="form-item clickable-item" @click="openProgressPicker">
<view class="form-icon">👤%</view>
<view class="form-content">
<text v-if="formData.progress !== null" class="form-value">{{ formData.progress }}%</text>
<text v-else class="form-placeholder">输入任务进度</text>
</view>
<text class="arrow"></text>
</view>
<!-- 添加照片 -->
<view class="form-item clickable-item" @click="chooseImages">
<view class="form-icon">🏔</view>
<text class="form-label">添加照片</text>
<text class="arrow"></text>
</view>
<!-- 照片预览 -->
<view class="images-preview" v-if="formData.images.length > 0">
<view
class="image-item"
v-for="(image, index) in formData.images"
:key="index"
>
<image :src="image" mode="aspectFill" class="preview-image" @click="previewImage(index)" />
<view class="remove-btn" @click="removeImage(index)"></view>
</view>
</view>
<!-- 添加文件 -->
<view class="form-item clickable-item" @click="chooseFiles">
<view class="form-icon">📄</view>
<text class="form-label">添加文件</text>
<text class="arrow"></text>
</view>
<!-- 文件列表 -->
<view class="files-list" v-if="formData.files.length > 0">
<view
class="file-item"
v-for="(file, index) in formData.files"
:key="index"
2025-11-06 18:01:41 +08:00
@click="previewFile(file)"
2025-11-05 15:23:52 +08:00
>
2025-11-06 18:01:41 +08:00
<text class="file-icon">{{ getFileIcon(file.name) }}</text>
<view class="file-info">
<text class="file-name">{{ file.name }}</text>
<text class="file-size" v-if="file.size > 0">{{ formatFileSize(file.size) }}</text>
</view>
<view class="remove-btn" @click.stop="removeFile(index)"></view>
2025-11-05 15:23:52 +08:00
</view>
</view>
2025-11-05 15:52:46 +08:00
</view>
2025-11-05 15:23:52 +08:00
</scroll-view>
<!-- 进度选择弹窗 -->
<view v-if="showProgressPicker" class="modal-mask" @click="showProgressPicker = false">
<view class="modal-content progress-modal" @click.stop>
<view class="modal-title">选择任务进度</view>
<view class="progress-content">
<slider
2025-11-05 15:52:46 +08:00
:value="tempProgress !== null ? tempProgress : 0"
2025-11-05 15:23:52 +08:00
:min="0"
:max="100"
:step="10"
:show-value="true"
activeColor="#1976d2"
@change="onProgressChange"
/>
<view class="progress-options">
<view
class="progress-option"
v-for="progress in progressOptions"
:key="progress"
2025-11-05 15:52:46 +08:00
:class="{ active: tempProgress === progress }"
2025-11-05 15:23:52 +08:00
@click="selectProgress(progress)"
>
<text>{{ progress }}%</text>
</view>
</view>
</view>
<view class="modal-actions">
<text class="modal-btn cancel-btn" @click="showProgressPicker = false">取消</text>
<text class="modal-btn confirm-btn" @click="confirmProgress">确定</text>
</view>
</view>
</view>
<!-- 确认提交按钮 -->
<view class="submit-button-wrapper">
<uv-button
type="primary"
size="normal"
:disabled="!canSubmit"
@click="handleSubmit"
>
2025-11-05 15:56:46 +08:00
{{ isEditMode ? '确认更新' : '确认提交' }}
2025-11-05 15:23:52 +08:00
</uv-button>
</view>
</view>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
2025-11-06 18:01:41 +08:00
import { chooseAndUploadImages, uploadFileToQiniu, batchUploadFilesToQiniu } from '@/utils/qiniu.js';
2025-11-12 15:33:53 +08:00
import { submitTask } from '@/api';
2025-11-05 15:23:52 +08:00
// 表单数据
const formData = ref({
description: '',
progress: null,
images: [],
files: []
});
// 任务ID
const taskId = ref(null);
2025-11-05 15:56:46 +08:00
// 编辑模式标识
const isEditMode = ref(false);
const editRecordIndex = ref(-1);
const editRecordData = ref(null);
2025-11-05 15:23:52 +08:00
// 进度选择弹窗
const showProgressPicker = ref(false);
const tempProgress = ref(null);
// 打开进度选择器
const openProgressPicker = () => {
tempProgress.value = formData.value.progress !== null ? formData.value.progress : 0;
showProgressPicker.value = true;
};
// 进度选项
const progressOptions = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
// 是否可以提交
const canSubmit = computed(() => {
return formData.value.description.trim() !== '' ||
formData.value.images.length > 0 ||
formData.value.files.length > 0;
});
// 页面加载
onLoad((options) => {
taskId.value = options.taskId || options.id;
2025-11-05 15:56:46 +08:00
// 检查是否是编辑模式
if (options.mode === 'edit' || options.recordIndex !== undefined) {
isEditMode.value = true;
editRecordIndex.value = parseInt(options.recordIndex || -1);
// 从存储中获取编辑数据
const editData = uni.getStorageSync('editSubmitRecord');
if (editData && editData.record) {
editRecordData.value = editData.record;
// 预填充表单数据
formData.value.description = editData.record.content || '';
formData.value.progress = editData.record.progress !== null && editData.record.progress !== undefined
? editData.record.progress
: null;
// 处理附件
if (editData.record.attachments && editData.record.attachments.length > 0) {
editData.record.attachments.forEach(attachment => {
if (attachment.type === 'image' && attachment.path) {
formData.value.images.push(attachment.path);
} else if (attachment.type === 'file') {
formData.value.files.push({
name: attachment.name || '文件',
path: attachment.path || '',
size: attachment.size || 0
});
}
});
}
// 清除存储的编辑数据
uni.removeStorageSync('editSubmitRecord');
}
}
2025-11-05 15:23:52 +08:00
});
// 取消
const handleCancel = () => {
uni.showModal({
title: '提示',
content: '确定要取消提交吗?未保存的内容将丢失',
success: (res) => {
if (res.confirm) {
uni.navigateBack();
}
}
});
};
// 进度变化
const onProgressChange = (e) => {
tempProgress.value = e.detail.value;
};
2025-11-05 15:52:46 +08:00
// 选择进度(点击按钮直接确认)
2025-11-05 15:23:52 +08:00
const selectProgress = (progress) => {
2025-11-05 15:52:46 +08:00
formData.value.progress = progress;
showProgressPicker.value = false;
2025-11-05 15:23:52 +08:00
};
// 确认进度
const confirmProgress = () => {
formData.value.progress = tempProgress.value;
showProgressPicker.value = false;
};
2025-11-06 16:16:58 +08:00
// 选择图片并自动上传到七牛云
const chooseImages = async () => {
try {
const remainingCount = 9 - formData.value.images.length;
if (remainingCount <= 0) {
2025-11-05 15:23:52 +08:00
uni.showToast({
2025-11-06 16:16:58 +08:00
title: '最多只能添加9张图片',
2025-11-05 15:23:52 +08:00
icon: 'none'
});
2025-11-06 16:16:58 +08:00
return;
2025-11-05 15:23:52 +08:00
}
2025-11-06 16:16:58 +08:00
// 使用封装好的选择并上传功能
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'
});
}
2025-11-05 15:23:52 +08:00
};
// 预览图片
const previewImage = (index) => {
uni.previewImage({
urls: formData.value.images,
current: index
});
};
// 删除图片
const removeImage = (index) => {
formData.value.images.splice(index, 1);
};
2025-11-06 18:01:41 +08:00
// 选择文件(支持多平台)
const chooseFiles = async () => {
2025-11-05 15:52:46 +08:00
const remainingCount = 5 - formData.value.files.length;
if (remainingCount <= 0) {
uni.showToast({
title: '最多只能添加5个文件',
icon: 'none'
});
return;
}
2025-11-06 18:01:41 +08:00
// 优先使用 uni.chooseFileH5和部分平台支持
// #ifdef H5 || MP-WEIXIN || APP-PLUS
try {
uni.chooseFile({
count: remainingCount,
2025-11-07 09:14:06 +08:00
extension: ['.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.txt', '.zip', '.rar','.jpg','.png'],
2025-11-06 18:01:41 +08:00
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;
2025-11-05 15:52:46 +08:00
// 安卓平台使用 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;
2025-11-06 18:01:41 +08:00
main.onActivityResult = async (requestCode, resultCode, data) => {
2025-11-05 15:52:46 +08:00
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) {
2025-11-06 18:01:41 +08:00
// 显示上传中提示
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'
});
}
2025-11-05 15:52:46 +08:00
}
// 恢复原始的 onActivityResult
if (originalOnActivityResult) {
main.onActivityResult = originalOnActivityResult;
}
} catch (error) {
2025-11-06 18:01:41 +08:00
uni.hideLoading();
2025-11-05 15:52:46 +08:00
console.error('处理文件选择结果失败:', error);
uni.showToast({
title: '处理文件失败',
icon: 'none'
});
}
2025-11-05 15:23:52 +08:00
}
2025-11-05 15:52:46 +08:00
} else {
// 调用原始的 onActivityResult
if (originalOnActivityResult) {
originalOnActivityResult(requestCode, resultCode, data);
}
}
};
} catch (error) {
console.error('打开文件选择器失败:', error);
2025-11-05 15:23:52 +08:00
uni.showToast({
2025-11-05 15:52:46 +08:00
title: '文件选择功能暂不可用',
2025-11-05 15:23:52 +08:00
icon: 'none'
});
}
2025-11-05 15:52:46 +08:00
} else {
uni.showToast({
title: '当前环境不支持文件选择',
icon: 'none'
});
}
2025-11-05 15:23:52 +08:00
};
// 删除文件
const removeFile = (index) => {
formData.value.files.splice(index, 1);
};
2025-11-06 18:01:41 +08:00
// 获取文件图标
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 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
}
};
2025-11-05 15:52:46 +08:00
// 格式化时间为中文格式:年月日星期几时分秒
const formatTimeToChinese = (date) => {
const weekdays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const weekday = weekdays[date.getDay()];
const hour = String(date.getHours()).padStart(2, '0');
const minute = String(date.getMinutes()).padStart(2, '0');
const second = String(date.getSeconds()).padStart(2, '0');
return `${year}${month}${day}${weekday} ${hour}:${minute}:${second}`;
};
2025-11-05 15:23:52 +08:00
// 提交任务
2025-11-06 16:49:06 +08:00
const handleSubmit = async () => {
2025-11-05 15:23:52 +08:00
if (!canSubmit.value) {
uni.showToast({
title: '请至少填写提交说明或添加附件',
icon: 'none'
});
return;
}
2025-11-06 16:49:06 +08:00
if (!taskId.value) {
uni.showToast({
title: '任务ID不能为空',
icon: 'none'
});
return;
}
2025-11-05 15:23:52 +08:00
uni.showLoading({
2025-11-05 15:56:46 +08:00
title: isEditMode.value ? '更新中...' : '提交中...'
2025-11-05 15:23:52 +08:00
});
2025-11-06 16:49:06 +08:00
try {
// 合并所有附件URL图片和文件
2025-11-06 18:01:41 +08:00
// 图片和文件都已经上传到七牛云直接使用URL
2025-11-06 16:49:06 +08:00
const allAttaches = [
...formData.value.images, // 图片已经是七牛云URL
2025-11-06 18:01:41 +08:00
...formData.value.files.map(file => file.path) // 文件已经是七牛云URL
2025-11-06 16:49:06 +08:00
].filter(url => url && url.trim() !== ''); // 过滤空值
// 将附件数组转换为逗号分隔的字符串
const submitAttaches = allAttaches.join(',');
// 调用提交接口
await submitTask({
id: taskId.value,
submitAttaches: submitAttaches,
submitRemark: formData.value.description.trim()
});
2025-11-05 15:23:52 +08:00
uni.hideLoading();
2025-11-06 16:49:06 +08:00
// 提交成功后的处理
2025-11-05 15:56:46 +08:00
if (isEditMode.value) {
// 编辑模式:更新现有记录
const updatedRecord = {
userName: editRecordData.value?.userName || '当前用户', // 保持原用户名
time: formatTimeToChinese(new Date()), // 更新时间
2025-11-06 16:49:06 +08:00
content: formData.value.description.trim() || '',
progress: formData.value.progress,
2025-11-05 15:56:46 +08:00
attachments: [
2025-11-06 16:49:06 +08:00
...formData.value.images.map(img => ({ type: 'image', path: img })),
...formData.value.files.map(file => ({ type: 'file', name: file.name, path: file.path }))
2025-11-05 15:56:46 +08:00
],
canEdit: true, // 保持可编辑权限
showDelayBtn: editRecordData.value?.showDelayBtn || false
};
2025-11-05 15:23:52 +08:00
2025-11-05 15:56:46 +08:00
// 将更新的记录存储到本地,供任务详情页使用
uni.setStorageSync('updatedSubmitRecord', {
recordIndex: editRecordIndex.value,
record: updatedRecord
});
uni.showToast({
title: '更新成功',
icon: 'success'
});
} else {
// 新建模式:添加新记录
const submitRecord = {
userName: '当前用户', // TODO: 从用户信息获取
time: formatTimeToChinese(new Date()),
2025-11-06 16:49:06 +08:00
content: formData.value.description.trim() || '',
progress: formData.value.progress,
2025-11-05 15:56:46 +08:00
attachments: [
2025-11-06 16:49:06 +08:00
...formData.value.images.map(img => ({ type: 'image', path: img })),
...formData.value.files.map(file => ({ type: 'file', name: file.name, path: file.path }))
2025-11-05 15:56:46 +08:00
],
canEdit: true,
showDelayBtn: false
};
// 将提交记录存储到本地,供任务详情页使用
uni.setStorageSync('newSubmitRecord', submitRecord);
uni.showToast({
title: '提交成功',
icon: 'success'
});
}
2025-11-05 15:23:52 +08:00
// 延迟返回,让用户看到成功提示
setTimeout(() => {
uni.navigateBack();
}, 1500);
2025-11-06 16:49:06 +08:00
} catch (error) {
uni.hideLoading();
console.error('提交任务失败:', error);
uni.showToast({
title: error.message || '提交失败,请重试',
icon: 'none',
duration: 2000
});
}
2025-11-05 15:23:52 +08:00
};
</script>
<style lang="scss" scoped>
.submit-task-page {
min-height: 100vh;
background-color: #f5f5f5;
display: flex;
flex-direction: column;
padding-bottom: 80px;
}
/* 自定义导航栏 */
.custom-navbar {
background-color: #fff;
border-bottom: 1px solid #eee;
position: sticky;
top: 0;
z-index: 100;
}
.navbar-content {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 16px;
height: 44px;
}
.nav-btn {
font-size: 20px;
color: #333;
padding: 4px 8px;
cursor: pointer;
}
.nav-title {
font-size: 18px;
font-weight: 600;
color: #333;
}
.nav-placeholder {
width: 36px;
}
/* 内容滚动区域 */
.content-scroll {
flex: 1;
2025-11-05 15:52:46 +08:00
2025-11-05 15:23:52 +08:00
}
/* 表单项 */
.form-item {
display: flex;
align-items: center;
padding: 16px;
background-color: #fff;
border-radius: 8px;
margin-bottom: 12px;
gap: 12px;
}
.clickable-item {
cursor: pointer;
&:active {
background-color: #f5f5f5;
}
}
.form-icon {
font-size: 20px;
flex-shrink: 0;
}
.form-content {
flex: 1;
display: flex;
flex-direction: column;
}
.form-label {
flex: 1;
font-size: 15px;
color: #333;
}
.form-value {
font-size: 15px;
color: #333;
font-weight: 500;
}
.form-placeholder {
font-size: 15px;
color: #999;
}
.arrow {
font-size: 20px;
color: #999;
flex-shrink: 0;
}
.description-input {
flex: 1;
min-height: 80px;
font-size: 15px;
color: #333;
line-height: 1.6;
}
/* 图片预览 */
.images-preview {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-bottom: 12px;
padding: 0 16px;
}
.image-item {
position: relative;
width: 100px;
height: 100px;
border-radius: 8px;
overflow: hidden;
}
.preview-image {
width: 100%;
height: 100%;
}
.remove-btn {
2025-11-06 18:01:41 +08:00
position: relative;
2025-11-05 15:23:52 +08:00
width: 24px;
height: 24px;
background-color: rgba(0, 0, 0, 0.6);
color: #fff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
cursor: pointer;
}
/* 文件列表 */
.files-list {
padding: 0 16px;
margin-bottom: 12px;
}
.file-item {
display: flex;
align-items: center;
padding: 12px;
background-color: #fff;
border-radius: 8px;
margin-bottom: 8px;
gap: 12px;
2025-11-06 18:01:41 +08:00
cursor: pointer;
&:active {
background-color: #f5f5f5;
}
2025-11-05 15:23:52 +08:00
}
.file-icon {
2025-11-06 18:01:41 +08:00
font-size: 24px;
2025-11-05 15:23:52 +08:00
flex-shrink: 0;
}
2025-11-06 18:01:41 +08:00
.file-info {
2025-11-05 15:23:52 +08:00
flex: 1;
2025-11-06 18:01:41 +08:00
display: flex;
flex-direction: column;
gap: 4px;
min-width: 0;
}
.file-name {
2025-11-05 15:23:52 +08:00
font-size: 14px;
color: #333;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
2025-11-06 18:01:41 +08:00
font-weight: 500;
}
.file-size {
font-size: 12px;
color: #999;
2025-11-05 15:23:52 +08:00
}
/* 进度选择弹窗 */
.modal-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.modal-content {
background-color: #fff;
border-radius: 12px;
width: 90%;
max-width: 400px;
padding: 20px;
}
.modal-title {
font-size: 18px;
font-weight: 600;
color: #333;
text-align: center;
margin-bottom: 20px;
}
.progress-content {
padding: 20px 0;
}
.progress-options {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 20px;
}
.progress-option {
flex: 1;
min-width: 60px;
padding: 10px;
text-align: center;
background-color: #f5f5f5;
border-radius: 6px;
font-size: 14px;
color: #666;
cursor: pointer;
&.active {
background-color: #1976d2;
color: #fff;
}
&:active {
opacity: 0.8;
}
}
.modal-actions {
display: flex;
gap: 12px;
margin-top: 20px;
}
.modal-btn {
flex: 1;
padding: 12px;
text-align: center;
border-radius: 6px;
font-size: 16px;
cursor: pointer;
}
.cancel-btn {
background-color: #f5f5f5;
color: #666;
}
.confirm-btn {
background-color: #1976d2;
color: #fff;
}
/* 提交按钮 */
.submit-button-wrapper {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 16px;
background-color: #fff;
border-top: 1px solid #eee;
z-index: 100;
}
</style>