Files
shj-app/components/nbd-history-card.vue
2026-08-18 18:05:16 +08:00

340 lines
8.5 KiB
Vue
Raw Permalink 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="history-card">
<!-- 空态 -->
<view v-if="list.length === 0" class="history-card__empty">
<text class="history-card__empty-text">暂无{{ title }}记录</text>
</view>
<!-- 有记录 -->
<template v-else>
<view class="history-card__section">
<view class="history-card__header">
<view class="history-card__bar"></view>
<text class="history-card__title">{{ title }}记录</text>
<text v-if="list.length > 1" class="history-card__more" @click="showPopup = true">查看全部({{ list.length }})</text>
</view>
<!-- 最新一条 -->
<view v-if="latest" class="history-card__card"
:class="isPass(latest) ? 'history-card__card--pass' : 'history-card__card--fail'">
<view class="history-card__row">
<text class="history-card__label">外观是否合格</text>
<view class="history-card__tag" :style="tagBgStyle(latest)">
<text class="history-card__tag-icon" :style="tagIconStyle(latest)">
{{ isPass(latest) ? '\u2713' : '\u2717' }}
</text>
<text class="history-card__tag-text" :style="tagTextStyle(latest)">
{{ qualifiedText(latest) }}
</text>
</view>
</view>
<view v-for="field in extraFields" :key="field.key" class="history-card__row">
<text class="history-card__label">{{ field.label }}</text>
<text class="history-card__value">{{ latest[field.key] || '--' }}</text>
</view>
<view class="history-card__row">
<text class="history-card__label">检测人</text>
<text class="history-card__value">{{ latest.CheckPersonName || '--' }}</text>
</view>
<view class="history-card__row">
<text class="history-card__label">检测时间</text>
<text class="history-card__value">{{ latest.CheckTime || '--' }}</text>
</view>
<view class="history-card__row">
<text class="history-card__label">备注</text>
<text class="history-card__value">{{ latest.Remark || '--' }}</text>
</view>
<view class="history-card__row history-card__row--stack">
<text class="history-card__label history-card__label--stack">照片</text>
<view class="history-card__value--stack">
<nbd-photo-view :attachUrl="latest.AttachUrl || ''" :cols="4" />
</view>
</view>
</view>
</view>
<!-- 弹窗:全部记录 -->
<u-popup v-model="showPopup" mode="bottom" :safe-area-inset-bottom="true">
<view class="history-card__popup">
<view class="history-card__popup-hd">
<text class="history-card__popup-title">全部{{ title }}记录</text>
<text class="history-card__popup-close" @click="showPopup = false">✕</text>
</view>
<scroll-view class="history-card__popup-bd" scroll-y>
<view v-for="(item, index) in list" :key="item.AppearanceCheckId || index"
class="history-card__card history-card__card--popup"
:class="isPass(item) ? 'history-card__card--pass' : 'history-card__card--fail'">
<view class="history-card__row">
<text class="history-card__label">外观是否合格</text>
<view class="history-card__tag" :style="tagBgStyle(item)">
<text class="history-card__tag-icon" :style="tagIconStyle(item)">
{{ isPass(item) ? '\u2713' : '\u2717' }}
</text>
<text class="history-card__tag-text" :style="tagTextStyle(item)">
{{ qualifiedText(item) }}
</text>
</view>
</view>
<view v-for="field in extraFields" :key="field.key" class="history-card__row">
<text class="history-card__label">{{ field.label }}</text>
<text class="history-card__value">{{ item[field.key] || '--' }}</text>
</view>
<view class="history-card__row">
<text class="history-card__label">检测人</text>
<text class="history-card__value">{{ item.CheckPersonName || '--' }}</text>
</view>
<view class="history-card__row">
<text class="history-card__label">检测时间</text>
<text class="history-card__value">{{ item.CheckTime || '--' }}</text>
</view>
<view class="history-card__row">
<text class="history-card__label">备注</text>
<text class="history-card__value">{{ item.Remark || '--' }}</text>
</view>
<view class="history-card__row history-card__row--stack">
<text class="history-card__label history-card__label--stack">照片</text>
<view class="history-card__value--stack">
<nbd-photo-view :attachUrl="item.AttachUrl || ''" :cols="4" />
</view>
</view>
</view>
</scroll-view>
</view>
</u-popup>
</template>
</view>
</template>
<script setup>
import {
ref,
computed
} from 'vue'
const props = defineProps({
list: {
type: Array,
default: () => []
},
title: {
type: String,
default: '外观检测'
},
})
const showPopup = ref(false)
const latest = computed(() => props.list[0] || null)
const extraFields = [
{ label: '焊缝余高', key: 'WeldReinforcement' },
{ label: '焊缝高度', key: 'WeldHeight' },
{ label: '焊缝宽度', key: 'WeldWidth' },
{ label: '表面缺陷', key: 'SurfaceDefect' },
{ label: '预热温度', key: 'PreheatTemperature' },
{ label: '层间温度', key: 'InterpassTemperature' },
]
const isPass = (item) => item?.IsQualified === true
const qualifiedText = (item) => {
if (item?.QualifiedText) return item.QualifiedText
return isPass(item) ? '合格' : '不合格'
}
const tagIconStyle = (item) => ({
color: isPass(item) ? '#22c55e' : '#ef4444',
})
const tagTextStyle = (item) => ({
color: isPass(item) ? '#16a34a' : '#dc2626',
})
const tagBgStyle = (item) => ({
background: isPass(item) ? '#ebf9f0' : '#fef2f2',
})
</script>
<style lang="scss" scoped>
$primary: #2979ff;
$card-bg: #fff;
$card-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.06);
$text: #1a1a2e;
$text-secondary: #8e99a4;
.history-card {
&__empty {
padding: 40rpx 24rpx;
text-align: center;
}
&__empty-text {
font-size: 26rpx;
color: $text-secondary;
}
&__header {
display: flex;
align-items: center;
margin-bottom: 12rpx;
padding: 0 6rpx;
}
&__bar {
width: 6rpx;
height: 32rpx;
border-radius: 3rpx;
background: $primary;
margin-right: 14rpx;
}
&__title {
font-size: 28rpx;
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;
right: 0;
height: 6rpx;
}
&--pass::before {
background: #22c55e;
}
&--fail::before {
background: #ef4444;
}
&--popup {
margin-bottom: 12rpx;
&:last-child {
margin-bottom: 0;
}
}
}
&__row {
display: flex;
align-items: center;
padding: 8rpx 0;
border-bottom: 1rpx solid #f0f0f0;
&--stack {
flex-direction: column;
align-items: flex-start;
}
}
&__label {
font-size: 26rpx;
color: $text-secondary;
flex-shrink: 0;
margin-right: 24rpx;
width: 160rpx;
&--stack {
width: 140rpx;
margin-top: 8rpx;
}
}
&__value {
flex: 1;
text-align: left;
font-family: "SF Mono", "Menlo", "Consolas", monospace;
font-size: 28rpx;
font-weight: 500;
color: #0f1724;
letter-spacing: 0.3rpx;
&--stack {
padding: 8rpx 0 8rpx 20rpx;
width: 100%;
box-sizing: border-box;
}
}
&__tag {
display: inline-flex;
align-items: center;
gap: 6rpx;
padding: 6rpx 16rpx;
border-radius: 8rpx;
min-width: 100rpx;
justify-content: center;
&-icon {
font-size: 22rpx;
font-weight: 700;
}
&-text {
font-size: 24rpx;
font-weight: 600;
}
}
&__popup {
background: #fff;
display: flex;
flex-direction: column;
height: 80vh;
border-radius: 24rpx 24rpx 0 0;
}
&__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 20rpx 20rpx;
}
}
</style>