Files
ys-app/src/pages/business/polling/searchList.vue
2025-12-18 17:58:21 +08:00

685 lines
25 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="con-body">
<view class="con-bg">
<!-- 头部 -->
<customHeader ref="customHeaderRef" title="" :leftFlag="true" :rightFlag="true">
<template #title>
<view class="tab-list">
<view class="tab-item" :class="{active:index==activeTab,active1:index==1}"
v-for="(item,index) in tabList" :key="index"
@click="handleTab(index)"
>{{item}}</view>
</view>
</template>
</customHeader>
<!-- 高度来避免头部遮挡 -->
<view class="top-height"></view>
<!-- 列表 @down="downCallback" @up="upCallback"
:up="upOption" :down="downOption" :fixed="false" -->
<mescroll-uni ref="mescrollRef" @init="mescrollInit" :fixed="false"
class="scroll-h" :class="{'loading-scroll':cssFlag}"
@down="downCallback" :down="downOption"
@up="upCallback" :up="upOption"
@scroll="onScroll"
>
<view class="white-bg">
<!-- 日历 -->
<view class="white-top" v-if="isMonth">
<view class="calender-con">
<uni-calendar class="uni-calendar--hook" v-if="activeTab==0"
:selected="calendarInfo.selected"
:showMonth="false" @change="calendarChange"
@monthSwitch="monthSwitch"
/>
<calenderMonth :year="year" :month="month" v-else-if="activeTab==1"
@change="calendarChange2"
></calenderMonth>
</view>
<view class="calender-list">
<view class="calender-item">
<view class="item-blue">{{count1}}</view>
<view class="font28">已巡检</view>
</view>
<view class="calender-item">
<view :class="{'item-red':count2>0,'item-blue':count2==0}">{{count2}}</view>
<view class="font28">待巡检</view>
</view>
<view class="calender-item">
<view class="item-red">{{count3}}</view>
<view class="font28">已过期</view>
</view>
</view>
</view>
<!-- 当是月的时候日历滚动没了的时候 显示 -->
<view v-else class="calender-blue">
<view class="calender-simple">
<calenderMonthSimple :year="year" :month="month"
@change="calendarChange2"
></calenderMonthSimple>
</view>
</view>
<view v-if="!isMonth" style="height:100rpx;"></view>
<block v-for="(row,index) in list" :key="index">
<!-- 日期展示 parseTime(row.date,'{y}-{m}-{d} 星期{a}')-->
<view class="date-title" v-if="activeTab==1 && row.day">{{row.day}}</view>
<view class="bg-border" v-else></view>
<!-- 日常巡检 -->
<view class="blue-title">日常巡检</view>
<block v-if="row.list1">
<block v-if="row.list1.length>0">
<view class="report-list" v-for="(item, index) in row.list1" :key="index" @click="handleDetail(item,1)">
<view class="r-list" style="padding-bottom:0">
<view class="r-name">{{ item.taskName }}</view>
<view class="r-right">
<!-- 任务(巡检)状态 1=未发布 2=已发布 3 进行中 4 已完成 5 已过期 -->
<!-- 状态为3进行中时 进度>0执行中 进度=0为待执行 -->
<block v-if="item.taskStatus==3">
<img v-if="item.beginTime" :src="'static/images/polling/icon-pending.png'" class="img-w" />
<img v-else :src="'static/images/polling/icon-start.png'" class="img-w" />
</block>
<img v-else-if="item.taskStatus==4" :src="'static/images/polling/icon-complete.png'" class="img-complete" />
<img v-else-if="item.taskStatus==5" :src="'static/images/polling/icon-Expired.png'" class="img-w" />
</view>
</view>
<view class="r-list">
<view class="r-left">巡检单号<span class="r-gray">{{ item.taskId }}</span></view>
</view>
<view class="r-list">
<view class="r-left">
<view v-if="item.beginTime">
执行时间<span class="r-gray">{{ parseTime(item.beginTime,'{y}-{m}-{d} {h}:{i}') }}</span>
</view>
<view v-else>
开始时间<span class="r-gray">{{ parseTime(item.planTime,'{y}-{m}-{d} {h}:{i}') }}</span>
</view>
</view>
</view>
<view class="r-list">
<view class="r-left">
<view class="r-l-left">
任务状态<span class="r-gray" v-if="item.taskStatus==3">
<block v-if="item.beginTime">执行中</block>
<block v-else>待执行</block>
</span>
<span class="r-gray" v-else>{{formatTaskStatus(item.taskStatus) }}</span>
</view>
<view class="r-l-right">
任务时长<span class="r-gray">{{ item.workHour }}小时</span>
</view>
</view>
</view>
<view class="r-list">
<view class="r-left">
<view class="r-l-left">
完成进度<span class="r-gray"><span :class="{'r-red':item.groupFinishNum<item.groupNum}">{{item.groupFinishNum}}</span>/{{item.groupNum}}</span>
</view>
<view class="r-l-right">
完成比率<span class="r-blue">{{(item.groupFinishNum/item.groupNum*100).toFixed()+'%'}}</span>
</view>
</view>
</view>
<view class="report-border" v-if="index<row.list1.length-1"></view>
</view>
</block>
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view>
</block>
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view>
<!-- 临时巡检 -->
<view class="green-title" style="margin-top:60rpx">临时巡检</view>
<block v-if="row.list2">
<block v-if="row.list2.length>0">
<view class="report-list" v-for="(item, index) in row.list2" :key="index" @click="handleDetail(item,1)">
<view class="r-list" style="padding-bottom:0">
<view class="r-name">{{ item.taskName }}</view>
<view class="r-right">
<!-- 任务(巡检)状态 1=未发布 2=已发布 3 进行中 4 已完成 5 已过期 -->
<!-- 状态为3进行中时 进度>0执行中 进度=0为待执行 -->
<block v-if="item.taskStatus==3">
<img v-if="item.beginTime" :src="'static/images/polling/icon-pending.png'" class="img-w" />
<img v-else :src="'static/images/polling/icon-start.png'" class="img-w" />
</block>
<img v-else-if="item.taskStatus==4" :src="'static/images/polling/icon-complete.png'" class="img-complete" />
<img v-else-if="item.taskStatus==5" :src="'static/images/polling/icon-Expired.png'" class="img-w" />
</view>
</view>
<view class="r-list">
<view class="r-left">巡检单号<span class="r-gray">{{ item.taskId }}</span></view>
</view>
<view class="r-list">
<view class="r-left">
<view v-if="item.beginTime">
执行时间<span class="r-gray">{{ parseTime(item.beginTime,'{y}-{m}-{d} {h}:{i}') }}</span>
</view>
<view v-else>
开始时间<span class="r-gray">{{ parseTime(item.planTime,'{y}-{m}-{d} {h}:{i}') }}</span>
</view>
</view>
</view>
<view class="r-list">
<view class="r-left">
<view class="r-l-left">
任务状态<span class="r-gray" v-if="item.taskStatus==3">
<block v-if="item.beginTime">执行中</block>
<block v-else>待执行</block>
</span>
<span class="r-gray" v-else>{{formatTaskStatus(item.taskStatus) }}</span>
</view>
<view class="r-l-right">
任务时长<span class="r-gray">{{ item.workHour }}小时</span>
</view>
</view>
</view>
<view class="r-list">
<view class="r-left">
<view class="r-l-left">
完成进度<span class="r-gray"><span :class="{'r-red':item.groupFinishNum<item.groupNum}">{{item.groupFinishNum}}</span>/{{item.groupNum}}</span>
</view>
<view class="r-l-right">
完成比率<span class="r-blue">{{item.percentage}}</span>
</view>
</view>
</view>
<view class="report-border" v-if="index<row.list2.length-1"></view>
</view>
</block>
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view>
</block>
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view>
<!-- 问题跟踪 按月没有问题跟踪-->
<block v-if="activeTab==0">
<view class="bg-border"></view>
<view class="red-title">问题跟踪</view>
<block v-if="row.list3">
<block v-if="row.list3.length>0">
<view class="report-list" v-for="(item, index) in row.list3" :key="index" @click="handleDetail(item,2)">
<view class="r-list" style="padding-bottom:0">
<view class="r-name">{{ item.groupName }}</view>
<view class="r-right">
<!-- 问题状态 1=追踪2=关闭 -->
<view v-if="item.problemStatus==1" class="btn-red">进行中</view>
<view v-if="item.problemStatus==2" class="btn-green">已解决</view>
</view>
</view>
<view class="r-list">
<view class="r-left">
<view class="r-l-left" style="width:220rpx">跟踪次数<span class="r-gray">{{ item.logNum }}</span></view>
<view class="r-l-right">最近跟踪时间<span class="r-gray">{{ parseTime(item.lastLogTime,'{y}-{m}-{d} {h}:{i}') }}</span></view>
</view>
</view>
<view class="report-border" v-if="index<row.list3.length-1"></view>
</view>
</block>
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view>
</block>
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view>
</block>
</block>
</view>
</mescroll-uni>
</view>
</view>
</template>
<script setup>
import { ref,onMounted } from 'vue'
import { onLoad,onHide } from '@dcloudio/uni-app';
import customHeader from '@/components/customHeader.vue';
import MescrollUni from 'mescroll-uni/mescroll-uni.vue';
import calenderMonth from '@/components/calenderMonth.vue'
import calenderMonthSimple from '@/components/calenderMonthSimple.vue'
import customTabs from '@/components/customTabs.vue';
import { parseTime } from '@/utils/datetime.js';
import { formatTaskStatus } from '@/utils/status.js';
import { taskList,taskListMonth } from '@/api/polling.js'
const selectDate = ref({});//查询条件
const year=ref('');//默认月份
const month=ref('');//默认月份
const activeTab = ref(0);//默认按天查看
const tabList = ['按天查看', '按月查看'];
let count1=ref(0);//已巡检
let count2=ref(0);//待巡检
let count3=ref(0);//已过期
onLoad(option => {
let date = new Date();
year.value = date.getFullYear();
month.value = date.getMonth()+1;
selectDate.value = parseTime(date,'{y}-{m}-{d}')//默认查今天
})
// tab切换 按日 or 按月 0-按日 1-按月
const handleTab = async (index)=>{
activeTab.value = index;
isMonth.value=true;
// scrollToPosition();
if(index==1){
selectDate.value = parseTime(new Date(),'{y}-{m}')
}else{
selectDate.value = parseTime(new Date(),'{y}-{m}-{d}')
}
const res = await getList();
list.value = res.list;
}
// 日历初始化
const calendarInfo = ref({
range: true,
insert: false,//插入模式可选值ture插入模式false弹窗模式默认为插入模式
selected: [],
showMonth:true,
});
// 按日选择 选月处理
const monthSwitch=(e)=>{
console.log('monthSwitchs 返回:', e)
}
// 按日选择 日历change
const calendarChange= async(e)=> {
// console.log('按日选择 返回:', e.fulldate)
selectDate.value = e.fulldate
const res = await getList();
list.value = res.list;
}
// 按月选择 日历change
const calendarChange2= async(value)=> {
// console.log("按月选择 选择具体月份=>",value)
selectDate.value = value.ymStr
year.value = value.year;
month.value = value.month;
const res = await getList();
list.value = res.list;
}
// 查询列表
let list = ref([])
const mescrollRef = ref(null);
const isMonth = ref(true);
const upOption = ref({
onScroll:true,
page: { num: 0, size: 10 },
noMoreSize: 5,
empty: {
tip: '~ 空空如也 ~',
icon: "../../../static/images/mescroll-empty.png"
},
textLoading: '加载中...',
textNoMore: '已经到底了'
});
const downOption = ref({
auto: false,
textInOffset: '下拉刷新',
textOutOffset: '释放更新',
textLoading: '刷新中...'
});
let cssFlag=ref(false);//控制样式
const mescrollInit = async(mescroll) => {
cssFlag.value = true;
mescrollRef.value = mescroll;
};
// 滚动到指定位置
const scrollToPosition = () => {
console.log(mescrollRef)
if (mescrollRef) {
// 滚动到指定Y坐标位置单位px
mescrollRef.value.scrollTo(0, 300) // 滚动到Y=500的位置动画时长300ms
// mescrollRef.value.scrollTop=0;
}
}
// 下拉刷新
const downCallback = async (mescroll) => {
try {
// console.log("下拉刷新")
isMonth.value=true;
const res = await getList(1, upOption.value.page.size);
cssFlag.value = false;
list.value = res.list;
// mescroll.resetUpScroll();
} catch (error) {
mescroll.endErr();
} finally {
setTimeout(async ()=>{
mescroll.endSuccess();
},500);
}
}
// 上拉加载更多
const upCallback = async (mescroll) => {
try {
// console.log("上拉加载更多")
let res = await getList(mescroll.num, mescroll.size);
if (mescroll.num === 1) {
list.value = res.list;
} else {
// list.value.push(...res.list);
}
mescroll.endBySize(res.list.length, res.total);
} catch (error) {
mescroll.endErr();
}
}
// 获取数据列表
const getList = (pageIndex, pageSize) => {
return new Promise(async (resolve) => {
let res ={};
if(activeTab.value==1){//月查询
let param = {
month: selectDate.value
}
let response = await taskListMonth(param);
res ={
...response,
list:response.list || []
}
// 没数据时补值
if(res.list.length==0){
res.list.push({
list1: [],
list2: [],
});
}
}else{//天查询
let param = {
day:selectDate.value
}
let response = await taskList(param);
res ={
...response,
list:[]
}
res.list.push({
list1:response.list1 || [],
list2:response.list2 || [],
list3:response.list3 || []
});
}
// console.log(res)
let data = res||{};
count1.value = data.finishNum;
count2.value = data.waitNum;
count3.value = data.expiredNum
resolve({
...data,
});
});
}
// 滚动位置
const onScroll = (mescrollInstance)=>{
const y = mescrollInstance.getScrollTop()
// const maxScroll = mescrollInstance.getScrollHeight() - mescrollInstance.getClientHeight()
// console.log(y)
if(activeTab.value==1){
if(y==0){
isMonth.value=true;
}
if(y>=200){
isMonth.value=false;
}
}
}
// 查看详情 type 1-任务详情 2-问题详情
const handleDetail = (item,type) =>{
let url=''
if(type==1){
url = '/pages/business/polling/taskDetail?id='+item.taskId;
}else{
url = '/pages/business/polling/problemDetail?problemId='+item.problemId;
}
uni.navigateTo({
url
});
}
// 跳转webview
const handleJump = (item)=>{
// uni.navigateTo({
// // url: '/pages/h5-webview/h5-webview?url=' + item.mobileLink+"&title="+item.subject
// // url:'/pages/notice/noticeDetail?title='+item.subject+'&time='+item.createTime+'&appName='+item.appName
// });
}
</script>
<style scoped>
.white-top{
position: relative;
padding-bottom:30rpx;
margin-bottom:26rpx;
}
.calender-list{
display: flex;
align-items: center;
justify-content: center;
padding:20rpx 0;
}
.calender-list .calender-item{
/* flex-grow: 1; */
width:33.3%;
text-align: center;
position: relative;
}
.calender-list .calender-item::after{
position: absolute;
content: " ";
width:1px;
height:80%;
background-color: #EAEAEA;
right:0;
top:25rpx;
}
.calender-list .calender-item:last-child::after{
display:none;
}
.calender-list .calender-item .item-blue,
.calender-list .calender-item .item-red{
color:#579FF9;
font-size:60rpx;
font-weight: bold;
}
.calender-list .calender-item .item-red{
color: #FF687A;
}
.calender-list .calender-item .font28{
font-size:28rpx;
}
.tab-list{
display: flex;
justify-content: center;
}
.tab-list .tab-item{
color:rgba(255, 255, 255, 0.5);
margin-right:74rpx;
font-size:32rpx;
padding-bottom:10rpx;
}
.tab-list .tab-item.active{
border-bottom:8rpx solid #fff;
color:#fff;
position: relative;
}
.tab-item.active::before {
content: '';
position: absolute;
bottom: -4px;
left:-4px;
width: 10px;
height: 4px;
background: #307AF5;
transform: skewX(45deg);
}
.tab-item.active::after{
content: '';
position: absolute;
bottom: -4px;
right:-4px;
width: 10px;
height: 4px;
background: #307AF5;
transform: skewX(-45deg);
}
.tab-item.active1::after{
background: #4F8EF7;
}
/* 日历 */
.date-title{
background-color: #F5F5F5;
padding:40rpx 40rpx 30rpx;
width:670rpx;
margin-left:-40rpx;
color:#919191;
font-size:28rpx;
margin-top:30rpx;
}
.scroll-h{
/* #ifdef APP-PLUS */
height: calc(100vh - 77px);
/* #endif */
/* #ifndef APP-PLUS */
height: calc(100vh - 58px);
/* #endif */
}
.head-right{
font-size:28rpx;
}
.img-calendar{
width: 30rpx;
height: 28rpx;
}
.week{
padding:0 40rpx;
color: #fff;
font-size:32rpx;
margin-bottom:20rpx;
}
.white-bg{
width: 670rpx;
padding: 30rpx 40rpx 40rpx;
margin-bottom: 0;
border-radius: 8px 8px 0 0;
position: relative;
}
.white-bg .blue-title,
.white-bg .red-title{
margin-top:30rpx
}
.white-bg .calender-blue{
position: fixed;
width:750rpx;
left:0rpx;
top:115rpx;
/* #ifdef APP-PLUS */
top:155rpx;
/* #endif */
z-index: 9999;
background-color: #307AF5;
}
.white-bg .calender-simple{
padding-top:30rpx;
background-color: #fff;
border-radius: 8px 8px 0 0;
}
.bg-border{
width:750rpx;
height:20rpx;
background-color: #F5F5F5;
margin-left:-40rpx;
margin-top:40rpx;
}
.report-list{
position: relative;
}
.img-w{
width:50rpx;
height:50rpx;
}
.img-complete{
position: absolute;
right:-40rpx;
top:60rpx;
width:133rpx;
height:150rpx;
}
.report-border{
border-bottom:1px solid #E7E7E7;
width:710rpx;
height: 1px;
margin:20rpx 0;
}
.report-list .r-list{
padding: 5rpx 0;
}
.report-list .r-list .r-left{
display: flex;
align-items:center;
}
.report-list .r-list .r-gray{
margin-left:10rpx;
}
.report-list .r-list .r-blue{
margin-left:10rpx;
font-weight: bold;
}
.report-list .r-list .r-red{
font-weight: bold;
}
.report-list .r-list .r-name{
width:525rpx
}
.r-left .r-l-left{
width:280rpx;
}
.r-left .r-l-right{
}
.no-data .no-pic{
display: block;
width:440rpx;
height:210rpx;
margin:40rpx auto;
}
:deep(.mescroll-upwarp){
display: none !important;
}
</style>