Files
im-uniapp/components/ReportDetail/index.vue
2025-07-11 10:07:03 +08:00

263 lines
5.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<uni-popup ref="popup" type="center" :mask-click="true" @mask-click="close">
<view class="detail-popup">
<view class="detail-header">
<text class="detail-title">报工详情</text>
<u-icon name="close" @click="close" size="40" color="#999"></u-icon>
</view>
<!-- 加载状态 -->
<view v-if="loading" class="loading-container">
<u-loading-icon mode="spinner" size="40"></u-loading-icon>
<text class="loading-text">加载中...</text>
</view>
<scroll-view v-else scroll-y class="detail-content">
<view class="detail-info">
<!-- 空数据提示 -->
<view v-if="!detail || Object.keys(detail).length === 0" class="empty-detail">
<text class="empty-text">暂无详情数据</text>
</view>
<!-- 项目信息 -->
<view v-else class="info-section">
<view class="section-title">项目信息</view>
<view class="info-item">
<text class="label">项目名称</text>
<text class="value">{{ detail.projectName }}</text>
</view>
<view class="info-item">
<text class="label">项目编号</text>
<text class="value">{{ detail.projectNum }}</text>
</view>
<view class="info-item" v-if="detail.projectCode">
<text class="label">项目代号</text>
<text class="value">{{ detail.projectCode }}</text>
</view>
</view>
<!-- 报工信息 -->
<view class="info-section">
<view class="section-title">报工信息</view>
<view class="info-item">
<text class="label">工作地点</text>
<text class="value">{{ detail.workPlace }}</text>
</view>
<view class="info-item">
<text class="label">是否出差</text>
<text class="value">{{ detail.isTrip === 1 ? '是' : '否' }}</text>
</view>
<view class="info-item" v-if="detail.isTrip === 1">
<text class="label">出差类型</text>
<text class="value">{{ detail.workType === 0 ? '国内' : '国外' }}</text>
</view>
<view class="info-item">
<text class="label">报工时间</text>
<text class="value">{{ formatDate(detail.createTime) }}</text>
</view>
</view>
<!-- 报工内容 -->
<view class="info-section">
<view class="section-title">报工内容</view>
<view class="content-box">
<mp-html :content="detail.content"></mp-html>
</view>
</view>
<!-- 备注信息 -->
<view class="info-section" v-if="detail.remark">
<view class="section-title">备注</view>
<view class="content-box">
<text>{{ detail.remark }}</text>
</view>
</view>
</view>
</scroll-view>
</view>
</uni-popup>
</template>
<script>
import mpHtml from '@/uni_modules/mp-html/components/mp-html/mp-html.vue'
export default {
name: 'ReportDetail',
components: {
mpHtml
},
props: {
// 报工详情数据
detail: {
type: Object,
default: () => ({})
}
},
data() {
return {
loading: false
}
},
watch: {
detail: {
handler(newVal) {
if (newVal && Object.keys(newVal).length > 0) {
this.loading = false;
}
},
immediate: true
}
},
methods: {
// 格式化日期
formatDate(date) {
if (!date) return '';
const d = new Date(date);
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
},
// 打开弹窗
open() {
this.loading = true;
this.$refs.popup.open();
// 延迟关闭加载状态,给内容渲染时间
setTimeout(() => {
this.loading = false;
}, 300);
},
// 关闭弹窗
close() {
this.$refs.popup.close();
}
}
}
</script>
<style lang="scss" scoped>
.detail-popup {
background-color: #fff;
border-radius: 20rpx;
width: 90vw;
max-height: 85vh;
display: flex;
flex-direction: column;
overflow: hidden;
.detail-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1rpx solid #e9ecef;
.detail-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
}
.loading-container {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60rpx 0;
box-sizing: border-box;
.loading-text {
font-size: 28rpx;
color: #666;
margin-top: 20rpx;
}
}
.detail-content {
flex: 1;
padding: 30rpx;
box-sizing: border-box;
max-height: 65vh;
}
.detail-info {
.empty-detail {
display: flex;
align-items: center;
justify-content: center;
padding: 100rpx 0;
.empty-text {
font-size: 28rpx;
color: #999;
}
}
.info-section {
margin-bottom: 40rpx;
&:last-child {
margin-bottom: 0;
}
.section-title {
font-size: 28rpx;
font-weight: 500;
color: #333;
margin-bottom: 20rpx;
padding-left: 20rpx;
border-left: 4rpx solid #007bff;
}
.info-item {
display: flex;
margin-bottom: 16rpx;
&:last-child {
margin-bottom: 0;
}
.label {
font-size: 26rpx;
color: #666;
width: 140rpx;
flex-shrink: 0;
}
.value {
font-size: 26rpx;
color: #333;
flex: 1;
word-break: break-all;
}
}
.content-box {
background-color: #f8f9fa;
border-radius: 12rpx;
padding: 20rpx;
min-height: 100rpx;
text {
font-size: 26rpx;
color: #333;
line-height: 1.6;
}
// 自定义mp-html样式
:deep(.mp-html) {
font-size: 26rpx;
color: #333;
line-height: 1.6;
p {
margin: 0;
padding: 0;
}
}
}
}
}
}
</style>