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

368 lines
8.3 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[0]" mode="widthFix" v-if="!isEditing"></image>
<view v-else>
<image class="work-order-img" :src="workOrderImg" mode="widthFix"></image>
<view class="upload-btn" @click="uploadImage">
<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" >{{detailObj.label}}</text>
<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.address}}</text>
<input class="edit-input" v-model="editAddress" v-else placeholder="请输入地点" />
</view>
<view class="label">
<text>工单内容</text>
<text v-if="!isEditing" style="font-weight: normal;">{{detailObj.title}}</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: {},
tempImagePath: '' // 临时存储上传的图片路径
};
},
mounted() {
let obj = uni.getStorageSync("Detail");
this.detailObj = {...obj};
this.workOrderImg = `${IMAGE_BASE_URL}${this.detailObj.images[0]}`;
},
methods: {
// 上传图片到服务器
uploadImage() {
uni.chooseImage({
count: 1,
success: async (res) => {
const tempFilePaths = res.tempFilePaths[0];
this.tempImagePath = tempFilePaths;
this.workOrderImg = tempFilePaths;
uni.showToast({
title: '图片已更换',
icon: 'success'
});
}
});
},
// 上传图片到服务器
async uploadImageToServer(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 handleModify() {
if (!this.isEditing) {
// 进入编辑模式
this.editLabel = this.detailObj.label;
this.editAddress = this.detailObj.address;
this.editTitle = this.detailObj.title;
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]; // 替换为新的图片
}
const requestData = {
label: this.editLabel,
address: this.editAddress,
title: this.editTitle,
images: images,
status:1
};
const res = await put(`/api/v1/app_auth/work-order/${this.detailObj.id}`, requestData);
if (res && res.success) {
// 更新本地数据
this.detailObj = {
...this.detailObj,
...requestData
};
uni.showToast({
title: '修改成功',
icon: 'success'
});
this.isEditing = false;
this.tempImagePath = ''; // 清空临时图片路径
} else {
uni.showToast({
title: res.message || '修改失败',
icon: 'none'
});
}
} catch (error) {
console.error('保存失败:', error);
uni.showToast({
title: '保存失败,请重试',
icon: 'none'
});
} finally {
this.isLoading = false;
}
}
},
// 撤回/取消操作
async handleWithdraw() {
const res = await put(`/api/v1/app_auth/work-order/${this.detailObj.id}`, {status:98});
if (res && res.success) {
uni.showToast({
title: '撤回成功',
icon: 'success'
});
} else {
uni.showToast({
title: res.message || '撤回失败',
icon: 'none'
});
}
}
}
};
</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;
}
.work-order-img {
width: 100%;
border-radius: $border-radius;
}
.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>