319 lines
8.0 KiB
Vue
319 lines
8.0 KiB
Vue
|
|
<template>
|
|||
|
|
<view class="container">
|
|||
|
|
<uni-section title="隐患申报详情" type="line" class="mb-10" />
|
|||
|
|
|
|||
|
|
<view v-if="detail.id" class="detail-content">
|
|||
|
|
<!-- 基本信息卡片 -->
|
|||
|
|
<uni-card title="基本信息" :is-shadow="true" class="info-card">
|
|||
|
|
<view class="info-grid">
|
|||
|
|
<view class="info-row">
|
|||
|
|
<text class="info-label">申报类型:</text>
|
|||
|
|
<text class="info-value">{{ detail.declarationLabel || '-' }}</text>
|
|||
|
|
</view>
|
|||
|
|
<view class="info-row">
|
|||
|
|
<text class="info-label">申报人:</text>
|
|||
|
|
<text class="info-value">{{ detail.applyUser || '-' }}</text>
|
|||
|
|
</view>
|
|||
|
|
<view class="info-row">
|
|||
|
|
<text class="info-label">申报时间:</text>
|
|||
|
|
<text class="info-value">{{ formatDate(detail.occurTime) }}</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</uni-card>
|
|||
|
|
|
|||
|
|
<!-- 申报内容卡片 -->
|
|||
|
|
<uni-card title="申报内容" :is-shadow="true" class="content-card">
|
|||
|
|
<view class="content-text">
|
|||
|
|
{{ detail.requirementDescription || '暂无内容' }}
|
|||
|
|
</view>
|
|||
|
|
<view v-if="detail.remark" class="remark-section">
|
|||
|
|
<text class="remark-label">备注:</text>
|
|||
|
|
<text class="remark-text">{{ detail.remark }}</text>
|
|||
|
|
</view>
|
|||
|
|
</uni-card>
|
|||
|
|
|
|||
|
|
<!-- 图片展示卡片 -->
|
|||
|
|
<uni-card title="相关图片" :is-shadow="true" class="image-card" v-if="imageArray(detail.declarationImg).length > 0">
|
|||
|
|
<view class="image-grid">
|
|||
|
|
<view v-for="(img, idx) in imageArray(detail.declarationImg)" :key="idx" class="image-item">
|
|||
|
|
<image :src="imageUrl(img)" mode="aspectFill" class="detail-image" @click="previewImage(img, detail.declarationImg)" />
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</uni-card>
|
|||
|
|
|
|||
|
|
<!-- 无图片提示 -->
|
|||
|
|
<uni-card title="相关图片" :is-shadow="true" class="image-card" v-else>
|
|||
|
|
<view class="no-image-tip">
|
|||
|
|
<uni-icons type="image" size="40" color="#ccc"></uni-icons>
|
|||
|
|
<text class="no-image-text">暂无相关图片</text>
|
|||
|
|
</view>
|
|||
|
|
</uni-card>
|
|||
|
|
|
|||
|
|
<!-- 操作按钮 -->
|
|||
|
|
<view class="action-buttons" v-if="detail.status === '0' || detail.status === 0">
|
|||
|
|
<button class="edit-btn" size="default" type="primary" @click="editDeclaration">编辑申报</button>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 加载状态 -->
|
|||
|
|
<view v-else-if="loading" class="loading-state">
|
|||
|
|
<uni-load-more status="loading" />
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 错误状态 -->
|
|||
|
|
<view v-else class="error-state">
|
|||
|
|
<uni-icons type="info" size="60" color="#ccc"></uni-icons>
|
|||
|
|
<text class="error-text">数据加载失败或记录不存在</text>
|
|||
|
|
<button size="mini" type="default" @click="goBack">返回列表</button>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
import { getSafetyDeclaration } from '@/api/sidebar/sidebar.js'
|
|||
|
|
import { listData } from '@/api/system/dict/data.js'
|
|||
|
|
import config from '@/config'
|
|||
|
|
|
|||
|
|
export default {
|
|||
|
|
name: "FilingDetail",
|
|||
|
|
data() {
|
|||
|
|
return {
|
|||
|
|
id: null,
|
|||
|
|
detail: {},
|
|||
|
|
loading: false,
|
|||
|
|
typeDict: []
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
async onLoad(options) {
|
|||
|
|
this.id = options?.id || null
|
|||
|
|
if (this.id) {
|
|||
|
|
await this.initDict()
|
|||
|
|
await this.fetchDetail()
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
methods: {
|
|||
|
|
async initDict() {
|
|||
|
|
try {
|
|||
|
|
const typeData = await listData({ dictType: 'hs_declaration_type' })
|
|||
|
|
this.typeDict = typeData.rows || []
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('获取字典数据失败:', e)
|
|||
|
|
this.typeDict = []
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
async fetchDetail() {
|
|||
|
|
if (!this.id) return
|
|||
|
|
try {
|
|||
|
|
this.loading = true
|
|||
|
|
const res = await getSafetyDeclaration(this.id)
|
|||
|
|
this.detail = res?.data || {}
|
|||
|
|
// 设置申报类型标签
|
|||
|
|
if (this.detail.declarationType) {
|
|||
|
|
const typeItem = this.typeDict.find(i => String(i.dictValue) === String(this.detail.declarationType))
|
|||
|
|
this.detail.declarationLabel = typeItem ? typeItem.dictLabel : this.detail.declarationType
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('获取详情失败:', e)
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '获取详情失败',
|
|||
|
|
icon: 'error'
|
|||
|
|
})
|
|||
|
|
} finally {
|
|||
|
|
this.loading = false
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
imageArray(declarationImg) {
|
|||
|
|
if (!declarationImg) return []
|
|||
|
|
if (typeof declarationImg === 'string') {
|
|||
|
|
return declarationImg.split(',').filter(Boolean)
|
|||
|
|
}
|
|||
|
|
return declarationImg.filter(Boolean)
|
|||
|
|
},
|
|||
|
|
imageUrl(path) {
|
|||
|
|
if (!path) return ''
|
|||
|
|
return config.baseUrl + path
|
|||
|
|
},
|
|||
|
|
previewImage(current, all) {
|
|||
|
|
const urls = this.imageArray(all).map(p => this.imageUrl(p))
|
|||
|
|
uni.previewImage({
|
|||
|
|
current: this.imageUrl(current),
|
|||
|
|
urls
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
formatDate(val) {
|
|||
|
|
if (!val) return '-'
|
|||
|
|
try {
|
|||
|
|
const d = new Date(val)
|
|||
|
|
const y = d.getFullYear()
|
|||
|
|
const m = String(d.getMonth() + 1).padStart(2, '0')
|
|||
|
|
const dd = String(d.getDate()).padStart(2, '0')
|
|||
|
|
const hh = String(d.getHours()).padStart(2, '0')
|
|||
|
|
const mm = String(d.getMinutes()).padStart(2, '0')
|
|||
|
|
return `${y}-${m}-${dd} ${hh}:${mm}`
|
|||
|
|
} catch (e) {
|
|||
|
|
return val
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
getStatusText(status) {
|
|||
|
|
const statusMap = {
|
|||
|
|
'0': '待处理',
|
|||
|
|
'1': '处理中',
|
|||
|
|
'2': '已完成',
|
|||
|
|
'3': '已关闭'
|
|||
|
|
}
|
|||
|
|
return statusMap[status] || '未知'
|
|||
|
|
},
|
|||
|
|
getStatusType(status) {
|
|||
|
|
const typeMap = {
|
|||
|
|
'0': 'error', // 待处理 - 红色
|
|||
|
|
'1': 'warning', // 处理中 - 橙色
|
|||
|
|
'2': 'success', // 已完成 - 绿色
|
|||
|
|
'3': 'info' // 已关闭 - 蓝色
|
|||
|
|
}
|
|||
|
|
return typeMap[status] || 'default'
|
|||
|
|
},
|
|||
|
|
editDeclaration() {
|
|||
|
|
if (!this.detail.id) return
|
|||
|
|
this.$tab.navigateTo(`/pages/work/sidebar/safetyDeclaratio/index?id=${this.detail.id}`)
|
|||
|
|
},
|
|||
|
|
goBack() {
|
|||
|
|
this.$tab.navigateBack()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style lang="scss">
|
|||
|
|
.container {
|
|||
|
|
padding: 15px;
|
|||
|
|
background-color: #f8f9fa;
|
|||
|
|
min-height: 100vh;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.mb-10 {
|
|||
|
|
margin-bottom: 15px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.detail-content {
|
|||
|
|
.info-card,
|
|||
|
|
.content-card,
|
|||
|
|
.image-card {
|
|||
|
|
margin-bottom: 15px;
|
|||
|
|
border-radius: 12px;
|
|||
|
|
overflow: hidden;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.info-grid {
|
|||
|
|
.info-row {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
margin-bottom: 12px;
|
|||
|
|
|
|||
|
|
&:last-child {
|
|||
|
|
margin-bottom: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.info-label {
|
|||
|
|
font-size: 14px;
|
|||
|
|
color: #666;
|
|||
|
|
min-width: 80px;
|
|||
|
|
flex-shrink: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.info-value {
|
|||
|
|
font-size: 14px;
|
|||
|
|
color: #333;
|
|||
|
|
flex: 1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.content-text {
|
|||
|
|
font-size: 15px;
|
|||
|
|
line-height: 1.6;
|
|||
|
|
color: #333;
|
|||
|
|
margin-bottom: 15px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.remark-section {
|
|||
|
|
padding-top: 15px;
|
|||
|
|
border-top: 1px solid #eee;
|
|||
|
|
|
|||
|
|
.remark-label {
|
|||
|
|
font-size: 14px;
|
|||
|
|
color: #666;
|
|||
|
|
margin-right: 8px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.remark-text {
|
|||
|
|
font-size: 14px;
|
|||
|
|
color: #333;
|
|||
|
|
line-height: 1.5;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.image-grid {
|
|||
|
|
display: flex;
|
|||
|
|
flex-wrap: wrap;
|
|||
|
|
gap: 10px;
|
|||
|
|
|
|||
|
|
.image-item {
|
|||
|
|
.detail-image {
|
|||
|
|
width: 100px;
|
|||
|
|
height: 100px;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
background: #f5f5f5;
|
|||
|
|
border: 2px solid #fff;
|
|||
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|||
|
|
transition: transform 0.2s ease;
|
|||
|
|
|
|||
|
|
&:active {
|
|||
|
|
transform: scale(0.95);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.no-image-tip {
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
padding: 40px 20px;
|
|||
|
|
|
|||
|
|
.no-image-text {
|
|||
|
|
margin-top: 10px;
|
|||
|
|
font-size: 14px;
|
|||
|
|
color: #999;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.action-buttons {
|
|||
|
|
margin-top: 20px;
|
|||
|
|
padding: 20px 0;
|
|||
|
|
|
|||
|
|
.edit-btn {
|
|||
|
|
width: 100%;
|
|||
|
|
border-radius: 25px;
|
|||
|
|
font-size: 16px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.loading-state,
|
|||
|
|
.error-state {
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
padding: 60px 20px;
|
|||
|
|
|
|||
|
|
.error-text {
|
|||
|
|
margin: 15px 0;
|
|||
|
|
font-size: 14px;
|
|||
|
|
color: #999;
|
|||
|
|
text-align: center;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|