440 lines
11 KiB
Vue
440 lines
11 KiB
Vue
<template>
|
||
<view class="image-upload-container">
|
||
<!-- 顶部导航栏 -->
|
||
<view class="top-navbar">
|
||
<text class="cancel" @click="navigateBack">取消</text>
|
||
<text class="title">图片上传</text>
|
||
<text class="save" @click="submitUpload" :class="{ disabled: !canSubmit }">提交</text>
|
||
</view>
|
||
|
||
<!-- 内容区域 -->
|
||
<scroll-view class="content" scroll-y>
|
||
<!-- 部门信息 -->
|
||
<view class="dept-info">
|
||
<text class="label">所属部门:</text>
|
||
<text class="value">{{ currentUser.department }}</text>
|
||
</view>
|
||
|
||
<!-- 图片选择区域 -->
|
||
<view class="section">
|
||
<text class="section-title">选择图片</text>
|
||
<view class="image-grid">
|
||
<view v-for="(image, index) in selectedImages" :key="index" class="image-item">
|
||
<image :src="image" mode="aspectFill"></image>
|
||
<view class="delete-btn" @click="removeImage(index)">
|
||
<u-icon name="close" size="28" color="#fff"></u-icon>
|
||
</view>
|
||
</view>
|
||
<view v-if="selectedImages.length < maxImages" class="add-image" @click="chooseImage">
|
||
<u-icon name="plus" size="60" color="#c0c4cc"></u-icon>
|
||
<text>添加图片</text>
|
||
</view>
|
||
</view>
|
||
<text class="hint">{{ selectedImages.length }}/{{ maxImages }} 张</text>
|
||
</view>
|
||
|
||
<!-- 表单信息 -->
|
||
<view class="section">
|
||
<text class="section-title">图片信息</text>
|
||
|
||
<!-- 标题 -->
|
||
<view class="form-item">
|
||
<text class="form-label">标题</text>
|
||
<u-input
|
||
v-model="formData.title"
|
||
placeholder="请输入图片标题"
|
||
border="bottom"
|
||
maxlength="50"
|
||
></u-input>
|
||
</view>
|
||
|
||
<!-- 标签 -->
|
||
<view class="form-item">
|
||
<text class="form-label">标签</text>
|
||
<view class="tags-container">
|
||
<view
|
||
v-for="tag in availableTags"
|
||
:key="tag.value"
|
||
class="tag"
|
||
:class="{ active: formData.tags.includes(tag.value) }"
|
||
@click="toggleTag(tag.value)"
|
||
>
|
||
{{ tag.label }}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 描述 -->
|
||
<view class="form-item">
|
||
<text class="form-label">描述</text>
|
||
<u-input
|
||
v-model="formData.description"
|
||
placeholder="请输入图片描述(选填)"
|
||
border="bottom"
|
||
type="textarea"
|
||
:rows="3"
|
||
maxlength="200"
|
||
></u-input>
|
||
</view>
|
||
|
||
<!-- 关联任务 -->
|
||
<view class="form-item">
|
||
<text class="form-label">关联任务</text>
|
||
<u-picker
|
||
v-model="showTaskPicker"
|
||
:columns="taskOptions"
|
||
@confirm="onTaskConfirm"
|
||
@cancel="showTaskPicker = false"
|
||
title="选择任务"
|
||
mode="selector"
|
||
@change="onTaskChange"
|
||
></u-picker>
|
||
<view class="task-select" @click="showTaskPicker = true">
|
||
<text v-if="formData.taskId" class="selected-task">{{ selectedTaskName }}</text>
|
||
<text v-else class="placeholder">请选择关联任务(选填)</text>
|
||
<u-icon name="arrow-right" size="20" color="#c0c4cc"></u-icon>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
|
||
<!-- 上传进度弹窗 -->
|
||
<u-modal v-model="showUploadModal" show-cancel-button="false" :close-on-click-modal="false">
|
||
<view class="upload-modal">
|
||
<u-loading-icon size="60" color="#1989fa"></u-loading-icon>
|
||
<text class="upload-status">{{ uploadStatus }}</text>
|
||
<u-progress :percent="uploadProgress" :show-percent="true" height="10"></u-progress>
|
||
</view>
|
||
</u-modal>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
data() {
|
||
return {
|
||
// 用户信息
|
||
currentUser: {
|
||
name: '张三',
|
||
department: '研发部'
|
||
},
|
||
// 表单数据
|
||
formData: {
|
||
title: '',
|
||
tags: [],
|
||
description: '',
|
||
taskId: ''
|
||
},
|
||
// 图片相关
|
||
selectedImages: [],
|
||
maxImages: 9,
|
||
// 任务选择器
|
||
showTaskPicker: false,
|
||
taskOptions: ['项目进度拍摄', '设备巡检', '活动照片收集', '其他任务'],
|
||
taskMap: {
|
||
'项目进度拍摄': '1',
|
||
'设备巡检': '2',
|
||
'活动照片收集': '3',
|
||
'其他任务': '4'
|
||
},
|
||
// 标签选项
|
||
availableTags: [
|
||
{ label: '工作进度', value: 'progress' },
|
||
{ label: '设备状态', value: 'equipment' },
|
||
{ label: '会议记录', value: 'meeting' },
|
||
{ label: '活动现场', value: 'activity' },
|
||
{ label: '产品展示', value: 'product' },
|
||
{ label: '其他', value: 'other' }
|
||
],
|
||
// 上传相关
|
||
showUploadModal: false,
|
||
uploadProgress: 0,
|
||
uploadStatus: '准备上传...'
|
||
}
|
||
},
|
||
computed: {
|
||
canSubmit() {
|
||
return this.selectedImages.length > 0 && this.formData.title.trim() !== ''
|
||
},
|
||
selectedTaskName() {
|
||
for (const [name, id] of Object.entries(this.taskMap)) {
|
||
if (id === this.formData.taskId) {
|
||
return name
|
||
}
|
||
}
|
||
return ''
|
||
}
|
||
},
|
||
methods: {
|
||
navigateBack() {
|
||
uni.navigateBack()
|
||
},
|
||
chooseImage() {
|
||
const remainingCount = this.maxImages - this.selectedImages.length
|
||
|
||
uni.chooseImage({
|
||
count: remainingCount,
|
||
sizeType: ['original', 'compressed'],
|
||
sourceType: ['album', 'camera'],
|
||
success: (res) => {
|
||
const tempFilePaths = res.tempFilePaths
|
||
this.selectedImages = [...this.selectedImages, ...tempFilePaths]
|
||
}
|
||
})
|
||
},
|
||
removeImage(index) {
|
||
this.selectedImages.splice(index, 1)
|
||
},
|
||
toggleTag(tagValue) {
|
||
const index = this.formData.tags.indexOf(tagValue)
|
||
if (index > -1) {
|
||
this.formData.tags.splice(index, 1)
|
||
} else {
|
||
this.formData.tags.push(tagValue)
|
||
}
|
||
},
|
||
onTaskConfirm(e) {
|
||
const name = this.taskOptions[e.index]
|
||
this.formData.taskId = this.taskMap[name]
|
||
},
|
||
onTaskChange(e) {
|
||
// 实时更新选中的任务名称
|
||
},
|
||
submitUpload() {
|
||
if (!this.canSubmit) return
|
||
|
||
// 显示上传进度弹窗
|
||
this.showUploadModal = true
|
||
this.uploadProgress = 0
|
||
this.uploadStatus = '正在上传...'
|
||
|
||
// 模拟上传过程
|
||
let progress = 0
|
||
const timer = setInterval(() => {
|
||
progress += 10
|
||
this.uploadProgress = progress
|
||
|
||
if (progress >= 100) {
|
||
clearInterval(timer)
|
||
this.uploadStatus = '上传成功!'
|
||
|
||
// 延迟关闭弹窗并返回
|
||
setTimeout(() => {
|
||
this.showUploadModal = false
|
||
this.$u.toast('上传成功')
|
||
|
||
// 返回上一页
|
||
setTimeout(() => {
|
||
uni.navigateBack()
|
||
}, 1000)
|
||
}, 1500)
|
||
}
|
||
}, 300)
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.image-upload-container {
|
||
padding-top: 44px; // 适配顶部安全区域
|
||
height: 100vh;
|
||
box-sizing: border-box;
|
||
background-color: #f5f7fa;
|
||
|
||
.top-navbar {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 44px;
|
||
background-color: #ffffff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 0 30rpx;
|
||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||
z-index: 999;
|
||
|
||
.cancel,
|
||
.save {
|
||
font-size: 32rpx;
|
||
color: #1989fa;
|
||
}
|
||
|
||
.save.disabled {
|
||
color: #c0c4cc;
|
||
}
|
||
|
||
.title {
|
||
font-size: 36rpx;
|
||
font-weight: bold;
|
||
color: #333;
|
||
}
|
||
}
|
||
|
||
.content {
|
||
height: calc(100% - 44px);
|
||
padding: 20rpx;
|
||
}
|
||
|
||
.dept-info {
|
||
background-color: #ffffff;
|
||
padding: 20rpx 30rpx;
|
||
border-radius: 16rpx;
|
||
margin-bottom: 20rpx;
|
||
font-size: 28rpx;
|
||
|
||
.label {
|
||
color: #606266;
|
||
}
|
||
|
||
.value {
|
||
color: #333;
|
||
font-weight: bold;
|
||
}
|
||
}
|
||
|
||
.section {
|
||
background-color: #ffffff;
|
||
border-radius: 16rpx;
|
||
padding: 30rpx;
|
||
margin-bottom: 20rpx;
|
||
|
||
.section-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #333;
|
||
margin-bottom: 20rpx;
|
||
display: block;
|
||
}
|
||
|
||
// 图片网格样式
|
||
.image-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 20rpx;
|
||
margin-bottom: 15rpx;
|
||
|
||
.image-item {
|
||
position: relative;
|
||
|
||
image {
|
||
width: 100%;
|
||
aspect-ratio: 1;
|
||
border-radius: 8rpx;
|
||
}
|
||
|
||
.delete-btn {
|
||
position: absolute;
|
||
top: -15rpx;
|
||
right: -15rpx;
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
background-color: rgba(0, 0, 0, 0.6);
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
}
|
||
|
||
.add-image {
|
||
width: 100%;
|
||
aspect-ratio: 1;
|
||
border: 2rpx dashed #c0c4cc;
|
||
border-radius: 8rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
text {
|
||
font-size: 24rpx;
|
||
color: #c0c4cc;
|
||
margin-top: 10rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.hint {
|
||
font-size: 24rpx;
|
||
color: #909399;
|
||
text-align: right;
|
||
}
|
||
|
||
// 表单样式
|
||
.form-item {
|
||
margin-bottom: 30rpx;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.form-label {
|
||
font-size: 28rpx;
|
||
color: #606266;
|
||
margin-bottom: 10rpx;
|
||
display: block;
|
||
}
|
||
|
||
// 标签样式
|
||
.tags-container {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 15rpx;
|
||
|
||
.tag {
|
||
padding: 10rpx 20rpx;
|
||
border: 2rpx solid #dcdfe6;
|
||
border-radius: 20rpx;
|
||
font-size: 24rpx;
|
||
color: #606266;
|
||
|
||
&.active {
|
||
border-color: #1989fa;
|
||
background-color: #ecf5ff;
|
||
color: #1989fa;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 任务选择样式
|
||
.task-select {
|
||
height: 88rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
border-bottom: 2rpx solid #ebeef5;
|
||
|
||
.selected-task {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.placeholder {
|
||
font-size: 28rpx;
|
||
color: #c0c4cc;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 上传弹窗样式
|
||
.upload-modal {
|
||
padding: 40rpx 20rpx;
|
||
|
||
.upload-status {
|
||
display: block;
|
||
text-align: center;
|
||
font-size: 28rpx;
|
||
color: #606266;
|
||
margin: 20rpx 0;
|
||
}
|
||
|
||
:deep(.u-progress) {
|
||
margin-top: 20rpx;
|
||
}
|
||
}
|
||
}
|
||
</style> |