优化后,再次提交

This commit is contained in:
王利强
2026-05-03 09:08:56 +08:00
parent 721ef0ad54
commit 805747d1d9
1243 changed files with 46213 additions and 221 deletions

View File

@@ -1,144 +1,170 @@
<template>
<view class="content">
<view class="flex padding-top-xl padding-bottom-xl text-white " style="background-color:#007aff ;">
<view class="cu-avatar xl round margin-left">
<image class="avatar-image" :src="getImageUrl(userInfo.avatar) || defaultAvatar" mode="aspectFill"></image>
</view>
<view class="padding-left" style="display: flex;flex-direction: column;gap: 10rpx;justify-content: center;align-items: center;">
<view class="text-bold">{{ userInfo.deptName || '未知部门' }}</view>
<view class="flex padding-top-xs">
<view>用户</view>
<view>{{ userInfo.nickName || userInfo.username || '未登录' }}</view>
<!-- 顶部背景区域 -->
<view class="header-wrapper">
<!-- 渐变图片叠加在蓝色底色上 -->
<image class="header-bg-image" src="/static/home_icon/jianbianbeijing.png" mode="aspectFill"></image>
<!-- 自定义导航栏 -->
<u-navbar
title="三查一曝光"
:placeholder="false"
:fixed="false"
:safeAreaInsetTop="true"
bgColor="transparent"
titleColor="#fff"
:border="false"
leftIcon=""
>
</u-navbar>
<!-- 用户信息卡片 -->
<view class="user-card">
<view class="user-avatar">
<image class="avatar-image" :src="getImageUrl(userInfo.avatar) || defaultAvatar" mode="aspectFill"></image>
</view>
<!-- <view class="flex justify-between">
<view></view>
<view class="cu-btn text-blue margin-top text-bold">切换</view>
<view class="user-info">
<view class="user-dept text-bold">{{ userInfo.deptName || '未知部门' }}</view>
<view class="user-phone">手机号{{ userInfo.phone || '未绑定' }}</view>
</view>
<!-- <view class="switch-btn">
<text>切换</text>
<u-icon name="list" color="#285CE9" size="14"></u-icon>
</view> -->
</view>
</view>
<view class="padding page-content" style="background: #EBF2FC;">
<view class="bg-white padding radius">
<view class="flex margin-bottom-xl">
<view class="border-tite"></view>
<view class="margin-left-xs text-bold " >功能菜单</view>
</view>
<view class=" grid col-3 grid-square">
<view class="list " v-for="(item, index) in infoList" :key="index" @click="handleMenuClick(item)">
<image style="width: 102rpx;height: 102rpx;" :src="item.src"></image>
<view>{{ item.name}}</view>
<view class="padding page-content">
<!-- 功能菜单 -->
<view class="menu-card">
<view class="menu-grid">
<view class="menu-item" v-for="(item, index) in infoList" :key="index" @click="handleMenuClick(item)">
<image class="menu-icon" :src="item.src"></image>
<text class="menu-text">{{ item.name }}</text>
</view>
</view>
</view>
<!-- 我的检查计划 -->
<view class="padding bg-white margin-top radius">
<view class="bg-white margin-top radius" style="padding: 40rpx; margin-left: -30rpx; margin-right: -30rpx;">
<view class="flex margin-bottom-xl">
<view class="border-tite"></view>
<view class="text-bold margin-left-xs">我的检查计划</view>
<!-- <view class="border-tite"></view> -->
<view class="text-bold margin-left-xs" style="font-size: 32rpx;">我的检查计划</view>
</view>
<!-- 无数据提示 -->
<view v-if="checkPlanData.length === 0" class="text-center text-gray padding">
暂无检查计划
</view>
<!-- 列表渲染 -->
<view class="list-list padding margin-bottom" v-for="(item, index) in checkPlanData" :key="item.id">
<view class="flex">
<image src="/static/蒙版组 273.png" style="width: 40rpx;height: 40rpx;"></image>
<view class="text-bold margin-left">{{ item.name }}</view>
<view class="plan-card margin-bottom" v-for="(item, index) in checkPlanData" :key="item.id">
<!-- 蓝色标题栏 -->
<view class="plan-header">
<!-- <image src="/static/蒙版组 273.png" class="plan-header-icon"></image> -->
<text class="plan-header-title">{{ item.name }}</text>
</view>
<view class="flex margin-top">
<view class="border-border margin-right-xs">{{ item.runModeName }}完成</view>
<view class="border-border">{{ item.cycle }}</view>
</view>
<view class="flex text-gray margin-top">
<view>计划时间</view>
<view>{{ formatDate(item.planStartTime) }}{{ formatDate(item.planEndTime) }}</view>
</view>
<view class="flex margin-top align-center">
<view>完成进度</view>
<view class="flex align-center margin-left-sm">
<view class="cu-progress round">
<view class="bg-green" :style="{ width: item.progress + '%' }"></view>
<!-- 内容区域 -->
<view class="plan-body">
<view class="flex">
<view class="border-border margin-right-xs">{{ item.runModeName }}完成</view>
<view class="border-border">{{ item.cycle }}</view>
</view>
<view class="flex text-gray margin-top">
<view>计划时间</view>
<view style="color: #333333;">{{ formatDate(item.planStartTime) }}{{ formatDate(item.planEndTime) }}</view>
</view>
<view class="flex margin-top align-center">
<view style="color: #B5B5B5;">完成进度</view>
<view class="flex align-center margin-left-sm">
<view class="cu-progress round">
<view class="bg-green" :style="{ width: item.progress + '%' }"></view>
</view>
<text class="margin-left-sm">{{ item.progress }}%</text>
</view>
<text class="margin-left-sm">{{ item.progress }}%</text>
</view>
</view>
<view class="grid col-4 bg-gray margin padding text-center radius">
<view>
<view class="text-orange">{{ item.totalCount }}</view>
<view>总数</view>
<view class="plan-stats margin-top">
<view class="plan-stat-item">
<view class="plan-stat-num text-orange">{{ item.totalCount }}</view>
<view class="plan-stat-label">隐患</view>
</view>
<view class="plan-stat-item">
<view class="plan-stat-num text-yellow">{{ item.totalCount - item.finishedCount }}</view>
<view class="plan-stat-label">待整改</view>
</view>
<view class="plan-stat-item">
<view class="plan-stat-num text-olive">0</view>
<view class="plan-stat-label">待验收</view>
</view>
<view class="plan-stat-item">
<view class="plan-stat-num text-blue">{{ item.finishedCount }}</view>
<view class="plan-stat-label">已完成</view>
</view>
</view>
<view>
<view class="text-yellow">{{ item.totalCount - item.finishedCount }}</view>
<view>待完成</view>
<view class="margin-top margin-bottom flex justify-end">
<button class="cu-btn round lg light bg-blue margin-right" @click.stop="ViewDetails(item)">查看详情</button>
<button v-if="item.finishedCount < item.totalCount" class="cu-btn round lg bg-blue" @click.stop="goDetails(item)">开始检查</button>
<view v-else class="cu-btn round lg bg-green">已完成</view>
</view>
<view>
<view class="text-olive">0</view>
<view>待验收</view>
</view>
<view>
<view class="text-blue">{{ item.finishedCount }}</view>
<view>已完成</view>
</view>
</view>
<view class="margin-top margin-bottom flex justify-end">
<button class="cu-btn round lg light bg-blue margin-right" @click.stop="ViewDetails(item)">查看详情</button>
<button v-if="item.finishedCount < item.totalCount" class="cu-btn round lg bg-blue" @click.stop="goDetails(item)">开始检查</button>
<view v-else class="cu-btn round lg bg-green">已完成</view>
</view>
</view>
</view>
<!-- 我的隐患 -->
<view class="padding bg-white margin-top radius" >
<view class="flex margin-bottom-xl ">
<view class="border-tite"></view>
<view class="text-bold margin-left-xs">我的隐患排查</view>
<view class="bg-white margin-top radius" style="padding: 40rpx; margin-left: -40rpx; margin-right: -40rpx;">
<view class="flex margin-bottom">
<!-- <view class="border-tite"></view> -->
<view class="text-bold margin-left-xs" style="font-size: 32rpx;">我的隐患排查</view>
</view>
<view class="list-list padding margin-bottom" v-for="(item,index) in hiddenDangerData" :key="item.hazardId">
<view class="flex text-bold justify-between">
<view class="flex">
<view>隐患</view>
<view class="text-bold margin-left">#{{ index + 1 }}</view>
<!-- Tab 筛选栏 -->
<scroll-view scroll-x class="danger-tab-scroll">
<view class="danger-tab-list">
<view
class="danger-tab-item"
:class="{ 'danger-tab-active': activeDangerTab === index }"
v-for="(tab, index) in dangerTabs"
:key="index"
@click="switchDangerTab(index)"
>{{ tab }}</view>
</view>
</scroll-view>
<!-- 无数据提示 -->
<view v-if="filteredDangerData.length === 0" class="text-center text-gray padding">
暂无隐患数据
</view>
<!-- 隐患卡片列表 -->
<view class="danger-card margin-top" v-for="(item, index) in filteredDangerData" :key="item.hazardId">
<!-- 标题行图标+标题 + 等级标签 -->
<view class="flex justify-between align-center">
<view class="flex align-center">
<text class="cuIcon-infofill text-blue" style="font-size: 36rpx; margin-right: 12rpx;"></text>
<text class="text-bold" style="font-size: 30rpx;">{{ item.title }}</text>
</view>
<view class="text-blue">{{item.statusName}}</view>
</view>
<view class="flex margin-top">
<view class="text-gray">标题</view>
<view>{{item.title}}</view>
</view>
<view class="flex margin-top">
<view class="text-gray">隐患来源</view>
<view>{{item.source}}</view>
</view>
<view class="flex margin-top">
<view class="text-gray" style="white-space: nowrap;">隐患位置</view>
<view>{{item.address}}</view>
</view>
<view class="flex margin-top">
<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>
}">{{ item.levelName }}</view>
</view>
<view class="flex margin-top">
<view class="text-gray">发现时间</view>
<view>{{item.createdAt}}</view>
<!-- 地址 -->
<view class="text-gray margin-top-sm" style="font-size: 26rpx; padding-left: 48rpx;">{{ item.address }}</view>
<!-- 分隔线 -->
<view style="height: 1rpx; background: #EEEEEE; margin: 20rpx 0;"></view>
<!-- 信息行 -->
<view class="danger-info-row">
<text class="text-gray">隐患来源</text>
<text style="color: #333333;">{{ item.source }}</text>
</view>
<view class="margin-top margin-bottom flex justify-end" style="gap: 10rpx;">
<!-- 所有状态都显示查看详情 -->
<view class="danger-info-row">
<text class="text-gray">隐患状态</text>
<text style="color: #333333;">{{ item.statusName }}</text>
</view>
<view class="danger-info-row">
<text class="text-gray">发现时间</text>
<text style="color: #333333;">{{ item.createdAt }}</text>
</view>
<!-- 操作按钮 -->
<view class="margin-top flex justify-end" style="gap: 16rpx;">
<button class="cu-btn round lg light bg-blue" @click.stop="viewHazardDetail(item)">查看详情</button>
<!-- 待整改状态canEdit为true时显示隐患交办和立即整改 -->
<button v-if="item.statusName === '待整改' && item.canEdit"
class="cu-btn round lg light bg-blue" @click.stop="assignHazard(item)">隐患交办</button>
<button v-if="item.statusName === '待整改' && item.canEdit"
class="cu-btn round lg bg-blue" @click.stop="goRectification(item)">立即整改</button>
<!-- 待验收显示编辑整改信息和立即验收 -->
<button v-if="item.statusName === '待验收' && item.canEdit"
class="cu-btn round lg light bg-blue" @click.stop="editRectification(item)">编辑整改信息</button>
<button v-if="item.statusName === '待验收' && canAcceptance"
class="cu-btn round lg bg-blue" @click.stop="goAcceptance(item)">立即验收</button>
<!-- 待交办显示隐患交办 -->
<button v-if="item.statusName === '待交办'"
class="cu-btn round lg bg-blue" @click.stop="assignHazard(item)">隐患交办</button>
</view>
@@ -154,7 +180,7 @@
import {getCheckPlanList,getHiddenDangerList} from '@/request/api.js'
import { getProfileDetail } from '@/request/three_one_api/info.js';
import { onLoad, onShow } from '@dcloudio/uni-app';
import { baseUrl } from '@/request/request.js';
import { toImageUrl } from '@/request/request.js';
const loading = ref(true);
const defaultAvatar = 'https://ossweb-img.qq.com/images/lol/web201310/skin/big99008.jpg';
@@ -167,7 +193,8 @@
deptId: '',
deptName: '',
role: '',
avatar: ''
avatar: '',
phone: ''
});
// 获取用户角色判断是否有验收权限admin或manage才能验收
@@ -178,8 +205,7 @@
// 获取图片完整URL用于显示
const getImageUrl = (path) => {
if (!path) return '';
if (path.startsWith('http')) return path;
return baseUrl + path;
return toImageUrl(path);
};
// 获取用户信息(从接口获取)
@@ -193,6 +219,7 @@
userInfo.deptId = res.data.deptId || '';
userInfo.deptName = res.data.deptName || '';
userInfo.avatar = res.data.avatar || '';
userInfo.phone = res.data.phonenumber || res.data.phone || '';
// 获取角色信息
if (res.data.roles && res.data.roles.length > 0) {
userInfo.role = res.data.roles[0].roleKey || '';
@@ -212,49 +239,51 @@
userInfo.deptName = info.deptName || '';
userInfo.role = info.role || '';
userInfo.avatar = info.avatar || '';
userInfo.phone = info.phone || '';
}
} catch (storageError) {
console.error('从本地存储获取用户信息失败:', storageError);
}
}
};
const infoList = ref([{
const infoList = ref([
{
name: '成员管理',
src: '../../static/组 19378.png'
src: '/static/home_icon/chengyuangaunli.png'
},
{
name: '企业信息填报',
src: '../../static/组 19387.png'
name: '信息填报',
src: '/static/home_icon/xinxitianbao.png'
},
{
name: '区域设置',
src: '../../static/组 20253.png'
src: '/static/home_icon/quyushezhi.png'
},
{
name: '检查',
src: '../../static/组 20254.png'
name: '检查清单',
src: '/static/home_icon/jiachaqingdan.png'
},
{
name: '检查记录',
src: '../../static/组 20255.png'
src: '/static/home_icon/jianchajilu.png'
},
{
name: '证管理',
src: '../../static/组 20256.png'
name: '证管理',
src: '/static/home_icon/zhengjianguanli.png'
},
{
name: '隐患排查',
src: '../../static/组 20257.png'
src: '/static/home_icon/yinhuanpaicha.png'
},
{
name: '隐患销号申请',
src: '../../static/组 20258.png'
},
{
name: '设备登记',
src: '../../static/组 20259.png'
name: '隐患销号',
src: '/static/home_icon/yinhuanxiaohao.png'
}
// ,
// {
// name: '设备登记',
// src: '/static/home_icon/shebeidengji.png'
// }
]);
const ViewDetails = (item) => {
uni.navigateTo({
@@ -270,15 +299,14 @@
const handleMenuClick = (item) => {
const menuRoutes = {
'成员管理': '/pages/membermanagemen/membermanagemen',
'企业信息填报': '/pages/corporateInformation/corporateInformation',
'信息填报': '/pages/corporateInformation/corporateInformation',
'区域设置':'/pages/area/management',
'检查' :'/pages/checklist/checklist',
'检查清单' :'/pages/checklist/checklist',
'检查记录': '/pages/Inspectionlog/Inspectionlog',
'证管理': '/pages/Idphotomanagement/Idphotomanagement',
'证管理': '/pages/Idphotomanagement/Idphotomanagement',
'隐患排查':'/pages/hiddendanger/Inspection',
'隐患销号申请':'/pages/closeout/application',
'隐患销号':'/pages/closeout/application',
'设备登记':'/pages/equipmentregistration/equipmentregistration',
// 可以在这里添加其他菜单的跳转路径
};
const url = menuRoutes[item.name];
@@ -336,6 +364,24 @@
});
const hiddenDangerData = ref([]);
// 隐患排查 Tab 筛选
const dangerTabs = ref(['全部状态', '待验收', '待整改', '待交办', '验收通过']);
const activeDangerTab = ref(0);
// 切换 Tab
const switchDangerTab = (index) => {
activeDangerTab.value = index;
};
// 根据 Tab 过滤隐患数据
const filteredDangerData = computed(() => {
if (activeDangerTab.value === 0) {
return hiddenDangerData.value;
}
const status = dangerTabs.value[activeDangerTab.value];
return hiddenDangerData.value.filter(item => item.statusName === status);
});
const getHiddenDangerLists = async () => {
try {
const res = await getHiddenDangerList(hiddenDangerParams.value);
@@ -392,13 +438,97 @@
url: `/pages/hiddendanger/assignment?hazardId=${item.hazardId}&assignId=${item.assignId}`
})
}
// 切换账户
const switchAccount = () => {
uni.showToast({
title: '切换账户功能开发中',
icon: 'none'
});
}
</script>
<style lang="scss" scoped>
// ========== 顶部背景区域样式 ==========
.header-wrapper {
position: relative;
padding-bottom: 40rpx;
overflow: hidden;
// 蓝色底色
background-color: #2472EA;
}
// 渐变图片叠加在蓝色底色上
.header-bg-image {
position: absolute;
top: 2rpx; // 往下移动
left: 0;
width: 100%;
height: 100%;
z-index: 0;
opacity: 1.6;
}
// 用户信息卡片
.user-card {
position: relative;
z-index: 10;
display: flex;
align-items: center;
padding: 42rpx 30rpx 54rpx 30rpx; // 上42 右30 下54 左30
.user-avatar {
flex-shrink: 0;
width: 144rpx;
height: 144rpx;
border-radius: 50%;
overflow: hidden;
background: #fff;
}
.user-info {
flex: 1;
margin-left: 24rpx;
overflow: hidden;
max-width: 576rpx;
.user-dept {
font-size: 34rpx;
color: #fff;
font-weight: bold;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.user-phone {
font-size: 26rpx;
color: rgba(255, 255, 255, 0.9);
margin-top: 10rpx;
}
}
.switch-btn {
display: flex;
align-items: center;
background: #fff;
padding: 16rpx 24rpx;
border-radius: 30rpx;
color: #285CE9;
font-size: 26rpx;
flex-shrink: 0;
margin-left: 20rpx;
text {
margin-right: 8rpx;
}
}
}
.page-content {
background: #EBF2FC;
background: #F4F7FB;
border-radius: 40rpx 40rpx 0rpx 0rpx;
margin-top: -30rpx;
margin-top: -40rpx;
padding: 30rpx;
padding-bottom: 50rpx;
position: relative;
@@ -406,6 +536,42 @@
min-height: calc(100vh - 400rpx);
}
// ========== 功能菜单区域 ==========
.menu-card {
background: #fff;
border-radius: 40rpx 40rpx 0 0rpx;
padding: 44rpx 30rpx 30rpx 30rpx;
margin-left: -40rpx;
margin-right: -40rpx;
margin-top: -30rpx;
}
.menu-grid {
display: flex;
flex-wrap: wrap;
}
.menu-item {
width: 20%;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 38rpx;
.menu-icon {
width: 72rpx;
height: 80rpx;
}
.menu-text {
font-size: 24rpx;
color: #333;
margin-top: 14rpx;
text-align: center;
white-space: nowrap;
}
}
// 头像图片样式
.avatar-image {
width: 100%;
@@ -413,20 +579,6 @@
border-radius: 50%;
}
.grid-list {
gap: 30rpx;
margin-top: 30rpx;
}
.list {
background: #F2F6FF;
box-shadow: 0rpx 4rpx 8rpx 2rpx #CADDFC;
border-radius: 10rpx;
text-align: center;
padding: 20rpx 0;
}
.list-list {
background: #FFFFFF;
box-shadow: 0rpx 2rpx 6rpx 2rpx rgba(0, 0, 0, 0.08);
@@ -435,6 +587,67 @@
padding: 20rpx;
}
// ========== 检查计划卡片 ==========
.plan-card {
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0rpx 2rpx 6rpx 2rpx rgba(0, 0, 0, 0.06);
}
.plan-header {
background: linear-gradient(135deg, #4A90E2 0%, #2667E9 100%);
padding: 24rpx 30rpx;
display: flex;
align-items: center;
.plan-header-icon {
width: 36rpx;
height: 36rpx;
margin-right: 12rpx;
}
.plan-header-title {
color: #fff;
font-size: 30rpx;
font-weight: bold;
}
}
.plan-body {
padding: 24rpx 30rpx 10rpx 30rpx;
background: #fff;
}
.plan-stats {
display: flex;
background: #F5F7FA;
border-radius: 12rpx;
border: 1rpx solid #E8ECF0;
overflow: hidden;
.plan-stat-item {
flex: 1;
text-align: center;
padding: 20rpx 0;
border-right: 1rpx solid #E8ECF0;
&:last-child {
border-right: none;
}
}
.plan-stat-num {
font-size: 36rpx;
font-weight: bold;
}
.plan-stat-label {
font-size: 24rpx;
color: #666;
margin-top: 8rpx;
}
}
.border-tite {
width: 10rpx;
height: 32rpx;
@@ -499,4 +712,62 @@
border: 2rpx solid #FFA39E;
color: #F5222D;
}
// ========== 隐患排查 Tab 筛选栏 ==========
.danger-tab-scroll {
white-space: nowrap;
margin-bottom: 20rpx;
}
.danger-tab-list {
display: inline-flex;
gap: 42rpx;
margin-left: 10rpx;
}
.danger-tab-item {
font-size: 28rpx;
color: #666;
padding-bottom: 12rpx;
position: relative;
flex-shrink: 0;
}
.danger-tab-active {
font-weight: bold;
color: #2667E9 !important;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 40rpx;
height: 6rpx;
background: #2667E9;
border-radius: 3rpx;
}
}
// ========== 隐患卡片 ==========
.danger-card {
padding: 30rpx;
margin-bottom: 20rpx;
background: #FFFFFF;
box-shadow: 0rpx 6rpx 12rpx 2rpx #F1F5FE;
border-radius: 16rpx 16rpx 16rpx 16rpx;
border: 2rpx solid #EAECEF;
}
.danger-info-row {
font-size: 28rpx;
margin-top: 16rpx;
display: flex;
.text-gray {
white-space: nowrap;
flex-shrink: 0;
}
}
</style>