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

437 lines
10 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="work-order-detail">
<!-- 头部用户信息区域 -->
<view class="header">
<image class="avatar" :src="detailObj.customerPortrait" mode="aspectFill"></image>
<text class="username">{{detailObj.customerName}}</text>
</view>
<!-- 图片区域 - 编辑状态下可修改 -->
<view class="image-area">
<image
class="work-order-img"
:src="`${IMAGE_BASE_URL}${detailObj.images && detailObj.images[0] ? detailObj.images[0] : ''}`"
mode="widthFix"
v-if="!isEditing && detailObj.images && detailObj.images.length > 0">
</image>
<view v-else>
<image
:src="isEditing ? workOrderImg : `${IMAGE_BASE_URL}${detailObj.images && detailObj.images[0] ? detailObj.images[0] : ''}`" >
</image>
<view class="upload-btn" @click="uploadImage" v-if="isEditing">
<u-icon name="camera" size="40" color="#fff"></u-icon>
<text class="upload-text">更换图片</text>
</view>
</view>
</view>
<!-- 标题与日期 -->
<view class="title-area">
<text class="title" v-if="!isEditing">{{detailObj.title}}</text>
<input class="title-input" v-model="editLabel" v-else placeholder="请输入标题" />
<text class="date">{{formatTime(detailObj.createdAt,"YYYY-MM-DD")}}</text>
</view>
<!-- 工单详情内容 - 编辑状态下可修改 -->
<view class="content">
<view class="label">
<text>求助内容</text>
<text v-if="!isEditing" style="font-weight: normal;">{{detailObj.content}}</text>
<textarea
class="edit-textarea"
v-model="editTitle"
v-else
placeholder="请输入内容"
auto-height
/>
</view>
</view>
<!-- 操作按钮 -->
<view class="btn-group">
<u-button
@click="handleModify"
:type="isEditing ? 'success' : 'primary'"
class="action-btn"
:loading="isLoading"
>
{{isEditing ? '保存修改' : '修改'}}
</u-button>
<u-button
@click="handleWithdraw"
:type="isEditing ? 'default' : 'primary'"
class="action-btn"
>
{{isEditing ? '取消编辑' : '撤回'}}
</u-button>
</view>
</view>
</template>
<script>
import { get, put } from '@/utils/request';
import { IMAGE_BASE_URL, BASE_URL } from '@/utils/config';
import { formatTime } from '@/utils/timeFormat';
export default {
data() {
return {
IMAGE_BASE_URL,
BASE_URL,
formatTime,
isEditing: false, // 编辑状态
isLoading: false, // 加载状态
workOrderImg: '', // 编辑时的图片
// 编辑状态下的临时数据
editLabel: '',
editAddress: '',
editTitle: '',
detailObj: {
images: [], // 确保images数组初始化
customerPortrait: '',
customerName: '',
createdAt: '',
label: '',
address: '',
title: '',
id: ''
},
tempImagePath: '' // 临时存储上传的图片路径
};
},
mounted() {
let obj = uni.getStorageSync("Detail") || {};
console.log("===boj",obj)
this.detailObj = {
...obj // 覆盖默认值
};
// 安全设置workOrderImg
if (this.detailObj.images && this.detailObj.images.length > 0) {
this.workOrderImg = `${IMAGE_BASE_URL}${this.detailObj.images[0]}`;
}
},
methods: {
// 上传图片到服务器
uploadImage() {
uni.chooseImage({
count: 1,
success: (res) => {
const tempFilePaths = res.tempFilePaths[0];
this.tempImagePath = tempFilePaths;
this.workOrderImg = tempFilePaths;
uni.showToast({
title: '图片已更换',
icon: 'success'
});
},
fail: (err) => {
console.error('选择图片失败:', err);
uni.showToast({
title: '选择图片失败',
icon: 'none'
});
}
});
},
// 上传图片到服务器
async uploadImageToServer(filePath) {
try {
const res = await 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);
resolve(res);
} catch (e) {
reject(new Error('解析响应失败'));
}
},
fail: (err) => {
reject(new Error('上传失败: ' + JSON.stringify(err)));
}
});
});
if (res && res.success) {
return res.data; // 只返回路径部分
} else {
throw new Error(res.message || '上传失败');
}
} catch (error) {
console.error('上传图片失败:', error);
uni.showToast({
title: '上传图片失败',
icon: 'none'
});
throw error;
}
},
// 修改/保存操作
async handleModify() {
if (!this.isEditing) {
// 进入编辑模式
this.editLabel = this.detailObj.title || '';
this.editAddress = this.detailObj.address || '';
this.editTitle = this.detailObj.content || '';
if (!this.workOrderImg && this.detailObj.images && this.detailObj.images.length > 0) {
this.workOrderImg = `${IMAGE_BASE_URL}${this.detailObj.images[0]}`;
}
this.isEditing = true;
} else {
// 保存修改
this.isLoading = true;
try {
let images = [...(this.detailObj.images || [])];
// 如果有新图片上传
if (this.tempImagePath) {
const uploadedPath = await this.uploadImageToServer(this.tempImagePath);
images = [uploadedPath]; // 替换为新的图片
this.workOrderImg = `${IMAGE_BASE_URL}${uploadedPath}`;
}
const requestData = {
content: this.editTitle,
title: this.editLabel,
images: images,
status: 1
};
const res = await put(`/api/v1/app_auth/reciprocities/${this.detailObj.id}`, requestData);
if (res && res.success) {
// 更新本地数据
this.detailObj = {
...this.detailObj,
...requestData
};
uni.showToast({
title: '修改成功',
icon: 'success'
});
this.isEditing = false;
this.tempImagePath = ''; // 清空临时图片路径
// 更新workOrderImg显示
if (images.length > 0) {
this.workOrderImg = `${IMAGE_BASE_URL}${images[0]}`;
}
} else {
throw new Error(res.message || '修改失败');
}
} catch (error) {
console.error('保存失败:', error);
uni.showToast({
title: error.message || '保存失败,请重试',
icon: 'none'
});
} finally {
this.isLoading = false;
}
}
},
// 撤回/取消操作
async handleWithdraw() {
if (this.isEditing) {
// 取消编辑
this.isEditing = false;
this.tempImagePath = '';
// 恢复原来的图片显示
if (this.detailObj.images && this.detailObj.images.length > 0) {
this.workOrderImg = `${IMAGE_BASE_URL}${this.detailObj.images[0]}`;
}
} else {
// 撤回操作
try {
this.isLoading = true;
const res = await put(`/api/v1/app_auth/reciprocities/${this.detailObj.id}`, {status: 98});
if (res && res.success) {
uni.showToast({
title: '撤回成功',
icon: 'success'
});
// 返回上一页或刷新数据
uni.navigateBack();
} else {
throw new Error(res.message || '撤回失败');
}
} catch (error) {
console.error('撤回失败:', error);
uni.showToast({
title: error.message || '撤回失败',
icon: 'none'
});
} finally {
this.isLoading = false;
}
}
}
}
};
</script>
<style lang="scss" scoped>
/* 原有样式保持不变 */
// 定义变量
$primary-color: #007AFF;
$success-color: #4cd964;
$warning-color: #FF9500;
$text-color: #333;
$subtext-color: #999;
$border-radius: 10rpx;
$padding-base: 15rpx;
$font-base: 32rpx;
// 定义 mixin
@mixin flex-center {
display: flex;
align-items: center;
}
.work-order-detail {
padding: $padding-base;
width: 90%;
margin: 0 auto;
border-radius: 10rpx;
box-shadow: 0rpx 2rpx 10rpx rgba(0, 0, 0, 0.25);
.header {
@include flex-center;
margin-bottom: $padding-base;
.avatar {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
margin-right: 10rpx;
}
.username {
font-size: $font-base;
font-weight: bold;
color: $text-color;
}
}
.image-area {
position: relative;
margin-bottom: $padding-base;
min-height: 200rpx;
background-color: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
}
.work-order-img {
width: 100%;
border-radius: $border-radius;
max-height: 400rpx;
}
.upload-btn {
position: absolute;
bottom: 20rpx;
right: 20rpx;
background: rgba(0, 0, 0, 0.6);
padding: 8rpx 20rpx;
border-radius: 30rpx;
@include flex-center;
.upload-text {
color: #fff;
font-size: 24rpx;
margin-left: 8rpx;
}
}
.title-area {
@include flex-center;
justify-content: space-between;
margin-bottom: $padding-base;
border-bottom: 2rpx solid $subtext-color;
height: 70rpx;
line-height: 70rpx;
.title {
font-size: $font-base + 2rpx;
font-weight: bold;
color: $text-color;
max-width: 70%;
}
.title-input {
font-size: $font-base + 2rpx;
font-weight: bold;
color: $text-color;
width: 70%;
padding: 10rpx;
background: #f8f8f8;
border-radius: 8rpx;
}
.date {
font-size: $font-base - 4rpx;
color: $subtext-color;
}
}
.content {
margin-bottom: $padding-base;
line-height: 50rpx;
font-size: 24rpx;
.label {
text {
font-weight: bold;
}
margin-bottom: 20rpx;
}
.edit-input {
width: 95%;
padding: 10rpx;
background: #f8f8f8;
border-radius: 8rpx;
margin-top: 5rpx;
}
.edit-textarea {
width: 95%;
padding: 10rpx;
background: #f8f8f8;
border-radius: 8rpx;
margin-top: 5rpx;
min-height: 150rpx;
}
}
.btn-group {
@include flex-center;
justify-content: space-around;
margin-top: 30rpx;
gap:30rpx;
.action-btn {
width: 30%; // 调整为原来的一半
height: 80rpx;
border-radius: 40rpx;
font-size: $font-base - 4rpx;
}
}
}
</style>