Files
sh-app/scanpages/hj/do_anti_rust.vue
T
2026-07-07 18:02:29 +08:00

481 lines
14 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="detail-page">
<!-- 焊口主标识 -->
<view class="joint-hero">
<text class="joint-hero__code">{{ form.MaterialCode || '--' }}</text>
<view class="joint-hero__meta">
<view class="joint-hero__pill">
<text class="pill-label">材料编码</text>
<text class="pill-value">{{ form.Code || '--' }}</text>
</view>
<view class="joint-hero__pill">
<text class="pill-label">材料名称</text>
<text class="pill-value">{{ form.MaterialName }}</text>
</view>
</view>
</view>
<!-- 材料信息 -->
<view class="section">
<view class="section__header">
<view class="section__bar"></view>
<text class="section__title">材料信息</text>
</view>
<view class="card">
<view class="card__row">
<text class="card__label">炉号</text>
<text class="card__value">
{{ form.HeatNo || '--' }}
</text>
</view>
<view class="card__row">
<text class="card__label">批号</text>
<text class="card__value">{{ form.BatchNo || '--' }}</text>
</view>
<view class="card__row">
<text class="card__label">规格</text>
<text class="card__value">{{ form.MaterialSpec || '--' }}</text>
</view>
<view class="card__row">
<text class="card__label">单位</text>
<text class="card__value">{{ form.MaterialUnit || '--' }}</text>
</view>
<view class="card__row card__row--stack">
<text class="card__label">材料描述</text>
<text class="card__value">{{ form.MaterialDef || '--' }}</text>
</view>
</view>
</view>
<!-- 防腐填报 -->
<view class="section">
<view class="section__header">
<view class="section__bar"></view>
<text class="section__title">防腐填报</text>
</view>
<view class="card">
<!-- 防腐等级/涂漆代码下拉选择 -->
<view class="card__row" @click="showPaintCodePicker = true">
<text class="card__label required">防腐等级</text>
<view class="card__value-wrap card__value-wrap--clickable">
<text class="card__value" :class="{ 'card__value--placeholder': !antiForm.AnticorrosionLevel }">
{{ antiForm.AnticorrosionLevel || '请选择防腐等级' }}
</text>
<u-icon name="arrow-down" :size="24" color="#bbb" />
</view>
</view>
<!-- 中间漆 -->
<view class="card__row">
<text class="card__label">中间漆</text>
<view class="card__value-wrap">
{{ antiForm.IntermediatePaint || '--' }}
</view>
</view>
<!-- 面漆 -->
<view class="card__row">
<text class="card__label">面漆</text>
<view class="card__value">
{{ antiForm.Topcoat || '--' }}
</view>
</view>
<!-- 漆膜厚度 -->
<view class="card__row">
<text class="card__label required">漆膜厚度</text>
<view class="card__value-wrap">
<input class="card__input" v-model="antiForm.FilmThickness" type="digit"
placeholder="请输入漆膜厚度" />
<text class="card__unit">μm</text>
</view>
</view>
<!-- 喷砂情况 -->
<view class="card__row card__row--stack">
<text class="card__label">喷砂情况</text>
<view class="card__value-wrap">
<textarea class="remark-input" v-model="antiForm.SandBlasting" placeholder="请输入"
:maxlength="200" auto-height />
</view>
</view>
<!-- 除锈喷砂情况 -->
<view class="card__row card__row--stack">
<text class="card__label">除锈喷砂情况</text>
<view class="card__value-wrap">
<textarea class="remark-input" v-model="antiForm.RustSandBlasting" placeholder="请输入"
:maxlength="200" auto-height />
</view>
</view>
</view>
</view>
<!-- 自检 -->
<view class="section">
<view class="section__header">
<view class="section__bar"></view>
<text class="section__title">自检信息</text>
</view>
<view class="card">
<!-- 自检结果 -->
<view class="card__row">
<text class="card__label">自检结果</text>
<view class="card__value-wrap card__value-wrap--clickable">
<nbd-check-btn v-model="antiForm.CheckResult" passKey="合格" failKey="不合格" passText="合格"
failText="不合格" />
</view>
</view>
<view class="fail-section"
:class="{ 'is-visible': failVisible, 'is-enter': failAnimating, 'is-leave': failLeaving }">
<!-- 不合格原因 -->
<view class="card__row card__row--stack">
<text class="card__label">不合格原因</text>
<view class="card__value-wrap">
<textarea class="remark-input" v-model="antiForm.UnqualifiedReason" placeholder="请输入"
:maxlength="200" auto-height />
</view>
</view>
<!-- 整改要求 -->
<view class="card__row card__row--stack">
<text class="card__label">整改要求</text>
<view class="card__value-wrap">
<textarea class="remark-input" v-model="antiForm.RectifyRequirement" placeholder="请输入"
:maxlength="200" auto-height />
</view>
</view>
</view>
<!-- 备注 -->
<view class="card__row card__row--stack">
<text class="card__label">备注</text>
<view class="card__value-wrap">
<textarea class="remark-input" v-model="antiForm.Remark" placeholder="请输入备注信息(选填)"
:maxlength="200" auto-height />
</view>
</view>
<!-- 照片 -->
<view class="card__row card__row--stack">
<text class="card__label">照片</text>
<view class="card__value-wrap">
<nbd-photo-upload ref="photoRef" v-model:attachUrl="files" typeName="AntiRust" />
</view>
</view>
</view>
</view>
<!-- 防腐记录 -->
<view class="section">
<nbd-record-card title="防腐" :list="antiList" :fields="antiFields" status-key="CheckResult" status-match="合格" />
</view>
<nbd-submit-bar text="提交" :loading="submitting" @click="handleSubmit" />
</view>
<nbd-select v-model="showPaintCodePicker" title="选择防腐等级" :list="paintCodeList" label-key="PaintCode" value-key="Id"
@confirm="selectPaintCode" />
</template>
<script setup>
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { storeToRefs } from 'pinia'
import { watch, nextTick } from 'vue'
import { useUserStore } from '@/store'
import { reqMaterialInfoByMaterialCode, reqPaintCodeList, reqSaveAntiCorrosionCheck, reqGetAntiCorrosionCheck } from '@/api/hj.js'
// 防腐记录字段
const antiFields = [
{ label: '防腐等级', key: 'AnticorrosionLevel' },
{ label: '中间漆', key: 'IntermediatePaint' },
{ label: '面漆', key: 'Topcoat' },
{ label: '漆膜厚度', key: 'FilmThickness' },
{ label: '喷砂情况', key: 'SandBlasting' },
{ label: '除锈喷砂情况', key: 'RustSandBlasting' },
{ label: '检查人', key: 'CheckPersonName' },
{ label: '检查时间', key: 'CheckTime' },
{ label: '检查结果', key: 'CheckResult', type: 'tag', tagMatch: '合格' },
{ label: '不合格原因', key: 'UnqualifiedReason', showWhen: { key: 'CheckResult', notEqual: '合格' } },
{ label: '整改要求', key: 'RectifyRequirement', showWhen: { key: 'CheckResult', notEqual: '合格' } },
{ label: '照片', key: 'AttachUrl1', type: 'photo', cols: 4 },
]
const antiList = ref([])
const userStore = useUserStore()
const { userInfo, currentProject } = storeToRefs(userStore)
const form = ref({})
const showPaintCodePicker = ref(false)
const paintCodeList = ref([])
const files = ref('')
// 防腐填报
const antiForm = ref({
AnticorrosionLevel: '', // 防腐等级(显示用)
PaintId: '', // 防腐代码字典ID
IntermediatePaint: '', // 中间漆
Topcoat: '', // 面漆
FilmThickness: '', // 漆膜厚度 (两位小数,单位μm)
RustSandBlasting: '', // 除锈喷砂信息
SandBlasting: '', // 喷砂信息
Remark: '', // 备注
CheckResult: '合格', // 检查结果
UnqualifiedReason: '', // 不合格原因
RectifyRequirement: '', // 整改要求
})
const photoRef = ref(null)
const submitting = ref(false)
const failVisible = ref(antiForm.value.CheckResult === '不合格')
const failAnimating = ref(false)
const failLeaving = ref(false)
watch(() => antiForm.value.CheckResult, async (val) => {
if (val === '不合格') {
failVisible.value = true
await nextTick()
failAnimating.value = true
failLeaving.value = false
} else {
failLeaving.value = true
failAnimating.value = false
setTimeout(() => {
failVisible.value = false
failLeaving.value = false
}, 250)
}
})
const fetchPaintCodes = async () => {
try {
const res = await reqPaintCodeList()
if (res.code === 1 && res.data) {
paintCodeList.value = res.data
}
} catch (err) {
console.error('获取防腐等级列表失败:', err)
}
}
const selectPaintCode = (item) => {
antiForm.value.PaintId = item.Id
antiForm.value.AnticorrosionLevel = item.PaintCode
antiForm.value.IntermediatePaint = item.IntermediatePaint
antiForm.value.Topcoat = item.Topcoat
showPaintCodePicker.value = false
}
onLoad((opt) => {
fetchPaintCodes()
if (opt?.id) {
loadData(opt.id)
}
})
const loadData = async (id) => {
try {
uni.showLoading({ title: '加载中...', mask: true })
const [res, res1] = await Promise.all([
reqMaterialInfoByMaterialCode(encodeURIComponent(id)),
reqGetAntiCorrosionCheck({ materialCode: id, projectId: currentProject.value.ProjectId })
])
if (res.code === 1 && res.data) {
form.value = res.data
}
if (res1.code === 1 && res1.data) {
antiList.value = res1.data
let antiData = res1.data
if (antiData && antiData.length > 0) {
antiForm.value = {
...antiData[0],
CheckResult: '合格',
UnqualifiedReason: '',
RectifyRequirement: '',
Remark: ''
}
}
}
} catch (err) {
console.error('加载焊口数据失败:', err)
uni.showToast({ title: '加载失败', icon: 'none' })
} finally {
uni.hideLoading()
}
}
// 提交
const handleSubmit = async () => {
if (!antiForm.value.PaintId) {
uni.showToast({ title: '请选择防腐等级', icon: 'none' })
return
}
if (!antiForm.value.UnqualifiedReason && antiForm.value.CheckResult === '不合格') {
uni.showToast({ title: '请输入不合格原因', icon: 'none' })
return
}
if (!antiForm.value.RectifyRequirement && antiForm.value.CheckResult === '不合格') {
uni.showToast({ title: '请输入整改要求', icon: 'none' })
return
}
uni.showModal({
title: '确认提交',
content: '确定提交防腐处理结果吗?',
success: async (res) => {
if (res.confirm) {
submitting.value = true
if (photoRef.value?.hasPending()) {
uni.showLoading({ title: '上传照片中...', mask: true })
await photoRef.value.uploadAll()
uni.hideLoading()
}
let data = {
ProjectId: currentProject.value.ProjectId, // 项目ID
MaterialCode: form.value.MaterialCode, // 材料编码
AnticorrosionLevel: antiForm.value.AnticorrosionLevel, // 防腐等级
PaintId: antiForm.value.PaintId, // 防腐代码字典ID
FilmThickness: antiForm.value.FilmThickness, // 漆膜厚度
SandBlasting: antiForm.value.SandBlasting, // 喷砂信息
RustSandBlasting: antiForm.value.RustSandBlasting, // 除锈喷砂信息
Remark: antiForm.value.Remark, // 备注
CheckResult: antiForm.value.CheckResult, // 检查结果
UnqualifiedReason: antiForm.value.UnqualifiedReason, // 不合格原因
RectifyRequirement: antiForm.value.RectifyRequirement, // 整改要求
CheckPerson: userInfo.value.PersonId, // 检查人员
CheckTime: uni.formatTime(new Date().getTime(), 'YYYY-MM-DD HH:mm'), // 检查时间
CreateUser: userInfo.PersonId, // 创建人员
AttachUrl1: files.value, // 照片
}
console.log("提交数据==============>", data)
try {
const res = await reqSaveAntiCorrosionCheck(data)
if (res.code === 1) {
uni.showToast({ title: '提交成功', icon: 'success' })
setTimeout(() => uni.navigateBack(), 1500)
} else {
uni.showToast({ title: res.msg || '提交失败', icon: 'none' })
}
} catch (err) {
console.error('提交防腐填报失败:', err)
uni.showToast({ title: '提交失败', icon: 'none' })
} finally {
submitting.value = false
}
}
}
})
}
</script>
<style lang="scss" scoped>
// 继承全局变量(定义在 uni.scss)
$primary: $app-primary;
$primary-light: $app-primary-light;
$primary-mid: $app-primary-mid;
$primary-dark: $app-primary-dark;
$text: $app-text;
$text-secondary: $app-text-secondary;
$border: $app-border;
$radius: $app-radius;
// 页面专属
$bg: #f4f2ee;
$card-bg: #fefdfb;
$shadow-md: 0 2rpx 12rpx rgba(0, 0, 0, 0.04), 0 8rpx 24rpx rgba(0, 0, 0, 0.06);
.detail-page {
background: $bg;
}
// ===== 焊口主标识 =====
.joint-hero {
position: relative;
margin: 24rpx;
padding: 36rpx 32rpx 28rpx;
background: $card-bg;
border-radius: $radius;
box-shadow: $shadow-md;
overflow: hidden;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4rpx;
background: linear-gradient(90deg, $primary, #6ba3ff, $primary);
background-size: 200% 100%;
animation: shimmer 3s ease-in-out infinite;
}
@keyframes shimmer {
0%,
100% {
background-position: 0% 0;
}
50% {
background-position: 100% 0;
}
}
&__code {
display: block;
font-size: 52rpx;
font-weight: 800;
color: $text;
line-height: 1.2;
word-break: break-all;
font-family: monospace;
letter-spacing: 2rpx;
margin-bottom: 28rpx;
position: relative;
padding-left: 24rpx;
&::before {
content: '';
position: absolute;
left: 0;
top: 6rpx;
bottom: 6rpx;
width: 4rpx;
background: $primary;
border-radius: 2rpx;
}
}
&__meta {
display: flex;
flex-wrap: wrap;
gap: 12rpx;
}
&__pill {
display: inline-flex;
width: 100%;
align-items: center;
gap: 8rpx;
background: $primary-light;
padding: 10rpx 18rpx;
border-radius: 10rpx;
border: 1rpx solid $primary-mid;
.pill-label {
font-size: 22rpx;
color: $text-secondary;
width: 60rpx;
}
.pill-value {
font-size: 24rpx;
font-weight: 600;
color: $primary-dark;
font-family: monospace;
}
}
}
</style>