heli-mes/mes-ui/mini-app/src/pages/unqualifiedNotification/unqualifiedNotification-detail.vue
2025-07-11 17:31:41 +08:00

688 lines
17 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.

<script setup lang="ts">
import { toRaw, ref, computed } from 'vue'
import { formatDate } from '@/utils/index'
import { onLoad, onShow } from '@dcloudio/uni-app'
import { useLoginStore } from '@/stores/modules/login'
import { getNotificationDetailAPI, operateWx } from '@/services/unqualifiedNotification'
import { serviceDomain } from '@/services/constants'
const popup = ref<UniHelper.UniPopupInstance>()
const userStore = useLoginStore()
const dictInfo = userStore?.dictInfo || []
const unitDictData = dictInfo.filter(e => e.dictType == 'heli_material_unit') || []
const userId = userStore.userInfo.userId
const isShowStart = ref(false)
const isShowEnd = ref(false)
// const isShowStart = computed(() => {
// let flag = true
// if (historyList.value.length) {
// const obj = historyList.value[0]
// if (!obj?.endTime) {
// flag = false
// }
// }
// // // 派工数量和总报工数量相等了就不展示开始生产
// // if (detailInfo.value.amount == detailInfo.value.totalReportAmount) {
// // flag = false
// // }
// return flag
// })
// const isShowEnd = computed(() => {
// let flag = true
// if (historyList.value.length) {
// const obj = historyList.value[0]
// if (obj?.endTime) {
// flag = false
// }
// } else {
// flag = false
// }
// return flag
// })
const productionTitle = ref('开始生产')
const amount = ref('')
const workTime = ref('')
// 详情数据
const detailInfo = ref({})
let isLoading = ref(false)
const historyList = ref([])
const formObj = ref({})
// 历史明细
const getData = async () => {
// 发送请求
isLoading.value = true
const params = {
pageNo: 1,
integerpageSize: 5,
bgUser: userId,
zjMxId: detailInfo.value.id,
}
const data = await getTaskRepotPageAPI(params)
data.list.forEach((e) => {
e.startTimeStr = e.startTime && formatDate(e.startTime, 'YYYY-MM-DD HH:mm')
e.endTimeStr = e.endTime && formatDate(e.endTime, 'YYYY-MM-DD HH:mm')
e.bgTime = e.bgTime && formatDate(e.bgTime, 'YYYY-MM-DD HH:mm')
e.entTime = e.entTime && formatDate(e.entTime, 'YYYY-MM-DD HH:mm')
})
if (data.list[0]) {
formObj.value = data.list[0]
const time = formObj.value.endTime - formObj.value.startTime //时间差秒
const leave1 = time % (24 * 3600 * 1000) //计算天数后剩余的毫秒数
workTime.value = Math.floor(leave1 / (3600 * 1000))
}
historyList.value = data.list
isShowEnd.value = true;
isShowStart.value = true
if (historyList.value.length) {
const obj = historyList.value[0]
if (obj.amount != null && obj.amount >= 0) {
isShowStart.value = true
} else {
isShowStart.value = false
}
}
if (historyList.value.length) {
const obj = historyList.value[0]
if (obj.amount != null && obj.amount >= 0) {
isShowEnd.value = false
} else {
isShowEnd.value = true
detailId.value = obj.id
}
} else {
isShowEnd.value = false
}
isLoading.value = false
isLoading.value = false
}
// 详情
const getDetailData = async (id, type) => {
// 发送请求
// isLoading.value = true
// 请求参数
const queryParams = {
id: id,
type: type
}
detailInfo.value = await getNotificationDetailAPI(queryParams)
}
const idValue = ref()
onLoad(async (options : any) => {
idValue.value = options.id
typeName.value = options.type == 2 ? '终检' : '过程检'
await getDetailData(options.id, typeName.value)
})
// 生产完成
const handleComplate = async () => {
try {
isLoading.value = true;
const params = {
zjMxId: detailInfo.value?.id,
bgUser: userId,
type: 0,
}
const data = await postOperateAPIEnd(params)
} catch (error) {
uni.showToast({
icon: 'none',
duration: 3000,
title: error.data.msg,
})
} finally {
isLoading.value = false;
// const url = `/pages/pgMaster/pgMaster-detail?id=${detailInfo.value.id}`
// uni.redirectTo({
// url,
// })
await initPage();
const pages = getCurrentPages(); // 获取当前页面栈
const currentPage = pages[pages.length - 1]; // 当前页面
const url = `/${currentPage.route}?${Object.entries(currentPage.options).map(([key, val]) => `${key}=${val}`).join('&')}`;
uni.reLaunch({ url }); // 重新加载当前页面
}
}
const range = [
{ value: 1, text: "返修" },
{ value: 2, text: "让步接收" },
{ value: 3, text: "报废" },
]
// 提交报工
const handleOk = async () => {
if (detailInfo.value.auditOpinion) {
await submitForm(detailInfo.value.auditOpinion);
} else {
uni.showToast({
icon: 'none',
duration: 3000,
title: '请选择审核意见后提交',
})
return;
}
}
const submitForm = async (active) => {
try {
const params = {
id: detailInfo.value?.id,
type: typeName.value,
auditOpinion: active,
auditor: userId,
projectId: 0,
projectSubId: 0,
status: 1,
notificationStatus: 3
}
await operateWx(params);
} catch (error) {
uni.showToast({
icon: 'none',
duration: 3000,
title: error.data.msg,
})
} finally {
isLoading.value = false;
// const url = `/pages/unqualifiedNotification/unqualifiedNotification`
// uni.redirectTo({
// url,
// })
const pages = getCurrentPages(); // 获取当前页面栈
await initPage();
const currentPage = pages[pages.length - 1]; // 当前页面
const url = `/${currentPage.route}?${Object.entries(currentPage.options).map(([key, val]) => `${key}=${val}`).join('&')}`;
uni.reLaunch({ url }); // 重新加载当前页面
}
}
const typeName = ref('')
const initPage = async () => {
await getDetailData(idValue.value, typeName.value)
}
const audit = () => {
popup.value.open()
}
const cancel = () => {
uni.navigateBack({
delta: 1 // 返回的页面数这里1表示返回上一页
});
}
const getSuger = (val) => {
if (val == 1) {
return '返修'
} else if (val == 2) {
return '让步接收'
} else if (val == 3) {
return '报废'
}
}
const detailId = ref()
</script>
<template>
<view class="data-detail">
<template v-if="!isLoading">
<view class="module">
<view class="module-info">
<view class="product-item">检验单据:{{detailInfo.code}}</view>
<image src="/static/images/productionReport-page.png" class="product-img" mode="scaleToFill">
</image>
<view :class="[detailInfo.notificationStatus == 3 ? 'had' : 'unhad', 'product-status']">{{
detailInfo.notificationStatus == 2 ? '未审核' : '已审核' }}</view>
<view class="product-item">项目:{{detailInfo.projectName}}</view>
<view class="product-item">子项目:{{ detailInfo.projectSubCode || '' }}
{{' ' + detailInfo.projectSubName }}
</view>
<view class="product-item">通知日期:{{formatDate(detailInfo.createTime, 'YYYY-MM-DD HH:mm')}}</view>
<view class="product-item" v-if="detailInfo.notificationStatus === 3">
审核日期:{{formatDate(detailInfo.auditTime, 'YYYY-MM-DD HH:mm')}}</view>
<view class="product-item" v-if="detailInfo.notificationStatus === 3">
审核意见:{{getSuger(detailInfo.auditOpinion)}}</view>
<view class="product-row" v-if="detailInfo.typeName == '过程检'">
<view class="row-item">
<view class="label">零件名称:<text class="blue">{{ detailInfo.materialName }}</text></view>
</view>
<view class="row-item">
<view class="label">工序:<text class="blue">{{ detailInfo.procedureName }}</text></view>
</view>
</view>
<view class="product-row">
<view class="row-item">
<view class="label">质检员:<text class="blue">{{ detailInfo.creatorName }}</text></view>
</view>
<view class="row-item">
<view class="label">类型:<text class="blue">{{ detailInfo.typeName }}</text></view>
</view>
</view>
<view class="product-row">
<view class="row-item">
<view class="label">检查数量:<text class="blue">{{ detailInfo.amount }}</text></view>
</view>
<view class="row-item">
<view class="label">派工总数量:<text class="blue">{{ detailInfo.totalAmount }}</text></view>
</view>
</view>
<!-- <view class="product-item">预计生产日期:{{ detailInfo.startTime }} {{ detailInfo.entTime }}</view> -->
<!-- <view class="finish" v-if="isShowStart && historyList.length &&detailInfo.pgType != 1"
@click="handleComplate">
<image class="complate-img" src="/static/images/productionReport-detail-complate.png"
mode="scaleToFill" />
生产完成
</view> -->
</view>
</view>
<view class="module-list">
<view class="module-title">异常明细</view>
<view class="history-list">
<view class="item">
<view class="product-row">
<view class="row-item">
<view class="label">是否复检:</view>
<view class="val high-color">{{ detailInfo.isRepre == 1 ?'否':'是' }}</view>
</view>
<view class="row-item">
<view class="label">是否合格:</view>
<view class="val high-color">{{ detailInfo.isQua == 0?'合格':'不合格' }}</view>
</view>
</view>
<view v-if="detailInfo.remark" class="product-item">异常描述:{{ detailInfo.remark }}</view>
<view v-if="!detailInfo.fileUrlList">
<text class="red">暂无图片</text>
</view>
<view v-else>
<htz-image-upload v-model="detailInfo.fileUrlList" :max="9" :remove="false"
:add="false"></htz-image-upload>
</view>
<viw></viw>
</view>
</view>
</view>
<view class="action" v-if="detailInfo.notificationStatus !== 3">
<!-- <view class="action-item info" v-if="detailInfo.notificationStatus !== 3" @click="submitForm(3)">报废</view>
<view class="action-item start" v-if="detailInfo.notificationStatus !== 3" @click="submitForm(1)">返修</view>
<view class="action-item stop" v-if="detailInfo.notificationStatus !== 3" @click="submitForm(2)">让步接收</view> -->
<view class="action-item info" v-if="detailInfo.notificationStatus !== 3" @click="cancel()">取消</view>
<view class="action-item start" v-if="detailInfo.notificationStatus !== 3" @click="audit()">审核</view>
<!-- <view class="action-item stop" v-if="detailInfo.notificationStatus !== 3" @click="submitForm(2)">让步接收</view> -->
</view>
<uni-popup class="popup" ref="popup" :mask-click="false" type="bottom" background-color="#fff">
<view class="title">
<view class="text">审核信息</view>
<!-- <view class="close" @click="handleClose">X</view> -->
</view>
<view class="formHeight">
<uni-forms ref="formRef" :label-width="100">
<uni-forms-item class="auditSelect" label="审核意见" required name="type">
<uni-data-select style="width: 60%;" v-model="detailInfo.auditOpinion" :localdata="range"></uni-data-select>
</uni-forms-item>
</uni-forms>
</view>
<view class="ok" @click="handleOk">确定</view>
</uni-popup>
</template>
</view>
</template>
<style lang="scss">
.auditSelect{
margin-top: 10%;
margin-left: 10%;
}
.formHeight{
height: 600rpx;
}
// 订单列表
.data-detail {
border-radius: 10rpx;
padding-bottom: 200rpx;
.statusLabelzf {
font-size: 24rpx;
position: absolute;
right: 30rpx;
top: 15rpx;
border-radius: 10rpx;
font-size: 24rpx;
padding: 10rpx 30rpx;
border-radius: 10rpx;
font-size: 24rpx;
background: linear-gradient(149deg, #ffff00 4%, #cfcf00 98%);
color: #fff;
}
.module {
background: linear-gradient(178deg, #356899 7%, #356899 57%, #F4F6F9 94%);
padding: 20rpx;
.module-info {
padding: 20rpx 20rpx 80rpx;
border-radius: 10rpx;
min-height: 100rpx;
font-size: 28rpx;
border-bottom: 2rpx solid #F2F2F2;
background: linear-gradient(215deg, #C7D3E5 8%, rgba(222, 228, 236, 0) 13%), linear-gradient(162deg, #FFFFFF 25%, #E4EFFD 106%);
position: relative;
border-top-right-radius: 100rpx;
.product-img {
position: absolute;
right: 0rpx;
top: 0;
width: 100rpx;
height: 100rpx;
}
.product-status {
width: 140rpx;
border-radius: 10rpx;
text-align: center;
padding: 8rpx 12rpx;
&.had {
background: #E8FFEA;
color: #00B42A;
}
&.unhad {
background: #FFF7E8;
color: #FF7D00;
}
}
.product-item {
margin: 20rpx 0;
display: flex;
align-items: center;
color: #737D88
}
.product-row {
margin: 20rpx 0;
display: flex;
flex-direction: row;
justify-content: space-between;
color: #737D88;
.row-item {
flex: 1;
.label {
margin-bottom: 10rpx;
}
.val {
color: #1D2129;
&.high-color {
color: #00B42A
}
}
}
}
.finish {
position: absolute;
right: 40rpx;
bottom: 30rpx;
background: linear-gradient(142deg, #FEB34A 14%, #FE9B12 83%);
color: #fff;
width: 200rpx;
text-align: center;
padding: 10rpx;
border-radius: 31rpx;
display: flex;
align-items: center;
justify-content: center;
.complate-img {
width: 30rpx;
height: 30rpx;
margin-right: 10rpx;
}
}
}
}
.module-list {
padding: 20rpx 20rpx;
// box-shadow: 0px 0px 8px 0px rgba(161, 161, 177, 0.12);
.module-title {
color: #0D0D26;
font-size: 36rpx;
margin: 20rpx 0;
font-weight: 500;
}
.history-list {
display: flex;
flex-direction: column;
align-items: center;
min-height: 200rpx;
justify-content: center;
padding: 0rpx 10rpx;
.item {
margin: 10rpx 0;
background: #EAEEF4;
font-size: 28rpx;
padding: 20rpx;
width: 100%;
border-radius: 10rpx;
color: #737D88;
position: relative;
.product-item {
margin: 10rpx 0;
.hight-color {
color: #00B42A;
}
}
.product-row {
margin: 20rpx 0;
display: flex;
flex-direction: row;
justify-content: space-between;
color: #737D88;
.row-item {
flex: 1;
display: flex;
flex-direction: row;
.label {
margin-bottom: 10rpx;
&.high-color {
color: #00B42A
}
}
.val {
color: #1D2129;
&.high-color {
color: #00B42A
}
}
}
}
.tip-index {
position: absolute;
top: 0rpx;
right: 0rpx;
.icon-status {
width: 100rpx;
height: 72rpx;
z-index: 1;
}
.text {
color: #fff;
position: absolute;
top: 4rpx;
right: 30rpx;
z-index: 2;
}
}
}
.no-data {
font-size: 28rpx;
color: #444;
}
}
.table-cont {
font-size: 24rpx;
}
.button {
color: #356899;
}
}
.action {
display: flex;
justify-content: center;
align-items: center;
position: fixed;
bottom: 0rpx;
border-radius: 18rpx;
padding: 30rpx 30rpx;
background: #FFFFFF;
margin: 0 auto;
width: 100vw;
box-shadow: 0px -4px 10px 0px rgba(121, 153, 183, 0.2);
.action-item {
width: 272rpx;
height: 86rpx;
display: flex;
justify-content: center;
align-items: center;
margin: 0 20rpx;
font-size: 40rpx;
color: #fff;
width: 272rpx;
height: 86rpx;
border-radius: 24rpx;
&.info {
background: linear-gradient(157deg, #A9A9A9 -3%, #A9A9A9 90%);
}
&.start {
background: linear-gradient(157deg, #2EACE6 -3%, #356899 90%);
}
&.stop {
background: linear-gradient(167deg, #FEA97B -2%, #F75E40 87%);
}
&.danger {
background: linear-gradient(167deg, #C00000 -2%, #E80000 87%);
}
&.finish {
background: linear-gradient(142deg, #FEB34A 14%, #FE9B12 83%);
}
}
}
.loading-text {
text-align: center;
font-size: 28rpx;
color: #666;
padding: 20rpx 0;
}
.popup {
.title {
line-height: 1;
padding: 40rpx;
font-size: 32rpx;
font-weight: normal;
border-bottom: 1rpx solid #ddd;
color: #444;
.close {
position: absolute;
right: 24rpx;
top: 40rpx;
height: 60rpx;
width: 60rpx;
text-align: center;
}
}
.cont {
display: flex;
flex-direction: column;
align-items: center;
margin: 40rpx;
height: 50vh;
.item {
display: flex;
align-items: center;
margin: 20rpx 0;
color: #737D88;
width: 94%;
.label {
font-size: 32rpx;
width: 260rpx;
.star {
color: red
}
}
.val {
flex: 1;
font-size: 32rpx;
}
.unit {
width: 100rpx;
margin-left: 4rpx;
text-align: center;
}
}
}
.ok {
font-size: 32rpx;
margin: 20rpx auto 80rpx;
text-align: center;
width: 200rpx;
border-radius: 10rpx;
padding: 8rpx 0;
background-color: #3C8AF7;
color: #fff;
}
}
}
</style>