Files
threeonecheck_web/pages/hiddendanger/Inspection.vue

416 lines
10 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 padding">
<!-- 顶部状态筛选 Tab -->
<scroll-view class="status-tabs" scroll-x :show-scrollbar="false">
<view class="status-tabs-inner">
<view v-for="(tab, index) in statusTabs" :key="index" class="status-tab-item"
:class="{ 'status-tab-active': activeTab === index }" @click="switchStatusTab(index)">
<text class="status-tab-text">{{ tab.label }}</text>
<view v-if="activeTab === index" class="status-tab-bar"></view>
</view>
</view>
</scroll-view>
<view v-if="hiddenDangerList.length === 0 && !listLoading" class="empty-tip text-gray text-center padding">暂无数据</view>
<view class="padding radius bg-white list-list margin-bottom" v-for="item in hiddenDangerList"
:key="item.hazardId">
<view class="flex justify-between margin-bottom">
<view class="text-bold text-black" style="word-break: break-all; flex: 1;">{{item.title}}</view>
<view class="text-blue" style="white-space: nowrap; flex-shrink: 0; margin-left: 16rpx;">{{item.statusName}}</view>
</view>
<view class="flex margin-bottom">
<view class="text-gray">隐患等级</view>
<view class="level-tag" :class="{
'level-minor': item.levelName === '轻微隐患',
'level-normal': item.levelName === '一般隐患',
'level-major': item.levelName === '重大隐患'
}">{{item.levelName}}</view>
</view>
<view class="flex margin-bottom">
<view class="text-gray" style="white-space: nowrap;">隐患位置</view>
<view class="text-black">{{item.address}}</view>
</view>
<view class="flex margin-bottom">
<view class="text-gray">创建时间</view>
<view class="text-black">{{item.createdAt}}</view>
</view>
<view class="flex justify-end card-actions" style="gap: 10rpx;">
<button class="round cu-btn light bg-blue" @click="details(item)">查看详情</button>
<template v-if="!isApprovalRole">
<button v-if="item.statusName === '待整改' && item.canEdit"
class="round cu-btn light bg-blue" @click="assignHazard(item)">隐患交办</button>
<button v-if="item.statusName === '待整改' && item.canEdit"
class="round cu-btn bg-blue" @click="Rectification(item)">立即整改</button>
<button v-if="item.statusName === '待验收' && item.canEdit"
class="round cu-btn light bg-blue" @click="editRectification(item)">编辑整改信息</button>
<button v-if="canShowAcceptanceButton(item, userRole)"
class="round cu-btn bg-blue" @click="acceptance(item)">立即验收</button>
<button v-if="item.statusName === '待交办'"
class="round cu-btn bg-blue" @click="assignHazard(item)">隐患交办</button>
<button v-if="canShowWriteoffApplyButton(item)"
class="round cu-btn bg-blue" @click="goWriteoffApply(item)">销号申请</button>
<button v-if="canShowWriteoffApprovalButton(item, userRole)"
class="round cu-btn bg-blue" @click="goWriteoffApproval(item)">销号审批</button>
</template>
</view>
</view>
<u-loadmore
v-if="hiddenDangerList.length > 0"
:status="loadStatus"
style="margin-top: 20rpx; margin-bottom: 140rpx;"
/>
<view v-if="!isApprovalRole" class="fixed-add-btn" @click="goToAdd">
<text class="cuIcon-add"></text>
<text>新增</text>
</view>
</view>
</template>
<script setup>
import { ref, computed } from 'vue'
import { onLoad, onShow, onReachBottom } from '@dcloudio/uni-app'
import {
enterCheckPlan,
getCheckTaskDetail,
getMyHiddenDangerList
} from '@/request/api.js'
import {
buildRectificationUrl,
buildEditRectificationUrl,
buildAssignmentUrl,
buildAcceptanceUrl,
buildWriteoffApplyUrl,
buildWriteoffApprovalUrl,
canShowAcceptanceButton,
canShowWriteoffApplyButton,
canShowWriteoffApprovalButton
} from '@/utils/hazardNav.js'
import { resolveUserIdentityRoleKey } from '@/utils/userInfo.js'
const taskId = ref('')
const checkPointId = ref('')
const oneTableId = ref('')
const userRole = ref('')
const isApprovalRole = computed(() => userRole.value === 'approval')
const getUserRole = () => {
try {
const userInfoStr = uni.getStorageSync('userInfo')
if (userInfoStr) {
userRole.value = resolveUserIdentityRoleKey(JSON.parse(userInfoStr))
}
} catch (error) {
console.error('获取用户信息失败:', error)
}
}
const fetchTaskInfo = async (oneTableId) => {
try {
const startRes = await enterCheckPlan(oneTableId)
if (startRes.code === 0 && startRes.data) {
const tid = startRes.data.taskId
const detailRes = await getCheckTaskDetail(tid)
if (detailRes.code === 0 && detailRes.data) {
taskId.value = detailRes.data.taskId
checkPointId.value = detailRes.data.checkPointId
}
}
} catch (error) {
console.error('获取任务信息失败:', error)
}
}
onLoad((options) => {
getUserRole()
if (options.id) {
oneTableId.value = options.id
fetchTaskInfo(options.id)
}
})
const HAZARD_PAGE_SIZE = 10
const hiddenDangerList = ref([])
const pageNum = ref(1)
const listLoading = ref(false)
const loadStatus = ref('loadmore')
const statusTabs = ref([
{ label: '全部', value: null },
{ label: '待交办', value: 1 },
{ label: '待整改', value: 2 },
{ label: '待验收', value: 3 },
{ label: '待销号', value: 4 },
{ label: '已完成', value: 5 }
])
const activeTab = ref(0)
const buildListParams = () => {
const params = {
pageNum: pageNum.value,
pageSize: HAZARD_PAGE_SIZE
}
const currentTab = statusTabs.value[activeTab.value]
if (currentTab?.value != null) {
params.status = currentTab.value
}
return params
}
const resetHiddenDangerList = () => {
pageNum.value = 1
hiddenDangerList.value = []
loadStatus.value = 'loadmore'
}
const switchStatusTab = (index) => {
if (activeTab.value === index) return
activeTab.value = index
resetHiddenDangerList()
fetchHiddenDangerList()
}
const fetchHiddenDangerList = async () => {
if (listLoading.value) return
if (pageNum.value > 1 && loadStatus.value === 'nomore') return
listLoading.value = true
if (pageNum.value > 1) {
loadStatus.value = 'loading'
}
try {
const res = await getMyHiddenDangerList(buildListParams())
if (res.code === 0) {
const records = res.data?.records || []
const total = Number(res.data?.total ?? 0)
if (pageNum.value === 1) {
hiddenDangerList.value = records
} else {
hiddenDangerList.value = [...hiddenDangerList.value, ...records]
}
if (hiddenDangerList.value.length >= total || records.length < HAZARD_PAGE_SIZE) {
loadStatus.value = 'nomore'
} else {
loadStatus.value = 'loadmore'
}
} else {
if (pageNum.value === 1) {
hiddenDangerList.value = []
}
loadStatus.value = 'nomore'
uni.showToast({
title: res.msg || '获取隐患列表失败',
icon: 'none'
})
}
} catch (error) {
console.error(error)
if (pageNum.value > 1) {
pageNum.value--
}
loadStatus.value = 'loadmore'
uni.showToast({
title: '请求失败',
icon: 'none'
})
} finally {
listLoading.value = false
}
}
const loadMoreHiddenDangerList = () => {
if (loadStatus.value !== 'loadmore' || listLoading.value) return
pageNum.value++
fetchHiddenDangerList()
}
onShow(() => {
getUserRole()
resetHiddenDangerList()
fetchHiddenDangerList()
})
onReachBottom(() => {
loadMoreHiddenDangerList()
})
const goToAdd = () => {
let url = '/pages/hiddendanger/add'
const params = []
if (oneTableId.value) {
params.push(`id=${oneTableId.value}`)
}
if (taskId.value) {
params.push(`taskId=${taskId.value}`)
}
if (checkPointId.value) {
params.push(`checkPointId=${checkPointId.value}`)
}
if (params.length) {
url += `?${params.join('&')}`
}
uni.navigateTo({ url })
}
const details = (item) => {
uni.navigateTo({
url: `/pages/hiddendanger/process-chain?hazardId=${item.hazardId}`
})
}
const Rectification = (item) => {
uni.navigateTo({ url: buildRectificationUrl(item) });
}
const editRectification = (item) => {
uni.navigateTo({ url: buildEditRectificationUrl(item) });
}
const acceptance = (item) => {
uni.navigateTo({ url: buildAcceptanceUrl(item) });
}
const assignHazard = (item) => {
uni.navigateTo({ url: buildAssignmentUrl(item) });
}
const goWriteoffApply = (item) => {
uni.navigateTo({ url: buildWriteoffApplyUrl(item) });
}
const goWriteoffApproval = (item) => {
uni.navigateTo({ url: buildWriteoffApprovalUrl(item) });
}
</script>
<style lang="scss" scoped>
.page {
min-height: 100vh;
background: #EBF2FC;
padding-top: 100rpx;
padding-bottom: 120rpx;
}
.fixed-add-btn {
position: fixed;
bottom: 40rpx;
left: 30rpx;
right: 30rpx;
height: 88rpx;
background: linear-gradient(135deg, #667eea 0%, #2668EA 100%);
border-radius: 44rpx;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 32rpx;
font-weight: 500;
box-shadow: 0 8rpx 24rpx rgba(38, 104, 234, 0.4);
z-index: 100;
.cuIcon-add {
margin-right: 10rpx;
font-size: 36rpx;
}
}
.list-list {
background: #FFFFFF;
box-shadow: 0rpx 2rpx 6rpx 2rpx rgba(0, 0, 0, 0.08);
border-left: 5px solid #2667E9;
border-radius: 20rpx;
padding: 20rpx;
}
.level-tag {
padding: 4rpx 16rpx;
border-radius: 8rpx;
white-space: nowrap;
flex-shrink: 0;
}
.level-minor {
background: #F6FFED;
border: 2rpx solid #B7EB8F;
color: #52C41A;
}
.level-normal {
background: #FFF7E6;
border: 2rpx solid #FFD591;
color: #FA8C16;
}
.level-major {
background: #FFF1F0;
border: 2rpx solid #FFA39E;
color: #F5222D;
}
.status-tabs {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 99;
white-space: nowrap;
background: #fff;
padding: 0 10rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.06);
}
.status-tabs-inner {
display: inline-flex;
align-items: center;
height: 88rpx;
}
.status-tab-item {
display: inline-flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 0 28rpx;
height: 88rpx;
position: relative;
}
.status-tab-text {
font-size: 28rpx;
color: #666;
}
.status-tab-active .status-tab-text {
color: #2667E9;
font-weight: bold;
}
.status-tab-bar {
position: absolute;
bottom: 8rpx;
width: 40rpx;
height: 6rpx;
background: #2667E9;
border-radius: 3rpx;
}
</style>
<style lang="scss">
.card-actions {
margin-top: 20rpx;
.cu-btn {
padding: 0 24rpx !important;
font-size: 28rpx !important;
height: 64rpx !important;
line-height: 64rpx !important;
white-space: nowrap !important;
flex-shrink: 0 !important;
width: auto !important;
}
}
</style>