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>
|
|
|
|
|
|
|
2025-11-13 14:30:06 +08:00
|
|
|
|
|
2025-11-05 15:23:52 +08:00
|
|
|
|
|
2025-11-14 17:57:26 +08:00
|
|
|
|
<AttachmentImageUploader v-model="formData.images" />
|
|
|
|
|
|
<AttachmentFileUploader v-model="formData.files" />
|
2025-11-05 15:52:46 +08:00
|
|
|
|
</view>
|
2025-11-05 15:23:52 +08:00
|
|
|
|
</scroll-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>
|
2025-11-14 17:57:26 +08:00
|
|
|
|
import { ref, computed } from 'vue';
|
2025-11-05 15:23:52 +08:00
|
|
|
|
import { onLoad } from '@dcloudio/uni-app';
|
2025-11-12 15:33:53 +08:00
|
|
|
|
import { submitTask } from '@/api';
|
2025-11-14 17:57:26 +08:00
|
|
|
|
import AttachmentImageUploader from '@/components/task/AttachmentImageUploader.vue';
|
|
|
|
|
|
import AttachmentFileUploader from '@/components/task/AttachmentFileUploader.vue';
|
2025-11-05 15:23:52 +08:00
|
|
|
|
|
|
|
|
|
|
// 表单数据
|
|
|
|
|
|
const formData = ref({
|
|
|
|
|
|
description: '',
|
|
|
|
|
|
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 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 || '';
|
|
|
|
|
|
// 处理附件
|
|
|
|
|
|
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();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
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() || '',
|
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() || '',
|
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 {
|
|
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 图片预览 */
|
|
|
|
|
|
/* 提交按钮 */
|
|
|
|
|
|
.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>
|
|
|
|
|
|
|