2025-07-16 15:07:16 +08:00

282 lines
7.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="container">
<view class="content">
<view class="content_wapper">
<!-- 添加标题 -->
<view class="input-section">
<u-input placeholder="添加标题" v-model="title" border></u-input>
</view>
<!-- 输入求助内容 -->
<view class="textarea-section">
<u--textarea placeholder="请输入求助内容..." v-model="content" border height="300"></u--textarea>
</view>
<!-- 图片上传 -->
<view class="upload-section">
<u-upload
@afterRead="afterRead"
@delete="deletePic"
:fileList="fileList"
:maxCount="9"
:previewFullImage="true"
:accept="'image/*'"
:capture="['album', 'camera']"
width="220"
height="220">
<view class="upload-btn" v-if="fileList.length < 1">
<u-icon name="plus" size="40" color="#666"></u-icon>
</view>
</u-upload>
</view>
<!-- 发布按钮 -->
<view class="publish-section">
<u-button type="primary" text="立即发布" @click="publish"></u-button>
</view>
</view>
</view>
<Footer></Footer>
</view>
</template>
<script>
import Footer from '@/components/footer_common.vue';
import {
get,
post
} from '@/utils/request';
import {
IMAGE_BASE_URL,
BASE_URL
} from '@/utils/config';
export default {
components: {
Footer
},
data() {
return {
title: '',
content: '',
fileList: [],
uploadedImageUrls: []
};
},
methods: {
handleBack() {
uni.navigateBack({
delta: 1 // 返回上一级页面
});
},
async afterRead(event) {
// 处理单张或多张图片上传
const files = event.file; // 可能是数组或单个文件
const uploadFiles = Array.isArray(files) ? files : [files];
// 检查文件类型 - 更健壮的验证方式
for (const file of uploadFiles) {
// 方法1检查文件扩展名
const fileExt = file.url.split('.').pop().toLowerCase();
const allowedExts = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
// 方法2检查MIME类型如果可用
const isImage = file.type?.startsWith('image/') ||
allowedExts.includes(fileExt);
if (!isImage) {
uni.showToast({
title: '只能上传图片文件(JPG/PNG等)',
icon: 'none',
duration: 2000
});
return;
}
}
uni.showLoading({ title: '上传中...' });
try {
// 上传所有图片
const uploadPromises = uploadFiles.map(file => this.uploadAvatar(file.url));
const uploadedUrls = await Promise.all(uploadPromises);
// 更新上传的图片URL数组
this.uploadedImageUrls = [...this.uploadedImageUrls, ...uploadedUrls];
// 更新文件列表显示
this.fileList = [
...this.fileList,
...uploadFiles.map((file, index) => ({
url: file.url,
status: 'success',
uploadedUrl: uploadedUrls[index]
}))
];
uni.showToast({ title: '上传成功', icon: 'success' });
} catch (error) {
console.error('上传失败:', error);
uni.showToast({
title: '上传失败: ' + error.message,
icon: 'none',
duration: 2000
});
} finally {
uni.hideLoading();
}
},
deletePic(event) {
// 删除对应的图片URL
const deletedFile = this.fileList[event.index];
this.uploadedImageUrls = this.uploadedImageUrls.filter(
url => url !== deletedFile.uploadedUrl
);
// 更新文件列表
this.fileList.splice(event.index, 1);
},
uploadAvatar(filePath) {
return new Promise((resolve, reject) => {
uni.uploadFile({
url: `${BASE_URL}/api/v1/upload`,
filePath: filePath,
name: 'file',
header: {
'Authorization': `Bearer ${uni.getStorageSync('token')}`
},
success: (uploadRes) => {
try {
const res = JSON.parse(uploadRes.data);
if (res && res.success) {
resolve(res.data);
} else {
reject(new Error(res.message || '上传失败'));
}
} catch (e) {
reject(new Error('解析响应失败'));
}
},
fail: (err) => {
reject(new Error('上传失败: ' + JSON.stringify(err)));
}
});
});
},
async publish() {
if (!this.title.trim()) {
uni.showToast({
title: '请输入标题',
icon: 'none'
});
return;
}
if (!this.content.trim()) {
uni.showToast({
title: '请输入内容',
icon: 'none'
});
return;
}
uni.showLoading({
title: '发布中...'
});
try {
// 构造请求数据图片URL以数组形式传递
const postData = {
title: this.title,
content: this.content,
images: this.uploadedImageUrls.length > 0 ?
this.uploadedImageUrls :
[] // 如果没有图片则传空数组
};
// 调用API
const res = await post('/api/v1/app_auth/reciprocities', postData);
if (!res || !res.success) {
throw new Error('发布失败');
}
uni.showToast({
title: '发布成功',
icon: 'success'
});
// 发布成功后返回上一页
setTimeout(() => {
uni.navigateBack();
}, 1500);
} catch (error) {
console.error('发布失败:', error);
uni.showToast({
title: '发布失败',
icon: 'none'
});
} finally {
uni.hideLoading();
}
}
}
};
</script>
<style lang="scss" scoped>
.container {
width: 100%;
height: 100vh;
/* 占满整个视口高度 */
opacity: 1;
background: linear-gradient(0deg, rgba(240, 240, 240, 1) 0%, rgba(255, 250, 250, 0) 100%),
linear-gradient(0deg, rgba(255, 241, 235, 1) 0%, rgba(192, 219, 250, 1) 100%);
position: relative;
.content {
width: 100%;
position: absolute;
margin-top: 40rpx;
border-top-left-radius: 30rpx;
border-top-right-radius: 30rpx;
background-color: rgba(255, 255, 255, 0.65);
padding-bottom: 60rpx;
.content_wapper {
width: 90%;
margin: 0 auto;
}
}
.input-section {
border-bottom: 2rpx solid #C3DCFA;
height: 90rpx;
line-height: 90rpx;
}
.input-section,
.textarea-section,
.upload-section {
margin-bottom: 30rpx;
}
.upload-btn {
width: 220rpx;
height: 220rpx;
display: flex;
align-items: center;
justify-content: center;
background-color: #f0f0f0;
border-radius: 10rpx;
}
.publish-section {
text-align: center;
margin-top: 100rpx;
}
}
</style>