| | |
| | | <template> |
| | | <view class="inspection-page"> |
| | | <!-- 使用通用页面头部组件 --> |
| | | <PageHeader title="设备巡检" @back="goBack" /> |
| | | |
| | | <PageHeader title="巡检管理" |
| | | @back="goBack" /> |
| | | <!-- 统计信息卡片 --> |
| | | <view class="stats-cards"> |
| | | <view class="stat-card"> |
| | |
| | | <text class="stat-label">待巡检</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 巡检清单 --> |
| | | <view class="inspection-list" v-if="inspectionList.length > 0"> |
| | | <view v-for="(item, index) in inspectionList" :key="index"> |
| | | <view class="inspection-item" @click="startInspection(item)"> |
| | | <view class="inspection-list" |
| | | v-if="inspectionList.length > 0"> |
| | | <view v-for="(item, index) in inspectionList" |
| | | :key="index"> |
| | | <view class="inspection-item" |
| | | @click="startInspection(item)"> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="device-icon" :class="getStatusClass(item.status)"> |
| | | <up-icon :name="getStatusIcon(item.status)" size="16" color="#ffffff"></up-icon> |
| | | <view class="device-icon" |
| | | :class="getStatusClass(item.status)"> |
| | | <up-icon :name="getStatusIcon(item.status)" |
| | | size="16" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <view class="device-info"> |
| | | <text class="device-name">{{ item.deviceName }}</text> |
| | |
| | | </view> |
| | | </view> |
| | | <view class="status-tag"> |
| | | <u-tag :type="getTagType(item.status)" size="mini"> |
| | | <u-tag :type="getTagType(item.status)" |
| | | size="mini"> |
| | | {{ getStatusText(item.status) }} |
| | | </u-tag> |
| | | </view> |
| | | </view> |
| | | |
| | | <up-divider></up-divider> |
| | | |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">设备编号</text> |
| | |
| | | <text class="detail-label">负责人</text> |
| | | <text class="detail-value">{{ item.inspector || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row" v-if="item.status === 2"> |
| | | <view class="detail-row" |
| | | v-if="item.status === 2"> |
| | | <text class="detail-label">完成时间</text> |
| | | <text class="detail-value">{{ formatDateTime(item.completedTime) || '-' }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 操作按钮 --> |
| | | <view class="action-buttons"> |
| | | <u-button |
| | | type="primary" |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.status === 2" |
| | | @click.stop="startInspection(item)" |
| | | > |
| | | @click.stop="startInspection(item)"> |
| | | {{ item.status === 0 ? '开始巡检' : item.status === 1 ? '继续巡检' : '查看详情' }} |
| | | </u-button> |
| | | <u-button |
| | | type="success" |
| | | <u-button type="success" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.status !== 1" |
| | | @click.stop="scanQRCode(item)" |
| | | > |
| | | @click.stop="scanQRCode(item)"> |
| | | 扫码打卡 |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view v-else class="no-data"> |
| | | <up-empty mode="data" text="暂无巡检任务"></up-empty> |
| | | <view v-else |
| | | class="no-data"> |
| | | <up-empty mode="data" |
| | | text="暂无巡检任务"></up-empty> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, onMounted } from 'vue' |
| | | import { onShow } from '@dcloudio/uni-app' |
| | | import PageHeader from '@/components/PageHeader.vue' |
| | | import { ref, computed, onMounted } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | // import { getInspectionList } from '@/api/inspectionUpload/index' |
| | | import dayjs from 'dayjs' |
| | | import dayjs from "dayjs"; |
| | | |
| | | // 选中的日期 |
| | | const selectedDate = ref(Date.now()) |
| | | const selectedDate = ref(Date.now()); |
| | | |
| | | // 巡检清单数据 |
| | | const inspectionList = ref([]) |
| | | const inspectionList = ref([]); |
| | | |
| | | // 显示提示信息 |
| | | const showToast = (message) => { |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | // 计算统计数据 |
| | | const totalCount = computed(() => inspectionList.value.length) |
| | | const completedCount = computed(() => inspectionList.value.filter(item => item.status === 2).length) |
| | | const pendingCount = computed(() => inspectionList.value.filter(item => item.status === 0).length) |
| | | const totalCount = computed(() => inspectionList.value.length); |
| | | const completedCount = computed( |
| | | () => inspectionList.value.filter(item => item.status === 2).length |
| | | ); |
| | | const pendingCount = computed( |
| | | () => inspectionList.value.filter(item => item.status === 0).length |
| | | ); |
| | | |
| | | // 返回上一页 |
| | | const goBack = () => { |
| | | uni.navigateBack() |
| | | } |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // 日期格式化器 |
| | | const dateFormatter = (type, value) => { |
| | | if (type === 'year') { |
| | | return `${value}年` |
| | | if (type === "year") { |
| | | return `${value}年`; |
| | | } |
| | | if (type === 'month') { |
| | | return `${value}月` |
| | | if (type === "month") { |
| | | return `${value}月`; |
| | | } |
| | | if (type === 'day') { |
| | | return `${value}日` |
| | | if (type === "day") { |
| | | return `${value}日`; |
| | | } |
| | | return value |
| | | } |
| | | return value; |
| | | }; |
| | | |
| | | // 格式化日期 |
| | | const formatDate = (timestamp) => { |
| | | return dayjs(timestamp).format('YYYY年MM月DD日') |
| | | } |
| | | const formatDate = timestamp => { |
| | | return dayjs(timestamp).format("YYYY年MM月DD日"); |
| | | }; |
| | | |
| | | // 格式化日期时间 |
| | | const formatDateTime = (dateStr) => { |
| | | if (!dateStr) return '' |
| | | return dayjs(dateStr).format('MM-DD HH:mm') |
| | | } |
| | | const formatDateTime = dateStr => { |
| | | if (!dateStr) return ""; |
| | | return dayjs(dateStr).format("MM-DD HH:mm"); |
| | | }; |
| | | |
| | | // 日期改变事件 |
| | | const onDateChange = (value) => { |
| | | selectedDate.value = value.value |
| | | getList() |
| | | } |
| | | const onDateChange = value => { |
| | | selectedDate.value = value.value; |
| | | getList(); |
| | | }; |
| | | |
| | | // 获取状态样式类 |
| | | const getStatusClass = (status) => { |
| | | const getStatusClass = status => { |
| | | switch (status) { |
| | | case 0: return 'status-pending' |
| | | case 1: return 'status-progress' |
| | | case 2: return 'status-completed' |
| | | default: return 'status-pending' |
| | | case 0: |
| | | return "status-pending"; |
| | | case 1: |
| | | return "status-progress"; |
| | | case 2: |
| | | return "status-completed"; |
| | | default: |
| | | return "status-pending"; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 获取状态图标 |
| | | const getStatusIcon = (status) => { |
| | | const getStatusIcon = status => { |
| | | switch (status) { |
| | | case 0: return 'clock' |
| | | case 1: return 'play-circle' |
| | | case 2: return 'checkmark-circle' |
| | | default: return 'clock' |
| | | case 0: |
| | | return "clock"; |
| | | case 1: |
| | | return "play-circle"; |
| | | case 2: |
| | | return "checkmark-circle"; |
| | | default: |
| | | return "clock"; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 获取标签类型 |
| | | const getTagType = (status) => { |
| | | const getTagType = status => { |
| | | switch (status) { |
| | | case 0: return 'warning' |
| | | case 1: return 'primary' |
| | | case 2: return 'success' |
| | | default: return 'info' |
| | | case 0: |
| | | return "warning"; |
| | | case 1: |
| | | return "primary"; |
| | | case 2: |
| | | return "success"; |
| | | default: |
| | | return "info"; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 获取状态文本 |
| | | const getStatusText = (status) => { |
| | | const getStatusText = status => { |
| | | switch (status) { |
| | | case 0: return '待巡检' |
| | | case 1: return '巡检中' |
| | | case 2: return '已完成' |
| | | default: return '未知' |
| | | case 0: |
| | | return "待巡检"; |
| | | case 1: |
| | | return "巡检中"; |
| | | case 2: |
| | | return "已完成"; |
| | | default: |
| | | return "未知"; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 开始巡检 |
| | | const startInspection = (item) => { |
| | | const startInspection = item => { |
| | | // 存储当前巡检项目信息 |
| | | uni.setStorageSync('currentInspection', item) |
| | | uni.setStorageSync("currentInspection", item); |
| | | uni.navigateTo({ |
| | | url: '/pages/equipmentManagement/inspection/detail' |
| | | }) |
| | | } |
| | | url: "/pages/equipmentManagement/inspection/detail", |
| | | }); |
| | | }; |
| | | |
| | | // 扫码打卡 |
| | | const scanQRCode = (item) => { |
| | | const scanQRCode = item => { |
| | | uni.scanCode({ |
| | | success: (res) => { |
| | | console.log('扫码结果:', res) |
| | | success: res => { |
| | | console.log("扫码结果:", res); |
| | | // 验证二维码内容 |
| | | if (res.result.includes(item.deviceCode)) { |
| | | showToast('打卡成功') |
| | | showToast("打卡成功"); |
| | | // 更新打卡状态 |
| | | updateCheckInStatus(item.id) |
| | | updateCheckInStatus(item.id); |
| | | } else { |
| | | showToast('二维码不匹配,请扫描正确的设备二维码') |
| | | showToast("二维码不匹配,请扫描正确的设备二维码"); |
| | | } |
| | | }, |
| | | fail: (err) => { |
| | | console.log('扫码失败:', err) |
| | | showToast('扫码失败') |
| | | } |
| | | }) |
| | | } |
| | | fail: err => { |
| | | console.log("扫码失败:", err); |
| | | showToast("扫码失败"); |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // 更新打卡状态 |
| | | const updateCheckInStatus = (id) => { |
| | | const updateCheckInStatus = id => { |
| | | // 这里应该调用API更新打卡状态 |
| | | // 暂时模拟更新本地数据 |
| | | const item = inspectionList.value.find(item => item.id === id) |
| | | const item = inspectionList.value.find(item => item.id === id); |
| | | if (item) { |
| | | item.checkInTime = new Date().toISOString() |
| | | item.checkInTime = new Date().toISOString(); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 查询巡检清单 |
| | | const getList = () => { |
| | | uni.showLoading({ |
| | | title: '加载中...', |
| | | mask: true |
| | | }) |
| | | title: "加载中...", |
| | | mask: true, |
| | | }); |
| | | |
| | | const params = { |
| | | date: dayjs(selectedDate.value).format('YYYY-MM-DD') |
| | | } |
| | | date: dayjs(selectedDate.value).format("YYYY-MM-DD"), |
| | | }; |
| | | |
| | | // 模拟数据,实际应该调用API |
| | | setTimeout(() => { |
| | | inspectionList.value = [ |
| | | { |
| | | id: 1, |
| | | deviceName: '空压机A01', |
| | | deviceCode: 'KYJ-A01', |
| | | location: '生产车间A区', |
| | | inspectionTime: '08:00-09:00', |
| | | inspector: '张三', |
| | | deviceName: "空压机A01", |
| | | deviceCode: "KYJ-A01", |
| | | location: "生产车间A区", |
| | | inspectionTime: "08:00-09:00", |
| | | inspector: "张三", |
| | | status: 0, // 0:待巡检 1:巡检中 2:已完成 |
| | | completedTime: null |
| | | completedTime: null, |
| | | }, |
| | | { |
| | | id: 2, |
| | | deviceName: '冷却塔B02', |
| | | deviceCode: 'LQT-B02', |
| | | location: '生产车间B区', |
| | | inspectionTime: '09:00-10:00', |
| | | inspector: '李四', |
| | | deviceName: "冷却塔B02", |
| | | deviceCode: "LQT-B02", |
| | | location: "生产车间B区", |
| | | inspectionTime: "09:00-10:00", |
| | | inspector: "李四", |
| | | status: 1, |
| | | completedTime: null |
| | | completedTime: null, |
| | | }, |
| | | { |
| | | id: 3, |
| | | deviceName: '变压器C03', |
| | | deviceCode: 'BYQ-C03', |
| | | location: '配电房', |
| | | inspectionTime: '10:00-11:00', |
| | | inspector: '王五', |
| | | deviceName: "变压器C03", |
| | | deviceCode: "BYQ-C03", |
| | | location: "配电房", |
| | | inspectionTime: "10:00-11:00", |
| | | inspector: "王五", |
| | | status: 2, |
| | | completedTime: '2024-01-15T10:30:00' |
| | | } |
| | | ] |
| | | uni.hideLoading() |
| | | }, 1000) |
| | | completedTime: "2024-01-15T10:30:00", |
| | | }, |
| | | ]; |
| | | uni.hideLoading(); |
| | | }, 1000); |
| | | |
| | | // 实际API调用 |
| | | // getInspectionList(params) |
| | |
| | | // uni.hideLoading() |
| | | // showToast('获取数据失败') |
| | | // }) |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | }) |
| | | getList(); |
| | | }); |
| | | |
| | | onShow(() => { |
| | | getList() |
| | | }) |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/styles/sales-common.scss'; |
| | | @import "@/styles/sales-common.scss"; |
| | | |
| | | .inspection-page { |
| | | background: #ffffff; |
| | | min-height: 100vh; |
| | | padding-bottom: 20px; |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | .stats-cards { |
| | | display: flex; |