feat: Batch 3 - business pages (19 pages)
Agent Loop: 3 agents, all passed iteration 1 - 7 report/problem pages (flooded/inspection/equipment/supervise/project/construction) - 6 supervisor+records pages - 6 equipment+records pages
This commit is contained in:
@@ -210,6 +210,162 @@ const routes: RouteRecordRaw[] = [
|
|||||||
title: '养护检查',
|
title: '养护检查',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/maintenanceCheckRecords',
|
||||||
|
name: 'MaintenanceCheckRecords',
|
||||||
|
component: () => import('@/views/maintenanceCheckRecords/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '养护检查记录',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/maintenanceCheckRecords/detail',
|
||||||
|
name: 'MaintenanceCheckRecordsDetail',
|
||||||
|
component: () => import('@/views/maintenanceCheckRecords/detail.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '检查记录详情',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// ── 第三方监督模块 ──
|
||||||
|
{
|
||||||
|
path: '/supervisor',
|
||||||
|
name: 'Supervisor',
|
||||||
|
component: () => import('@/views/supervisor/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '第三方监督人员',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/supervisor/detail',
|
||||||
|
name: 'SupervisorDetail',
|
||||||
|
component: () => import('@/views/supervisor/detail.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '人员详情',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/superviseRecord',
|
||||||
|
name: 'SuperviseRecord',
|
||||||
|
component: () => import('@/views/superviseRecord/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '监督记录',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/superviseRecord/detail',
|
||||||
|
name: 'SuperviseRecordDetail',
|
||||||
|
component: () => import('@/views/superviseRecord/detail.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '记录详情',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// ── 监测设备模块 ──
|
||||||
|
{
|
||||||
|
path: '/monitoringEquipment/:type?',
|
||||||
|
name: 'MonitoringEquipment',
|
||||||
|
component: () => import('@/views/monitoringEquipment/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '监测设备',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/equipmentInfo',
|
||||||
|
name: 'EquipmentInfo',
|
||||||
|
component: () => import('@/views/monitoringEquipment/equipmentInfo.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '设备详情',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/mapMonitoring',
|
||||||
|
name: 'MapMonitoring',
|
||||||
|
component: () => import('@/views/monitoringEquipment/mapMonitoring.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '地图监控',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/monitoringDetail',
|
||||||
|
name: 'MonitoringDetail',
|
||||||
|
component: () => import('@/views/monitoringEquipment/monitoringDetail.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '监测详情',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// ── 有限空间作业记录模块 ──
|
||||||
|
{
|
||||||
|
path: '/yxkjzyRecords',
|
||||||
|
name: 'YxkjzyRecords',
|
||||||
|
component: () => import('@/views/yxkjzyRecords/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '有限空间作业记录',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/yxkjzyRecordsDetail/:detail?',
|
||||||
|
name: 'YxkjzyRecordsDetail',
|
||||||
|
component: () => import('@/views/yxkjzyRecords/detail.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '作业记录详情',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// ── 问题上报模块 ──
|
||||||
|
{
|
||||||
|
path: '/problemReport',
|
||||||
|
name: 'ProblemReport',
|
||||||
|
component: () => import('@/views/problemReport/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '问题上报',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/reportFloodedPoints',
|
||||||
|
name: 'ReportFloodedPoints',
|
||||||
|
component: () => import('@/views/problemReport/reportFloodedPoints.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '积淹点上报',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/reportInspection',
|
||||||
|
name: 'ReportInspection',
|
||||||
|
component: () => import('@/views/problemReport/reportInspection.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '巡检问题上报',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/reportEquipmentRepair',
|
||||||
|
name: 'ReportEquipmentRepair',
|
||||||
|
component: () => import('@/views/problemReport/reportEquipmentRepair.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '设备报修',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/reportSupervise/:detail?',
|
||||||
|
name: 'ReportSupervise',
|
||||||
|
component: () => import('@/views/problemReport/reportSupervise.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '督办问题上报',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/reportProject/:detail?',
|
||||||
|
name: 'ReportProject',
|
||||||
|
component: () => import('@/views/problemReport/reportProject.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '项目问题上报',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/reportConstruction/:detail?',
|
||||||
|
name: 'ReportConstruction',
|
||||||
|
component: () => import('@/views/problemReport/reportConstruction.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '施工问题上报',
|
||||||
|
},
|
||||||
|
},
|
||||||
// 404 兜底
|
// 404 兜底
|
||||||
{
|
{
|
||||||
path: '/:pathMatch(.*)*',
|
path: '/:pathMatch(.*)*',
|
||||||
|
|||||||
219
src/views/maintenanceCheckRecords/detail.vue
Normal file
219
src/views/maintenanceCheckRecords/detail.vue
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* 养护检查记录详情页
|
||||||
|
*
|
||||||
|
* 展示检查记录的详细信息,包含基本信息、评分详情、检查内容、照片和结论。
|
||||||
|
*/
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
|
import { showImagePreview } from 'vant'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
const detailId = (route.query.id as string) || '1'
|
||||||
|
|
||||||
|
/** 模拟检查记录详情 */
|
||||||
|
const record = ref({
|
||||||
|
id: detailId,
|
||||||
|
project: '城北供水管网养护',
|
||||||
|
inspector: '张检查员',
|
||||||
|
result: 'qualified',
|
||||||
|
score: 95,
|
||||||
|
date: '2025-06-15',
|
||||||
|
time: '14:00 - 16:30',
|
||||||
|
address: '城北工业大道1-50号',
|
||||||
|
content: '对城北片区供水管网养护工作进行验收检查,检查内容包括管道冲洗效果、阀门润滑情况、井盖完整性等。',
|
||||||
|
conclusion: '养护工作总体良好,各项指标达标,同意验收。',
|
||||||
|
remark: '建议加强井盖周围杂草清理。',
|
||||||
|
createTime: '2025-06-15 17:00:00',
|
||||||
|
scoreDetail: [
|
||||||
|
{ name: '管道冲洗', score: 18, maxScore: 20 },
|
||||||
|
{ name: '阀门润滑', score: 19, maxScore: 20 },
|
||||||
|
{ name: '井盖检查', score: 20, maxScore: 20 },
|
||||||
|
{ name: '防腐处理', score: 19, maxScore: 20 },
|
||||||
|
{ name: '安全措施', score: 19, maxScore: 20 },
|
||||||
|
],
|
||||||
|
photos: [
|
||||||
|
{ id: 1, url: 'https://via.placeholder.com/400x300/4CAF50/white?text=Check+1', desc: '管道冲洗效果' },
|
||||||
|
{ id: 2, url: 'https://via.placeholder.com/400x300/2196F3/white?text=Check+2', desc: '阀门润滑情况' },
|
||||||
|
{ id: 3, url: 'https://via.placeholder.com/400x300/FF9800/white?text=Check+3', desc: '井盖完整性' },
|
||||||
|
{ id: 4, url: 'https://via.placeholder.com/400x300/9C27B0/white?text=Check+4', desc: '现场安全措施' },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultMap: Record<string, string> = {
|
||||||
|
qualified: '合格',
|
||||||
|
unqualified: '不合格',
|
||||||
|
}
|
||||||
|
|
||||||
|
const resultColorMap: Record<string, 'success' | 'danger'> = {
|
||||||
|
qualified: 'success',
|
||||||
|
unqualified: 'danger',
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 评分颜色 */
|
||||||
|
function scoreColor(score: number): string {
|
||||||
|
if (score >= 90) return '#4CAF50'
|
||||||
|
if (score >= 70) return '#FF9800'
|
||||||
|
return '#F44336'
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 单项评分颜色 */
|
||||||
|
function itemScoreColor(score: number, maxScore: number): string {
|
||||||
|
const ratio = score / maxScore
|
||||||
|
if (ratio >= 0.9) return '#4CAF50'
|
||||||
|
if (ratio >= 0.7) return '#FF9800'
|
||||||
|
return '#F44336'
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 预览照片 */
|
||||||
|
function previewPhoto(index: number) {
|
||||||
|
showImagePreview({
|
||||||
|
images: record.value.photos.map(p => p.url),
|
||||||
|
startPosition: index,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="check-detail-page">
|
||||||
|
<van-nav-bar title="检查记录详情" left-text="返回" left-arrow fixed placeholder @click-left="router.back()" />
|
||||||
|
|
||||||
|
<!-- 结果与评分 -->
|
||||||
|
<div class="result-bar">
|
||||||
|
<van-tag :type="resultColorMap[record.result]" size="large">
|
||||||
|
{{ resultMap[record.result] }}
|
||||||
|
</van-tag>
|
||||||
|
<div class="total-score" :style="{ color: scoreColor(record.score) }">
|
||||||
|
{{ record.score }} 分
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 基本信息 -->
|
||||||
|
<van-cell-group title="基本信息" class="info-group">
|
||||||
|
<van-cell title="检查项目" :value="record.project" />
|
||||||
|
<van-cell title="检查员" :value="record.inspector" />
|
||||||
|
<van-cell title="检查日期" :value="record.date" />
|
||||||
|
<van-cell title="检查时间" :value="record.time" />
|
||||||
|
<van-cell title="检查地址" :value="record.address" />
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 评分详情 -->
|
||||||
|
<van-cell-group title="评分详情" class="info-group">
|
||||||
|
<van-cell v-for="item in record.scoreDetail" :key="item.name" :title="item.name">
|
||||||
|
<template #value>
|
||||||
|
<span :style="{ color: itemScoreColor(item.score, item.maxScore), fontWeight: 'bold' }">
|
||||||
|
{{ item.score }} / {{ item.maxScore }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</van-cell>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 检查内容 -->
|
||||||
|
<van-cell-group title="检查内容" class="info-group">
|
||||||
|
<van-cell>
|
||||||
|
<p class="desc-text">{{ record.content }}</p>
|
||||||
|
</van-cell>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 现场照片 -->
|
||||||
|
<van-cell-group title="现场照片" class="info-group">
|
||||||
|
<van-cell>
|
||||||
|
<div class="photo-grid">
|
||||||
|
<div
|
||||||
|
v-for="(photo, index) in record.photos"
|
||||||
|
:key="photo.id"
|
||||||
|
class="photo-item"
|
||||||
|
@click="previewPhoto(index)"
|
||||||
|
>
|
||||||
|
<van-image
|
||||||
|
:src="photo.url"
|
||||||
|
width="100%"
|
||||||
|
height="100"
|
||||||
|
fit="cover"
|
||||||
|
radius="6"
|
||||||
|
/>
|
||||||
|
<p class="photo-desc">{{ photo.desc }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</van-cell>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 结论与备注 -->
|
||||||
|
<van-cell-group title="检查结论" class="info-group">
|
||||||
|
<van-cell>
|
||||||
|
<p class="desc-text">{{ record.conclusion }}</p>
|
||||||
|
</van-cell>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<van-cell-group title="备注" class="info-group">
|
||||||
|
<van-cell>
|
||||||
|
<p class="desc-text">{{ record.remark }}</p>
|
||||||
|
</van-cell>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 时间信息 -->
|
||||||
|
<van-cell-group title="时间信息" class="info-group">
|
||||||
|
<van-cell title="创建时间" :value="record.createTime" />
|
||||||
|
</van-cell-group>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.check-detail-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--color-bg-page);
|
||||||
|
padding-bottom: 24px;
|
||||||
|
|
||||||
|
:deep(.van-nav-bar) {
|
||||||
|
background: var(--color-primary);
|
||||||
|
--van-nav-bar-title-text-color: #fff;
|
||||||
|
--van-nav-bar-text-color: #fff;
|
||||||
|
--van-nav-bar-icon-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-bar {
|
||||||
|
padding: 12px 16px;
|
||||||
|
background: var(--color-bg-card);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-score {
|
||||||
|
margin-top: 8px;
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-group {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desc-text {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: var(--color-text-regular);
|
||||||
|
padding: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-item {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-desc {
|
||||||
|
margin: 4px 0 0 0;
|
||||||
|
font-size: 11px;
|
||||||
|
color: var(--color-text-placeholder);
|
||||||
|
text-align: center;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
142
src/views/maintenanceCheckRecords/index.vue
Normal file
142
src/views/maintenanceCheckRecords/index.vue
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* 养护检查记录列表页
|
||||||
|
*
|
||||||
|
* 展示养护检查记录,支持搜索和结果筛选(全部/合格/不合格),
|
||||||
|
* 卡片中显示评分,点击跳转检查记录详情。
|
||||||
|
*/
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
/** 搜索关键词 */
|
||||||
|
const searchText = ref('')
|
||||||
|
|
||||||
|
/** 当前激活的 Tab */
|
||||||
|
const activeTab = ref(0)
|
||||||
|
|
||||||
|
/** 模拟检查记录数据 */
|
||||||
|
const mockCheckRecords = [
|
||||||
|
{ id: 1, project: '城北供水管网养护', inspector: '张检查员', result: 'qualified', score: 95, date: '2025-06-15', content: '管道冲洗、阀门润滑、井盖检查' },
|
||||||
|
{ id: 2, project: '高新区阀门养护', inspector: '李检查员', result: 'unqualified', score: 58, date: '2025-06-14', content: '部分阀门操作卡涩,需重新养护' },
|
||||||
|
{ id: 3, project: '老城区水表更换', inspector: '王检查员', result: 'qualified', score: 88, date: '2025-06-13', content: '水表安装规范,计量准确' },
|
||||||
|
{ id: 4, project: '商业区消防栓检查', inspector: '赵检查员', result: 'qualified', score: 92, date: '2025-06-12', content: '消防栓出水正常,压力达标' },
|
||||||
|
{ id: 5, project: '东区泵站养护', inspector: '孙检查员', result: 'unqualified', score: 62, date: '2025-06-11', content: '泵站噪音超标,需维修后复查' },
|
||||||
|
]
|
||||||
|
|
||||||
|
/** 结果映射 */
|
||||||
|
const resultMap: Record<string, string> = {
|
||||||
|
qualified: '合格',
|
||||||
|
unqualified: '不合格',
|
||||||
|
}
|
||||||
|
|
||||||
|
const resultColorMap: Record<string, 'success' | 'danger'> = {
|
||||||
|
qualified: 'success',
|
||||||
|
unqualified: 'danger',
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 评分颜色 */
|
||||||
|
function scoreColor(score: number): string {
|
||||||
|
if (score >= 90) return '#4CAF50'
|
||||||
|
if (score >= 70) return '#FF9800'
|
||||||
|
return '#F44336'
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 筛选后的记录列表 */
|
||||||
|
const filteredRecords = computed(() => {
|
||||||
|
let list = mockCheckRecords
|
||||||
|
if (searchText.value) {
|
||||||
|
const kw = searchText.value.toLowerCase()
|
||||||
|
list = list.filter(r =>
|
||||||
|
r.project.toLowerCase().includes(kw) ||
|
||||||
|
r.inspector.toLowerCase().includes(kw) ||
|
||||||
|
r.content.toLowerCase().includes(kw)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (activeTab.value === 1) list = list.filter(r => r.result === 'qualified')
|
||||||
|
else if (activeTab.value === 2) list = list.filter(r => r.result === 'unqualified')
|
||||||
|
return list
|
||||||
|
})
|
||||||
|
|
||||||
|
/** 跳转详情 */
|
||||||
|
function goDetail(id: number) {
|
||||||
|
router.push(`/maintenanceCheckRecords/detail?id=${id}`)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="check-records-page">
|
||||||
|
<van-nav-bar title="养护检查记录" left-arrow fixed placeholder @click-left="router.back()" />
|
||||||
|
|
||||||
|
<van-search v-model="searchText" placeholder="搜索项目、检查员、内容" shape="round" />
|
||||||
|
|
||||||
|
<van-tabs v-model:active="activeTab" sticky>
|
||||||
|
<van-tab title="全部" />
|
||||||
|
<van-tab title="合格" />
|
||||||
|
<van-tab title="不合格" />
|
||||||
|
</van-tabs>
|
||||||
|
|
||||||
|
<div class="record-list">
|
||||||
|
<van-empty v-if="filteredRecords.length === 0" description="暂无检查记录" />
|
||||||
|
<van-card
|
||||||
|
v-for="record in filteredRecords"
|
||||||
|
:key="record.id"
|
||||||
|
:title="record.project"
|
||||||
|
:desc="`检查员: ${record.inspector}`"
|
||||||
|
@click="goDetail(record.id)"
|
||||||
|
>
|
||||||
|
<template #tags>
|
||||||
|
<van-tag :type="resultColorMap[record.result]" size="medium">
|
||||||
|
{{ resultMap[record.result] }}
|
||||||
|
</van-tag>
|
||||||
|
<van-tag size="medium" :color="scoreColor(record.score)" text-color="#fff">
|
||||||
|
{{ record.score }} 分
|
||||||
|
</van-tag>
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<div class="record-meta">
|
||||||
|
<span>{{ record.date }}</span>
|
||||||
|
<span>{{ record.content }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</van-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.check-records-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--color-bg-page);
|
||||||
|
|
||||||
|
:deep(.van-nav-bar) {
|
||||||
|
background: var(--color-primary);
|
||||||
|
--van-nav-bar-title-text-color: #fff;
|
||||||
|
--van-nav-bar-text-color: #fff;
|
||||||
|
--van-nav-bar-icon-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-list {
|
||||||
|
padding: 0 8px;
|
||||||
|
|
||||||
|
:deep(.van-card) {
|
||||||
|
margin: 8px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: var(--color-bg-card);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.van-tag) {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-meta {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
133
src/views/monitoringEquipment/equipmentInfo.vue
Normal file
133
src/views/monitoringEquipment/equipmentInfo.vue
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* 设备详情页
|
||||||
|
*
|
||||||
|
* 展示监测设备的详细信息,包含基本参数、运行状态、
|
||||||
|
* 最新数据和维护记录。
|
||||||
|
*/
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
const detailId = (route.query.id as string) || '1'
|
||||||
|
|
||||||
|
/** 模拟设备详情 */
|
||||||
|
const equipment = ref({
|
||||||
|
id: detailId,
|
||||||
|
name: '流量监测仪 A-01',
|
||||||
|
type: 'flow_meter',
|
||||||
|
typeLabel: '流量计',
|
||||||
|
model: 'LDG-200S',
|
||||||
|
sn: 'SN2024LDG00201',
|
||||||
|
status: 'normal',
|
||||||
|
location: '城北供水管网1号节点',
|
||||||
|
installDate: '2025-01-15',
|
||||||
|
manufacturer: '南方测控科技有限公司',
|
||||||
|
range: '0-500 m³/h',
|
||||||
|
precision: '±0.5%',
|
||||||
|
protocol: 'Modbus RTU',
|
||||||
|
ipRating: 'IP68',
|
||||||
|
lastData: '125.6 m³/h',
|
||||||
|
lastUpdateTime: '2025-06-15 08:30:00',
|
||||||
|
batteryLevel: 85,
|
||||||
|
signalStrength: 92,
|
||||||
|
maintenanceRecords: [
|
||||||
|
{ date: '2025-05-20', type: '定期巡检', result: '正常', operator: '张维护员' },
|
||||||
|
{ date: '2025-04-15', type: '校准', result: '合格', operator: '李技术员' },
|
||||||
|
{ date: '2025-03-10', type: '电池更换', result: '已完成', operator: '王工程师' },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const statusMap: Record<string, string> = {
|
||||||
|
normal: '正常',
|
||||||
|
alarm: '报警',
|
||||||
|
offline: '离线',
|
||||||
|
}
|
||||||
|
|
||||||
|
const statusColorMap: Record<string, string> = {
|
||||||
|
normal: 'success',
|
||||||
|
alarm: 'danger',
|
||||||
|
offline: '#999',
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="equipment-detail-page">
|
||||||
|
<van-nav-bar title="设备详情" left-text="返回" left-arrow fixed placeholder @click-left="router.back()" />
|
||||||
|
|
||||||
|
<!-- 状态标签 -->
|
||||||
|
<div class="status-bar">
|
||||||
|
<van-tag :type="statusColorMap[equipment.status] as never" size="large">
|
||||||
|
{{ statusMap[equipment.status] }}
|
||||||
|
</van-tag>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 基本信息 -->
|
||||||
|
<van-cell-group title="基本信息" class="info-group">
|
||||||
|
<van-cell title="设备名称" :value="equipment.name" />
|
||||||
|
<van-cell title="设备类型" :value="equipment.typeLabel" />
|
||||||
|
<van-cell title="设备型号" :value="equipment.model" />
|
||||||
|
<van-cell title="设备编号" :value="equipment.sn" />
|
||||||
|
<van-cell title="安装位置" :value="equipment.location" />
|
||||||
|
<van-cell title="安装日期" :value="equipment.installDate" />
|
||||||
|
<van-cell title="生产厂家" :value="equipment.manufacturer" />
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 技术参数 -->
|
||||||
|
<van-cell-group title="技术参数" class="info-group">
|
||||||
|
<van-cell title="量程范围" :value="equipment.range" />
|
||||||
|
<van-cell title="精度等级" :value="equipment.precision" />
|
||||||
|
<van-cell title="通信协议" :value="equipment.protocol" />
|
||||||
|
<van-cell title="防护等级" :value="equipment.ipRating" />
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 运行数据 -->
|
||||||
|
<van-cell-group title="运行数据" class="info-group">
|
||||||
|
<van-cell title="最新数据" :value="equipment.lastData" />
|
||||||
|
<van-cell title="更新时间" :value="equipment.lastUpdateTime" />
|
||||||
|
<van-cell title="电池电量" :value="`${equipment.batteryLevel}%`" />
|
||||||
|
<van-cell title="信号强度" :value="`${equipment.signalStrength}%`" />
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 维护记录 -->
|
||||||
|
<van-cell-group title="维护记录" class="info-group">
|
||||||
|
<van-cell v-for="(record, idx) in equipment.maintenanceRecords" :key="idx" :title="record.date">
|
||||||
|
<template #label>
|
||||||
|
<span>{{ record.type }} - {{ record.operator }}</span>
|
||||||
|
</template>
|
||||||
|
<template #value>
|
||||||
|
<van-tag :type="record.result === '正常' || record.result === '合格' || record.result === '已完成' ? 'success' : 'warning'" size="medium">
|
||||||
|
{{ record.result }}
|
||||||
|
</van-tag>
|
||||||
|
</template>
|
||||||
|
</van-cell>
|
||||||
|
</van-cell-group>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.equipment-detail-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--color-bg-page);
|
||||||
|
padding-bottom: 24px;
|
||||||
|
|
||||||
|
:deep(.van-nav-bar) {
|
||||||
|
background: var(--color-primary);
|
||||||
|
--van-nav-bar-title-text-color: #fff;
|
||||||
|
--van-nav-bar-text-color: #fff;
|
||||||
|
--van-nav-bar-icon-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-bar {
|
||||||
|
padding: 12px 16px;
|
||||||
|
background: var(--color-bg-card);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-group {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
169
src/views/monitoringEquipment/index.vue
Normal file
169
src/views/monitoringEquipment/index.vue
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* 监测设备列表页
|
||||||
|
*
|
||||||
|
* 展示监测设备列表,支持搜索和类型筛选,
|
||||||
|
* 点击卡片跳转设备详情,可进入地图监控和监测详情。
|
||||||
|
*/
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
/** 搜索关键词 */
|
||||||
|
const searchText = ref('')
|
||||||
|
|
||||||
|
/** 当前激活的 Tab */
|
||||||
|
const activeTab = ref(0)
|
||||||
|
|
||||||
|
/** 模拟监测设备数据 */
|
||||||
|
const mockEquipments = [
|
||||||
|
{ id: 1, name: '流量监测仪 A-01', type: 'flow_meter', typeLabel: '流量计', status: 'normal', location: '城北供水管网1号节点', lastData: '125.6 m³/h', updateTime: '2025-06-15 08:30' },
|
||||||
|
{ id: 2, name: '压力传感器 P-03', type: 'pressure_sensor', typeLabel: '压力传感器', status: 'alarm', location: '高新区主管网3号泵站', lastData: '0.85 MPa', updateTime: '2025-06-15 08:25' },
|
||||||
|
{ id: 3, name: '水质监测仪 W-07', type: 'water_quality', typeLabel: '水质监测仪', status: 'normal', location: '老城区饮用水源口', lastData: 'pH 7.2 / 浊度 0.5NTU', updateTime: '2025-06-15 08:28' },
|
||||||
|
{ id: 4, name: '液位计 L-02', type: 'liquid_level', typeLabel: '液位计', status: 'offline', location: '东区蓄水池2号', lastData: '3.2 m', updateTime: '2025-06-14 22:00' },
|
||||||
|
{ id: 5, name: '流量监测仪 A-05', type: 'flow_meter', typeLabel: '流量计', status: 'normal', location: '商业区供水管网12号', lastData: '98.3 m³/h', updateTime: '2025-06-15 08:32' },
|
||||||
|
{ id: 6, name: '水质监测仪 W-02', type: 'water_quality', typeLabel: '水质监测仪', status: 'alarm', location: '南城污水处理厂出水口', lastData: 'COD 85mg/L (超标)', updateTime: '2025-06-15 08:20' },
|
||||||
|
{ id: 7, name: '压力传感器 P-07', type: 'pressure_sensor', typeLabel: '压力传感器', status: 'normal', location: '城西加压站', lastData: '0.62 MPa', updateTime: '2025-06-15 08:31' },
|
||||||
|
{ id: 8, name: '液位计 L-05', type: 'liquid_level', typeLabel: '液位计', status: 'offline', location: '北区污水井5号', lastData: '1.8 m', updateTime: '2025-06-14 18:00' },
|
||||||
|
]
|
||||||
|
|
||||||
|
/** 状态映射 */
|
||||||
|
const statusMap: Record<string, string> = {
|
||||||
|
normal: '正常',
|
||||||
|
alarm: '报警',
|
||||||
|
offline: '离线',
|
||||||
|
}
|
||||||
|
|
||||||
|
const statusColorMap: Record<string, string> = {
|
||||||
|
normal: 'success',
|
||||||
|
alarm: 'danger',
|
||||||
|
offline: '#999',
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 类型 Tab 映射 */
|
||||||
|
const typeTabs = ['全部', '流量计', '压力传感器', '水质监测仪', '液位计']
|
||||||
|
const typeKeys = ['', 'flow_meter', 'pressure_sensor', 'water_quality', 'liquid_level']
|
||||||
|
|
||||||
|
/** 筛选后的列表 */
|
||||||
|
const filteredEquipments = computed(() => {
|
||||||
|
let list = mockEquipments
|
||||||
|
if (searchText.value) {
|
||||||
|
const kw = searchText.value.toLowerCase()
|
||||||
|
list = list.filter(e =>
|
||||||
|
e.name.toLowerCase().includes(kw) ||
|
||||||
|
e.typeLabel.toLowerCase().includes(kw) ||
|
||||||
|
e.location.toLowerCase().includes(kw)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (activeTab.value > 0 && typeKeys[activeTab.value]) {
|
||||||
|
list = list.filter(e => e.type === typeKeys[activeTab.value])
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
})
|
||||||
|
|
||||||
|
/** 跳转设备详情 */
|
||||||
|
function goEquipmentInfo(id: number) {
|
||||||
|
router.push(`/equipmentInfo?id=${id}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 跳转地图监控 */
|
||||||
|
function goMapMonitoring() {
|
||||||
|
router.push('/mapMonitoring')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="equipment-page">
|
||||||
|
<van-nav-bar
|
||||||
|
title="监测设备"
|
||||||
|
left-arrow fixed placeholder
|
||||||
|
@click-left="router.back()"
|
||||||
|
>
|
||||||
|
<template #right>
|
||||||
|
<van-icon name="map-marked" size="20" @click="goMapMonitoring" />
|
||||||
|
</template>
|
||||||
|
</van-nav-bar>
|
||||||
|
|
||||||
|
<van-search v-model="searchText" placeholder="搜索设备名称、类型、位置" shape="round" />
|
||||||
|
|
||||||
|
<van-tabs v-model:active="activeTab" sticky scrollspy>
|
||||||
|
<van-tab v-for="(tab, idx) in typeTabs" :key="idx" :title="tab" />
|
||||||
|
</van-tabs>
|
||||||
|
|
||||||
|
<div class="equipment-list">
|
||||||
|
<van-empty v-if="filteredEquipments.length === 0" description="暂无监测设备" />
|
||||||
|
<van-card
|
||||||
|
v-for="equip in filteredEquipments"
|
||||||
|
:key="equip.id"
|
||||||
|
:title="equip.name"
|
||||||
|
:desc="`类型: ${equip.typeLabel}`"
|
||||||
|
@click="goEquipmentInfo(equip.id)"
|
||||||
|
>
|
||||||
|
<template #tags>
|
||||||
|
<van-tag :color="statusColorMap[equip.status]" text-color="#fff" size="medium" v-if="equip.status !== 'normal'">
|
||||||
|
{{ statusMap[equip.status] }}
|
||||||
|
</van-tag>
|
||||||
|
<van-tag type="success" size="medium" v-else>
|
||||||
|
{{ statusMap[equip.status] }}
|
||||||
|
</van-tag>
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<div class="equipment-meta">
|
||||||
|
<span class="meta-location">{{ equip.location }}</span>
|
||||||
|
<span class="meta-data">最新数据: {{ equip.lastData }}</span>
|
||||||
|
<span class="meta-time">更新时间: {{ equip.updateTime }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</van-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.equipment-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--color-bg-page);
|
||||||
|
|
||||||
|
:deep(.van-nav-bar) {
|
||||||
|
background: var(--color-primary);
|
||||||
|
--van-nav-bar-title-text-color: #fff;
|
||||||
|
--van-nav-bar-text-color: #fff;
|
||||||
|
--van-nav-bar-icon-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.equipment-list {
|
||||||
|
padding: 0 8px;
|
||||||
|
|
||||||
|
:deep(.van-card) {
|
||||||
|
margin: 8px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: var(--color-bg-card);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.van-tag) {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.equipment-meta {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
|
||||||
|
.meta-location {
|
||||||
|
color: var(--color-text-regular);
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-data {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-time {
|
||||||
|
color: var(--color-text-placeholder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
172
src/views/monitoringEquipment/mapMonitoring.vue
Normal file
172
src/views/monitoringEquipment/mapMonitoring.vue
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* 地图监控页
|
||||||
|
*
|
||||||
|
* 在地图上展示监测设备位置和状态,
|
||||||
|
* 可点击设备查看实时数据。
|
||||||
|
*/
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
/** 地图加载状态 */
|
||||||
|
const mapLoaded = ref(false)
|
||||||
|
|
||||||
|
/** 模拟设备点位 */
|
||||||
|
const devicePoints = ref([
|
||||||
|
{ id: 1, name: '流量监测仪 A-01', status: 'normal', lat: 30.5, lng: 104.0 },
|
||||||
|
{ id: 2, name: '压力传感器 P-03', status: 'alarm', lat: 30.51, lng: 104.02 },
|
||||||
|
{ id: 3, name: '水质监测仪 W-07', status: 'normal', lat: 30.48, lng: 103.98 },
|
||||||
|
{ id: 4, name: '液位计 L-02', status: 'offline', lat: 30.52, lng: 104.05 },
|
||||||
|
])
|
||||||
|
|
||||||
|
const statusColorMap: Record<string, string> = {
|
||||||
|
normal: '#4CAF50',
|
||||||
|
alarm: '#F44336',
|
||||||
|
offline: '#999',
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 跳转设备详情 */
|
||||||
|
function goEquipmentInfo(id: number) {
|
||||||
|
router.push(`/equipmentInfo?id=${id}`)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="map-monitoring-page">
|
||||||
|
<van-nav-bar title="地图监控" left-text="返回" left-arrow fixed placeholder @click-left="router.back()" />
|
||||||
|
|
||||||
|
<!-- 地图占位区 -->
|
||||||
|
<div class="map-placeholder">
|
||||||
|
<van-icon name="location-o" size="48" color="#ccc" />
|
||||||
|
<p class="map-title">地图监控</p>
|
||||||
|
<p class="map-hint">设备点位将在此地图上展示</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 设备点位列表面板(底部浮动) -->
|
||||||
|
<div class="device-panel">
|
||||||
|
<div class="panel-header">
|
||||||
|
<span class="panel-title">设备列表</span>
|
||||||
|
<span class="panel-count">共 {{ devicePoints.length }} 台</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-for="point in devicePoints"
|
||||||
|
:key="point.id"
|
||||||
|
class="device-item"
|
||||||
|
@click="goEquipmentInfo(point.id)"
|
||||||
|
>
|
||||||
|
<div class="device-dot" :style="{ backgroundColor: statusColorMap[point.status] }" />
|
||||||
|
<div class="device-info">
|
||||||
|
<span class="device-name">{{ point.name }}</span>
|
||||||
|
<span class="device-coord">{{ point.lat }}, {{ point.lng }}</span>
|
||||||
|
</div>
|
||||||
|
<van-icon name="arrow" color="#ccc" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.map-monitoring-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--color-bg-page);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
:deep(.van-nav-bar) {
|
||||||
|
background: var(--color-primary);
|
||||||
|
--van-nav-bar-title-text-color: #fff;
|
||||||
|
--van-nav-bar-text-color: #fff;
|
||||||
|
--van-nav-bar-icon-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-placeholder {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: #f5f7fa;
|
||||||
|
margin: 8px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px dashed #ddd;
|
||||||
|
min-height: 300px;
|
||||||
|
|
||||||
|
.map-title {
|
||||||
|
margin: 12px 0 4px 0;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--color-text-regular);
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-hint {
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--color-text-placeholder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.device-panel {
|
||||||
|
background: var(--color-bg-card);
|
||||||
|
margin: 0 8px 8px;
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.panel-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 12px 16px;
|
||||||
|
border-bottom: 1px solid var(--color-border);
|
||||||
|
|
||||||
|
.panel-title {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--color-text-regular);
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-count {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--color-text-placeholder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.device-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 12px 16px;
|
||||||
|
border-bottom: 1px solid var(--color-border);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.device-dot {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 12px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.device-info {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
|
||||||
|
.device-name {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--color-text-regular);
|
||||||
|
}
|
||||||
|
|
||||||
|
.device-coord {
|
||||||
|
font-size: 11px;
|
||||||
|
color: var(--color-text-placeholder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
177
src/views/monitoringEquipment/monitoringDetail.vue
Normal file
177
src/views/monitoringEquipment/monitoringDetail.vue
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* 监测详情页
|
||||||
|
*
|
||||||
|
* 展示设备的监测数据详情,包含实时数据、历史趋势图表占位、
|
||||||
|
* 告警记录和数据分析。
|
||||||
|
*/
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
const detailId = (route.query.id as string) || '1'
|
||||||
|
|
||||||
|
/** 模拟监测详情 */
|
||||||
|
const monitoring = ref({
|
||||||
|
id: detailId,
|
||||||
|
equipmentName: '流量监测仪 A-01',
|
||||||
|
equipmentType: '流量计',
|
||||||
|
currentValue: '125.6 m³/h',
|
||||||
|
status: 'normal',
|
||||||
|
updateTime: '2025-06-15 08:30:00',
|
||||||
|
statistics: {
|
||||||
|
today: { avg: '122.3 m³/h', max: '135.8 m³/h', min: '110.2 m³/h', total: '2935.2 m³' },
|
||||||
|
yesterday: { avg: '118.7 m³/h', max: '130.1 m³/h', min: '105.8 m³/h', total: '2848.8 m³' },
|
||||||
|
thisMonth: { avg: '120.5 m³/h', max: '145.2 m³/h', min: '95.6 m³/h', total: '86760 m³' },
|
||||||
|
},
|
||||||
|
alarmRecords: [
|
||||||
|
{ time: '2025-06-14 16:30:00', level: 'warning', content: '流量超过预警值 130 m³/h', value: '131.5 m³/h' },
|
||||||
|
{ time: '2025-06-10 09:15:00', level: 'alarm', content: '流量异常下降', value: '45.2 m³/h' },
|
||||||
|
{ time: '2025-06-05 22:00:00', level: 'warning', content: '信号短暂丢失', value: '-' },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const levelColorMap: Record<string, string> = {
|
||||||
|
warning: '#FF9800',
|
||||||
|
alarm: '#F44336',
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="monitoring-detail-page">
|
||||||
|
<van-nav-bar title="监测详情" left-text="返回" left-arrow fixed placeholder @click-left="router.back()" />
|
||||||
|
|
||||||
|
<!-- 实时数据 -->
|
||||||
|
<div class="realtime-card">
|
||||||
|
<div class="realtime-value">{{ monitoring.currentValue }}</div>
|
||||||
|
<div class="realtime-label">当前流量</div>
|
||||||
|
<div class="realtime-time">更新时间: {{ monitoring.updateTime }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 图表占位区(趋势图) -->
|
||||||
|
<van-cell-group title="流量趋势" class="info-group">
|
||||||
|
<van-cell>
|
||||||
|
<div class="chart-placeholder">
|
||||||
|
<van-icon name="chart-trending-o" size="36" color="#ccc" />
|
||||||
|
<span>流量趋势图表</span>
|
||||||
|
</div>
|
||||||
|
</van-cell>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 今日统计 -->
|
||||||
|
<van-cell-group title="今日统计" class="info-group">
|
||||||
|
<van-cell title="平均流量" :value="monitoring.statistics.today.avg" />
|
||||||
|
<van-cell title="最大流量" :value="monitoring.statistics.today.max" />
|
||||||
|
<van-cell title="最小流量" :value="monitoring.statistics.today.min" />
|
||||||
|
<van-cell title="累计流量" :value="monitoring.statistics.today.total" />
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 昨日统计 -->
|
||||||
|
<van-cell-group title="昨日统计" class="info-group">
|
||||||
|
<van-cell title="平均流量" :value="monitoring.statistics.yesterday.avg" />
|
||||||
|
<van-cell title="最大流量" :value="monitoring.statistics.yesterday.max" />
|
||||||
|
<van-cell title="最小流量" :value="monitoring.statistics.yesterday.min" />
|
||||||
|
<van-cell title="累计流量" :value="monitoring.statistics.yesterday.total" />
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 本月统计 -->
|
||||||
|
<van-cell-group title="本月统计" class="info-group">
|
||||||
|
<van-cell title="平均流量" :value="monitoring.statistics.thisMonth.avg" />
|
||||||
|
<van-cell title="最大流量" :value="monitoring.statistics.thisMonth.max" />
|
||||||
|
<van-cell title="最小流量" :value="monitoring.statistics.thisMonth.min" />
|
||||||
|
<van-cell title="累计流量" :value="monitoring.statistics.thisMonth.total" />
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 告警记录 -->
|
||||||
|
<van-cell-group title="告警记录" class="info-group">
|
||||||
|
<van-empty v-if="monitoring.alarmRecords.length === 0" description="暂无告警" />
|
||||||
|
<van-cell v-for="(alarm, idx) in monitoring.alarmRecords" :key="idx" :title="alarm.content">
|
||||||
|
<template #label>
|
||||||
|
<span>{{ alarm.time }}</span>
|
||||||
|
</template>
|
||||||
|
<template #value>
|
||||||
|
<div class="alarm-info">
|
||||||
|
<span class="alarm-dot" :style="{ backgroundColor: levelColorMap[alarm.level] }" />
|
||||||
|
<span class="alarm-value">{{ alarm.value }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</van-cell>
|
||||||
|
</van-cell-group>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.monitoring-detail-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--color-bg-page);
|
||||||
|
padding-bottom: 24px;
|
||||||
|
|
||||||
|
:deep(.van-nav-bar) {
|
||||||
|
background: var(--color-primary);
|
||||||
|
--van-nav-bar-title-text-color: #fff;
|
||||||
|
--van-nav-bar-text-color: #fff;
|
||||||
|
--van-nav-bar-icon-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.realtime-card {
|
||||||
|
margin: 8px;
|
||||||
|
padding: 20px 16px;
|
||||||
|
background: linear-gradient(135deg, var(--color-primary), #36a3f7);
|
||||||
|
border-radius: 12px;
|
||||||
|
text-align: center;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
.realtime-value {
|
||||||
|
font-size: 36px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.realtime-label {
|
||||||
|
margin-top: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.realtime-time {
|
||||||
|
margin-top: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-placeholder {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 180px;
|
||||||
|
background: #f5f7fa;
|
||||||
|
border-radius: 8px;
|
||||||
|
color: var(--color-text-placeholder);
|
||||||
|
font-size: 13px;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-group {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alarm-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alarm-dot {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alarm-value {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
153
src/views/problemReport/index.vue
Normal file
153
src/views/problemReport/index.vue
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* 问题上报入口页
|
||||||
|
*
|
||||||
|
* 通过 van-grid 展示可上报的问题类型,
|
||||||
|
* 点击卡片跳转到对应的上报表单页。
|
||||||
|
*/
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
/** 上报类型列表 */
|
||||||
|
const reportTypes = [
|
||||||
|
{
|
||||||
|
text: '积淹点',
|
||||||
|
icon: 'warning-o',
|
||||||
|
route: '/reportFloodedPoints',
|
||||||
|
desc: '积水、淹没点位上报',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '巡检问题',
|
||||||
|
icon: 'search',
|
||||||
|
route: '/reportInspection',
|
||||||
|
desc: '巡检发现的问题',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '设备报修',
|
||||||
|
icon: 'setting-o',
|
||||||
|
route: '/reportEquipmentRepair',
|
||||||
|
desc: '设备故障报修',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '督办问题',
|
||||||
|
icon: 'records',
|
||||||
|
route: '/reportSupervise',
|
||||||
|
desc: '督办项目问题',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '项目问题',
|
||||||
|
icon: 'bulb-o',
|
||||||
|
route: '/reportProject',
|
||||||
|
desc: '项目相关问题',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '施工问题',
|
||||||
|
icon: 'cluster-o',
|
||||||
|
route: '/reportConstruction',
|
||||||
|
desc: '施工现场问题',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '积水调查',
|
||||||
|
icon: 'water-o' as string,
|
||||||
|
route: '/reportFloodedPoints',
|
||||||
|
desc: '积水调查记录',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '养护上报',
|
||||||
|
icon: 'logistics',
|
||||||
|
route: '/reportEquipmentRepair',
|
||||||
|
desc: '养护问题上报',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
/** 跳转 */
|
||||||
|
function goReport(route: string) {
|
||||||
|
router.push(route)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="report-index-page">
|
||||||
|
<van-nav-bar
|
||||||
|
title="问题上报"
|
||||||
|
left-arrow
|
||||||
|
fixed
|
||||||
|
placeholder
|
||||||
|
@click-left="router.back()"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="report-banner">
|
||||||
|
<div class="banner-title">选择上报类型</div>
|
||||||
|
<div class="banner-desc">请根据实际情况选择对应的问题类型进行上报</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<van-grid :column-num="3" :border="false" :gutter="12" class="report-grid">
|
||||||
|
<van-grid-item
|
||||||
|
v-for="item in reportTypes"
|
||||||
|
:key="item.text"
|
||||||
|
:icon="item.icon"
|
||||||
|
:text="item.text"
|
||||||
|
@click="goReport(item.route)"
|
||||||
|
>
|
||||||
|
<template #description>
|
||||||
|
<span class="grid-desc">{{ item.desc }}</span>
|
||||||
|
</template>
|
||||||
|
</van-grid-item>
|
||||||
|
</van-grid>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.report-index-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--color-bg-page);
|
||||||
|
|
||||||
|
:deep(.van-nav-bar) {
|
||||||
|
background: var(--color-primary);
|
||||||
|
--van-nav-bar-title-text-color: #fff;
|
||||||
|
--van-nav-bar-text-color: #fff;
|
||||||
|
--van-nav-bar-icon-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-banner {
|
||||||
|
padding: 20px 16px 12px;
|
||||||
|
background: #fff;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
.banner-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-desc {
|
||||||
|
margin-top: 6px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-grid {
|
||||||
|
padding: 0 4px;
|
||||||
|
|
||||||
|
:deep(.van-grid-item__content) {
|
||||||
|
padding: 16px 8px;
|
||||||
|
background: var(--color-bg-card);
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.van-grid-item__text) {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-desc {
|
||||||
|
font-size: 11px;
|
||||||
|
color: #999;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
144
src/views/problemReport/reportConstruction.vue
Normal file
144
src/views/problemReport/reportConstruction.vue
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* 施工问题上报表单
|
||||||
|
*
|
||||||
|
* 用于上报施工现场发现的问题,
|
||||||
|
* 支持可选的 detail 路由参数预填充施工点信息。
|
||||||
|
*/
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
|
import { showSuccessToast } from 'vant'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
/** 路由参数 — 预填充的施工点信息 */
|
||||||
|
const detailParam = (route.params.detail as string) || ''
|
||||||
|
|
||||||
|
/** 表单数据 */
|
||||||
|
const site = ref(detailParam)
|
||||||
|
const issue = ref('')
|
||||||
|
const description = ref('')
|
||||||
|
const photos = ref<Array<{ url: string }>>([])
|
||||||
|
|
||||||
|
/** 提交上报 */
|
||||||
|
function onSubmit() {
|
||||||
|
if (!site.value) {
|
||||||
|
showSuccessToast('请选择施工点')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!issue.value) {
|
||||||
|
showSuccessToast('请填写问题')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!description.value) {
|
||||||
|
showSuccessToast('请填写描述')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
showSuccessToast('上报成功')
|
||||||
|
router.back()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="report-form-page">
|
||||||
|
<van-nav-bar
|
||||||
|
title="施工问题上报"
|
||||||
|
left-arrow
|
||||||
|
fixed
|
||||||
|
placeholder
|
||||||
|
@click-left="router.back()"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<van-form @submit="onSubmit">
|
||||||
|
<van-cell-group inset>
|
||||||
|
<van-field
|
||||||
|
v-model="site"
|
||||||
|
name="site"
|
||||||
|
label="施工点"
|
||||||
|
placeholder="请选择施工点"
|
||||||
|
is-link
|
||||||
|
readonly
|
||||||
|
:rules="[{ required: true, message: '请选择施工点' }]"
|
||||||
|
/>
|
||||||
|
<van-field
|
||||||
|
v-model="issue"
|
||||||
|
name="issue"
|
||||||
|
label="问题"
|
||||||
|
placeholder="请输入问题标题"
|
||||||
|
:rules="[{ required: true, message: '请填写问题' }]"
|
||||||
|
/>
|
||||||
|
<van-field
|
||||||
|
v-model="description"
|
||||||
|
name="description"
|
||||||
|
label="描述"
|
||||||
|
placeholder="请描述施工问题"
|
||||||
|
type="textarea"
|
||||||
|
rows="3"
|
||||||
|
autosize
|
||||||
|
:rules="[{ required: true, message: '请填写描述' }]"
|
||||||
|
/>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<div class="upload-section">
|
||||||
|
<div class="section-title">现场照片</div>
|
||||||
|
<van-uploader
|
||||||
|
v-model="photos"
|
||||||
|
:max-count="6"
|
||||||
|
:max-size="10 * 1024 * 1024"
|
||||||
|
accept="image/*"
|
||||||
|
multiple
|
||||||
|
:preview-full-image="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="submit-wrap">
|
||||||
|
<van-button
|
||||||
|
type="primary"
|
||||||
|
block
|
||||||
|
round
|
||||||
|
native-type="submit"
|
||||||
|
class="submit-btn"
|
||||||
|
>
|
||||||
|
提交上报
|
||||||
|
</van-button>
|
||||||
|
</div>
|
||||||
|
</van-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.report-form-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--color-bg-page);
|
||||||
|
|
||||||
|
:deep(.van-nav-bar) {
|
||||||
|
background: var(--color-primary);
|
||||||
|
--van-nav-bar-title-text-color: #fff;
|
||||||
|
--van-nav-bar-text-color: #fff;
|
||||||
|
--van-nav-bar-icon-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-section {
|
||||||
|
margin: 12px 16px;
|
||||||
|
padding: 12px;
|
||||||
|
background: var(--color-bg-card);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-wrap {
|
||||||
|
padding: 24px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
height: 44px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
181
src/views/problemReport/reportEquipmentRepair.vue
Normal file
181
src/views/problemReport/reportEquipmentRepair.vue
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* 设备报修上报表单
|
||||||
|
*
|
||||||
|
* 用于上报设备故障报修,
|
||||||
|
* 包含设备选择、故障类型、描述和紧急程度。
|
||||||
|
*/
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { showSuccessToast } from 'vant'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
/** 表单数据 */
|
||||||
|
const equipment = ref('')
|
||||||
|
const faultType = ref('')
|
||||||
|
const description = ref('')
|
||||||
|
const urgency = ref('')
|
||||||
|
const photos = ref<Array<{ url: string }>>([])
|
||||||
|
|
||||||
|
/** 设备选项 */
|
||||||
|
const equipmentOptions = [
|
||||||
|
{ text: '水泵', value: 'pump' },
|
||||||
|
{ text: '阀门', value: 'valve' },
|
||||||
|
{ text: '电机', value: 'motor' },
|
||||||
|
{ text: '仪表', value: 'meter' },
|
||||||
|
{ text: '管道', value: 'pipe' },
|
||||||
|
]
|
||||||
|
|
||||||
|
/** 故障类型 */
|
||||||
|
const faultTypeOptions = [
|
||||||
|
{ text: '无法启动', value: 'noStart' },
|
||||||
|
{ text: '异常噪音', value: 'noise' },
|
||||||
|
{ text: '漏水', value: 'leak' },
|
||||||
|
{ text: '运行不稳定', value: 'unstable' },
|
||||||
|
{ text: '其他故障', value: 'other' },
|
||||||
|
]
|
||||||
|
|
||||||
|
/** 紧急程度 */
|
||||||
|
const urgencyColumns = [
|
||||||
|
{ text: '紧急', value: 'urgent' },
|
||||||
|
{ text: '一般', value: 'normal' },
|
||||||
|
{ text: '低', value: 'low' },
|
||||||
|
]
|
||||||
|
|
||||||
|
/** 提交上报 */
|
||||||
|
function onSubmit() {
|
||||||
|
if (!equipment.value) {
|
||||||
|
showSuccessToast('请选择设备')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!faultType.value) {
|
||||||
|
showSuccessToast('请选择故障类型')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!description.value) {
|
||||||
|
showSuccessToast('请填写描述')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!urgency.value) {
|
||||||
|
showSuccessToast('请选择紧急程度')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
showSuccessToast('上报成功')
|
||||||
|
router.back()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="report-form-page">
|
||||||
|
<van-nav-bar
|
||||||
|
title="设备报修"
|
||||||
|
left-arrow
|
||||||
|
fixed
|
||||||
|
placeholder
|
||||||
|
@click-left="router.back()"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<van-form @submit="onSubmit">
|
||||||
|
<van-cell-group inset>
|
||||||
|
<van-field
|
||||||
|
v-model="equipment"
|
||||||
|
name="equipment"
|
||||||
|
label="设备"
|
||||||
|
placeholder="请选择设备"
|
||||||
|
is-link
|
||||||
|
readonly
|
||||||
|
:rules="[{ required: true, message: '请选择设备' }]"
|
||||||
|
/>
|
||||||
|
<van-field
|
||||||
|
v-model="faultType"
|
||||||
|
name="faultType"
|
||||||
|
label="故障类型"
|
||||||
|
placeholder="请选择故障类型"
|
||||||
|
is-link
|
||||||
|
readonly
|
||||||
|
:rules="[{ required: true, message: '请选择故障类型' }]"
|
||||||
|
/>
|
||||||
|
<van-field
|
||||||
|
v-model="urgency"
|
||||||
|
name="urgency"
|
||||||
|
label="紧急程度"
|
||||||
|
placeholder="请选择紧急程度"
|
||||||
|
is-link
|
||||||
|
readonly
|
||||||
|
:rules="[{ required: true, message: '请选择紧急程度' }]"
|
||||||
|
/>
|
||||||
|
<van-field
|
||||||
|
v-model="description"
|
||||||
|
name="description"
|
||||||
|
label="描述"
|
||||||
|
placeholder="请描述设备故障情况"
|
||||||
|
type="textarea"
|
||||||
|
rows="3"
|
||||||
|
autosize
|
||||||
|
:rules="[{ required: true, message: '请填写描述' }]"
|
||||||
|
/>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<div class="upload-section">
|
||||||
|
<div class="section-title">现场照片</div>
|
||||||
|
<van-uploader
|
||||||
|
v-model="photos"
|
||||||
|
:max-count="6"
|
||||||
|
:max-size="10 * 1024 * 1024"
|
||||||
|
accept="image/*"
|
||||||
|
multiple
|
||||||
|
:preview-full-image="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="submit-wrap">
|
||||||
|
<van-button
|
||||||
|
type="primary"
|
||||||
|
block
|
||||||
|
round
|
||||||
|
native-type="submit"
|
||||||
|
class="submit-btn"
|
||||||
|
>
|
||||||
|
提交上报
|
||||||
|
</van-button>
|
||||||
|
</div>
|
||||||
|
</van-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.report-form-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--color-bg-page);
|
||||||
|
|
||||||
|
:deep(.van-nav-bar) {
|
||||||
|
background: var(--color-primary);
|
||||||
|
--van-nav-bar-title-text-color: #fff;
|
||||||
|
--van-nav-bar-text-color: #fff;
|
||||||
|
--van-nav-bar-icon-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-section {
|
||||||
|
margin: 12px 16px;
|
||||||
|
padding: 12px;
|
||||||
|
background: var(--color-bg-card);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-wrap {
|
||||||
|
padding: 24px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
height: 44px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
136
src/views/problemReport/reportFloodedPoints.vue
Normal file
136
src/views/problemReport/reportFloodedPoints.vue
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* 积淹点上报表单
|
||||||
|
*
|
||||||
|
* 用于上报积水、淹没点位信息,
|
||||||
|
* 包含位置选择、水位、描述和照片上传。
|
||||||
|
*/
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { showSuccessToast } from 'vant'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
/** 表单数据 */
|
||||||
|
const location = ref('')
|
||||||
|
const waterLevel = ref('')
|
||||||
|
const description = ref('')
|
||||||
|
const photos = ref<Array<{ url: string }>>([])
|
||||||
|
|
||||||
|
/** 提交上报 */
|
||||||
|
function onSubmit() {
|
||||||
|
if (!location.value) {
|
||||||
|
showSuccessToast('请选择位置')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!description.value) {
|
||||||
|
showSuccessToast('请填写描述')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
showSuccessToast('上报成功')
|
||||||
|
router.back()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="report-form-page">
|
||||||
|
<van-nav-bar
|
||||||
|
title="积淹点上报"
|
||||||
|
left-arrow
|
||||||
|
fixed
|
||||||
|
placeholder
|
||||||
|
@click-left="router.back()"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<van-form @submit="onSubmit">
|
||||||
|
<van-cell-group inset>
|
||||||
|
<van-field
|
||||||
|
v-model="location"
|
||||||
|
name="location"
|
||||||
|
label="位置"
|
||||||
|
placeholder="点击选择位置"
|
||||||
|
is-link
|
||||||
|
readonly
|
||||||
|
:rules="[{ required: true, message: '请选择位置' }]"
|
||||||
|
/>
|
||||||
|
<van-field
|
||||||
|
v-model="waterLevel"
|
||||||
|
name="waterLevel"
|
||||||
|
label="水位(cm)"
|
||||||
|
placeholder="请输入水位高度"
|
||||||
|
type="number"
|
||||||
|
/>
|
||||||
|
<van-field
|
||||||
|
v-model="description"
|
||||||
|
name="description"
|
||||||
|
label="描述"
|
||||||
|
placeholder="请描述积水情况"
|
||||||
|
type="textarea"
|
||||||
|
rows="3"
|
||||||
|
autosize
|
||||||
|
:rules="[{ required: true, message: '请填写描述' }]"
|
||||||
|
/>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<div class="upload-section">
|
||||||
|
<div class="section-title">现场照片</div>
|
||||||
|
<van-uploader
|
||||||
|
v-model="photos"
|
||||||
|
:max-count="6"
|
||||||
|
:max-size="10 * 1024 * 1024"
|
||||||
|
accept="image/*"
|
||||||
|
multiple
|
||||||
|
:preview-full-image="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="submit-wrap">
|
||||||
|
<van-button
|
||||||
|
type="primary"
|
||||||
|
block
|
||||||
|
round
|
||||||
|
native-type="submit"
|
||||||
|
class="submit-btn"
|
||||||
|
>
|
||||||
|
提交上报
|
||||||
|
</van-button>
|
||||||
|
</div>
|
||||||
|
</van-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.report-form-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--color-bg-page);
|
||||||
|
|
||||||
|
:deep(.van-nav-bar) {
|
||||||
|
background: var(--color-primary);
|
||||||
|
--van-nav-bar-title-text-color: #fff;
|
||||||
|
--van-nav-bar-text-color: #fff;
|
||||||
|
--van-nav-bar-icon-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-section {
|
||||||
|
margin: 12px 16px;
|
||||||
|
padding: 12px;
|
||||||
|
background: var(--color-bg-card);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-wrap {
|
||||||
|
padding: 24px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
height: 44px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
160
src/views/problemReport/reportInspection.vue
Normal file
160
src/views/problemReport/reportInspection.vue
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* 巡检问题上报表单
|
||||||
|
*
|
||||||
|
* 用于上报巡检过程中发现的问题,
|
||||||
|
* 包含设施选择、问题类型、描述和照片上传。
|
||||||
|
*/
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { showSuccessToast } from 'vant'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
/** 表单数据 */
|
||||||
|
const facility = ref('')
|
||||||
|
const problemType = ref('')
|
||||||
|
const description = ref('')
|
||||||
|
const photos = ref<Array<{ url: string }>>([])
|
||||||
|
|
||||||
|
/** 设施选项 */
|
||||||
|
const facilityOptions = [
|
||||||
|
{ text: '供水管网', value: 'pipe' },
|
||||||
|
{ text: '阀门井', value: 'valve' },
|
||||||
|
{ text: '消防栓', value: 'hydrant' },
|
||||||
|
{ text: '水表', value: 'meter' },
|
||||||
|
{ text: '泵站', value: 'pump' },
|
||||||
|
]
|
||||||
|
|
||||||
|
/** 问题类型选项 */
|
||||||
|
const problemTypeOptions = [
|
||||||
|
{ text: '管道渗漏', value: 'leak' },
|
||||||
|
{ text: '阀门故障', value: 'valveFault' },
|
||||||
|
{ text: '水表异常', value: 'meterFault' },
|
||||||
|
{ text: '设施损坏', value: 'damage' },
|
||||||
|
{ text: '其他问题', value: 'other' },
|
||||||
|
]
|
||||||
|
|
||||||
|
/** 提交上报 */
|
||||||
|
function onSubmit() {
|
||||||
|
if (!facility.value) {
|
||||||
|
showSuccessToast('请选择设施')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!problemType.value) {
|
||||||
|
showSuccessToast('请选择问题类型')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!description.value) {
|
||||||
|
showSuccessToast('请填写描述')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
showSuccessToast('上报成功')
|
||||||
|
router.back()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="report-form-page">
|
||||||
|
<van-nav-bar
|
||||||
|
title="巡检问题上报"
|
||||||
|
left-arrow
|
||||||
|
fixed
|
||||||
|
placeholder
|
||||||
|
@click-left="router.back()"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<van-form @submit="onSubmit">
|
||||||
|
<van-cell-group inset>
|
||||||
|
<van-field
|
||||||
|
v-model="facility"
|
||||||
|
name="facility"
|
||||||
|
label="设施"
|
||||||
|
placeholder="请选择设施类型"
|
||||||
|
is-link
|
||||||
|
readonly
|
||||||
|
:rules="[{ required: true, message: '请选择设施' }]"
|
||||||
|
/>
|
||||||
|
<van-field
|
||||||
|
v-model="problemType"
|
||||||
|
name="problemType"
|
||||||
|
label="问题类型"
|
||||||
|
placeholder="请选择问题类型"
|
||||||
|
is-link
|
||||||
|
readonly
|
||||||
|
:rules="[{ required: true, message: '请选择问题类型' }]"
|
||||||
|
/>
|
||||||
|
<van-field
|
||||||
|
v-model="description"
|
||||||
|
name="description"
|
||||||
|
label="描述"
|
||||||
|
placeholder="请描述巡检发现的问题"
|
||||||
|
type="textarea"
|
||||||
|
rows="3"
|
||||||
|
autosize
|
||||||
|
:rules="[{ required: true, message: '请填写描述' }]"
|
||||||
|
/>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<div class="upload-section">
|
||||||
|
<div class="section-title">现场照片</div>
|
||||||
|
<van-uploader
|
||||||
|
v-model="photos"
|
||||||
|
:max-count="6"
|
||||||
|
:max-size="10 * 1024 * 1024"
|
||||||
|
accept="image/*"
|
||||||
|
multiple
|
||||||
|
:preview-full-image="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="submit-wrap">
|
||||||
|
<van-button
|
||||||
|
type="primary"
|
||||||
|
block
|
||||||
|
round
|
||||||
|
native-type="submit"
|
||||||
|
class="submit-btn"
|
||||||
|
>
|
||||||
|
提交上报
|
||||||
|
</van-button>
|
||||||
|
</div>
|
||||||
|
</van-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.report-form-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--color-bg-page);
|
||||||
|
|
||||||
|
:deep(.van-nav-bar) {
|
||||||
|
background: var(--color-primary);
|
||||||
|
--van-nav-bar-title-text-color: #fff;
|
||||||
|
--van-nav-bar-text-color: #fff;
|
||||||
|
--van-nav-bar-icon-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-section {
|
||||||
|
margin: 12px 16px;
|
||||||
|
padding: 12px;
|
||||||
|
background: var(--color-bg-card);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-wrap {
|
||||||
|
padding: 24px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
height: 44px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
155
src/views/problemReport/reportProject.vue
Normal file
155
src/views/problemReport/reportProject.vue
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* 项目问题上报表单
|
||||||
|
*
|
||||||
|
* 用于上报项目相关问题,
|
||||||
|
* 支持可选的 detail 路由参数预填充项目信息。
|
||||||
|
*/
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
|
import { showSuccessToast } from 'vant'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
/** 路由参数 — 预填充的项目信息 */
|
||||||
|
const detailParam = (route.params.detail as string) || ''
|
||||||
|
|
||||||
|
/** 表单数据 */
|
||||||
|
const project = ref(detailParam)
|
||||||
|
const issueType = ref('')
|
||||||
|
const description = ref('')
|
||||||
|
const photos = ref<Array<{ url: string }>>([])
|
||||||
|
|
||||||
|
/** 问题类型选项 */
|
||||||
|
const issueTypeOptions = [
|
||||||
|
{ text: '进度延迟', value: 'delay' },
|
||||||
|
{ text: '质量问题', value: 'quality' },
|
||||||
|
{ text: '安全隐患', value: 'safety' },
|
||||||
|
{ text: '材料问题', value: 'material' },
|
||||||
|
{ text: '其他', value: 'other' },
|
||||||
|
]
|
||||||
|
|
||||||
|
/** 提交上报 */
|
||||||
|
function onSubmit() {
|
||||||
|
if (!project.value) {
|
||||||
|
showSuccessToast('请选择项目')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!issueType.value) {
|
||||||
|
showSuccessToast('请选择问题类型')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!description.value) {
|
||||||
|
showSuccessToast('请填写描述')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
showSuccessToast('上报成功')
|
||||||
|
router.back()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="report-form-page">
|
||||||
|
<van-nav-bar
|
||||||
|
title="项目问题上报"
|
||||||
|
left-arrow
|
||||||
|
fixed
|
||||||
|
placeholder
|
||||||
|
@click-left="router.back()"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<van-form @submit="onSubmit">
|
||||||
|
<van-cell-group inset>
|
||||||
|
<van-field
|
||||||
|
v-model="project"
|
||||||
|
name="project"
|
||||||
|
label="项目"
|
||||||
|
placeholder="请选择项目"
|
||||||
|
is-link
|
||||||
|
readonly
|
||||||
|
:rules="[{ required: true, message: '请选择项目' }]"
|
||||||
|
/>
|
||||||
|
<van-field
|
||||||
|
v-model="issueType"
|
||||||
|
name="issueType"
|
||||||
|
label="问题类型"
|
||||||
|
placeholder="请选择问题类型"
|
||||||
|
is-link
|
||||||
|
readonly
|
||||||
|
:rules="[{ required: true, message: '请选择问题类型' }]"
|
||||||
|
/>
|
||||||
|
<van-field
|
||||||
|
v-model="description"
|
||||||
|
name="description"
|
||||||
|
label="描述"
|
||||||
|
placeholder="请描述项目问题"
|
||||||
|
type="textarea"
|
||||||
|
rows="3"
|
||||||
|
autosize
|
||||||
|
:rules="[{ required: true, message: '请填写描述' }]"
|
||||||
|
/>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<div class="upload-section">
|
||||||
|
<div class="section-title">现场照片</div>
|
||||||
|
<van-uploader
|
||||||
|
v-model="photos"
|
||||||
|
:max-count="6"
|
||||||
|
:max-size="10 * 1024 * 1024"
|
||||||
|
accept="image/*"
|
||||||
|
multiple
|
||||||
|
:preview-full-image="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="submit-wrap">
|
||||||
|
<van-button
|
||||||
|
type="primary"
|
||||||
|
block
|
||||||
|
round
|
||||||
|
native-type="submit"
|
||||||
|
class="submit-btn"
|
||||||
|
>
|
||||||
|
提交上报
|
||||||
|
</van-button>
|
||||||
|
</div>
|
||||||
|
</van-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.report-form-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--color-bg-page);
|
||||||
|
|
||||||
|
:deep(.van-nav-bar) {
|
||||||
|
background: var(--color-primary);
|
||||||
|
--van-nav-bar-title-text-color: #fff;
|
||||||
|
--van-nav-bar-text-color: #fff;
|
||||||
|
--van-nav-bar-icon-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-section {
|
||||||
|
margin: 12px 16px;
|
||||||
|
padding: 12px;
|
||||||
|
background: var(--color-bg-card);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-wrap {
|
||||||
|
padding: 24px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
height: 44px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
144
src/views/problemReport/reportSupervise.vue
Normal file
144
src/views/problemReport/reportSupervise.vue
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* 督办问题上报表单
|
||||||
|
*
|
||||||
|
* 用于上报督办项目中发现的问题,
|
||||||
|
* 支持可选的 detail 路由参数。
|
||||||
|
*/
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
|
import { showSuccessToast } from 'vant'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
/** 路由参数 — 预填充的项目信息 */
|
||||||
|
const detailParam = (route.params.detail as string) || ''
|
||||||
|
|
||||||
|
/** 表单数据 */
|
||||||
|
const project = ref(detailParam)
|
||||||
|
const problem = ref('')
|
||||||
|
const description = ref('')
|
||||||
|
const photos = ref<Array<{ url: string }>>([])
|
||||||
|
|
||||||
|
/** 提交上报 */
|
||||||
|
function onSubmit() {
|
||||||
|
if (!project.value) {
|
||||||
|
showSuccessToast('请选择督办项目')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!problem.value) {
|
||||||
|
showSuccessToast('请选择问题')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!description.value) {
|
||||||
|
showSuccessToast('请填写描述')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
showSuccessToast('上报成功')
|
||||||
|
router.back()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="report-form-page">
|
||||||
|
<van-nav-bar
|
||||||
|
title="督办问题上报"
|
||||||
|
left-arrow
|
||||||
|
fixed
|
||||||
|
placeholder
|
||||||
|
@click-left="router.back()"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<van-form @submit="onSubmit">
|
||||||
|
<van-cell-group inset>
|
||||||
|
<van-field
|
||||||
|
v-model="project"
|
||||||
|
name="project"
|
||||||
|
label="督办项目"
|
||||||
|
placeholder="请选择督办项目"
|
||||||
|
is-link
|
||||||
|
readonly
|
||||||
|
:rules="[{ required: true, message: '请选择督办项目' }]"
|
||||||
|
/>
|
||||||
|
<van-field
|
||||||
|
v-model="problem"
|
||||||
|
name="problem"
|
||||||
|
label="问题"
|
||||||
|
placeholder="请输入问题标题"
|
||||||
|
:rules="[{ required: true, message: '请填写问题' }]"
|
||||||
|
/>
|
||||||
|
<van-field
|
||||||
|
v-model="description"
|
||||||
|
name="description"
|
||||||
|
label="描述"
|
||||||
|
placeholder="请描述督办发现的问题"
|
||||||
|
type="textarea"
|
||||||
|
rows="3"
|
||||||
|
autosize
|
||||||
|
:rules="[{ required: true, message: '请填写描述' }]"
|
||||||
|
/>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<div class="upload-section">
|
||||||
|
<div class="section-title">现场照片</div>
|
||||||
|
<van-uploader
|
||||||
|
v-model="photos"
|
||||||
|
:max-count="6"
|
||||||
|
:max-size="10 * 1024 * 1024"
|
||||||
|
accept="image/*"
|
||||||
|
multiple
|
||||||
|
:preview-full-image="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="submit-wrap">
|
||||||
|
<van-button
|
||||||
|
type="primary"
|
||||||
|
block
|
||||||
|
round
|
||||||
|
native-type="submit"
|
||||||
|
class="submit-btn"
|
||||||
|
>
|
||||||
|
提交上报
|
||||||
|
</van-button>
|
||||||
|
</div>
|
||||||
|
</van-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.report-form-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--color-bg-page);
|
||||||
|
|
||||||
|
:deep(.van-nav-bar) {
|
||||||
|
background: var(--color-primary);
|
||||||
|
--van-nav-bar-title-text-color: #fff;
|
||||||
|
--van-nav-bar-text-color: #fff;
|
||||||
|
--van-nav-bar-icon-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-section {
|
||||||
|
margin: 12px 16px;
|
||||||
|
padding: 12px;
|
||||||
|
background: var(--color-bg-card);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-wrap {
|
||||||
|
padding: 24px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
height: 44px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
183
src/views/superviseRecord/detail.vue
Normal file
183
src/views/superviseRecord/detail.vue
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* 监督记录详情页
|
||||||
|
*
|
||||||
|
* 展示监督记录的详细信息,包含基本信息、监督内容、现场照片和结论。
|
||||||
|
*/
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
|
import { showToast, showImagePreview } from 'vant'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
const detailId = (route.query.id as string) || '1'
|
||||||
|
|
||||||
|
/** 模拟监督记录详情 */
|
||||||
|
const record = ref({
|
||||||
|
id: detailId,
|
||||||
|
supervisorName: '张监督',
|
||||||
|
project: '城北供水改造工程',
|
||||||
|
type: 'daily',
|
||||||
|
result: 'qualified',
|
||||||
|
date: '2025-06-15',
|
||||||
|
time: '09:30 - 11:00',
|
||||||
|
address: '城北工业大道12号施工段',
|
||||||
|
content: '对管道焊接质量进行日常监督,检查焊缝外观、焊接参数记录、焊工资质等。焊接质量良好,符合规范要求。',
|
||||||
|
conclusion: '合格。焊接作业规范,焊接参数符合设计要求,建议继续保持。',
|
||||||
|
remark: '现场焊接环境良好,防护措施到位。',
|
||||||
|
createTime: '2025-06-15 11:15:00',
|
||||||
|
photos: [
|
||||||
|
{ id: 1, url: 'https://via.placeholder.com/400x300/4CAF50/white?text=Photo+1', desc: '焊接现场全景' },
|
||||||
|
{ id: 2, url: 'https://via.placeholder.com/400x300/2196F3/white?text=Photo+2', desc: '焊缝细节' },
|
||||||
|
{ id: 3, url: 'https://via.placeholder.com/400x300/FF9800/white?text=Photo+3', desc: '焊工资质核查' },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const typeMap: Record<string, string> = {
|
||||||
|
daily: '日常监督',
|
||||||
|
special: '专项监督',
|
||||||
|
rectify: '整改复查',
|
||||||
|
}
|
||||||
|
|
||||||
|
const resultMap: Record<string, string> = {
|
||||||
|
qualified: '合格',
|
||||||
|
unqualified: '不合格',
|
||||||
|
}
|
||||||
|
|
||||||
|
const resultColorMap: Record<string, 'success' | 'danger'> = {
|
||||||
|
qualified: 'success',
|
||||||
|
unqualified: 'danger',
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 预览照片 */
|
||||||
|
function previewPhoto(index: number) {
|
||||||
|
showImagePreview({
|
||||||
|
images: record.value.photos.map(p => p.url),
|
||||||
|
startPosition: index,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="record-detail-page">
|
||||||
|
<van-nav-bar title="记录详情" left-text="返回" left-arrow fixed placeholder @click-left="router.back()" />
|
||||||
|
|
||||||
|
<!-- 结果标签 -->
|
||||||
|
<div class="result-bar">
|
||||||
|
<van-tag :type="resultColorMap[record.result]" size="large">
|
||||||
|
{{ resultMap[record.result] }}
|
||||||
|
</van-tag>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 基本信息 -->
|
||||||
|
<van-cell-group title="基本信息" class="info-group">
|
||||||
|
<van-cell title="监督人" :value="record.supervisorName" />
|
||||||
|
<van-cell title="所属项目" :value="record.project" />
|
||||||
|
<van-cell title="监督类型" :value="typeMap[record.type]" />
|
||||||
|
<van-cell title="监督日期" :value="record.date" />
|
||||||
|
<van-cell title="监督时间" :value="record.time" />
|
||||||
|
<van-cell title="监督地址" :value="record.address" />
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 监督内容 -->
|
||||||
|
<van-cell-group title="监督内容" class="info-group">
|
||||||
|
<van-cell>
|
||||||
|
<p class="desc-text">{{ record.content }}</p>
|
||||||
|
</van-cell>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 现场照片 -->
|
||||||
|
<van-cell-group title="现场照片" class="info-group">
|
||||||
|
<van-cell>
|
||||||
|
<div class="photo-grid">
|
||||||
|
<div
|
||||||
|
v-for="(photo, index) in record.photos"
|
||||||
|
:key="photo.id"
|
||||||
|
class="photo-item"
|
||||||
|
@click="previewPhoto(index)"
|
||||||
|
>
|
||||||
|
<van-image
|
||||||
|
:src="photo.url"
|
||||||
|
width="100%"
|
||||||
|
height="100"
|
||||||
|
fit="cover"
|
||||||
|
radius="6"
|
||||||
|
/>
|
||||||
|
<p class="photo-desc">{{ photo.desc }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</van-cell>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 结论与备注 -->
|
||||||
|
<van-cell-group title="监督结论" class="info-group">
|
||||||
|
<van-cell>
|
||||||
|
<p class="desc-text">{{ record.conclusion }}</p>
|
||||||
|
</van-cell>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<van-cell-group title="备注" class="info-group">
|
||||||
|
<van-cell>
|
||||||
|
<p class="desc-text">{{ record.remark }}</p>
|
||||||
|
</van-cell>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 时间信息 -->
|
||||||
|
<van-cell-group title="时间信息" class="info-group">
|
||||||
|
<van-cell title="创建时间" :value="record.createTime" />
|
||||||
|
</van-cell-group>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.record-detail-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--color-bg-page);
|
||||||
|
padding-bottom: 24px;
|
||||||
|
|
||||||
|
:deep(.van-nav-bar) {
|
||||||
|
background: var(--color-primary);
|
||||||
|
--van-nav-bar-title-text-color: #fff;
|
||||||
|
--van-nav-bar-text-color: #fff;
|
||||||
|
--van-nav-bar-icon-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-bar {
|
||||||
|
padding: 12px 16px;
|
||||||
|
background: var(--color-bg-card);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-group {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desc-text {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: var(--color-text-regular);
|
||||||
|
padding: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-item {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-desc {
|
||||||
|
margin: 4px 0 0 0;
|
||||||
|
font-size: 11px;
|
||||||
|
color: var(--color-text-placeholder);
|
||||||
|
text-align: center;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
150
src/views/superviseRecord/index.vue
Normal file
150
src/views/superviseRecord/index.vue
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* 监督记录列表页
|
||||||
|
*
|
||||||
|
* 展示第三方监督记录,支持搜索和类型筛选(全部/日常监督/专项监督/整改复查),
|
||||||
|
* 点击卡片跳转记录详情。
|
||||||
|
*/
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
/** 搜索关键词 */
|
||||||
|
const searchText = ref('')
|
||||||
|
|
||||||
|
/** 当前激活的 Tab */
|
||||||
|
const activeTab = ref(0)
|
||||||
|
|
||||||
|
/** 模拟监督记录数据 */
|
||||||
|
const mockRecords = [
|
||||||
|
{ id: 1, supervisorName: '张监督', project: '城北供水改造工程', type: 'daily', result: 'qualified', date: '2025-06-15', content: '对管道焊接质量进行日常监督' },
|
||||||
|
{ id: 2, supervisorName: '李监督', project: '高新区管网新建', type: 'special', result: 'unqualified', date: '2025-06-14', content: '专项检查管材进场质量' },
|
||||||
|
{ id: 3, supervisorName: '王监督', project: '老城区雨污分流', type: 'rectify', result: 'qualified', date: '2025-06-13', content: '复查上次整改问题落实情况' },
|
||||||
|
{ id: 4, supervisorName: '赵监督', project: '东区泵站升级', type: 'daily', result: 'qualified', date: '2025-06-12', content: '泵站基础施工日常监督' },
|
||||||
|
{ id: 5, supervisorName: '孙监督', project: '商业区管道维护', type: 'special', result: 'unqualified', date: '2025-06-11', content: '专项检查管道防腐处理' },
|
||||||
|
]
|
||||||
|
|
||||||
|
/** 类型映射 */
|
||||||
|
const typeMap: Record<string, string> = {
|
||||||
|
daily: '日常监督',
|
||||||
|
special: '专项监督',
|
||||||
|
rectify: '整改复查',
|
||||||
|
}
|
||||||
|
|
||||||
|
const typeColorMap: Record<string, string> = {
|
||||||
|
daily: 'primary',
|
||||||
|
special: 'warning',
|
||||||
|
rectify: 'success',
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 结果映射 */
|
||||||
|
const resultMap: Record<string, string> = {
|
||||||
|
qualified: '合格',
|
||||||
|
unqualified: '不合格',
|
||||||
|
}
|
||||||
|
|
||||||
|
const resultColorMap: Record<string, 'success' | 'danger'> = {
|
||||||
|
qualified: 'success',
|
||||||
|
unqualified: 'danger',
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 筛选后的记录列表 */
|
||||||
|
const filteredRecords = computed(() => {
|
||||||
|
let list = mockRecords
|
||||||
|
if (searchText.value) {
|
||||||
|
const kw = searchText.value.toLowerCase()
|
||||||
|
list = list.filter(r =>
|
||||||
|
r.supervisorName.toLowerCase().includes(kw) ||
|
||||||
|
r.project.toLowerCase().includes(kw) ||
|
||||||
|
r.content.toLowerCase().includes(kw)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (activeTab.value === 1) list = list.filter(r => r.type === 'daily')
|
||||||
|
else if (activeTab.value === 2) list = list.filter(r => r.type === 'special')
|
||||||
|
else if (activeTab.value === 3) list = list.filter(r => r.type === 'rectify')
|
||||||
|
return list
|
||||||
|
})
|
||||||
|
|
||||||
|
/** 跳转详情 */
|
||||||
|
function goDetail(id: number) {
|
||||||
|
router.push(`/superviseRecord/detail?id=${id}`)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="record-page">
|
||||||
|
<van-nav-bar title="监督记录" left-arrow fixed placeholder @click-left="router.back()" />
|
||||||
|
|
||||||
|
<van-search v-model="searchText" placeholder="搜索监督人、项目、内容" shape="round" />
|
||||||
|
|
||||||
|
<van-tabs v-model:active="activeTab" sticky>
|
||||||
|
<van-tab title="全部" />
|
||||||
|
<van-tab title="日常监督" />
|
||||||
|
<van-tab title="专项监督" />
|
||||||
|
<van-tab title="整改复查" />
|
||||||
|
</van-tabs>
|
||||||
|
|
||||||
|
<div class="record-list">
|
||||||
|
<van-empty v-if="filteredRecords.length === 0" description="暂无监督记录" />
|
||||||
|
<van-card
|
||||||
|
v-for="record in filteredRecords"
|
||||||
|
:key="record.id"
|
||||||
|
:title="record.project"
|
||||||
|
:desc="`监督人: ${record.supervisorName}`"
|
||||||
|
@click="goDetail(record.id)"
|
||||||
|
>
|
||||||
|
<template #tags>
|
||||||
|
<van-tag :type="typeColorMap[record.type] as 'primary' | 'success' | 'warning' | 'danger'" size="medium">
|
||||||
|
{{ typeMap[record.type] }}
|
||||||
|
</van-tag>
|
||||||
|
<van-tag :type="resultColorMap[record.result]" size="medium" plain>
|
||||||
|
{{ resultMap[record.result] }}
|
||||||
|
</van-tag>
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<div class="record-meta">
|
||||||
|
<span>{{ record.date }}</span>
|
||||||
|
<span>{{ record.content }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</van-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.record-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--color-bg-page);
|
||||||
|
|
||||||
|
:deep(.van-nav-bar) {
|
||||||
|
background: var(--color-primary);
|
||||||
|
--van-nav-bar-title-text-color: #fff;
|
||||||
|
--van-nav-bar-text-color: #fff;
|
||||||
|
--van-nav-bar-icon-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-list {
|
||||||
|
padding: 0 8px;
|
||||||
|
|
||||||
|
:deep(.van-card) {
|
||||||
|
margin: 8px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: var(--color-bg-card);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.van-tag) {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-meta {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
108
src/views/supervisor/detail.vue
Normal file
108
src/views/supervisor/detail.vue
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* 监督人员详情页
|
||||||
|
*
|
||||||
|
* 展示第三方监督人员详细信息,包含基本信息、在岗状态和履职记录。
|
||||||
|
*/
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
const detailId = (route.query.id as string) || '1'
|
||||||
|
|
||||||
|
/** 模拟监督人员详情 */
|
||||||
|
const supervisor = ref({
|
||||||
|
id: detailId,
|
||||||
|
name: '张监督',
|
||||||
|
company: '水务监理公司A',
|
||||||
|
status: 'on_duty',
|
||||||
|
phone: '13800001001',
|
||||||
|
project: '城北供水改造工程',
|
||||||
|
rating: 4.8,
|
||||||
|
certNo: 'JL2023001',
|
||||||
|
certType: '注册监理工程师',
|
||||||
|
entryDate: '2025-01-15',
|
||||||
|
education: '本科',
|
||||||
|
major: '水利工程',
|
||||||
|
superviseYears: 8,
|
||||||
|
superviseCount: 126,
|
||||||
|
problemCount: 34,
|
||||||
|
lastOnDuty: '2025-06-15 08:30',
|
||||||
|
})
|
||||||
|
|
||||||
|
const statusMap: Record<string, string> = {
|
||||||
|
on_duty: '在岗',
|
||||||
|
off_duty: '离岗',
|
||||||
|
}
|
||||||
|
|
||||||
|
const statusColorMap: Record<string, 'success' | 'danger'> = {
|
||||||
|
on_duty: 'success',
|
||||||
|
off_duty: 'danger',
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="supervisor-detail-page">
|
||||||
|
<van-nav-bar title="人员详情" left-text="返回" left-arrow fixed placeholder @click-left="router.back()" />
|
||||||
|
|
||||||
|
<!-- 状态标签 -->
|
||||||
|
<div class="status-bar">
|
||||||
|
<van-tag :type="statusColorMap[supervisor.status]" size="large">
|
||||||
|
{{ statusMap[supervisor.status] }}
|
||||||
|
</van-tag>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 基本信息 -->
|
||||||
|
<van-cell-group title="基本信息" class="info-group">
|
||||||
|
<van-cell title="姓名" :value="supervisor.name" />
|
||||||
|
<van-cell title="所属公司" :value="supervisor.company" />
|
||||||
|
<van-cell title="联系电话" :value="supervisor.phone" />
|
||||||
|
<van-cell title="所属项目" :value="supervisor.project" />
|
||||||
|
<van-cell title="评分" :value="`${supervisor.rating} 分`" />
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 资质信息 -->
|
||||||
|
<van-cell-group title="资质信息" class="info-group">
|
||||||
|
<van-cell title="证书编号" :value="supervisor.certNo" />
|
||||||
|
<van-cell title="证书类型" :value="supervisor.certType" />
|
||||||
|
<van-cell title="学历" :value="supervisor.education" />
|
||||||
|
<van-cell title="专业" :value="supervisor.major" />
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 履职统计 -->
|
||||||
|
<van-cell-group title="履职统计" class="info-group">
|
||||||
|
<van-cell title="从业年限" :value="`${supervisor.superviseYears} 年`" />
|
||||||
|
<van-cell title="监督次数" :value="`${supervisor.superviseCount} 次`" />
|
||||||
|
<van-cell title="发现问题" :value="`${supervisor.problemCount} 个`" />
|
||||||
|
<van-cell title="最近到岗" :value="supervisor.lastOnDuty" />
|
||||||
|
<van-cell title="入职日期" :value="supervisor.entryDate" />
|
||||||
|
</van-cell-group>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.supervisor-detail-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--color-bg-page);
|
||||||
|
padding-bottom: 24px;
|
||||||
|
|
||||||
|
:deep(.van-nav-bar) {
|
||||||
|
background: var(--color-primary);
|
||||||
|
--van-nav-bar-title-text-color: #fff;
|
||||||
|
--van-nav-bar-text-color: #fff;
|
||||||
|
--van-nav-bar-icon-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-bar {
|
||||||
|
padding: 12px 16px;
|
||||||
|
background: var(--color-bg-card);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-group {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
135
src/views/supervisor/index.vue
Normal file
135
src/views/supervisor/index.vue
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* 第三方监督人员列表页
|
||||||
|
*
|
||||||
|
* 展示监督人员列表,支持搜索和状态筛选(全部/在岗/离岗),
|
||||||
|
* 点击卡片跳转人员详情。
|
||||||
|
*/
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
/** 搜索关键词 */
|
||||||
|
const searchText = ref('')
|
||||||
|
|
||||||
|
/** 当前激活的 Tab */
|
||||||
|
const activeTab = ref(0)
|
||||||
|
|
||||||
|
/** 模拟监督人员数据 */
|
||||||
|
const mockSupervisors = [
|
||||||
|
{ id: 1, name: '张监督', company: '水务监理公司A', status: 'on_duty', phone: '13800001001', project: '城北供水改造工程', rating: 4.8 },
|
||||||
|
{ id: 2, name: '李监督', company: '市政监理公司B', status: 'off_duty', phone: '13800001002', project: '高新区管网新建', rating: 4.5 },
|
||||||
|
{ id: 3, name: '王监督', company: '环境监理公司C', status: 'on_duty', phone: '13800001003', project: '老城区雨污分流', rating: 4.9 },
|
||||||
|
{ id: 4, name: '赵监督', company: '水务监理公司A', status: 'on_duty', phone: '13800001004', project: '东区泵站升级', rating: 4.6 },
|
||||||
|
{ id: 5, name: '孙监督', company: '市政监理公司B', status: 'off_duty', phone: '13800001005', project: '商业区管道维护', rating: 4.3 },
|
||||||
|
]
|
||||||
|
|
||||||
|
/** 状态映射 */
|
||||||
|
const statusMap: Record<string, string> = {
|
||||||
|
on_duty: '在岗',
|
||||||
|
off_duty: '离岗',
|
||||||
|
}
|
||||||
|
|
||||||
|
const statusColorMap: Record<string, 'success' | 'danger'> = {
|
||||||
|
on_duty: 'success',
|
||||||
|
off_duty: 'danger',
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 筛选后的列表 */
|
||||||
|
const filteredSupervisors = computed(() => {
|
||||||
|
let list = mockSupervisors
|
||||||
|
if (searchText.value) {
|
||||||
|
const kw = searchText.value.toLowerCase()
|
||||||
|
list = list.filter(s =>
|
||||||
|
s.name.toLowerCase().includes(kw) ||
|
||||||
|
s.company.toLowerCase().includes(kw) ||
|
||||||
|
s.project.toLowerCase().includes(kw)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (activeTab.value === 1) list = list.filter(s => s.status === 'on_duty')
|
||||||
|
else if (activeTab.value === 2) list = list.filter(s => s.status === 'off_duty')
|
||||||
|
return list
|
||||||
|
})
|
||||||
|
|
||||||
|
/** 跳转详情 */
|
||||||
|
function goDetail(id: number) {
|
||||||
|
router.push(`/supervisor/detail?id=${id}`)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="supervisor-page">
|
||||||
|
<van-nav-bar title="第三方监督人员" left-arrow fixed placeholder @click-left="router.back()" />
|
||||||
|
|
||||||
|
<van-search v-model="searchText" placeholder="搜索姓名、公司、项目" shape="round" />
|
||||||
|
|
||||||
|
<van-tabs v-model:active="activeTab" sticky>
|
||||||
|
<van-tab title="全部" />
|
||||||
|
<van-tab title="在岗" />
|
||||||
|
<van-tab title="离岗" />
|
||||||
|
</van-tabs>
|
||||||
|
|
||||||
|
<div class="supervisor-list">
|
||||||
|
<van-empty v-if="filteredSupervisors.length === 0" description="暂无监督人员" />
|
||||||
|
<van-card
|
||||||
|
v-for="supervisor in filteredSupervisors"
|
||||||
|
:key="supervisor.id"
|
||||||
|
:title="supervisor.name"
|
||||||
|
:desc="supervisor.company"
|
||||||
|
@click="goDetail(supervisor.id)"
|
||||||
|
>
|
||||||
|
<template #tags>
|
||||||
|
<van-tag :type="statusColorMap[supervisor.status]" size="medium">
|
||||||
|
{{ statusMap[supervisor.status] }}
|
||||||
|
</van-tag>
|
||||||
|
<van-tag type="primary" size="medium" plain>
|
||||||
|
{{ supervisor.rating }} 分
|
||||||
|
</van-tag>
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<div class="supervisor-meta">
|
||||||
|
<span>{{ supervisor.phone }}</span>
|
||||||
|
<span>{{ supervisor.project }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</van-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.supervisor-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--color-bg-page);
|
||||||
|
|
||||||
|
:deep(.van-nav-bar) {
|
||||||
|
background: var(--color-primary);
|
||||||
|
--van-nav-bar-title-text-color: #fff;
|
||||||
|
--van-nav-bar-text-color: #fff;
|
||||||
|
--van-nav-bar-icon-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.supervisor-list {
|
||||||
|
padding: 0 8px;
|
||||||
|
|
||||||
|
:deep(.van-card) {
|
||||||
|
margin: 8px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: var(--color-bg-card);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.van-tag) {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.supervisor-meta {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
200
src/views/yxkjzyRecords/detail.vue
Normal file
200
src/views/yxkjzyRecords/detail.vue
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* 有限空间作业记录详情页
|
||||||
|
*
|
||||||
|
* 展示有限空间作业的详细信息,包含基本信息、
|
||||||
|
* 安全条件确认清单、作业审批和参与人员。
|
||||||
|
*/
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
const detailId = (route.params.detail as string) || '1'
|
||||||
|
|
||||||
|
/** 模拟作业记录详情 */
|
||||||
|
const record = ref({
|
||||||
|
id: detailId,
|
||||||
|
title: '污水井清淤作业 2025-0615-01',
|
||||||
|
location: '城北工业大道12号污水井',
|
||||||
|
spaceType: '污水井',
|
||||||
|
status: 'in_progress',
|
||||||
|
operator: '张作业员',
|
||||||
|
supervisor: '王监督员',
|
||||||
|
guardian: '李监护人',
|
||||||
|
startTime: '2025-06-15 08:00',
|
||||||
|
endTime: '',
|
||||||
|
duration: '进行中',
|
||||||
|
depth: '4.5 m',
|
||||||
|
diameter: '1.2 m',
|
||||||
|
oxygenContent: '20.8%',
|
||||||
|
hazardousGas: '未检出',
|
||||||
|
temperature: '28°C',
|
||||||
|
humidity: '65%',
|
||||||
|
ventilation: '正常',
|
||||||
|
description: '对城北工业大道12号污水井进行清淤作业,清理井内沉积物,检查井壁结构完整性。',
|
||||||
|
/** 安全条件确认清单 */
|
||||||
|
safetyChecklist: [
|
||||||
|
{ id: 1, item: '作业审批手续是否完备', checked: true, required: true },
|
||||||
|
{ id: 2, item: '通风设备是否正常运行', checked: true, required: true },
|
||||||
|
{ id: 3, item: '气体检测是否合格', checked: true, required: true },
|
||||||
|
{ id: 4, item: '安全绳/安全带是否完好', checked: true, required: true },
|
||||||
|
{ id: 5, item: '通讯设备是否畅通', checked: true, required: true },
|
||||||
|
{ id: 6, item: '应急救援设备是否就位', checked: true, required: true },
|
||||||
|
{ id: 7, item: '人员防护装备是否齐全', checked: true, required: true },
|
||||||
|
{ id: 8, item: '现场警示标识是否设置', checked: false, required: true },
|
||||||
|
{ id: 9, item: '现场监护人是否到位', checked: true, required: true },
|
||||||
|
{ id: 10, item: '作业环境照明是否充足', checked: true, required: false },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const statusMap: Record<string, string> = {
|
||||||
|
pending: '待开始',
|
||||||
|
in_progress: '进行中',
|
||||||
|
completed: '已完成',
|
||||||
|
}
|
||||||
|
|
||||||
|
const statusColorMap: Record<string, string> = {
|
||||||
|
pending: 'warning',
|
||||||
|
in_progress: 'primary',
|
||||||
|
completed: 'success',
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 安全清单统计 */
|
||||||
|
const checklistStats = computed(() => {
|
||||||
|
const total = record.value.safetyChecklist.length
|
||||||
|
const checked = record.value.safetyChecklist.filter(c => c.checked).length
|
||||||
|
const required = record.value.safetyChecklist.filter(c => c.required).length
|
||||||
|
const requiredChecked = record.value.safetyChecklist.filter(c => c.required && c.checked).length
|
||||||
|
return { total, checked, required, requiredChecked }
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="yxkjzy-detail-page">
|
||||||
|
<van-nav-bar title="作业记录详情" left-text="返回" left-arrow fixed placeholder @click-left="router.back()" />
|
||||||
|
|
||||||
|
<!-- 状态标签 -->
|
||||||
|
<div class="status-bar">
|
||||||
|
<van-tag :type="statusColorMap[record.status] as never" size="large">
|
||||||
|
{{ statusMap[record.status] }}
|
||||||
|
</van-tag>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 基本信息 -->
|
||||||
|
<van-cell-group title="基本信息" class="info-group">
|
||||||
|
<van-cell title="作业编号" :value="record.title" />
|
||||||
|
<van-cell title="作业地点" :value="record.location" />
|
||||||
|
<van-cell title="空间类型" :value="record.spaceType" />
|
||||||
|
<van-cell title="作业员" :value="record.operator" />
|
||||||
|
<van-cell title="监督员" :value="record.supervisor" />
|
||||||
|
<van-cell title="监护人" :value="record.guardian" />
|
||||||
|
<van-cell title="开始时间" :value="record.startTime" />
|
||||||
|
<van-cell title="结束时间" :value="record.endTime || '-'" />
|
||||||
|
<van-cell title="作业时长" :value="record.duration" />
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 空间参数 -->
|
||||||
|
<van-cell-group title="空间参数" class="info-group">
|
||||||
|
<van-cell title="深度" :value="record.depth" />
|
||||||
|
<van-cell title="直径" :value="record.diameter" />
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 环境监测 -->
|
||||||
|
<van-cell-group title="环境监测" class="info-group">
|
||||||
|
<van-cell title="氧气含量" :value="record.oxygenContent" />
|
||||||
|
<van-cell title="有害气体" :value="record.hazardousGas" />
|
||||||
|
<van-cell title="温度" :value="record.temperature" />
|
||||||
|
<van-cell title="湿度" :value="record.humidity" />
|
||||||
|
<van-cell title="通风状态" :value="record.ventilation" />
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 安全条件确认清单 -->
|
||||||
|
<van-cell-group :title="`安全条件确认清单 (${checklistStats.requiredChecked}/${checklistStats.required} 必检项)`" class="info-group">
|
||||||
|
<van-cell v-for="item in record.safetyChecklist" :key="item.id">
|
||||||
|
<template #title>
|
||||||
|
<div class="checklist-item">
|
||||||
|
<van-icon
|
||||||
|
:name="item.checked ? 'success' : 'close'"
|
||||||
|
:color="item.checked ? '#4CAF50' : '#F44336'"
|
||||||
|
size="18"
|
||||||
|
/>
|
||||||
|
<span :class="{ 'required-tag': item.required }">{{ item.required ? '【必检】' : '' }}{{ item.item }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #value>
|
||||||
|
<van-tag :type="item.checked ? 'success' : 'danger'" size="medium">
|
||||||
|
{{ item.checked ? '已确认' : '未确认' }}
|
||||||
|
</van-tag>
|
||||||
|
</template>
|
||||||
|
</van-cell>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 作业描述 -->
|
||||||
|
<van-cell-group title="作业描述" class="info-group">
|
||||||
|
<van-cell>
|
||||||
|
<p class="desc-text">{{ record.description }}</p>
|
||||||
|
</van-cell>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<!-- 安全提示 -->
|
||||||
|
<div class="safety-tips">
|
||||||
|
<van-notice-bar
|
||||||
|
left-icon="warning-o"
|
||||||
|
color="#FF9800"
|
||||||
|
background="#FFF3E0"
|
||||||
|
:scrollable="false"
|
||||||
|
>
|
||||||
|
有限空间作业必须严格遵守"先通风、再检测、后作业"原则,未确认安全条件不得进入。
|
||||||
|
</van-notice-bar>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.yxkjzy-detail-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--color-bg-page);
|
||||||
|
padding-bottom: 24px;
|
||||||
|
|
||||||
|
:deep(.van-nav-bar) {
|
||||||
|
background: var(--color-primary);
|
||||||
|
--van-nav-bar-title-text-color: #fff;
|
||||||
|
--van-nav-bar-text-color: #fff;
|
||||||
|
--van-nav-bar-icon-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-bar {
|
||||||
|
padding: 12px 16px;
|
||||||
|
background: var(--color-bg-card);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-group {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checklist-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.required-tag {
|
||||||
|
color: var(--color-text-regular);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.desc-text {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.8;
|
||||||
|
color: var(--color-text-regular);
|
||||||
|
padding: 4px 0;
|
||||||
|
text-indent: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.safety-tips {
|
||||||
|
margin: 12px 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
153
src/views/yxkjzyRecords/index.vue
Normal file
153
src/views/yxkjzyRecords/index.vue
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* 有限空间作业记录列表页
|
||||||
|
*
|
||||||
|
* 展示有限空间作业记录,支持搜索和状态筛选(全部/进行中/已完成),
|
||||||
|
* 点击卡片跳转作业记录详情。
|
||||||
|
*/
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
/** 搜索关键词 */
|
||||||
|
const searchText = ref('')
|
||||||
|
|
||||||
|
/** 当前激活的 Tab */
|
||||||
|
const activeTab = ref(0)
|
||||||
|
|
||||||
|
/** 模拟有限空间作业记录数据 */
|
||||||
|
const mockRecords = [
|
||||||
|
{ id: 1, title: '污水井清淤作业 2025-0615-01', location: '城北工业大道12号污水井', status: 'in_progress', operator: '张作业员', startTime: '2025-06-15 08:00', spaceType: '污水井' },
|
||||||
|
{ id: 2, title: '阀门井维修作业 2025-0614-03', location: '高新区3号阀门井', status: 'completed', operator: '李作业员', startTime: '2025-06-14 14:00', spaceType: '阀门井' },
|
||||||
|
{ id: 3, title: '蓄水池清洗作业 2025-0615-02', location: '东区蓄水池2号', status: 'in_progress', operator: '王作业员', startTime: '2025-06-15 09:00', spaceType: '蓄水池' },
|
||||||
|
{ id: 4, title: '管道检修作业 2025-0613-01', location: '商业区地下管廊B段', status: 'completed', operator: '赵作业员', startTime: '2025-06-13 10:00', spaceType: '管廊' },
|
||||||
|
{ id: 5, title: '检查井勘察作业 2025-0615-04', location: '老城区中山路检查井', status: 'pending', operator: '孙作业员', startTime: '2025-06-15 13:00', spaceType: '检查井' },
|
||||||
|
{ id: 6, title: '污水井疏通作业 2025-0612-02', location: '南城污水处理厂入口井', status: 'completed', operator: '钱作业员', startTime: '2025-06-12 08:30', spaceType: '污水井' },
|
||||||
|
]
|
||||||
|
|
||||||
|
/** 状态映射 */
|
||||||
|
const statusMap: Record<string, string> = {
|
||||||
|
pending: '待开始',
|
||||||
|
in_progress: '进行中',
|
||||||
|
completed: '已完成',
|
||||||
|
}
|
||||||
|
|
||||||
|
const statusColorMap: Record<string, string> = {
|
||||||
|
pending: 'warning',
|
||||||
|
in_progress: 'primary',
|
||||||
|
completed: 'success',
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 空间类型图标映射 */
|
||||||
|
const spaceIconMap: Record<string, string> = {
|
||||||
|
'污水井': 'orders-o',
|
||||||
|
'阀门井': 'setting-o',
|
||||||
|
'蓄水池': 'aim-o',
|
||||||
|
'管廊': 'guide-o',
|
||||||
|
'检查井': 'search',
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 筛选后的列表 */
|
||||||
|
const filteredRecords = computed(() => {
|
||||||
|
let list = mockRecords
|
||||||
|
if (searchText.value) {
|
||||||
|
const kw = searchText.value.toLowerCase()
|
||||||
|
list = list.filter(r =>
|
||||||
|
r.title.toLowerCase().includes(kw) ||
|
||||||
|
r.location.toLowerCase().includes(kw) ||
|
||||||
|
r.operator.toLowerCase().includes(kw) ||
|
||||||
|
r.spaceType.toLowerCase().includes(kw)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (activeTab.value === 1) list = list.filter(r => r.status === 'in_progress')
|
||||||
|
else if (activeTab.value === 2) list = list.filter(r => r.status === 'completed')
|
||||||
|
return list
|
||||||
|
})
|
||||||
|
|
||||||
|
/** 跳转详情 */
|
||||||
|
function goDetail(id: number) {
|
||||||
|
router.push(`/yxkjzyRecordsDetail/${id}`)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="yxkjzy-records-page">
|
||||||
|
<van-nav-bar title="有限空间作业记录" left-arrow fixed placeholder @click-left="router.back()" />
|
||||||
|
|
||||||
|
<van-search v-model="searchText" placeholder="搜索作业标题、位置、作业员" shape="round" />
|
||||||
|
|
||||||
|
<van-tabs v-model:active="activeTab" sticky>
|
||||||
|
<van-tab title="全部" />
|
||||||
|
<van-tab title="进行中" />
|
||||||
|
<van-tab title="已完成" />
|
||||||
|
</van-tabs>
|
||||||
|
|
||||||
|
<div class="record-list">
|
||||||
|
<van-empty v-if="filteredRecords.length === 0" description="暂无作业记录" />
|
||||||
|
<van-card
|
||||||
|
v-for="record in filteredRecords"
|
||||||
|
:key="record.id"
|
||||||
|
:title="record.title"
|
||||||
|
:desc="`位置: ${record.location}`"
|
||||||
|
@click="goDetail(record.id)"
|
||||||
|
>
|
||||||
|
<template #tags>
|
||||||
|
<van-tag :type="statusColorMap[record.status] as never" size="medium">
|
||||||
|
{{ statusMap[record.status] }}
|
||||||
|
</van-tag>
|
||||||
|
</template>
|
||||||
|
<template #thumb>
|
||||||
|
<van-icon :name="spaceIconMap[record.spaceType] || 'label-o'" size="32" color="#999" />
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<div class="record-meta">
|
||||||
|
<span class="meta-type">空间类型: {{ record.spaceType }}</span>
|
||||||
|
<span>作业员: {{ record.operator }}</span>
|
||||||
|
<span>开始时间: {{ record.startTime }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</van-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.yxkjzy-records-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--color-bg-page);
|
||||||
|
|
||||||
|
:deep(.van-nav-bar) {
|
||||||
|
background: var(--color-primary);
|
||||||
|
--van-nav-bar-title-text-color: #fff;
|
||||||
|
--van-nav-bar-text-color: #fff;
|
||||||
|
--van-nav-bar-icon-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-list {
|
||||||
|
padding: 0 8px;
|
||||||
|
|
||||||
|
:deep(.van-card) {
|
||||||
|
margin: 8px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: var(--color-bg-card);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.van-tag) {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-meta {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
|
||||||
|
.meta-type {
|
||||||
|
color: var(--color-text-regular);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user