Files
app-govern/pages/index/comp/steadyState.vue
2026-07-02 09:55:30 +08:00

437 lines
14 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="dateReport">
<!-- {{ height }} -->
<view class="pd20">
<uni-segmented-control :current="curSub" class="subsection" active-color="#376cf3" :values="subsectionList"
@clickItem="sectionChange" />
</view>
<view class="filterCriteria">
<!-- 筛选条件 -->
<Cn-filterCriteria @select="select" :singleChoice="true" :showDatetime="curSub == 0"> </Cn-filterCriteria>
</view>
<!-- 卡片 -->
<scroll-view scroll-y="true" @scroll="onScroll" :scroll-top="scrollTop" scroll-with-animation
@refresherrefresh="refresherrefresh" :refresher-triggered="triggered" refresher-enabled="true"
class="event-list mt20"
:style="{ height: 'calc(100vh - ' + (navHeight + height) + 'px)', overflow: 'auto' }">
<!-- 循环渲染事件项 -->
<uni-card class="event-item" :class="item.type" v-for="(item, index) in store.data" :key="index">
<!-- 头部图标 + 信息 + 操作 -->
<view class="event-header">
<view class="event-icon">
<!-- 动态图标根据类型切换 -->
<!-- <uni-icons
custom-prefix="iconfont"
type="icon-kouanjiancedian"
size="40"
color="#E6A23C"
></uni-icons> -->
<Cn-icon-transient :name="`报告1`" />
<view class="badge1" v-if="item.isRead == 0"> </view>
</view>
<view class="event-info">
<view class="event-title">
<text class="event-id">{{ item.lineName }}</text>
<!-- <view class="event-tags"
>{{ selectValue.report == 0 ? item.startTime : item.startTime + '至' + item.endTime }}
</view> -->
</view>
<view class="event-desc">
<text>统计时间{{
curSub == 0 ? item.startTime : item.startTime + ' 至 ' + item.endTime
}}</text>
</view>
</view>
<view class="event-action" v-if="!showNotGenerated(item)">
<view class="iconText boxClick" @click="download(item)"><uni-icons type="arrow-down"
color="#fff" size="16"></uni-icons>
</view>
</view>
</view>
<!-- 详情区域 -->
<view class="event-detail textBox" @touchmove.stop>
<text v-if="!showNotGenerated(item)">{{
item.overLimitDesc == '' ? '该监测点暂无指标越限' : item.overLimitDesc
}}</text>
<text v-else>数据未生成暂不支持下载</text>
</view>
<!-- <view class="downloadReport" @click="download">
<uni-icons type="download" size="16" color="#376cf3"></uni-icons>下载报告
</view> -->
</uni-card>
<uni-load-more v-if="store.status == 'loading' || (store.data && store.data.length > 0)"
:status="store.status"></uni-load-more>
<Cn-empty v-else style="top: 20%"></Cn-empty>
</scroll-view>
<!-- <view class="back-top boxClick" v-show="showBackTop" @click="backToTop">
<uni-icons type="arrow-up" size="22" color="#fff"></uni-icons>
</view> -->
</view>
</template>
<script>
import list from '@/common/js/list'
import { downloadHarmonicReport } from '@/common/api/report.js'
export default {
components: {},
props: {
indexList: {
type: Array,
default: () => [],
},
total: {
type: Number,
default: 0,
},
navHeight: {
type: Number,
default: 0,
},
},
mixins: [list],
data() {
return {
status: 'noMore',
curSub: 0,
subsectionList: ['日报', '月报'],
thisSelectValue: {},
triggered: true,
height: 0,
thisMonth01: '',
scrollTop: 0,
oldScrollTop: 0,
showBackTop: false,
}
},
created() { },
mounted() {
this.thisMonth01 = this.$util.getToday().slice(0, -3) + '-01'
// this.setHeight()
},
methods: {
setHeight() {
uni.createSelectorQuery()
.select('.filterCriteria')
.boundingClientRect((rect) => {
//
// #ifdef H5
this.height = rect?.height + 140 || 0
// #endif
// #ifdef APP-PLUS
this.height = rect?.height + 75 || 0
// #endif
})
.exec()
},
sectionChange(index) {
this.curSub = index.currentIndex
this.showBackTop = false
this.scrollTop = 0
this.init()
},
init() {
if (this.selectValue.lineId == '') return
this.store = this.DataSource('/cs-report-boot/csAppReport/reportList')
// this.store.params.pageSize = 10000
this.store.params.timeType = this.curSub //this.selectValue.report
this.store.params.engineerId = this.selectValue.engineeringId
this.store.params.projectId = this.selectValue.projectId
this.store.params.devId = this.selectValue.deviceId
this.store.params.lineId = this.selectValue.lineId
if (this.curSub == 0) {
this.store.params.time = this.selectValue.date
} else {
this.store.params.time = this.selectValue.range + '-01'
}
// this.store.params.startTime = this.selectValue.range[0]
// this.store.params.endTime = this.selectValue.range[1]
this.store.loadedCallback = () => {
this.store.status = 'noMore'
}
this.store.reload()
},
select(value) {
this.selectValue = value
setTimeout(() => {
this.setHeight()
}, 200)
this.init()
},
// 下载
download(item) {
uni.showLoading({
title: '下载中,请稍等...',
mask: true,
})
downloadHarmonicReport({
devId: this.selectValue.deviceId,
endTime: item.endTime,
engineerId: this.selectValue.engineeringId,
lineId: this.selectValue.lineId,
list: [],
projectId: this.selectValue.projectId,
startTime: item.startTime,
time: '',
timeType: this.selectValue.report,
})
.then((res) => {
const match = this.$config.static + res.data.match(/excelreport([^?]*)/)[1]
uni.downloadFile({
url: match,
success: (downloadRes) => {
if (downloadRes.statusCode === 200) {
this.openReportFile(downloadRes.tempFilePath)
} else {
uni.hideLoading()
uni.showToast({
icon: 'none',
mask: true,
title: '下载失败!',
duration: 1000,
})
}
},
fail: () => {
uni.hideLoading()
uni.showToast({
icon: 'none',
mask: true,
title: '下载失败!',
duration: 1000,
})
},
})
})
.catch((err) => {
uni.hideLoading()
uni.showToast({
icon: 'none',
mask: true,
title: err.message,
duration: 1000,
})
})
},
openReportFile(tempFilePath) {
const previewFile = (filePath) => {
uni.hideLoading()
uni.openDocument({
filePath,
fileType: 'xlsx',
showMenu: true,
success: () => {
console.log('成功打开文件')
},
fail: (err) => {
console.log('打开文件失败', err)
uni.showToast({
icon: 'none',
title: '预览失败',
})
},
})
}
// #ifdef APP-PLUS
// iOS 需保留 xlsx 后缀saveFile 随机路径会导致 openDocument 失败
if (plus.os.name === 'iOS') {
const fileName = `harmonic_report_${Date.now()}.xlsx`
plus.io.resolveLocalFileSystemURL(
tempFilePath,
(entry) => {
plus.io.resolveLocalFileSystemURL(
'_doc/',
(docEntry) => {
entry.copyTo(
docEntry,
fileName,
(newEntry) => previewFile(newEntry.fullPath),
() => previewFile(tempFilePath)
)
},
() => previewFile(tempFilePath)
)
},
() => previewFile(tempFilePath)
)
return
}
// #endif
uni.saveFile({
tempFilePath,
success: (data) => {
uni.showToast({
icon: 'success',
mask: true,
title: '下载成功!',
duration: 1000,
})
setTimeout(() => previewFile(data.savedFilePath), 500)
},
fail: () => {
uni.hideLoading()
uni.showToast({
icon: 'none',
title: '保存失败!',
})
},
})
},
// 下拉
refresherrefresh() {
this.triggered = true
uni.startPullDownRefresh()
setTimeout(() => {
this.triggered = false
}, 500)
},
onScroll(e) {
this.oldScrollTop = e.detail.scrollTop
this.showBackTop = e.detail.scrollTop > 200
},
backToTop() {
this.scrollTop = this.oldScrollTop
this.$nextTick(() => {
this.scrollTop = 0
})
this.showBackTop = false
},
/** 日报统计时间与今天相同月报开始、结束时间均为当月1号 */
showNotGenerated(item) {
if (this.curSub === 0) {
return item.startTime === this.$util.getToday()
}
return item.startTime === this.thisMonth01 && item.endTime === this.thisMonth01
},
},
computed: {},
watch: {},
}
</script>
<style lang="scss" scoped>
@import '@/pages/message1/index.scss';
.event-title {
justify-content: space-between;
}
.event-tags {
display: flex;
font-size: 27rpx !important;
line-height: 50rpx;
}
.event-detail {
// font-size: 25rpx !important;
// display: grid;
// grid-template-columns: 1fr 1fr;
}
.downloadReport {
width: 100%;
background: #376cf320;
height: 60rpx;
line-height: 60rpx;
color: #376cf3;
font-weight: 600;
border-radius: 15rpx;
margin-top: 10rpx;
display: flex;
justify-content: center;
}
.filterCriteria {
.nav {
background-color: #fff;
}
.choose1 {
background-color: #fff;
padding: 0 20rpx;
display: flex;
justify-content: space-between;
/deep/ .uni-checkbox-input {
width: 30rpx;
height: 30rpx;
}
font-size: 26rpx;
}
}
/deep/ .uni-scroll-view-refresher {
display: none;
}
.iconText {
width: 45rpx;
height: 45rpx;
border-radius: 50%;
background-color: $uni-theme-color;
text-align: center;
line-height: 40rpx;
}
.segmented-control {
flex: 1;
margin-right: 24rpx;
height: 60rpx;
}
/* 列表容器 */
.event-list {
/* 头部:图标 + 信息 + 操作 */
.event-header {
display: flex;
align-items: center;
margin-bottom: 10rpx;
}
/* 图标区域(按类型区分背景色) */
.event-icon {
background-color: #376cf320;
width: 80rpx;
height: 80rpx;
}
.event-tags {
font-size: 24rpx;
}
}
.textBox {
// @touchmove.stop
max-height: 110rpx;
overflow-y: auto;
}
.back-top {
position: fixed;
right: 30rpx;
bottom: 60rpx;
width: 80rpx;
height: 80rpx;
border-radius: 50%;
background: #376cf3;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4rpx 16rpx rgba(55, 108, 243, 0.35);
z-index: 1;
}
/deep/ .segmented-control__text {
line-height: 60rpx !important;
}
</style>