Files
shj-app/scanpages/hj/weld_task_detail.vue

326 lines
8.0 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="detail-page">
<!-- 任务单摘要 -->
<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 card__value--mono">{{ detail.TaskCode || '--' }}</text>
</view>
<view class="card__row">
<text class="card__label">任务日期</text>
<text class="card__value">{{ fmtDate(detail.TaskDate) }}</text>
</view>
<view class="card__row">
<text class="card__label">单位工程</text>
<text class="card__value">{{ detail.UnitWorkName || '--' }}</text>
</view>
<view class="card__row">
<text class="card__label">施工单位</text>
<text class="card__value">{{ detail.UnitName || '--' }}</text>
</view>
<view class="card__row">
<text class="card__label">班组</text>
<text class="card__value">{{ detail.TeamGroupName || '--' }}</text>
</view>
<view class="card__row">
<text class="card__label">流水号</text>
<text class="card__value">{{ detail.SerialNumber || '--' }}</text>
</view>
<view class="card__row">
<text class="card__label">焊口数量</text>
<text class="card__value">{{ detail.WeldJointCount != null ? detail.WeldJointCount : joints.length }}</text>
</view>
</view>
</view>
<!-- 焊口明细 -->
<view class="section">
<view class="section__header">
<view class="section__bar"></view>
<text class="section__title">焊口明细({{ joints.length }})</text>
</view>
<view
v-for="(item, index) in joints"
:key="item.WeldTaskId || item.WeldJointId || index"
class="card joint-card"
>
<view class="joint-card__title">{{ item.WeldJointCode || '--' }}</view>
<view class="card__row">
<text class="card__label">管线编号</text>
<text class="card__value">{{ item.PipelineCode || '--' }}</text>
</view>
<view class="card__row">
<text class="card__label">焊口属性</text>
<text class="card__value">{{ item.JointAttribute || '--' }}</text>
</view>
<view class="card__row">
<text class="card__label">焊接模式</text>
<text class="card__value">{{ item.WeldingMode || '--' }}</text>
</view>
<view class="card__row">
<text class="card__label">焊接类型</text>
<text class="card__value">{{ item.WeldTypeCode || '--' }}</text>
</view>
<view class="card__row">
<text class="card__label">达因</text>
<text class="card__value">{{ formatSize(item.Size) }}</text>
</view>
<view class="card__row">
<text class="card__label">盖面焊工</text>
<text class="card__value">{{ item.CoverWelderId || '--' }}</text>
</view>
<view class="card__row">
<text class="card__label">打底焊工</text>
<text class="card__value">{{ item.BackingWelderId || '--' }}</text>
</view>
</view>
<u-empty
v-if="!loading && joints.length === 0"
mode="list"
text="暂无焊口明细"
/>
</view>
<!-- 生成出库申请 -->
<view class="submit-bar">
<view
class="btn-primary-gradient"
:class="{ 'btn-primary-gradient--disabled': submitting || !canGenerate }"
@click="handleGenerate"
>
<text class="btn-primary-gradient__text">
{{ submitting ? '处理中...' : '生成出库申请单' }}
</text>
</view>
</view>
</view>
</template>
<script setup>
/**
* 焊接任务单详情:展示 Joints,支持生成出库申请单
* 使用 Promise 链而非 async/await,规避微信小程序 Babel regenerator 的 "a" is read-only
*/
import { computed, ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { useUserStore } from '@/store'
import { reqWeldTaskDetail, reqWeldTaskGenerateOutPlan } from '@/api/hj.js'
const userStore = useUserStore()
const projectId = ref('')
const taskCode = ref('')
const unitWorkId = ref('')
const detail = ref({})
const loading = ref(false)
const submitting = ref(false)
const joints = computed(function () {
const d = detail.value
const list = d ? d.Joints : null
return Array.isArray(list) ? list : []
})
const canGenerate = computed(function () {
return !!(projectId.value && taskCode.value)
})
const fmtDate = (val) => {
if (!val) return '--'
const d = new Date(val)
if (isNaN(d.getTime())) return String(val).slice(0, 10)
const y = d.getFullYear()
const m = String(d.getMonth() + 1).padStart(2, '0')
const day = String(d.getDate()).padStart(2, '0')
return y + '-' + m + '-' + day
}
const formatSize = (val) => {
if (val === undefined || val === null || val === '') return '--'
return String(val)
}
const loadDetail = () => {
if (!projectId.value || !taskCode.value) {
uni.showToast({ title: '入口参数错误', icon: 'none' })
return
}
loading.value = true
const params = {
projectId: projectId.value,
taskCode: taskCode.value,
unitWorkId: unitWorkId.value || '',
}
reqWeldTaskDetail(params).then(function (res) {
const data = res ? res.data : null
detail.value = data || {}
if (!data) {
uni.showToast({ title: '未找到任务单', icon: 'none' })
}
}).catch(function (e) {
console.error('任务单详情加载失败:', e)
detail.value = {}
}).then(function () {
loading.value = false
})
}
const handleGenerate = () => {
if (submitting.value || !canGenerate.value) return
uni.showModal({
title: '确认生成',
content: '确定根据当前任务单生成出库申请单吗?已生成过的不会重复建单。',
success: function (modalRes) {
if (!modalRes.confirm) return
const user = userStore.userInfo
const personId = (user && user.PersonId) || userStore.token
if (!personId) {
uni.showToast({ title: '缺少登录人信息', icon: 'none' })
return
}
submitting.value = true
reqWeldTaskGenerateOutPlan({
ProjectId: projectId.value,
TaskCode: taskCode.value,
PersonId: personId,
}).then(function () {
uni.showToast({
title: '生成请求已处理',
icon: 'none',
})
}).catch(function (e) {
console.error('生成出库申请失败:', e)
}).then(function () {
submitting.value = false
})
},
})
}
onLoad(function (opt) {
projectId.value = decodeURIComponent((opt && opt.projectId) || '')
taskCode.value = decodeURIComponent((opt && opt.taskCode) || '')
unitWorkId.value = decodeURIComponent((opt && opt.unitWorkId) || '')
loadDetail()
})
</script>
<style lang="scss" scoped>
.detail-page {
min-height: 100vh;
padding: 24rpx 24rpx 160rpx;
background: #f5f6f8;
box-sizing: border-box;
}
.section {
margin-bottom: 24rpx;
&__header {
display: flex;
align-items: center;
gap: 12rpx;
margin-bottom: 16rpx;
}
&__bar {
width: 8rpx;
height: 28rpx;
border-radius: 4rpx;
background: #2979ff;
}
&__title {
font-size: 30rpx;
font-weight: 600;
color: #1a2332;
}
}
.card {
background: #fff;
border-radius: 16rpx;
padding: 8rpx 24rpx;
margin-bottom: 16rpx;
&__row {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 24rpx;
padding: 20rpx 0;
border-bottom: 1rpx solid #f0f0f0;
&:last-child {
border-bottom: none;
}
}
&__label {
flex-shrink: 0;
font-size: 26rpx;
color: #999;
}
&__value {
flex: 1;
text-align: right;
font-size: 26rpx;
color: #333;
word-break: break-all;
&--mono {
font-family: monospace;
font-weight: 600;
color: #1a2332;
}
}
}
.joint-card {
&__title {
padding: 20rpx 0 4rpx;
font-size: 28rpx;
font-weight: 600;
color: #1a2332;
font-family: monospace;
}
}
.submit-bar {
position: fixed;
left: 0;
right: 0;
bottom: 0;
padding: 20rpx 24rpx calc(20rpx + env(safe-area-inset-bottom));
background: #fff;
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.06);
}
.btn-primary-gradient {
height: 88rpx;
border-radius: 44rpx;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #2979ff, #5a9aff);
&--disabled {
opacity: 0.55;
}
&__text {
font-size: 30rpx;
color: #fff;
font-weight: 600;
}
}
</style>