bonus-material-app/src/pages/repair/fieldMaintenance/index.vue

612 lines
13 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="page-container">
<!-- Tab 切换 -->
<view class="complete-btn">
<view class="btn" :class="{ active: active === 1 }" @click="changeTab(1)">
<span>未完成</span>
<view v-if="active === 1" class="bt-line"></view>
</view>
<view class="btn" style="margin-left: 120rpx" :class="{ active: active === 2 }" @click="changeTab(2)">
<span>已完成</span>
<view v-if="active === 2" class="bt-line"></view>
</view>
</view>
<!-- 日期范围 -->
<uni-row class="search-form">
<!-- <uni-col :span="24">
<uni-datetime-picker v-model="dateArray" type="daterange" placeholder="选择日期范围" @change="onChangeDate"
@maskClick="maskClick" />
</uni-col> -->
<uni-col :span="12">
<view>
<uni-datetime-picker v-model="queryParams.startTime" type="date" placeholder="开始日期" />
</view>
</uni-col>
-
<uni-col :span="12">
<view>
<uni-datetime-picker v-model="queryParams.endTime" type="date" placeholder="结束日期" />
</view>
</uni-col>
</uni-row>
<!-- 搜索框 -->
<uni-row :gutter="24" class="search-form">
<uni-col :span="16">
<uni-easyinput v-model="queryParams.keyWord" placeholder="请输入内容" />
</uni-col>
<uni-col :span="4">
<view class="search" @click="onSearchBtn">搜索</view>
</uni-col>
<uni-col :span="4">
<view class="add" @click="handleAdded">新增</view>
</uni-col>
</uni-row>
<!-- 列表区域 -->
<scroll-view scroll-y class="scroll-container" @scrolltolower="onScrollTolower">
<view v-for="(item, index) in tableList" :key="index" class="table-list-item" @click="handleItem(item)">
<div class="title">
<div class="title-left">
<span class="code">{{ item.code }}</span>
</div>
<div class="status-tag">
<view @click.stop="submitItem(item)" v-show="item.taskStatus === '0'" style="padding-right: 10rpx;">
<uni-icons type="paperplane" size="24" color="#00aa00" />
</view>
<view @click.stop="deleteItem(item)" v-show="item.taskStatus === '0'" style="padding-right: 10rpx;">
<uni-icons type="trash" size="24" color="#ff0000" />
</view>
</div>
</div>
<view class="line"></view>
<template v-for="field in fieldMap" :key="field.label">
<uni-row :gutter="24">
<uni-col :span="field.labelSpan">{{ field.label }}</uni-col>
<uni-col :span="field.valueSpan">
<view class="cont">{{ item[field.key] }}</view>
</uni-col>
</uni-row>
</template>
</view>
<view class="loading-text">{{ finish ? '没有更多数据了~' : '正在加载...' }}</view>
</scroll-view>
</view>
</template>
<script setup>
import {
ref,
computed
} from 'vue'
import {
getList,
deleteFieldApplyInfoById,
submitTask
} from '@/services/fieldMaintenance/fieldMaintenance.js'
import {
onLoad
} from '@dcloudio/uni-app'
import {
debounce
} from 'lodash-es'
const total = ref(0)
const active = ref(1)
const tableList = ref([])
const dateArray = ref([
new Date(new Date().getTime() - 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
new Date().toISOString().split('T')[0]
])
const queryParams = ref({
startTime: dateArray.value[0] || '',
endTime: dateArray.value[1] || '',
keyWord: '',
taskStatus: 0,
pageNum: 1,
pageSize: 3
})
const fieldMap = [{
label: '任务时间',
key: 'createTime',
labelSpan: 6,
valueSpan: 18
},
{
label: '维修物资',
key: 'typeNames',
labelSpan: 6,
valueSpan: 18
},
{
label: '单位名称',
key: 'unitName',
labelSpan: 6,
valueSpan: 18
},
{
label: '工程名称',
key: 'proName',
labelSpan: 6,
valueSpan: 18
},
{
label: '创建人',
key: 'createBy',
labelSpan: 6,
valueSpan: 18
},
{
label: '维修数量',
key: 'num',
labelSpan: 6,
valueSpan: 18
},
]
const submitItem = item => {
submitTask({
taskId: item.taskId
}).then(res => {
if (res.code == 200) {
uni.showToast({
title: '提交成功',
icon: 'none'
})
getTableList(true)
} else {
uni.showToast({
title: '提交失败',
icon: 'none'
})
}
}).catch(error => {
console.log(error)
})
}
const deleteItem = item => {
uni.showModal({
title: '提示',
content: '确定要删除该条记录吗?',
confirmText: '删除',
cancelText: '取消',
success: res => {
if (res.confirm) {
// 用户点击了“删除”
deleteFieldApplyInfoById({
id: item.id,
taskId: item.taskId
}).then(res => {
if (res.code == 200) {
uni.showToast({
title: '刪除成功',
icon: 'none'
})
getTableList(true)
} else {
uni.showToast({
title: '刪除失败',
icon: 'none'
})
}
}).catch(error => {
console.log(error)
})
}
// 用户点击了“取消”时不做任何处理
}
})
}
const onChangeDate = val => {
const [start, end] = val
queryParams.value.startTime = start
queryParams.value.endTime = end
}
const onSearchBtn = () => {
queryParams.value.pageNum = 1
tableList.value = []
getTableList(true)
}
const getTableList = async (isTap = false) => {
try {
uni.showLoading({
title: '加载中...',
mask: true
})
const res = await getList(queryParams.value)
total.value = res.data.total
if (isTap) {
tableList.value = res.data.rows
} else {
const merged = [...tableList.value, ...res.data.rows]
// 根据 id 去重(保留前面的)
const unique = []
const seen = new Set()
for (const item of merged) {
if (!seen.has(item.taskId)) {
seen.add(item.taskId)
unique.push(item)
}
}
console.log('🚀 ~ getTableList ~ unique:', unique)
tableList.value = unique
}
} catch (error) {
console.log('🚀 ~ getTableList ~ error:', error)
} finally {
uni.hideLoading()
}
}
onLoad(() => {
tableList.value = []
total.value = 0
getTableList(true)
})
const onScrollTolower = debounce(() => {
if (total.value > tableList.value.length) {
queryParams.value.pageSize += 5
getTableList()
}
}, 500)
const changeTab = index => {
active.value = index
queryParams.value.taskStatus = index === 1 ? 0 : 2
queryParams.value.pageNum = 1
getTableList(true)
}
const handleAdded = () => {
uni.navigateTo({
url: '/pages/repair/fieldMaintenance/added'
})
}
const handleItem = item => {
uni.navigateTo({
url: `/pages/repair/fieldMaintenance/detail?item=${JSON.stringify(item)}`
})
}
const finish = computed(() => total.value === tableList.value.length)
const maskClick = () => {}
</script>
<style lang="scss" scoped>
.title-left {
display: flex;
flex-direction: column;
.code {
font-size: 32rpx;
font-weight: 600;
color: #3784fb;
letter-spacing: 1rpx;
}
.sub-code {
font-size: 28rpx;
/* 比主code小一点 */
color: #8c8c8c;
/* 灰色更柔和 */
margin-top: 4rpx;
/* 与主code有一点间距 */
}
}
.status-tag {
display: flex;
align-items: center;
}
.page-container {
display: flex;
height: 100vh;
padding: 24rpx;
flex-direction: column;
background-color: #f7f8fa;
.complete-btn {
display: flex;
justify-content: center;
/* padding: 20rpx 24rpx;
background: #fff;
border-radius: 20rpx;
margin-bottom: 20rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05); */
.btn {
display: flex;
flex-direction: column;
align-items: center;
padding: 0 60rpx;
position: relative;
transition: all 0.3s ease;
span {
font-size: 32rpx;
color: #8c8c8c;
font-weight: 500;
&.active {
color: #3784fb;
font-weight: 600;
.second-active & {
color: #fa8c16;
}
}
}
.bt-line {
width: 32rpx;
height: 6rpx;
background: #3784fb;
margin-top: 12rpx;
border-radius: 6rpx;
transition: all 0.3s ease;
.second-active & {
background: #fa8c16;
}
}
}
}
.search-form {
display: flex;
align-items: center;
padding: 20rpx;
/* background: #fff;
border-radius: 20rpx;
margin-bottom: 20rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05); */
:deep(.uni-easyinput__content),
:deep(.uni-date-editor) {
background-color: #f7f8fa;
border: 2rpx solid #e8e8e8;
border-radius: 12rpx;
height: 75rpx;
transition: all 0.3s ease;
&:focus-within {
border-color: #3784fb;
box-shadow: 0 0 0 2rpx rgba(55, 132, 251, 0.1);
}
}
:deep(.uni-date) {
width: 100%;
.uni-date-x {
width: 100%;
}
.uni-date-editor--x {
width: 100%;
}
.uni-date-range--x {
width: 100%;
.uni-date-range--x-input {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24rpx;
.uni-date-range--x-text {
font-size: 28rpx;
color: #262626;
}
}
}
.uni-date-x--border {
width: 100%;
border: 2rpx solid #e8e8e8;
border-radius: 12rpx;
background-color: #f7f8fa;
height: 80rpx;
transition: all 0.3s ease;
&:focus-within {
border-color: #3784fb;
box-shadow: 0 0 0 2rpx rgba(55, 132, 251, 0.1);
}
}
}
:deep(.uni-date-editor) {
.uni-date-range {
display: flex;
align-items: center;
width: 100%;
.uni-date-range--text {
width: 50%;
text-align: center;
color: #333;
}
}
}
}
.search {
height: 60rpx;
background: linear-gradient(135deg, #4b8eff 0%, #3784fb 100%);
text-align: center;
line-height: 60rpx;
color: #fff;
border-radius: 12rpx;
font-size: 28rpx;
font-weight: 600;
box-shadow: 0 6rpx 20rpx rgba(55, 132, 251, 0.2);
transition: all 0.3s ease;
&:active {
transform: translateY(2rpx);
opacity: 0.9;
}
}
.add {
height: 60rpx;
background: linear-gradient(135deg, #00aa00 0%, #00aa7f 100%);
text-align: center;
line-height: 60rpx;
color: #fff;
border-radius: 12rpx;
font-size: 28rpx;
font-weight: 600;
box-shadow: 0 6rpx 20rpx rgba(55, 132, 251, 0.2);
transition: all 0.3s ease;
&:active {
transform: translateY(2rpx);
opacity: 0.9;
}
}
.scroll-container {
padding: 0 2rpx;
.table-list-item {
margin: 24rpx 0;
padding: 32rpx;
background-color: #fff;
min-height: 300rpx;
border-radius: 20rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
&:active {
transform: scale(0.985);
background-color: #fafbfc;
}
.title {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
.title-left {
.code {
font-size: 32rpx;
font-weight: 600;
color: #3784fb;
letter-spacing: 1rpx;
}
}
span.status {
padding: 8rpx 28rpx;
border-radius: 8rpx;
font-size: 26rpx;
font-weight: 600;
&.completed {
background-color: rgba(82, 196, 26, 0.1);
color: #52c41a;
}
&.pending {
background-color: rgba(250, 140, 22, 0.1);
color: #fa8c16;
}
}
}
.line {
margin: 24rpx 0;
height: 2rpx;
background: linear-gradient(90deg,
rgba(232, 232, 232, 0) 0%,
rgba(232, 232, 232, 1) 50%,
rgba(232, 232, 232, 0) 100%);
}
:deep(.uni-row) {
/* margin-bottom: 20rpx; */
.uni-col-6 {
color: #8c8c8c;
font-size: 28rpx;
font-weight: 500;
}
}
.cont {
display: flex;
justify-content: flex-end;
line-height: 1.8;
color: #262626;
font-size: 28rpx;
font-weight: 500;
}
}
}
.loading-text {
text-align: center;
font-size: 26rpx;
color: #8c8c8c;
padding: 32rpx 0;
letter-spacing: 1rpx;
}
}
// 优化滑动区域样式
:deep(.uni-swipe_action) {
border-radius: 20rpx;
overflow: hidden;
.uni-swipe_content {
margin: 0 !important;
padding: 0;
background-color: #fff;
}
.uni-swipe_button-group {
height: 100%;
.uni-swipe_button {
writing-mode: vertical-rl;
padding: 0 24rpx;
font-size: 28rpx !important;
font-weight: 600;
// 查看按钮
&:nth-child(1) {
background: linear-gradient(to bottom, #3ad980, #34C759) !important;
}
// 出库按钮
&:nth-child(2) {
background: linear-gradient(to bottom, #3b95ff, #007AFF) !important;
}
&:active {
opacity: 0.85;
}
}
}
}
</style>