Files
SmartParks_uniapp/pages/sys/user/myRepair/myRepair.vue
2025-08-21 14:25:49 +08:00

467 lines
11 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="repair-container">
<!-- 可滚动内容区 -->
<scroll-view
scroll-y
class="repair-scroll-content"
refresher-background="#f7f7f7"
@scroll="handleScroll"
@scrolltolower="loadMore"
refresher-enabled
:refresher-triggered="refreshing"
@refresherrefresh="onRefresh">
<!-- 空状态 -->
<view v-if="records.length === 0 && !loading" class="repair-empty-box">
<view class="repair-empty-img-box">
<image src="/static/ic_my_repair_01.png" class="repair-empty-img" />
</view>
<view class="repair-add-btn-box">
<image src="/static/ic_my_repair_02.png" class="repair-add-btn" @click="addRepair" />
</view>
</view>
<!-- 有数据时 -->
<view v-else class="repair-list-box">
<view v-for="(item, idx) in records" :key="idx" class="repair-card" @click="showDetail(item)">
<view class="repair-row">
<view class="repair-no">工单号{{ item.orderNo }}</view>
<view class="repair-status" :class="getStatusColor(item.status)">
{{ getStatusLabel(item.status) }}
</view>
</view>
<image class="repair-line-image" src="/static/ic_my_repair_03.png" />
<view class="repair-info">建立时间{{ item.createTime }}</view>
<view class="repair-info">报事内容{{ item.typeName }}</view>
<view class="repair-info">报事位置{{ item.location }}</view>
<view v-if="getStatusLabel(item.status) === '已结束'" class="repair-eval-btn eval-btn-right">服务评价</view>
</view>
<!-- 加载提示 -->
<view v-if="loading" style="text-align:center;color:#999;font-size:26rpx;padding:20rpx;">
加载中...
</view>
<view v-if="finished && records.length > 0" style="text-align:center;color:#999;font-size:26rpx;padding:20rpx;">
没有更多数据了
</view>
<!-- 悬浮新增按钮 -->
<image src="/static/ic_my_repair_02.png" :class="['repair-add-btn-fixed', { 'hide': isAddBtnHidden }]"
@click="addRepair" />
</view>
</scroll-view>
<!-- 详情弹窗 -->
<view v-if="showDetailDialog" class="repair-detail-mask" @click.self="closeDetail">
<view class="repair-detail-dialog">
<view class="repair-detail-title">报事详情
<image src="/static/ic_close_01.png" class="repair-detail-close" @click.stop="closeDetail" />
</view>
<view class="repair-detail-progress-box">
<view class="repair-detail-progress">
<view v-for="(step, idx) in progressSteps" :key="idx" class="repair-detail-step">
<view
:class="['repair-detail-dot', detailStep >= idx ? 'active' : '', (detailStep === idx && detailStatus !== '已结束') ? 'current' : '']">
</view>
<view v-if="idx < progressSteps.length - 1"
:class="['repair-detail-line', detailStep > idx ? 'active' : '']"></view>
</view>
</view>
<view class="repair-detail-progress-labels">
<view v-for="(step, idx) in progressSteps" :key="idx" class="repair-detail-label">{{ step }}</view>
</view>
</view>
<view class="repair-detail-info">建立时间{{ detailItem.createTime }}</view>
<view class="repair-detail-info">报事内容{{ detailItem.typeName }}</view>
<view class="repair-detail-info">报事位置{{ detailItem.location }}</view>
<button v-if="getStatusLabel(detailItem.status) === '已结束'" class="repair-detail-btn"
@click="goTEvaluate">评价服务</button>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
records: [],
showDetailDialog: false,
detailItem: {},
detailStep: 0,
detailStatus: '',
progressSteps: ['创建工单', '已接单', '处理中', '已结束'],
lastScrollTop: 0,
isAddBtnHidden: false,
// 分页相关
pageNum: 1,
pageSize: 10,
finished: false,
loading: false,
refreshing: false
}
},
onLoad() {
this.onRefresh()
},
onShow() {
uni.$once('refreshData', () => {
this.onRefresh()
});
},
methods: {
goBack() {
uni.navigateBack();
},
addRepair() {
uni.navigateTo({
url: '/pages/sys/user/myRepair/addRepair'
});
},
// 获取工单列表
async getOrders(reset = false) {
if (this.loading) return;
if (reset) {
this.pageNum = 1;
this.finished = false;
this.records = [];
}
this.loading = true;
let params = {
type: "1952989217332658178",
pageNum: this.pageNum,
pageSize: this.pageSize
};
let res = await this.$u.api.getOrderList(params);
if (res.code == '200') {
const rows = res.rows || [];
if (reset) {
this.records = rows;
} else {
this.records = this.records.concat(rows);
}
if (rows.length < this.pageSize) {
this.finished = true;
} else {
this.pageNum++;
}
}
this.loading = false;
this.refreshing = false;
},
// 下拉刷新
onRefresh() {
this.refreshing = true;
this.getOrders(true);
},
// 滚动加载更多
loadMore() {
if (!this.finished) {
this.getOrders(false);
}
},
getStatusColor(status) {
const statusMap = {
0: 'orange',
1: 'doing',
2: 'doing',
3: 'doing',
4: 'done'
};
return statusMap[status] || '';
},
showDetail(item) {
this.detailItem = item;
if (item.status == 0) {
this.detailStep = 0;
this.detailStatus = '创建工单';
} else if (item.status == 4) {
this.detailStep = 3;
this.detailStatus = '已结束';
} else if (item.status == 3) {
this.detailStep = 2;
this.detailStatus = '处理中';
} else {
this.detailStep = 1;
this.detailStatus = '已接单';
}
this.showDetailDialog = true;
},
closeDetail() {
this.showDetailDialog = false;
},
getStatusLabel(status) {
const statusMap = {
0: '创建工单',
1: '已接单',
2: '已接单',
3: '处理中',
4: '已结束'
};
return statusMap[status] || '';
},
goTEvaluate() {
const detailItemStr = encodeURIComponent(JSON.stringify(this.detailItem));
uni.navigateTo({
url: `/pages/sys/user/myRepair/repairEvaluate?detailItem=${detailItemStr}`
});
},
handleScroll(e) {
const scrollTop = e.detail.scrollTop;
if (Math.abs(scrollTop - this.lastScrollTop) < 20) return;
if (scrollTop > this.lastScrollTop && scrollTop > 50) {
this.isAddBtnHidden = true;
} else {
this.isAddBtnHidden = false;
}
this.lastScrollTop = scrollTop;
}
}
}
</script>
<style scoped>
.repair-container {
height: 100vh;
background: #f7f7f7;
display: flex;
flex-direction: column;
}
.repair-scroll-content {
flex: 1;
overflow-y: auto;
padding-bottom: 40rpx;
}
.repair-empty-box {
margin: 48rpx 24rpx 0 24rpx;
position: relative;
}
.repair-empty-img-box {
border: 2rpx dashed #BDBDBD;
border-radius: 8rpx;
background: #fafbfc;
width: 100%;
min-height: 220rpx;
display: flex;
align-items: center;
justify-content: center;
}
.repair-empty-img {
width: 90%;
max-width: 400rpx;
height: 180rpx;
object-fit: contain;
margin: 24rpx auto;
}
.repair-add-btn-box {
position: absolute;
right: 24rpx;
bottom: -40rpx;
}
.repair-add-btn {
width: 80rpx;
height: 80rpx;
border: 2rpx dashed #BDBDBD;
border-radius: 50%;
background: #fff;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
}
.repair-list-box {
margin: 32rpx 0 0 0;
padding: 0 24rpx;
position: relative;
}
.repair-card {
background: #fff;
border-radius: 12rpx;
margin-bottom: 24rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03);
padding-top: 25rpx;
padding-bottom: 32rpx;
}
.repair-row {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 12rpx;
margin-top: 25rpx;
margin-left: 19rpx;
margin-right: 50rpx;
}
.repair-no {
font-size: 24rpx;
color: #0B0B0B;
font-weight: 500;
}
.repair-status {
font-size: 24rpx;
font-weight: 500;
}
.repair-status.orange { color: #F3AB44; }
.repair-status.doing { color: #00C9AA; }
.repair-status.done { color: #8A8A8A; }
.repair-line-image {
margin-left: 29rpx;
margin-right: 39rpx;
height: 2rpx;
margin-bottom: 29rpx;
}
.repair-info {
font-size: 24rpx;
color: #888;
margin-bottom: 30rpx;
margin-left: 47rpx;
}
.repair-eval-btn {
margin-top: -20rpx;
margin-bottom: 0;
margin-left: auto;
margin-right: 44rpx;
display: flex;
justify-content: flex-end;
align-items: center;
padding: 0 18rpx;
height: 44rpx;
line-height: 44rpx;
border-radius: 8rpx;
border: 2rpx solid #2186FF;
color: #2186FF;
font-size: 24rpx;
background: #fff;
font-weight: 500;
width: fit-content;
}
.repair-add-btn-fixed {
position: fixed;
right: 40rpx;
bottom: 80rpx;
width: 100rpx;
height: 100rpx;
z-index: 100;
transition: transform 0.3s ease;
transform: translateX(0);
}
.repair-add-btn-fixed.hide { transform: translateX(200%); }
.repair-detail-mask {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.45);
z-index: 999;
display: flex;
align-items: flex-end;
justify-content: center;
}
.repair-detail-dialog {
width: 100vw;
background: #fff;
border-radius: 18rpx 18rpx 0 0;
box-shadow: 0 -2rpx 24rpx rgba(0, 0, 0, 0.10);
padding: 52rpx 56rpx 69rpx 56rpx;
margin-bottom: 0;
}
.repair-detail-title {
font-size: 36rpx;
color: #000;
text-align: center;
position: relative;
margin-bottom: 48rpx;
}
.repair-detail-close {
width: 32rpx;
height: 32rpx;
position: absolute;
right: 0;
top: 0;
}
.repair-detail-progress-box {
height: 107rpx;
margin-bottom: 41rpx;
background: #F7F7F7;
border-radius: 10rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: stretch;
}
.repair-detail-progress {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 5rpx;
margin-left: 75rpx;
width: 100%;
}
.repair-detail-step {
display: flex;
align-items: center;
flex: 1;
position: relative;
}
.repair-detail-dot {
width: 22rpx;
height: 22rpx;
border-radius: 50%;
background: #BDBDBD;
border: 2rpx solid #BDBDBD;
position: relative;
z-index: 2;
}
.repair-detail-dot.active {
background: #2186FF;
border-color: #2186FF;
}
.repair-detail-dot.current {
background: #EF8D00;
border-color: #EF8D00;
}
.repair-detail-line {
flex: 1;
height: 4rpx;
background: #BDBDBD;
margin: 0 2rpx;
z-index: 1;
}
.repair-detail-line.active { background: #2186FF; }
.repair-detail-progress-labels {
display: flex;
justify-content: space-between;
margin-left: 0;
width: 100%;
}
.repair-detail-label {
font-size: 22rpx;
color: #888;
text-align: center;
flex: 1;
position: relative;
top: 8rpx;
}
.repair-detail-info {
font-size: 26rpx;
color: #222;
margin-bottom: 30rpx;
}
.repair-detail-btn {
width: 445rpx;
height: 73rpx;
background: linear-gradient(90deg, #005DE9 0%, #4B9BFF 100%);
color: #fff;
font-size: 32rpx;
border: none;
border-radius: 30rpx;
margin-top: 100rpx;
font-weight: 600;
}
/* 让服务评价按钮靠右 */
.eval-btn-right {
margin-left: auto;
display: block;
width: fit-content;
}
</style>