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

326 lines
8.0 KiB
Vue
Raw Normal View History

2026-08-18 18:05:16 +08:00
<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>
2026-08-18 18:05:16 +08:00
</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
2026-08-18 18:05:16 +08:00
*/
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
2026-08-18 18:05:16 +08:00
return Array.isArray(list) ? list : []
})
const canGenerate = computed(function () {
return !!(projectId.value && taskCode.value)
})
2026-08-18 18:05:16 +08:00
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
2026-08-18 18:05:16 +08:00
}
const formatSize = (val) => {
if (val === undefined || val === null || val === '') return '--'
return String(val)
}
const loadDetail = () => {
2026-08-18 18:05:16 +08:00
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) {
2026-08-18 18:05:16 +08:00
uni.showToast({ title: '未找到任务单', icon: 'none' })
}
}).catch(function (e) {
2026-08-18 18:05:16 +08:00
console.error('任务单详情加载失败:', e)
detail.value = {}
}).then(function () {
2026-08-18 18:05:16 +08:00
loading.value = false
})
2026-08-18 18:05:16 +08:00
}
const handleGenerate = () => {
if (submitting.value || !canGenerate.value) return
uni.showModal({
title: '确认生成',
content: '确定根据当前任务单生成出库申请单吗?已生成过的不会重复建单。',
success: function (modalRes) {
2026-08-18 18:05:16 +08:00
if (!modalRes.confirm) return
const user = userStore.userInfo
const personId = (user && user.PersonId) || userStore.token
2026-08-18 18:05:16 +08:00
if (!personId) {
uni.showToast({ title: '缺少登录人信息', icon: 'none' })
return
}
submitting.value = true
reqWeldTaskGenerateOutPlan({
ProjectId: projectId.value,
TaskCode: taskCode.value,
PersonId: personId,
}).then(function () {
2026-08-18 18:05:16 +08:00
uni.showToast({
title: '生成请求已处理',
icon: 'none',
})
}).catch(function (e) {
2026-08-18 18:05:16 +08:00
console.error('生成出库申请失败:', e)
}).then(function () {
2026-08-18 18:05:16 +08:00
submitting.value = false
})
2026-08-18 18:05:16 +08:00
},
})
}
onLoad(function (opt) {
projectId.value = decodeURIComponent((opt && opt.projectId) || '')
taskCode.value = decodeURIComponent((opt && opt.taskCode) || '')
unitWorkId.value = decodeURIComponent((opt && opt.unitWorkId) || '')
2026-08-18 18:05:16 +08:00
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>