1
This commit is contained in:
parent
0adc144dc4
commit
42b6d2db33
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
<view class="info-item">
|
<view class="info-item">
|
||||||
<u-icon name="clock" size="26" color="#5b9cf8"></u-icon>
|
<u-icon name="clock" size="26" color="#5b9cf8"></u-icon>
|
||||||
<view class="info-text"><text class="info-label">活动时间:</text>{{ activityInfo.openAt }}</view>
|
<view class="info-text"><text class="info-label">开始时间:</text>{{formatTime(activityInfo.startAt,"YYYY-MM-DD HH:mm:ss") }}</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="info-item">
|
<view class="info-item">
|
||||||
|
|||||||
@ -12,22 +12,26 @@
|
|||||||
<u--textarea placeholder="请输入求助内容..." v-model="content" border height="300"></u--textarea>
|
<u--textarea placeholder="请输入求助内容..." v-model="content" border height="300"></u--textarea>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 图片上传 -->
|
<!-- 图片上传 - 修改后的上传组件 -->
|
||||||
<view class="upload-section">
|
<view class="upload-section">
|
||||||
<u-upload
|
<view class="label">
|
||||||
@afterRead="afterRead"
|
<u-icon name="photo" color="#3B8CFF" size="38"></u-icon>
|
||||||
@delete="deletePic"
|
上传照片
|
||||||
:fileList="fileList"
|
</view>
|
||||||
:maxCount="9"
|
<view class="upload-area">
|
||||||
:previewFullImage="true"
|
<view class="upload-list">
|
||||||
:accept="'image/*'"
|
<view class="upload-item" v-for="(item, index) in fileList" :key="index">
|
||||||
:capture="['album', 'camera']"
|
<image :src="item.url" mode="aspectFill" @click="previewImage(index)"></image>
|
||||||
width="220"
|
<view class="delete-btn" @click="handleDelete(index)">
|
||||||
height="220">
|
<u-icon name="close" color="#fff" size="24"></u-icon>
|
||||||
<view class="upload-btn" v-if="fileList.length < 1">
|
</view>
|
||||||
<u-icon name="plus" size="40" color="#666"></u-icon>
|
</view>
|
||||||
|
<view class="upload-btn" @click="showUploadAction" v-if="fileList.length < 9">
|
||||||
|
<u-icon name="plus" size="40" color="#c0c4cc"></u-icon>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</u-upload>
|
</view>
|
||||||
|
<text class="note">注:照片支持分批上传,但最大数量为9</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 发布按钮 -->
|
<!-- 发布按钮 -->
|
||||||
@ -35,11 +39,9 @@
|
|||||||
<u-button type="primary" text="立即发布" @click="publish"></u-button>
|
<u-button type="primary" text="立即发布" @click="publish"></u-button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
<Footer></Footer>
|
<Footer></Footer>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -70,100 +72,132 @@
|
|||||||
delta: 1 // 返回上一级页面
|
delta: 1 // 返回上一级页面
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
async afterRead(event) {
|
|
||||||
// 处理单张或多张图片上传
|
|
||||||
const files = event.file; // 可能是数组或单个文件
|
|
||||||
const uploadFiles = Array.isArray(files) ? files : [files];
|
|
||||||
|
|
||||||
// 检查文件类型 - 更健壮的验证方式
|
// 显示上传选项
|
||||||
for (const file of uploadFiles) {
|
showUploadAction() {
|
||||||
// 方法1:检查文件扩展名
|
uni.showActionSheet({
|
||||||
const fileExt = file.url.split('.').pop().toLowerCase();
|
itemList: ['拍照', '从相册选择'],
|
||||||
const allowedExts = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
|
success: (res) => {
|
||||||
|
if (res.tapIndex === 0) {
|
||||||
|
this.chooseMedia('camera');
|
||||||
|
} else {
|
||||||
|
this.chooseMedia('album');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
// 方法2:检查MIME类型(如果可用)
|
// 选择媒体文件
|
||||||
const isImage = file.type?.startsWith('image/') ||
|
async chooseMedia(sourceType) {
|
||||||
allowedExts.includes(fileExt);
|
try {
|
||||||
|
// 1. 选择图片
|
||||||
|
const res = await new Promise((resolve, reject) => {
|
||||||
|
uni.chooseImage({
|
||||||
|
count: 9 - this.fileList.length,
|
||||||
|
sourceType: [sourceType === 'camera' ? 'camera' : 'album'],
|
||||||
|
success: resolve,
|
||||||
|
fail: reject
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
if (!isImage) {
|
// 2. 添加到预览列表
|
||||||
uni.showToast({
|
const newFiles = res.tempFilePaths.map(url => ({
|
||||||
title: '只能上传图片文件(JPG/PNG等)',
|
url,
|
||||||
icon: 'none',
|
status: 'uploading'
|
||||||
duration: 2000
|
}));
|
||||||
});
|
this.fileList = [...this.fileList, ...newFiles];
|
||||||
return;
|
|
||||||
}
|
// 3. 逐个上传文件
|
||||||
|
for (const file of newFiles) {
|
||||||
|
await this.uploadFile(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
uni.showLoading({ title: '上传中...' });
|
} catch (err) {
|
||||||
|
console.error('选择图片失败:', err);
|
||||||
|
uni.showToast({ title: '选择图片失败', icon: 'none' });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
try {
|
// 单个文件上传
|
||||||
// 上传所有图片
|
async uploadFile(file) {
|
||||||
const uploadPromises = uploadFiles.map(file => this.uploadAvatar(file.url));
|
try {
|
||||||
const uploadedUrls = await Promise.all(uploadPromises);
|
const res = await new Promise((resolve, reject) => {
|
||||||
|
uni.uploadFile({
|
||||||
|
url: `${BASE_URL}/api/v1/upload`,
|
||||||
|
filePath: file.url,
|
||||||
|
name: 'file',
|
||||||
|
header: {
|
||||||
|
'Authorization': `Bearer ${uni.getStorageSync('token')}`,
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
},
|
||||||
|
success: (uploadRes) => {
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(uploadRes.data);
|
||||||
|
if (data.success) {
|
||||||
|
resolve(data.data); // 使用服务器返回的完整URL
|
||||||
|
} else {
|
||||||
|
reject(data.message || '上传失败');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
reject('解析响应失败');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (err) => reject(err)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// 更新上传的图片URL数组
|
// 更新文件状态
|
||||||
this.uploadedImageUrls = [...this.uploadedImageUrls, ...uploadedUrls];
|
const index = this.fileList.findIndex(f => f.url === file.url);
|
||||||
|
if (index !== -1) {
|
||||||
|
this.$set(this.fileList, index, {
|
||||||
|
...file,
|
||||||
|
status: 'success',
|
||||||
|
serverUrl: res // 存储服务器返回的URL
|
||||||
|
});
|
||||||
|
|
||||||
// 更新文件列表显示
|
// 添加到提交数组
|
||||||
this.fileList = [
|
this.uploadedImageUrls.push(res);
|
||||||
...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
|
|
||||||
);
|
|
||||||
|
|
||||||
// 更新文件列表
|
} catch (err) {
|
||||||
this.fileList.splice(event.index, 1);
|
console.error('上传失败:', err);
|
||||||
|
const index = this.fileList.findIndex(f => f.url === file.url);
|
||||||
|
if (index !== -1) {
|
||||||
|
this.$set(this.fileList, index, {
|
||||||
|
...file,
|
||||||
|
status: 'failed',
|
||||||
|
error: err.message || err
|
||||||
|
});
|
||||||
|
}
|
||||||
|
uni.showToast({
|
||||||
|
title: `上传失败: ${err.message || err}`,
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
uploadAvatar(filePath) {
|
|
||||||
return new Promise((resolve, reject) => {
|
// 预览图片
|
||||||
uni.uploadFile({
|
previewImage(index) {
|
||||||
url: `${BASE_URL}/api/v1/upload`,
|
const images = this.fileList.map(item => item.url);
|
||||||
filePath: filePath,
|
|
||||||
name: 'file',
|
uni.previewImage({
|
||||||
header: {
|
current: index,
|
||||||
'Authorization': `Bearer ${uni.getStorageSync('token')}`
|
urls: images
|
||||||
},
|
});
|
||||||
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)));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 删除文件
|
||||||
|
handleDelete(index) {
|
||||||
|
const file = this.fileList[index];
|
||||||
|
|
||||||
|
if (file.serverUrl) {
|
||||||
|
const imageIndex = this.uploadedImageUrls.indexOf(file.serverUrl);
|
||||||
|
if (imageIndex !== -1) this.uploadedImageUrls.splice(imageIndex, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.fileList.splice(index, 1);
|
||||||
|
},
|
||||||
|
|
||||||
async publish() {
|
async publish() {
|
||||||
if (!this.title.trim()) {
|
if (!this.title.trim()) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
@ -226,7 +260,6 @@
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.container {
|
.container {
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
/* 占满整个视口高度 */
|
/* 占满整个视口高度 */
|
||||||
@ -263,20 +296,76 @@
|
|||||||
margin-bottom: 30rpx;
|
margin-bottom: 30rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-btn {
|
.upload-section {
|
||||||
width: 220rpx;
|
.label {
|
||||||
height: 220rpx;
|
font-size: 32rpx;
|
||||||
display: flex;
|
color: #333;
|
||||||
align-items: center;
|
font-weight: 500;
|
||||||
justify-content: center;
|
margin-bottom: 24rpx;
|
||||||
background-color: #f0f0f0;
|
display: flex;
|
||||||
border-radius: 10rpx;
|
align-items: center;
|
||||||
|
|
||||||
|
.u-icon {
|
||||||
|
margin-right: 12rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-area {
|
||||||
|
margin-top: 16rpx;
|
||||||
|
|
||||||
|
.upload-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin: -5rpx;
|
||||||
|
|
||||||
|
.upload-item, .upload-btn {
|
||||||
|
width: 160rpx;
|
||||||
|
height: 160rpx;
|
||||||
|
margin: 5rpx;
|
||||||
|
position: relative;
|
||||||
|
background: #f8f8f8;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-btn {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
border-radius: 0 0 0 8rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-btn {
|
||||||
|
border: 1rpx dashed #c0c4cc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.note {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
margin-top: 24rpx;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.publish-section {
|
.publish-section {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-top: 100rpx;
|
margin-top: 100rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@ -1,437 +1,464 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="work-order-detail">
|
<view class="work-order-detail">
|
||||||
<!-- 头部用户信息区域 -->
|
<!-- 头部用户信息区域 -->
|
||||||
<view class="header">
|
<view class="header">
|
||||||
<image class="avatar" :src="detailObj.customerPortrait" mode="aspectFill"></image>
|
<image class="avatar" :src="`${IMAGE_BASE_URL}`+detailObj.customerPortrait|| '/static/index/nav.png'" mode="aspectFill"></image>
|
||||||
<text class="username">{{detailObj.customerName}}</text>
|
<text class="username">{{detailObj.customerName || '未知用户'}}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 图片区域 - 编辑状态下可修改 -->
|
<!-- 图片区域 - 编辑状态下可修改 -->
|
||||||
<view class="image-area">
|
<view class="image-area">
|
||||||
<image
|
<template v-if="!isEditing">
|
||||||
class="work-order-img"
|
<template v-if="detailObj.images && detailObj.images.length > 0">
|
||||||
:src="`${IMAGE_BASE_URL}${detailObj.images && detailObj.images[0] ? detailObj.images[0] : ''}`"
|
<image
|
||||||
mode="widthFix"
|
class="work-order-img"
|
||||||
v-if="!isEditing && detailObj.images && detailObj.images.length > 0">
|
:src="`${IMAGE_BASE_URL}${detailObj.images[0]}`"
|
||||||
</image>
|
mode="aspectFit"
|
||||||
<view v-else>
|
/>
|
||||||
<image
|
</template>
|
||||||
:src="isEditing ? workOrderImg : `${IMAGE_BASE_URL}${detailObj.images && detailObj.images[0] ? detailObj.images[0] : ''}`" >
|
<view class="empty-placeholder" v-else>
|
||||||
</image>
|
<u-icon name="photo" size="48" color="#c0c4cc"></u-icon>
|
||||||
<view class="upload-btn" @click="uploadImage" v-if="isEditing">
|
<text class="empty-text">暂无图片</text>
|
||||||
<u-icon name="camera" size="40" color="#fff"></u-icon>
|
</view>
|
||||||
<text class="upload-text">更换图片</text>
|
</template>
|
||||||
</view>
|
<template v-else>
|
||||||
</view>
|
<image
|
||||||
</view>
|
class="work-order-img"
|
||||||
|
:src="tempImagePath || (detailObj.images && detailObj.images[0] ? `${IMAGE_BASE_URL}${detailObj.images[0]}` : '')"
|
||||||
|
mode="aspectFit"
|
||||||
|
v-if="tempImagePath || (detailObj.images && detailObj.images.length > 0)"
|
||||||
|
/>
|
||||||
|
<view class="empty-placeholder" v-else>
|
||||||
|
<u-icon name="photo" size="48" color="#c0c4cc"></u-icon>
|
||||||
|
<text class="empty-text">暂无图片</text>
|
||||||
|
</view>
|
||||||
|
<view class="upload-btn" @click="uploadImage">
|
||||||
|
<u-icon name="camera" size="40" color="#fff"></u-icon>
|
||||||
|
<text class="upload-text">{{tempImagePath ? '更换图片' : '上传图片'}}</text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 标题与日期 -->
|
<!-- 标题与日期 -->
|
||||||
<view class="title-area">
|
<view class="title-area" :class="{editing: isEditing}">
|
||||||
<text class="title" v-if="!isEditing">{{detailObj.title}}</text>
|
<text class="title" v-if="!isEditing">{{detailObj.title || '无标题'}}</text>
|
||||||
<input class="title-input" v-model="editLabel" v-else placeholder="请输入标题" />
|
<input class="title-input" v-model="editLabel" v-else placeholder="请输入标题" />
|
||||||
<text class="date">{{formatTime(detailObj.createdAt,"YYYY-MM-DD")}}</text>
|
<text class="date">{{formatTime(detailObj.createdAt,"YYYY-MM-DD") || '未知日期'}}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 工单详情内容 - 编辑状态下可修改 -->
|
<!-- 工单详情内容 - 编辑状态下可修改 -->
|
||||||
<view class="content">
|
<view class="content" :class="{editing: isEditing}">
|
||||||
<view class="label">
|
<view class="label">
|
||||||
<text>求助内容:</text>
|
<text>求助内容:</text>
|
||||||
<text v-if="!isEditing" style="font-weight: normal;">{{detailObj.content}}</text>
|
<text v-if="!isEditing" class="content-text">{{detailObj.content || '无内容描述'}}</text>
|
||||||
<textarea
|
<textarea
|
||||||
class="edit-textarea"
|
class="edit-textarea"
|
||||||
v-model="editTitle"
|
v-model="editTitle"
|
||||||
v-else
|
v-else
|
||||||
placeholder="请输入内容"
|
placeholder="请输入内容"
|
||||||
auto-height
|
auto-height
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 操作按钮 -->
|
<!-- 操作按钮 -->
|
||||||
<view class="btn-group">
|
<view class="btn-group">
|
||||||
<u-button
|
<u-button
|
||||||
@click="handleModify"
|
@click="handleModify"
|
||||||
:type="isEditing ? 'success' : 'primary'"
|
:type="isEditing ? 'primary' : 'primary'"
|
||||||
class="action-btn"
|
class="action-btn"
|
||||||
:loading="isLoading"
|
:loading="isLoading"
|
||||||
>
|
:custom-style="btnStyle"
|
||||||
{{isEditing ? '保存修改' : '修改'}}
|
>
|
||||||
</u-button>
|
{{isEditing ? '保存修改' : '修改'}}
|
||||||
<u-button
|
</u-button>
|
||||||
@click="handleWithdraw"
|
<u-button
|
||||||
:type="isEditing ? 'default' : 'primary'"
|
@click="handleWithdraw"
|
||||||
class="action-btn"
|
:type="isEditing ? 'error' : 'error'"
|
||||||
>
|
class="action-btn"
|
||||||
{{isEditing ? '取消编辑' : '撤回'}}
|
:custom-style="btnStyle"
|
||||||
</u-button>
|
>
|
||||||
</view>
|
{{isEditing ? '取消编辑' : '撤回'}}
|
||||||
</view>
|
</u-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { get, put } from '@/utils/request';
|
import { get, put } from '@/utils/request';
|
||||||
import { IMAGE_BASE_URL, BASE_URL } from '@/utils/config';
|
import { IMAGE_BASE_URL, BASE_URL } from '@/utils/config';
|
||||||
import { formatTime } from '@/utils/timeFormat';
|
import { formatTime } from '@/utils/timeFormat';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
IMAGE_BASE_URL,
|
IMAGE_BASE_URL,
|
||||||
BASE_URL,
|
BASE_URL,
|
||||||
formatTime,
|
formatTime,
|
||||||
isEditing: false, // 编辑状态
|
isEditing: false, // 编辑状态
|
||||||
isLoading: false, // 加载状态
|
isLoading: false, // 加载状态
|
||||||
workOrderImg: '', // 编辑时的图片
|
tempImagePath: '', // 临时存储上传的图片路径
|
||||||
// 编辑状态下的临时数据
|
// 编辑状态下的临时数据
|
||||||
editLabel: '',
|
editLabel: '',
|
||||||
editAddress: '',
|
editTitle: '',
|
||||||
editTitle: '',
|
detailObj: {
|
||||||
detailObj: {
|
images: [], // 确保images数组初始化
|
||||||
images: [], // 确保images数组初始化
|
customerPortrait: '',
|
||||||
customerPortrait: '',
|
customerName: '',
|
||||||
customerName: '',
|
createdAt: '',
|
||||||
createdAt: '',
|
title: '',
|
||||||
label: '',
|
content: '',
|
||||||
address: '',
|
id: ''
|
||||||
title: '',
|
},
|
||||||
id: ''
|
btnStyle: {
|
||||||
},
|
width: '45%',
|
||||||
tempImagePath: '' // 临时存储上传的图片路径
|
height: '80rpx'
|
||||||
};
|
}
|
||||||
},
|
};
|
||||||
mounted() {
|
},
|
||||||
let obj = uni.getStorageSync("Detail") || {};
|
mounted() {
|
||||||
console.log("===boj",obj)
|
let obj = uni.getStorageSync("Detail") || {};
|
||||||
this.detailObj = {
|
this.detailObj = {
|
||||||
|
...obj // 覆盖默认值
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 上传图片
|
||||||
|
uploadImage() {
|
||||||
|
uni.chooseImage({
|
||||||
|
count: 1,
|
||||||
|
success: (res) => {
|
||||||
|
this.tempImagePath = res.tempFilePaths[0];
|
||||||
|
uni.showToast({
|
||||||
|
title: '图片已选择',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.error('选择图片失败:', err);
|
||||||
|
uni.showToast({
|
||||||
|
title: '选择图片失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
...obj // 覆盖默认值
|
// 上传图片到服务器
|
||||||
};
|
async uploadImageToServer(filePath) {
|
||||||
// 安全设置workOrderImg
|
try {
|
||||||
if (this.detailObj.images && this.detailObj.images.length > 0) {
|
const res = await new Promise((resolve, reject) => {
|
||||||
this.workOrderImg = `${IMAGE_BASE_URL}${this.detailObj.images[0]}`;
|
uni.uploadFile({
|
||||||
}
|
url: `${BASE_URL}/api/v1/upload`,
|
||||||
},
|
filePath: filePath,
|
||||||
methods: {
|
name: 'file',
|
||||||
// 上传图片到服务器
|
header: {
|
||||||
uploadImage() {
|
'Authorization': `Bearer ${uni.getStorageSync('token')}`
|
||||||
uni.chooseImage({
|
},
|
||||||
count: 1,
|
success: (uploadRes) => {
|
||||||
success: (res) => {
|
try {
|
||||||
const tempFilePaths = res.tempFilePaths[0];
|
const res = JSON.parse(uploadRes.data);
|
||||||
this.tempImagePath = tempFilePaths;
|
resolve(res);
|
||||||
this.workOrderImg = tempFilePaths;
|
} catch (e) {
|
||||||
uni.showToast({
|
reject(new Error('解析响应失败'));
|
||||||
title: '图片已更换',
|
}
|
||||||
icon: 'success'
|
},
|
||||||
});
|
fail: (err) => {
|
||||||
},
|
reject(new Error('上传失败: ' + JSON.stringify(err)));
|
||||||
fail: (err) => {
|
}
|
||||||
console.error('选择图片失败:', err);
|
});
|
||||||
uni.showToast({
|
});
|
||||||
title: '选择图片失败',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// 上传图片到服务器
|
if (res && res.success) {
|
||||||
async uploadImageToServer(filePath) {
|
return res.data;
|
||||||
try {
|
} else {
|
||||||
const res = await new Promise((resolve, reject) => {
|
throw new Error(res.message || '上传失败');
|
||||||
uni.uploadFile({
|
}
|
||||||
url: `${BASE_URL}/api/v1/upload`,
|
} catch (error) {
|
||||||
filePath: filePath,
|
console.error('上传图片失败:', error);
|
||||||
name: 'file',
|
uni.showToast({
|
||||||
header: {
|
title: '上传图片失败',
|
||||||
'Authorization': `Bearer ${uni.getStorageSync('token')}`
|
icon: 'none'
|
||||||
},
|
});
|
||||||
success: (uploadRes) => {
|
throw error;
|
||||||
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; // 只返回路径部分
|
async handleModify() {
|
||||||
} else {
|
if (!this.isEditing) {
|
||||||
throw new Error(res.message || '上传失败');
|
// 进入编辑模式
|
||||||
}
|
this.editLabel = this.detailObj.title || '';
|
||||||
} catch (error) {
|
this.editTitle = this.detailObj.content || '';
|
||||||
console.error('上传图片失败:', error);
|
this.isEditing = true;
|
||||||
uni.showToast({
|
} else {
|
||||||
title: '上传图片失败',
|
// 保存修改
|
||||||
icon: 'none'
|
this.isLoading = true;
|
||||||
});
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// 修改/保存操作
|
try {
|
||||||
async handleModify() {
|
let images = [...(this.detailObj.images || [])];
|
||||||
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];
|
||||||
|
}
|
||||||
|
|
||||||
// 如果有新图片上传
|
const requestData = {
|
||||||
if (this.tempImagePath) {
|
content: this.editTitle,
|
||||||
const uploadedPath = await this.uploadImageToServer(this.tempImagePath);
|
title: this.editLabel,
|
||||||
images = [uploadedPath]; // 替换为新的图片
|
images: images,
|
||||||
this.workOrderImg = `${IMAGE_BASE_URL}${uploadedPath}`;
|
status: 1
|
||||||
}
|
};
|
||||||
|
|
||||||
const requestData = {
|
const res = await put(`/api/v1/app_auth/reciprocities/${this.detailObj.id}`, 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
|
||||||
|
};
|
||||||
|
|
||||||
if (res && res.success) {
|
uni.showToast({
|
||||||
// 更新本地数据
|
title: '修改成功',
|
||||||
this.detailObj = {
|
icon: 'success'
|
||||||
...this.detailObj,
|
});
|
||||||
...requestData
|
|
||||||
};
|
|
||||||
|
|
||||||
uni.showToast({
|
this.isEditing = false;
|
||||||
title: '修改成功',
|
this.tempImagePath = '';
|
||||||
icon: 'success'
|
} else {
|
||||||
});
|
throw new Error(res.message || '修改失败');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('保存失败:', error);
|
||||||
|
uni.showToast({
|
||||||
|
title: error.message || '保存失败,请重试',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
this.isLoading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
this.isEditing = false;
|
// 撤回/取消操作
|
||||||
this.tempImagePath = ''; // 清空临时图片路径
|
async handleWithdraw() {
|
||||||
|
if (this.isEditing) {
|
||||||
|
// 取消编辑
|
||||||
|
this.isEditing = false;
|
||||||
|
this.tempImagePath = '';
|
||||||
|
} else {
|
||||||
|
// 撤回操作
|
||||||
|
try {
|
||||||
|
this.isLoading = true;
|
||||||
|
const res = await put(`/api/v1/app_auth/reciprocities/${this.detailObj.id}`, {status: 98});
|
||||||
|
|
||||||
// 更新workOrderImg显示
|
if (res && res.success) {
|
||||||
if (images.length > 0) {
|
uni.showToast({
|
||||||
this.workOrderImg = `${IMAGE_BASE_URL}${images[0]}`;
|
title: '撤回成功',
|
||||||
}
|
icon: 'success'
|
||||||
} else {
|
});
|
||||||
throw new Error(res.message || '修改失败');
|
uni.navigateBack();
|
||||||
}
|
} else {
|
||||||
} catch (error) {
|
throw new Error(res.message || '撤回失败');
|
||||||
console.error('保存失败:', error);
|
}
|
||||||
uni.showToast({
|
} catch (error) {
|
||||||
title: error.message || '保存失败,请重试',
|
console.error('撤回失败:', error);
|
||||||
icon: 'none'
|
uni.showToast({
|
||||||
});
|
title: error.message || '撤回失败',
|
||||||
} finally {
|
icon: 'none'
|
||||||
this.isLoading = false;
|
});
|
||||||
}
|
} 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>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
/* 原有样式保持不变 */
|
// 定义变量
|
||||||
// 定义变量
|
$primary-color: #007AFF;
|
||||||
$primary-color: #007AFF;
|
$success-color: #4cd964;
|
||||||
$success-color: #4cd964;
|
$warning-color: #FF9500;
|
||||||
$warning-color: #FF9500;
|
$error-color: #dd524d;
|
||||||
$text-color: #333;
|
$text-color: #333;
|
||||||
$subtext-color: #999;
|
$subtext-color: #999;
|
||||||
$border-radius: 10rpx;
|
$border-radius: 12rpx;
|
||||||
$padding-base: 15rpx;
|
$padding-base: 20rpx;
|
||||||
$font-base: 32rpx;
|
$font-base: 32rpx;
|
||||||
|
$shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||||
|
|
||||||
// 定义 mixin
|
.work-order-detail {
|
||||||
@mixin flex-center {
|
padding: $padding-base;
|
||||||
display: flex;
|
width: 92%;
|
||||||
align-items: center;
|
margin: 20rpx auto;
|
||||||
}
|
border-radius: $border-radius;
|
||||||
|
box-shadow: $shadow;
|
||||||
|
background-color: #fff;
|
||||||
|
|
||||||
.work-order-detail {
|
.header {
|
||||||
padding: $padding-base;
|
display: flex;
|
||||||
width: 90%;
|
align-items: center;
|
||||||
margin: 0 auto;
|
margin-bottom: $padding-base;
|
||||||
border-radius: 10rpx;
|
padding-bottom: $padding-base;
|
||||||
box-shadow: 0rpx 2rpx 10rpx rgba(0, 0, 0, 0.25);
|
border-bottom: 1rpx solid #f5f5f5;
|
||||||
|
|
||||||
.header {
|
.avatar {
|
||||||
@include flex-center;
|
width: 80rpx;
|
||||||
margin-bottom: $padding-base;
|
height: 80rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
.avatar {
|
.username {
|
||||||
width: 80rpx;
|
font-size: $font-base;
|
||||||
height: 80rpx;
|
font-weight: bold;
|
||||||
border-radius: 50%;
|
color: $text-color;
|
||||||
margin-right: 10rpx;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.username {
|
.image-area {
|
||||||
font-size: $font-base;
|
position: relative;
|
||||||
font-weight: bold;
|
margin-bottom: $padding-base;
|
||||||
color: $text-color;
|
height: 400rpx;
|
||||||
}
|
background-color: #f9f9f9;
|
||||||
}
|
border-radius: $border-radius;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
.image-area {
|
.work-order-img {
|
||||||
position: relative;
|
width: 100%;
|
||||||
margin-bottom: $padding-base;
|
height: 100%;
|
||||||
min-height: 200rpx;
|
object-fit: contain;
|
||||||
background-color: #f5f5f5;
|
}
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.work-order-img {
|
.empty-placeholder {
|
||||||
width: 100%;
|
display: flex;
|
||||||
border-radius: $border-radius;
|
flex-direction: column;
|
||||||
max-height: 400rpx;
|
align-items: center;
|
||||||
}
|
justify-content: center;
|
||||||
|
color: #c0c4cc;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
.upload-btn {
|
.empty-text {
|
||||||
position: absolute;
|
font-size: 28rpx;
|
||||||
bottom: 20rpx;
|
margin-top: 16rpx;
|
||||||
right: 20rpx;
|
color: #c0c4cc;
|
||||||
background: rgba(0, 0, 0, 0.6);
|
}
|
||||||
padding: 8rpx 20rpx;
|
}
|
||||||
border-radius: 30rpx;
|
|
||||||
@include flex-center;
|
|
||||||
|
|
||||||
.upload-text {
|
.upload-btn {
|
||||||
color: #fff;
|
position: absolute;
|
||||||
font-size: 24rpx;
|
bottom: 30rpx;
|
||||||
margin-left: 8rpx;
|
right: 30rpx;
|
||||||
}
|
background: rgba(0, 0, 0, 0.6);
|
||||||
}
|
padding: 12rpx 24rpx;
|
||||||
|
border-radius: 40rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
.title-area {
|
.upload-text {
|
||||||
@include flex-center;
|
color: #fff;
|
||||||
justify-content: space-between;
|
font-size: 26rpx;
|
||||||
margin-bottom: $padding-base;
|
margin-left: 10rpx;
|
||||||
border-bottom: 2rpx solid $subtext-color;
|
}
|
||||||
height: 70rpx;
|
}
|
||||||
line-height: 70rpx;
|
}
|
||||||
|
|
||||||
.title {
|
.title-area {
|
||||||
font-size: $font-base + 2rpx;
|
display: flex;
|
||||||
font-weight: bold;
|
align-items: center;
|
||||||
color: $text-color;
|
justify-content: space-between;
|
||||||
max-width: 70%;
|
margin-bottom: $padding-base;
|
||||||
}
|
padding-bottom: $padding-base;
|
||||||
|
border-bottom: 1rpx solid #f5f5f5;
|
||||||
|
|
||||||
.title-input {
|
&.editing {
|
||||||
font-size: $font-base + 2rpx;
|
border-bottom: 1rpx solid #eaeaea;
|
||||||
font-weight: bold;
|
}
|
||||||
color: $text-color;
|
|
||||||
width: 70%;
|
|
||||||
padding: 10rpx;
|
|
||||||
background: #f8f8f8;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.date {
|
.title {
|
||||||
font-size: $font-base - 4rpx;
|
font-size: $font-base + 4rpx;
|
||||||
color: $subtext-color;
|
font-weight: bold;
|
||||||
}
|
color: $text-color;
|
||||||
}
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.content {
|
.title-input {
|
||||||
margin-bottom: $padding-base;
|
font-size: $font-base + 4rpx;
|
||||||
line-height: 50rpx;
|
font-weight: bold;
|
||||||
font-size: 24rpx;
|
color: $text-color;
|
||||||
|
flex: 1;
|
||||||
|
padding: 10rpx;
|
||||||
|
background: #f8f8f8;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
border: 1rpx solid #eaeaea;
|
||||||
|
}
|
||||||
|
|
||||||
.label {
|
.date {
|
||||||
text {
|
font-size: $font-base - 4rpx;
|
||||||
font-weight: bold;
|
color: $subtext-color;
|
||||||
}
|
margin-left: 20rpx;
|
||||||
margin-bottom: 20rpx;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit-input {
|
.content {
|
||||||
width: 95%;
|
margin-bottom: $padding-base * 2;
|
||||||
padding: 10rpx;
|
font-size: $font-base;
|
||||||
background: #f8f8f8;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
margin-top: 5rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.edit-textarea {
|
&.editing {
|
||||||
width: 95%;
|
padding: 10rpx;
|
||||||
padding: 10rpx;
|
background: #fafafa;
|
||||||
background: #f8f8f8;
|
border-radius: $border-radius;
|
||||||
border-radius: 8rpx;
|
}
|
||||||
margin-top: 5rpx;
|
|
||||||
min-height: 150rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-group {
|
.label {
|
||||||
@include flex-center;
|
display: flex;
|
||||||
justify-content: space-around;
|
flex-direction: column;
|
||||||
margin-top: 30rpx;
|
|
||||||
gap:30rpx;
|
|
||||||
|
|
||||||
.action-btn {
|
text {
|
||||||
width: 30%; // 调整为原来的一半
|
font-weight: bold;
|
||||||
height: 80rpx;
|
margin-bottom: 10rpx;
|
||||||
border-radius: 40rpx;
|
}
|
||||||
font-size: $font-base - 4rpx;
|
|
||||||
}
|
.content-text {
|
||||||
}
|
font-weight: normal;
|
||||||
}
|
color: #666;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-textarea {
|
||||||
|
width: 100%;
|
||||||
|
padding: 16rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
border: 1rpx solid #eaeaea;
|
||||||
|
min-height: 200rpx;
|
||||||
|
font-size: $font-base;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-group {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
gap: 20rpx;
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
flex: 1;
|
||||||
|
border-radius: 50rpx;
|
||||||
|
font-size: $font-base;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@ -3,7 +3,7 @@
|
|||||||
<!-- 主帖内容 -->
|
<!-- 主帖内容 -->
|
||||||
<view class="post-container">
|
<view class="post-container">
|
||||||
<view class="post-header">
|
<view class="post-header">
|
||||||
<image class="avatar" :src="postData.customerPortrait" mode="aspectFill"></image>
|
<image class="avatar" :src="`${IMAGE_BASE_URL}`+postData.customerPortrait" mode="aspectFill"></image>
|
||||||
<view class="post-info">
|
<view class="post-info">
|
||||||
<text class="username">{{ postData.customerName }}</text>
|
<text class="username">{{ postData.customerName }}</text>
|
||||||
<text class="time">{{ formatTime(postData.pushAt) }}</text>
|
<text class="time">{{ formatTime(postData.pushAt) }}</text>
|
||||||
@ -32,7 +32,8 @@
|
|||||||
<view v-for="comment in flatComments" :key="comment.id" class="comment-item"
|
<view v-for="comment in flatComments" :key="comment.id" class="comment-item"
|
||||||
:class="{'is-reply': comment.toUserName}">
|
:class="{'is-reply': comment.toUserName}">
|
||||||
<view class="comment-header">
|
<view class="comment-header">
|
||||||
<image class="avatar" :src="comment.pusherPortrait" mode="aspectFill"></image>
|
<image class="avatar"
|
||||||
|
:src="comment.pusherPortrait === '/static/imgs/index/nav.png' ? comment.pusherPortrait : `${IMAGE_BASE_URL}${comment.pusherPortrait}`" mode="aspectFill"></image>
|
||||||
<view class="comment-user-info">
|
<view class="comment-user-info">
|
||||||
<text class="username">{{ comment.pusherName }}</text>
|
<text class="username">{{ comment.pusherName }}</text>
|
||||||
<view class="meta-info">
|
<view class="meta-info">
|
||||||
|
|||||||
@ -41,7 +41,7 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="item_right">
|
<view class="item_right">
|
||||||
<view class="right_nav">
|
<view class="right_nav">
|
||||||
<image :src="item.customerPortrait ?item.customerPortrait :`/static/imgs/index/nav.png`" class="nav"></image>
|
<image :src="item.customerPortrait ?`${IMAGE_BASE_URL}`+item.customerPortrait :`/static/imgs/index/nav.png`" class="nav"></image>
|
||||||
<image src="/static/imgs/index/nav_bg.png" class="bg"></image>
|
<image src="/static/imgs/index/nav_bg.png" class="bg"></image>
|
||||||
</view>
|
</view>
|
||||||
<view class="right_name">
|
<view class="right_name">
|
||||||
@ -317,7 +317,7 @@
|
|||||||
.bg {
|
.bg {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
top: 20rpx;
|
top: 0rpx;
|
||||||
left: -118rpx;
|
left: -118rpx;
|
||||||
width: 260rpx;
|
width: 260rpx;
|
||||||
height: 260rpx;
|
height: 260rpx;
|
||||||
|
|||||||
@ -37,9 +37,6 @@
|
|||||||
工单内容
|
工单内容
|
||||||
</view>
|
</view>
|
||||||
<textarea v-model="workOrderContent" placeholder="请输入工单详细内容..." class="textarea" />
|
<textarea v-model="workOrderContent" placeholder="请输入工单详细内容..." class="textarea" />
|
||||||
<view class="voice-icon">
|
|
||||||
<u-icon name="mic" color="#409EFF" size="36"></u-icon>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 联系人信息 -->
|
<!-- 联系人信息 -->
|
||||||
@ -56,7 +53,13 @@
|
|||||||
<u-icon name="phone" color="#3B8CFF" size="38"></u-icon>
|
<u-icon name="phone" color="#3B8CFF" size="38"></u-icon>
|
||||||
电话
|
电话
|
||||||
</view>
|
</view>
|
||||||
<input v-model="customerPhone" placeholder="请输入联系人电话" class="contact-input" type="number" />
|
<input
|
||||||
|
v-model="customerPhone"
|
||||||
|
placeholder="请输入联系人电话"
|
||||||
|
class="contact-input"
|
||||||
|
type="number"
|
||||||
|
@blur="validatePhone"
|
||||||
|
/>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@ -151,6 +154,19 @@ export default {
|
|||||||
this.getOrderTypeList();
|
this.getOrderTypeList();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// 新增手机号验证方法
|
||||||
|
validatePhone() {
|
||||||
|
if (!this.customerPhone) return true;
|
||||||
|
const phoneReg = /^1[3-9]\d{9}$/;
|
||||||
|
if (!phoneReg.test(this.customerPhone)) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请输入正确的手机号码',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
// 显示上传选项
|
// 显示上传选项
|
||||||
showUploadAction() {
|
showUploadAction() {
|
||||||
uni.showActionSheet({
|
uni.showActionSheet({
|
||||||
@ -350,8 +366,11 @@ export default {
|
|||||||
this.fileList.splice(index, 1);
|
this.fileList.splice(index, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
// 其他原有方法保持不变...
|
|
||||||
async handleSubmit() {
|
async handleSubmit() {
|
||||||
|
// 在提交前验证手机号
|
||||||
|
if (!this.validatePhone()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!this.workOrderContent) {
|
if (!this.workOrderContent) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '请填写工单内容',
|
title: '请填写工单内容',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user