This commit is contained in:
qiuyuan 2025-08-06 18:05:09 +08:00
parent 4022a1ebcd
commit 9f052c8cc8

View File

@ -1,41 +1,5 @@
<template> <template>
<view class="work-order-detail"> <view class="work-order-detail">
<!-- 图片区域 - 编辑状态下可修改 -->
<view class="image-area card">
<view class="img-container">
<!-- 非编辑状态显示服务器图片 -->
<image
class="work-order-img"
:src="`${IMAGE_BASE_URL}${detailObj.images[0]}`"
mode="widthFix"
lazy-load="true"
v-if="!isEditing && detailObj.images && detailObj.images.length > 0"
></image>
<!-- 编辑状态显示本地选择的图片 -->
<image
class="work-order-img"
:src="workOrderImg"
mode="widthFix"
lazy-load="true"
v-if="isEditing && workOrderImg"
></image>
<!-- 没有图片时的占位 -->
<view class="empty-placeholder" v-if="(!detailObj.images || detailObj.images.length === 0) && !isEditing">
<u-icon name="photo" size="48" color="#c0c4cc"></u-icon>
<text class="empty-text">暂无图片</text>
</view>
<!-- 编辑状态的上传按钮 -->
<view class="upload-btn" @click="uploadImage" v-if="isEditing">
<u-icon name="camera" size="28" color="#fff"></u-icon>
<text class="upload-text">{{ workOrderImg ? '更换图片' : '上传图片' }}</text>
</view>
</view>
</view>
<!-- 标题与日期 --> <!-- 标题与日期 -->
<view class="title-area card"> <view class="title-area card">
<view class="title-wrap"> <view class="title-wrap">
@ -50,7 +14,6 @@
<view class="content card"> <view class="content card">
<view class="label"> <view class="label">
<view class="label-name"> <view class="label-name">
<!-- <u-icon name="map-marker" size="24" color="#409EFF"></u-icon> -->
<text>工单地点</text> <text>工单地点</text>
</view> </view>
<text v-if="!isEditing" style="font-weight: normal;" :class="{empty: !detailObj.address}">{{detailObj.address || '未填写'}}</text> <text v-if="!isEditing" style="font-weight: normal;" :class="{empty: !detailObj.address}">{{detailObj.address || '未填写'}}</text>
@ -58,7 +21,6 @@
</view> </view>
<view class="label"> <view class="label">
<view class="label-name"> <view class="label-name">
<!-- <u-icon name="user" size="24" color="#409EFF"></u-icon> -->
<text>联系人</text> <text>联系人</text>
</view> </view>
<text v-if="!isEditing" style="font-weight: normal;" :class="{empty: !detailObj.concatName}">{{detailObj.concatName || '未填写'}}</text> <text v-if="!isEditing" style="font-weight: normal;" :class="{empty: !detailObj.concatName}">{{detailObj.concatName || '未填写'}}</text>
@ -66,7 +28,6 @@
</view> </view>
<view class="label"> <view class="label">
<view class="label-name"> <view class="label-name">
<!-- <u-icon name="phone" size="24" color="#409EFF"></u-icon> -->
<text>联系电话</text> <text>联系电话</text>
</view> </view>
<text v-if="!isEditing" style="font-weight: normal;" :class="{empty: !detailObj.customerPhone}">{{detailObj.customerPhone || '未填写'}}</text> <text v-if="!isEditing" style="font-weight: normal;" :class="{empty: !detailObj.customerPhone}">{{detailObj.customerPhone || '未填写'}}</text>
@ -74,7 +35,6 @@
</view> </view>
<view class="label label-content"> <view class="label label-content">
<view class="label-name"> <view class="label-name">
<!-- <u-icon name="file-text" size="24" color="#409EFF"></u-icon> -->
<text>工单内容</text> <text>工单内容</text>
</view> </view>
<text v-if="!isEditing" style="font-weight: normal; white-space: pre-line;" :class="{empty: !detailObj.title}">{{detailObj.title || '未填写'}}</text> <text v-if="!isEditing" style="font-weight: normal; white-space: pre-line;" :class="{empty: !detailObj.title}">{{detailObj.title || '未填写'}}</text>
@ -87,6 +47,65 @@
/> />
</view> </view>
</view> </view>
<!-- 图片区域 - 支持多张展示和编辑 -->
<view class="image-area card">
<view class="img-container">
<!-- 非编辑状态显示服务器图片 -->
<scroll-view
class="image-scroll"
scroll-x="true"
v-if="!isEditing && detailObj.images && detailObj.images.length > 0"
>
<view class="image-list">
<image
class="work-order-img"
v-for="(img, index) in detailObj.images"
:key="index"
:src="`${IMAGE_BASE_URL}${img}`"
mode="aspectFill"
lazy-load="true"
@click="previewImage(index)"
></image>
</view>
</scroll-view>
<!-- 编辑状态显示本地选择的图片 -->
<scroll-view
class="image-scroll"
scroll-x="true"
v-if="isEditing && localImages.length > 0"
>
<view class="image-list">
<view class="image-item" v-for="(img, index) in localImages" :key="index">
<image
class="work-order-img"
:src="img"
mode="aspectFill"
lazy-load="true"
></image>
<view class="delete-btn" @click="removeImage(index)">
<u-icon name="close" size="20" color="#fff"></u-icon>
</view>
</view>
</view>
</scroll-view>
<!-- 没有图片时的占位 -->
<view class="empty-placeholder" v-if="(!detailObj.images || detailObj.images.length === 0) && !isEditing">
<u-icon name="photo" size="48" color="#c0c4cc"></u-icon>
<text class="empty-text">暂无图片</text>
</view>
<!-- 编辑状态的上传按钮 -->
<view class="upload-btn-container" v-if="isEditing">
<view class="upload-btn" @click="uploadImage">
<u-icon name="camera" size="28" color="#fff"></u-icon>
<text class="upload-text">{{ localImages.length > 0 ? '添加更多' : '上传图片' }}</text>
</view>
<text class="upload-tip" v-if="localImages.length > 0">最多可上传9张</text>
</view>
</view>
</view>
<!-- 操作按钮 --> <!-- 操作按钮 -->
<view class="btn-group"> <view class="btn-group">
@ -124,44 +143,85 @@
formatTime, formatTime,
isEditing: false, // isEditing: false, //
isLoading: false, // isLoading: false, //
workOrderImg: '', // localImages: [], //
// //
editLabel: '', editLabel: '',
editAddress: '', editAddress: '',
editTitle: '', editTitle: '',
editContactName: '', // editContactName: '',
editContactPhone: '', // editContactPhone: '',
detailObj: {}, detailObj: {},
tempImagePath: '' // tempImagePaths: [] //
}; };
}, },
mounted() { mounted() {
let obj = uni.getStorageSync("Detail"); let obj = uni.getStorageSync("Detail");
this.detailObj = {...obj}; this.detailObj = {...obj};
this.workOrderImg = `${IMAGE_BASE_URL}${this.detailObj.images[0]}`; //
if (this.detailObj.images && this.detailObj.images.length > 0) {
this.localImages = this.detailObj.images.map(img => `${IMAGE_BASE_URL}${img}`);
}
// //
this.editContactName = this.detailObj.concatName || ''; this.editContactName = this.detailObj.concatName || '';
this.editContactPhone = this.detailObj.customerPhone || ''; this.editContactPhone = this.detailObj.customerPhone || '';
}, },
methods: { methods: {
// //
uploadImage() { previewImage(index) {
uni.chooseImage({ uni.previewImage({
count: 1, current: index,
success: async (res) => { urls: this.detailObj.images.map(img => `${IMAGE_BASE_URL}${img}`)
const tempFilePaths = res.tempFilePaths[0];
this.tempImagePath = tempFilePaths;
this.workOrderImg = tempFilePaths;
uni.showToast({
title: '图片已更换',
icon: 'success'
}); });
},
//
uploadImage() {
const maxCount = 9 - this.localImages.length;
if (maxCount <= 0) {
uni.showToast({
title: '最多只能上传9张图片',
icon: 'none'
});
return;
}
uni.chooseImage({
count: maxCount,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
this.tempImagePaths = [...this.tempImagePaths, ...res.tempFilePaths];
this.localImages = [...this.localImages, ...res.tempFilePaths];
} }
}); });
}, },
//
removeImage(index) {
this.localImages.splice(index, 1);
// tempImagePaths
if (index >= this.localImages.length - this.tempImagePaths.length) {
this.tempImagePaths.splice(index - (this.localImages.length - this.tempImagePaths.length), 1);
}
},
// //
async uploadImageToServer(filePath) { async uploadImagesToServer() {
const uploadedPaths = [];
for (const filePath of this.tempImagePaths) {
try {
const path = await this.uploadSingleImage(filePath);
uploadedPaths.push(path);
} catch (error) {
console.error('图片上传失败:', error);
throw error;
}
}
return uploadedPaths;
},
//
uploadSingleImage(filePath) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
uni.uploadFile({ uni.uploadFile({
url: `${BASE_URL}/api/v1/upload`, url: `${BASE_URL}/api/v1/upload`,
@ -174,7 +234,7 @@
try { try {
const res = JSON.parse(uploadRes.data); const res = JSON.parse(uploadRes.data);
if (res && res.success) { if (res && res.success) {
resolve(res.data); // resolve(res.data);
} else { } else {
reject(new Error(res.message || '上传失败')); reject(new Error(res.message || '上传失败'));
} }
@ -207,9 +267,16 @@
let images = this.detailObj.images; let images = this.detailObj.images;
// //
if (this.tempImagePath) { if (this.tempImagePaths.length > 0) {
const uploadedPath = await this.uploadImageToServer(this.tempImagePath); const uploadedPaths = await this.uploadImagesToServer();
images = [uploadedPath]; // //
const originalPaths = this.localImages
.filter(img => img.startsWith(IMAGE_BASE_URL))
.map(img => img.replace(IMAGE_BASE_URL, ''));
images = [...originalPaths, ...uploadedPaths];
} else if (this.localImages.length === 0) {
//
images = [];
} }
const requestData = { const requestData = {
@ -218,8 +285,8 @@
title: this.editTitle, title: this.editTitle,
images: images, images: images,
status: 1, status: 1,
concatName: this.editContactName, // concatName: this.editContactName,
customerPhone: this.editContactPhone // customerPhone: this.editContactPhone
}; };
const res = await put(`/api/v1/app_auth/work-order/${this.detailObj.id}`, requestData); const res = await put(`/api/v1/app_auth/work-order/${this.detailObj.id}`, requestData);
@ -237,7 +304,7 @@
}); });
this.isEditing = false; this.isEditing = false;
this.tempImagePath = ''; // this.tempImagePaths = []; //
} else { } else {
uni.showToast({ uni.showToast({
title: res.message || '修改失败', title: res.message || '修改失败',
@ -259,9 +326,14 @@
// / // /
async handleWithdraw() { async handleWithdraw() {
if (this.isEditing) { if (this.isEditing) {
// //
this.isEditing = false; this.isEditing = false;
this.tempImagePath = ''; this.tempImagePaths = [];
if (this.detailObj.images && this.detailObj.images.length > 0) {
this.localImages = this.detailObj.images.map(img => `${IMAGE_BASE_URL}${img}`);
} else {
this.localImages = [];
}
return; return;
} }
@ -286,7 +358,7 @@
<style lang="scss" scoped> <style lang="scss" scoped>
/* 基础变量优化 */ /* 基础变量优化 */
$primary-color: #409EFF; // $primary-color: #409EFF;
$success-color: #67C23A; $success-color: #67C23A;
$warning-color: #F56C6C; $warning-color: #F56C6C;
$text-color: #303133; $text-color: #303133;
@ -317,6 +389,57 @@
margin-bottom: 0; margin-bottom: 0;
} }
} }
/* 图片区域优化 */
.image-area {
@include card;
padding: 24rpx;
.img-container {
position: relative;
width: 100%;
border-radius: 8rpx;
overflow: hidden;
background-color: $bg-color;
min-height: 200rpx;
}
.image-scroll {
width: 100%;
white-space: nowrap;
}
.image-list {
display: inline-flex;
gap: 16rpx;
}
.image-item {
position: relative;
width: 200rpx;
height: 200rpx;
border-radius: 8rpx;
overflow: hidden;
}
.work-order-img {
width: 200rpx;
height: 200rpx;
border-radius: 8rpx;
}
.delete-btn {
position: absolute;
right: 8rpx;
top: 8rpx;
width: 36rpx;
height: 36rpx;
background: rgba(0, 0, 0, 0.5);
border-radius: 50%;
@include flex-center;
justify-content: center;
}
.empty-placeholder { .empty-placeholder {
width: 100%; width: 100%;
height: 300rpx; height: 300rpx;
@ -333,129 +456,21 @@
color: #909399; color: #909399;
} }
} }
/* 页面容器 */
.work-order-detail {
background-color: $bg-color;
min-height: 100vh;
padding: 0 30rpx 40rpx;
}
/* 导航栏 */ .upload-btn-container {
.navbar { margin-top: 20rpx;
@include flex-center;
height: 100rpx;
width: 100%;
padding: 0 10rpx;
background: $card-bg;
border-bottom: 1px solid $border-color;
position: sticky;
top: 0;
z-index: 10;
margin-bottom: 24rpx;
.nav-title {
font-size: 36rpx;
color: $text-color;
font-weight: 500;
flex: 1;
text-align: center;
margin-left: -36rpx; //
}
}
/* 头部用户信息 */
.header {
@include card;
display: flex; display: flex;
flex-direction: column;
align-items: center; align-items: center;
padding: 24rpx 30rpx; gap: 10rpx;
.avatar {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
background-color: $bg-color;
border: 2rpx solid #F0F2F5;
}
.user-info {
margin-left: 24rpx;
flex: 1;
}
.user-name-wrap {
@include flex-center;
margin-bottom: 8rpx;
}
.username {
font-size: 34rpx;
color: $text-color;
font-weight: 500;
}
.status-tag {
margin-left: 12rpx;
height: 40rpx;
line-height: 40rpx;
}
.contact-info {
@include flex-center;
font-size: 28rpx;
}
.info-icon {
margin-right: 6rpx;
}
.user-phone {
color: $subtext-color;
}
}
/* 图片区域优化 */
.image-area {
@include card;
padding: 24rpx;
.img-container {
position: relative;
width: 100%;
border-radius: 8rpx;
overflow: hidden;
background-color: $bg-color;
}
.work-order-img {
width: 100%;
border-radius: 8rpx;
transition: $transition;
//
&:empty {
height: 300rpx;
background-color: $bg-color;
display: flex;
align-items: center;
justify-content: center;
color: $light-text;
}
} }
.upload-btn { .upload-btn {
position: absolute; background: $primary-color;
right: 16rpx; padding: 12rpx 24rpx;
bottom: 16rpx;
background: rgba(0, 0, 0, 0.5);
padding: 8rpx 16rpx;
border-radius: 24rpx; border-radius: 24rpx;
@include flex-center; @include flex-center;
transition: $transition; transition: $transition;
cursor: pointer;
&:hover {
background: rgba(0, 0, 0, 0.7);
}
.upload-text { .upload-text {
color: #fff; color: #fff;
@ -463,9 +478,20 @@
margin-left: 6rpx; margin-left: 6rpx;
} }
} }
.upload-tip {
font-size: 24rpx;
color: $light-text;
}
}
/* 其他样式保持不变 */
.work-order-detail {
background-color: $bg-color;
min-height: 100vh;
padding: 0 30rpx 40rpx;
} }
/* 标题区域优化 */
.title-area { .title-area {
@include card; @include card;
display: flex; display: flex;
@ -477,11 +503,6 @@
width: 100%; width: 100%;
} }
.title-icon {
margin-right: 12rpx;
flex-shrink: 0;
}
.title { .title {
font-size: 34rpx; font-size: 34rpx;
color: $text-color; color: $text-color;
@ -495,17 +516,12 @@
padding-top: 4rpx; padding-top: 4rpx;
} }
.date-icon {
margin-right: 6rpx;
}
.date { .date {
font-size: 26rpx; font-size: 26rpx;
color: $light-text; color: $light-text;
} }
} }
/* 内容区域优化 */
.content { .content {
@include card; @include card;
@ -532,10 +548,6 @@
flex-shrink: 0; flex-shrink: 0;
} }
.label-name u-icon {
margin-right: 8rpx;
}
& > text { & > text {
font-size: 28rpx; font-size: 28rpx;
color: $text-color; color: $text-color;
@ -583,7 +595,6 @@
} }
} }
/* 按钮区域优化 */
.btn-group { .btn-group {
display: flex; display: flex;
gap: 24rpx; gap: 24rpx;
@ -608,28 +619,4 @@
} }
} }
} }
/* 适配小屏幕 */
@media (max-width: 375px) {
$font-base: 28rpx;
.header {
padding: 18rpx;
.avatar {
width: 80rpx;
height: 80rpx;
}
}
.btn-group {
padding: 20rpx 5rpx;
.action-btn {
height: 80rpx;
line-height: 80rpx;
font-size: 28rpx;
}
}
}
</style> </style>