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

651 lines
20 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">{{ info.WeldJointCode || '--' }}</text>
<view class="joint-hero__meta">
<view class="joint-hero__pill">
<text class="pill-label">管线编码</text>
<text class="pill-value">{{ info.PipelineCode || '--' }}</text>
</view>
<view class="joint-hero__pill">
<text class="pill-label">项目名称</text>
<text class="pill-value">{{ info.ProjectName || info.ProjectId || '--' }}</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="showGrooveTypePicker = true">
<text class="card__label">坡口类型名称</text>
<view class="card__value-wrap card__value-wrap--clickable">
<text class="card__value"
:class="{ 'card__value--placeholder': !makeRightForm.GrooveTypeName }">
{{ makeRightForm.GrooveTypeName || '请选择坡口类型' }}
</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">
{{ makeRightForm.GrooveTypeCode || '--' }}
</view>
</view>
<!-- 坡口加工类型 -->
<view class="card__row">
<text class="card__label">坡口加工类型</text>
<view class="card__value-wrap">
<input class="card__input" v-model="makeRightForm.GrooveProcessType" type="text"
placeholder="请输入坡口加工类型" />
</view>
</view>
<!-- 坡口角度 -->
<view class="card__row">
<text class="card__label">坡口角度</text>
<view class="card__value-wrap">
<input class="card__input" v-model="makeRightForm.GrooveAngle" type="digit"
placeholder="请输入坡口角度" />
</view>
</view>
<!-- 组对间隙 -->
<view class="card__row">
<text class="card__label">组对间隙</text>
<view class="card__value-wrap">
<input class="card__input" v-model="makeRightForm.FitupGap" type="digit"
placeholder="请输入组对间隙" />
</view>
</view>
<!-- 错边量 -->
<view class="card__row">
<text class="card__label">错边量</text>
<view class="card__value-wrap">
<input class="card__input" v-model="makeRightForm.Misalignment" type="digit"
placeholder="请输入错边量" />
</view>
</view>
<!-- 焊缝余高 -->
<view class="card__row">
<text class="card__label">焊缝余高</text>
<view class="card__value-wrap">
<input class="card__input" v-model="makeRightForm.WeldReinforcement" type="digit"
placeholder="请输入焊缝余高" />
</view>
</view>
<!-- 焊缝高度 -->
<view class="card__row">
<text class="card__label">焊缝高度</text>
<view class="card__value-wrap">
<input class="card__input" v-model="makeRightForm.WeldHeight" type="digit"
placeholder="请输入焊缝高度" />
</view>
</view>
<!-- 焊缝宽度 -->
<view class="card__row">
<text class="card__label">焊缝宽度</text>
<view class="card__value-wrap">
<input class="card__input" v-model="makeRightForm.WeldWidth" type="digit"
placeholder="请输入焊缝宽度" />
</view>
</view>
<!-- 表面缺陷 -->
<view class="card__row">
<text class="card__label">表面缺陷</text>
<view class="card__value-wrap">
<input class="card__input" v-model="makeRightForm.SurfaceDefect" type="text"
placeholder="请输入表面缺陷" />
</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="makeRightForm.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="makeRightForm.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="makeRightForm.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="makeRightForm.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="formAttachUrl" typeName="AntiRust" />
</view>
</view>
</view>
</view>
<!-- 组对记录 -->
<view class="section">
<nbd-record-card title="组对" :list="fitupList" :fields="fitupFields" status-key="CheckResult"
status-match="合格" />
</view>
<!-- 下料记录 -->
<view class="section">
<nbd-record-card title="下料" :list="cuttingList" :fields="cuttingFields" status-key="CheckResult"
status-match="合格" />
<view class="nav-row" @click="handleMutualCheck">
<view class="nav-row__left">
<view class="nav-row__dot"></view>
<text class="nav-row__label">互检上一工序</text>
</view>
<text class="nav-row__arrow"></text>
</view>
</view>
<block v-for="(item, index) in info.preWeldMaterialItems" :key="item.MaterialCode || index">
<!-- 材料信息 -->
<view class="section">
<view class="section__header">
<view class="section__bar"></view>
<text class="section__title">{{ item.MaterialName || item.MaterialCode || '--' }}</text>
</view>
<view class="card">
<view class="card__row">
<text class="card__label">炉号</text>
<text class="card__value">
{{ item.HeatNo || '--' }}
</text>
</view>
<view class="card__row">
<text class="card__label">批号</text>
<text class="card__value">{{ item.BatchNo || '--' }}</text>
</view>
<view class="card__row">
<text class="card__label">规格</text>
<text class="card__value">{{ item.MaterialSpec || '--' }}</text>
</view>
<view class="card__row">
<text class="card__label">单位</text>
<text class="card__value">{{ item.MaterialUnit || '--' }}</text>
</view>
<view class="card__row card__row--stack">
<text class="card__label">材料描述</text>
<text class="card__value">{{ item.MaterialDef || '--' }}</text>
</view>
</view>
</view>
</block>
<!-- 提交按钮 -->
<view class="submit-bar">
<view class="btn-primary-gradient" @click="handleSubmit">
<text class="btn-primary-gradient__text">提交结果</text>
</view>
</view>
</view>
<nbd-select v-model="showGrooveTypePicker" title="选择坡口类型" :list="grooveTypeList" label-key="BaseInfoName"
value-key="BaseInfoCode" @confirm="selectGrooveType" />
</template>
<script setup>
import { ref, watch, nextTick } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { storeToRefs } from 'pinia'
import { useUserStore } from '@/store'
import { reqPreWeldJointByWeldJointId, reqSaveFitupCheck, reqCuttingCheckByWeldJointId, reqFitupCheckByWeldJointId } from '@/api/hj'
import { reqGetGrooveTypeList } from '@/api/base'
const cuttingFields = [
{ label: '下料长度', key: 'CuttingLength' },
{ label: '坡口形式', key: 'GrooveForm' },
{ label: '坡口角度', key: 'GrooveAngle' },
{ label: '材料编码批次', key: 'IsMaterialCodeBatchNoAccurate', type: 'tag', tagMatch: true, tagPassText: '准确', tagFailText: '不准确' },
{ label: '材料数量', key: 'IsMaterialQuantityAccurate', type: 'tag', tagMatch: true, tagPassText: '准确', tagFailText: '不准确' },
{ 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 fitupFields = [
{ label: '坡口类型名称', key: 'GrooveTypeName' },
{ label: '坡口类型编码', key: 'GrooveTypeCode' },
{ label: '坡口加工类型', key: 'GrooveProcessType' },
{ label: '坡口角度', key: 'GrooveAngle' },
{ label: '组对间隙', key: 'FitupGap' },
{ label: '错边量', key: 'Misalignment' },
{ label: '焊缝余高', key: 'WeldReinforcement' },
{ label: '焊缝高度', key: 'WeldHeight' },
{ label: '焊缝宽度', key: 'WeldWidth' },
{ label: '表面缺陷', key: 'SurfaceDefect' },
{ 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 cuttingList = ref([])
const fitupList = ref([])
const userStore = useUserStore()
const { userInfo, currentProject } = storeToRefs(userStore)
const info = ref({})
const remark = ref('')
const formAttachUrl = ref('')
const id = ref('')
const makeRightForm = ref({
GrooveTypeId: '', // 坡口类型ID
GrooveTypeName: '', // 坡口类型名称
GrooveTypeCode: '', // 坡口类型编码
GrooveProcessType: '', // 坡口加工类型
GrooveAngle: '', // 坡口角度
FitupGap: '', // 组对间隙
Misalignment: '', // 错边量
WeldReinforcement: '', // 焊缝余高
WeldHeight: '', // 焊缝高度
WeldWidth: '', // 焊缝宽度
SurfaceDefect: '', // 表面缺陷
CheckResult: '合格', // 检查结果
UnqualifiedReason: '', // 不合格原因
RectifyRequirement: '', // 整改要求
Remark: '', // 备注
})
const showGrooveTypePicker = ref(false)
const grooveTypeList = ref([])
// 照片组件引用
const photoRef = ref(null)
const failVisible = ref(makeRightForm.value.CheckResult === '不合格')
const failAnimating = ref(false)
const failLeaving = ref(false)
watch(() => makeRightForm.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 handleMutualCheck = () => {
uni.navigateTo({ url: '/scanpages/hj/material_sampling?id=' + id.value })
}
const handleSubmit = () => {
uni.showModal({
title: '确认提交',
content: '确定提交吗?',
success: async (res) => {
if (res.confirm) {
if (photoRef.value?.hasPending()) {
uni.showLoading({ title: '上传照片中...', mask: true })
await photoRef.value.uploadAll()
uni.hideLoading()
}
const CuttingAttachUrl1 = formAttachUrl.value||''
const params = {
ProjectId: currentProject.value?.ProjectId, // 项目ID
WeldJointId: info.value?.WeldJointId, // 焊口ID
GrooveTypeId: makeRightForm.value.GrooveTypeId, // 坡口类型ID
GrooveTypeCode: makeRightForm.value.GrooveTypeCode, // 坡口类型编码
GrooveTypeName: makeRightForm.value.GrooveTypeName, // 坡口类型名称
GrooveProcessType: makeRightForm.value.GrooveProcessType, // 坡口加工类型
GrooveAngle: makeRightForm.value.GrooveAngle, // 坡口角度
FitupGap: makeRightForm.value.FitupGap, // 组对间隙
Misalignment: makeRightForm.value.Misalignment, // 错边量
WeldReinforcement: makeRightForm.value.WeldReinforcement, // 焊缝余高
WeldHeight: makeRightForm.value.WeldHeight, // 焊缝高度
WeldWidth: makeRightForm.value.WeldWidth, // 焊缝宽度
SurfaceDefect: makeRightForm.value.SurfaceDefect, // 表面缺陷
CheckTime: uni.formatTime(new Date().getTime(), 'YYYY-MM-DD HH:mm'), // 检查时间
CreateUser: userInfo.value?.PersonId, // 创建人员
CheckPerson: userInfo.value?.PersonId, // 检查人员
CheckResult: makeRightForm.value.CheckResult, // 检查结果
Remark: remark.value, // 备注
UnqualifiedReason: makeRightForm.value.UnqualifiedReason, // 不合格原因
RectifyRequirement: makeRightForm.value.RectifyRequirement, // 整改要求
AttachUrl1: CuttingAttachUrl1,
}
console.log('提交参数:', params)
await reqSaveFitupCheck(params)
uni.showToast({ title: '提交成功', icon: 'none' })
setTimeout(() => { uni.navigateBack() }, 1500)
}
}
})
}
const selectGrooveType = (item) => {
makeRightForm.value.GrooveTypeId = item.BaseInfoId
makeRightForm.value.GrooveTypeCode = item.BaseInfoCode
makeRightForm.value.GrooveTypeName = item.BaseInfoName
showGrooveTypePicker.value = false
}
const fetchGrooveTypes = async () => {
try {
const res = await reqGetGrooveTypeList()
if (res.code === 1 && res.data) {
grooveTypeList.value = res.data
}
} catch (err) {
console.error('获取坡口类型列表失败:', err)
}
}
onLoad((opt) => {
fetchGrooveTypes()
if (opt.id) {
id.value = opt.id
getInfo(opt.id)
}
})
const getInfo = async (id) => {
try {
uni.showLoading({ title: '加载中...', mask: true })
const res = await reqPreWeldJointByWeldJointId(id)
if (res.code === 1) {
info.value = res.data
// 获取下料记录
if (info.value.WeldJointId) {
const cuttingRes = await reqCuttingCheckByWeldJointId(info.value.WeldJointId)
if (cuttingRes.code === 1 && cuttingRes.data) {
cuttingList.value = cuttingRes.data
}
const fitupRes = await reqFitupCheckByWeldJointId(info.value.WeldJointId)
if (fitupRes.code === 1 && fitupRes.data) {
fitupList.value = fitupRes.data
if (fitupRes.data.length > 0) {
makeRightForm.value.GrooveTypeId = fitupRes.data[0].GrooveTypeId
makeRightForm.value.GrooveTypeCode = fitupRes.data[0].GrooveTypeCode
makeRightForm.value.GrooveTypeName = fitupRes.data[0].GrooveTypeName
makeRightForm.value.GrooveProcessType = fitupRes.data[0].GrooveProcessType
makeRightForm.value.GrooveAngle = fitupRes.data[0].GrooveAngle
makeRightForm.value.FitupGap = fitupRes.data[0].FitupGap
makeRightForm.value.Misalignment = fitupRes.data[0].Misalignment
makeRightForm.value.WeldReinforcement = fitupRes.data[0].WeldReinforcement
makeRightForm.value.WeldHeight = fitupRes.data[0].WeldHeight
makeRightForm.value.WeldWidth = fitupRes.data[0].WeldWidth
makeRightForm.value.SurfaceDefect = fitupRes.data[0].SurfaceDefect
}
}
}
}
} catch (error) {
console.error('获取焊口详情失败:', error)
uni.showToast({ title: '加载失败', icon: 'none' })
} finally {
uni.hideLoading()
}
}
</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: #f0f2f5;
$card-bg: #ffffff;
$shadow-md: 0 4rpx 16rpx 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;
}
}
}
// ===== 提交栏(悬浮底部) =====
.submit-bar {
position: fixed;
left: 0;
right: 0;
bottom: 0;
padding: 20rpx 24rpx;
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
background: linear-gradient(180deg, rgba(240, 242, 245, 0) 0%, $bg 20%);
}
// ================================================================
// 材料质检区块 —— 三合一 section
// ================================================================
// section 容器:微背景 + 内边距聚合三个子元素
.section {
background: #fafbfc;
border-radius: 20rpx;
padding: 24rpx 0 0;
margin-bottom: 28rpx;
box-shadow: $shadow-md;
}
// ---- 材料详情卡片 ----
// 底部圆角清零,与下方 nav-row 无缝衔接
.card {
border-radius: $radius $radius 0 0;
box-shadow: none;
}
// 编码类字段(炉号 / 批号 / 规格 / 单位)→ monospace
.card__value {
font-family: 'SF Mono', 'Menlo', 'Consolas', monospace;
font-size: 28rpx;
font-weight: 500;
color: $text;
letter-spacing: 0.3rpx;
}
// 材料描述 → 回退系统字体
.card__row--stack .card__value {
font-family: inherit;
font-size: 26rpx;
font-weight: 400;
letter-spacing: normal;
color: $text-secondary;
}
// ---- 互检导航按钮 ----
.nav-row {
display: flex;
align-items: center;
justify-content: space-between;
margin: 0;
padding: 24rpx 28rpx;
background: $card-bg;
border-radius: 0;
border-top: 1rpx solid $border;
box-shadow: none;
transition: background 0.2s ease;
margin-bottom: 28rpx;
&:active {
background: #f5f7fa;
}
&__left {
display: flex;
align-items: center;
gap: 14rpx;
}
&__dot {
width: 10rpx;
height: 10rpx;
border-radius: 50%;
background: $primary;
flex-shrink: 0;
}
&__label {
font-size: 28rpx;
font-weight: 600;
color: $text;
letter-spacing: 1rpx;
}
&__arrow {
font-size: 36rpx;
color: $text-secondary;
font-weight: 300;
line-height: 1;
margin-right: -4rpx;
}
}
</style>