Files
sh-app/components/nbd-anti-record.vue
T
2026-07-02 19:36:49 +08:00

360 lines
8.0 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>
<view class="anti-record">
<!-- 加载中 -->
<view v-if="loading" class="anti-record__loading">
<text class="anti-record__loading-text">加载中...</text>
</view>
<!-- 无记录 -->
<view v-else-if="!loading && list.length === 0" class="anti-record__empty">
<text class="anti-record__empty-text">暂无防腐记录</text>
</view>
<!-- 有记录 -->
<template v-else>
<view class="anti-record__section">
<view class="anti-record__header">
<view class="anti-record__bar"></view>
<text class="anti-record__title">防腐记录</text>
<text
v-if="list.length > 1"
class="anti-record__more"
@click="showPopup = true"
>查看全部({{ list.length }})</text>
</view>
<!-- 最新一条记录 -->
<view class="anti-record__card" v-if="latest">
<view class="anti-record__row">
<text class="anti-record__label">检查结果</text>
<view class="anti-record__tag" :class="latest.CheckResult === '合格' ? 'anti-record__tag--pass' : 'anti-record__tag--fail'">
<text class="anti-record__tag-icon">{{ latest.CheckResult === '合格' ? '\u2713' : '\u2717' }}</text>
<text class="anti-record__tag-text">{{ latest.CheckResult || '--' }}</text>
</view>
</view>
<view class="anti-record__row">
<text class="anti-record__label">防腐等级</text>
<text class="anti-record__value">{{ latest.AnticorrosionLevel || '--' }}</text>
</view>
<view class="anti-record__row">
<text class="anti-record__label">检查时间</text>
<text class="anti-record__value">{{ latest.CheckTime || '--' }}</text>
</view>
<view v-if="latest.CheckResult === '不合格' && latest.UnqualifiedReason" class="anti-record__row anti-record__row--stack">
<text class="anti-record__label">不合格原因</text>
<text class="anti-record__value anti-record__value--fail">{{ latest.UnqualifiedReason }}</text>
</view>
</view>
</view>
<!-- 弹窗全部记录 -->
<view class="anti-record__overlay" v-if="showPopup" @click="showPopup = false">
<view class="anti-record__popup" @click.stop>
<view class="anti-record__popup-hd">
<text class="anti-record__popup-title">全部防腐记录</text>
<text class="anti-record__popup-close" @click="showPopup = false"></text>
</view>
<scroll-view class="anti-record__popup-bd" scroll-y>
<view
v-for="(item, index) in list"
:key="index"
class="anti-record__card anti-record__card--popup"
:class="item.CheckResult === '合格' ? 'anti-record__card--pass' : 'anti-record__card--fail'"
>
<view class="anti-record__row">
<text class="anti-record__label">检查结果</text>
<view class="anti-record__tag" :class="item.CheckResult === '合格' ? 'anti-record__tag--pass' : 'anti-record__tag--fail'">
<text class="anti-record__tag-icon">{{ item.CheckResult === '合格' ? '\u2713' : '\u2717' }}</text>
<text class="anti-record__tag-text">{{ item.CheckResult || '--' }}</text>
</view>
</view>
<view class="anti-record__row">
<text class="anti-record__label">防腐等级</text>
<text class="anti-record__value">{{ item.AnticorrosionLevel || '--' }}</text>
</view>
<view class="anti-record__row">
<text class="anti-record__label">检查时间</text>
<text class="anti-record__value">{{ item.CheckTime || '--' }}</text>
</view>
<view v-if="item.CheckResult === '不合格' && item.UnqualifiedReason" class="anti-record__row anti-record__row--stack">
<text class="anti-record__label">不合格原因</text>
<text class="anti-record__value anti-record__value--fail">{{ item.UnqualifiedReason }}</text>
</view>
</view>
</scroll-view>
</view>
</view>
</template>
</view>
</template>
<script setup>
import { ref, computed, watch } from 'vue'
import { reqGetAntiCorrosionCheck } from '@/api/hj.js'
const props = defineProps({
params: { type: Object, default: () => ({}) }
})
const list = ref([])
const loading = ref(false)
const showPopup = ref(false)
const latest = computed(() => list.value[0] || null)
const fetchRecords = async () => {
const { materialCode, projectId } = props.params
if (!materialCode || !projectId) return
loading.value = true
try {
const res = await reqGetAntiCorrosionCheck(props.params)
if (res.code === 1 && res.data) {
list.value = res.data
}
} catch (err) {
console.error('获取防腐记录失败:', err)
} finally {
loading.value = false
}
}
const materialCode = computed(() => props.params?.materialCode)
const projectId = computed(() => props.params?.projectId)
watch([materialCode, projectId], fetchRecords, { immediate: true })
</script>
<style lang="scss" scoped>
$primary: #2979ff;
$bg: #f4f2ee;
$card-bg: #fff;
$card-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.06);
$text: #1a1a2e;
$text-secondary: #8e99a4;
.anti-record {
&__loading,
&__empty {
padding: 40rpx 24rpx;
text-align: center;
}
&__loading-text,
&__empty-text {
font-size: 26rpx;
color: $text-secondary;
}
&__section {
margin: 0 24rpx 20rpx;
}
&__header {
display: flex;
align-items: center;
margin-bottom: 12rpx;
}
&__bar {
width: 6rpx;
height: 32rpx;
border-radius: 3rpx;
background: $primary;
margin-right: 14rpx;
}
&__title {
font-size: 30rpx;
font-weight: 700;
color: $text;
flex: 1;
}
&__more {
font-size: 24rpx;
color: $primary;
padding: 6rpx 16rpx;
background: rgba($primary, 0.08);
border-radius: 20rpx;
}
&__card {
position: relative;
box-sizing: border-box;
width: 100%;
background: $card-bg;
border-radius: 12rpx;
padding: 20rpx;
box-shadow: $card-shadow;
overflow: hidden;
&::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 6rpx;
transition: background 0.3s;
}
&--pass::before {
background: #22c55e;
}
&--fail::before {
background: #ef4444;
}
}
&__row {
display: flex;
align-items: center;
padding: 8rpx 0;
& + & {
border-top: 1rpx solid #f0f0f0;
}
&--stack {
flex-direction: column;
align-items: flex-start;
.anti-record__value {
margin-top: 8rpx;
width: 100%;
}
}
}
&__label {
font-size: 26rpx;
color: $text-secondary;
flex-shrink: 0;
margin-right: 24rpx;
width: 140rpx;
}
&__value {
font-size: 26rpx;
color: $text;
flex: 1;
text-align: left;
&--fail {
color: #dc2626;
font-size: 24rpx;
}
}
&__tag {
display: inline-flex;
align-items: center;
gap: 6rpx;
padding: 6rpx 16rpx;
border-radius: 8rpx;
min-width: 100rpx;
justify-content: center;
&--pass {
background: #ebf9f0;
}
&--fail {
background: #fef2f2;
}
&-icon {
font-size: 22rpx;
font-weight: 700;
}
&--pass &-icon {
color: #22c55e;
}
&--fail &-icon {
color: #ef4444;
}
&-text {
font-size: 24rpx;
font-weight: 600;
}
&--pass &-text {
color: #16a34a;
}
&--fail &-text {
color: #dc2626;
}
}
// ===== 弹窗 =====
&__overlay {
position: fixed;
inset: 0;
z-index: 999;
background: rgba(0, 0, 0, 0.45);
display: flex;
align-items: flex-end;
justify-content: center;
}
&__popup {
width: 100%;
height: 70vh;
background: #fff;
border-radius: 24rpx 24rpx 0 0;
display: flex;
flex-direction: column;
animation: slideUp 0.3s ease-out;
}
&__popup-hd {
display: flex;
align-items: center;
justify-content: space-between;
padding: 24rpx 28rpx 12rpx;
border-bottom: 1rpx solid #f0f0f0;
}
&__popup-title {
font-size: 30rpx;
font-weight: 700;
color: $text;
}
&__popup-close {
font-size: 32rpx;
color: $text-secondary;
padding: 8rpx;
}
&__popup-bd {
flex: 1;
box-sizing: border-box;
overflow-y: auto;
background: #f5f5f5;
padding: 12rpx 28rpx 36rpx;
}
&__card--popup {
box-sizing: border-box;
width: 100%;
margin-bottom: 12rpx;
box-shadow: $card-shadow;
}
&__card--popup:last-child {
margin-bottom: 0;
}
}
@keyframes slideUp {
0% { transform: translateY(100%); }
100% { transform: translateY(0); }
}
</style>