heli-mes/mes-ui/mini-app/src/pages/zjPgMaster/zjPgMaster-detail.vue
Ledo f01f5ac86a 1.生产任务单若有删除项编辑后无法保存
2.生产任务派工单预计开始时间和预计结束时间自动带出
3.生产任务派工单预计工时取消*
4.生产任务派工单设备对比不需要
5.全部发货时生产计划变更为已完成
6.终检过程检添加加载管控
7.发货两个订单更新状态bug问题查找和修复
8.任务派工单查询报错问题解决
2025-02-18 23:35:12 +08:00

621 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 { getTaskRepotPageAPI, getTaskDetailAPI, postOperateAPI,postOperateAPIEnd } from '@/services/zjPgMaster'
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 = 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
isLoading.value = false
}
// 详情
const getDetailData = async (id) => {
// 发送请求
// isLoading.value = true
const params = {
id,
}
const data = await getTaskDetailAPI(params)
data.startTime = formatDate(data.startTime, 'YYYY-MM-DD')
data.entTime = formatDate(data.entTime, 'YYYY-MM-DD')
// 单位枚举
const lineObj = unitDictData.find((q) => q.value == data.unit) || {}
data.unit = lineObj.label
detailInfo.value = data || {}
isLoading.value = false
}
onLoad(async (options: any) => {
await getDetailData(options.id)
await getData()
const obj = historyList.value[0]
// 最新的报工是否完成
if (obj && obj?.workTime == null && obj.endTime) {
popup.value?.open()
}
})
// 生产完成
const handleComplate = async () => {
/* const params = {
id: detailInfo.value?.id,
active: 'FINISH',
ownerId: userId,
}
const data = await postOperateAPI(params)
const url = `/pages/productionReport/productionReport-detail?id=${detailInfo.value.id}`
uni.redirectTo({
url,
}) */
}
// 提交报工
const handleOk = async (active) => {
if(amount.value>0&&workTime.value>0){
const params = {
zjMxId: detailInfo.value?.id,
amount: amount.value,
workTime: workTime.value,
bgUser: userId,
}
const data = await postOperateAPIEnd(params)
const url = `/pages/zjPgMaster/zjPgMaster-detail?id=${detailInfo.value.id}`
uni.redirectTo({
url,
})
}else{
uni.showToast({
title: '报工数量或报工时间必须大于0请检查',
icon: 'none', // 显示纯文本时icon设为none
duration: 2000
});
}
}
// 开始生产
const handleStart = async () => {
isLoading.value = true;
const params = {
zjMxId: detailInfo.value?.id,
workTime: workTime.value,
bgUser: userId,
}
const data = await postOperateAPI(params)
const url = `/pages/zjPgMaster/zjPgMaster-detail?id=${detailInfo.value.id}`
uni.redirectTo({
url,
})
/* const params = {
id: detailInfo.value.id,
active: 'START',
ownerId: userId,
}
const data = await postOperateAPI(params)
const url = `/pages/productionReport/productionReport-detail?id=${detailInfo.value.id}`
uni.redirectTo({
url,
})
productionTitle.value = '生产中' */
}
// 结束生产
const handleStop = async () => {
// var lastIndex = historyList.value.length-1;
var lastItem = historyList.value[0];
console.log(historyList.value)
workTime.value = Math.floor(Math.abs(lastItem.createTime - Date.now()) / (1000 * 60 * 60)).toString();
//算数量
if(historyList.value.length == 1){
amount.value = detailInfo.value.amount;
}else{
var beforeAmount = 0;
for (var i = historyList.value.length-1 ; i >0;i--){
console.log( historyList.value[i])
beforeAmount += historyList.value[i].amount
}
var finalamount = detailInfo.value.amount -beforeAmount
if(finalamount < 0){finalamount = 0}
amount.value = finalamount.toString();
}
popup.value.open();
/* const params = {
id: detailInfo.value?.id,
active: 'END',
}
const data = await postOperateAPI(params)
const url = `/pages/productionReport/productionReport-detail?id=${detailInfo.value.id}`
uni.redirectTo({
url,
})
popup.value?.open() */
}
</script>
<template>
<view class="data-detail">
<template v-if="!isLoading">
<view class="module">
<view class="module-info">
<view class="product-item">项目{{detailInfo.projectName}}</view>
<image src="/static/images/productionReport-page.png" class="product-img" mode="scaleToFill"></image>
<view :class="[detailInfo.pgType == 1 ? 'had' : 'unhad', 'product-status']">{{
detailInfo.pgType == 1 ? '已完成' : '未完成' }}</view>
<view class="product-item">子项目{{ detailInfo.projectSubCode || '' }} {{' ' + detailInfo.projectSubName }}
</view>
<view class="product-item">模具名称{{detailInfo.mouldName}}</view>
<view class="product-row">
<view class="row-item">
<view class="label">派工数量</view>
<view class="val">{{ detailInfo.amount }}</view>
</view>
<!-- <view class="row-item">
<view class="label">预计工时</view>
<view class="val">{{ detailInfo.gongShi }}</view>
</view> -->
</view>
<view class="product-row">
<view class="row-item">
<view class="label">总报工数量</view>
<view class="val high-color">{{ detailInfo.amounts }}</view>
</view>
<view class="row-item">
<view class="label">总报工工时</view>
<view class="val high-color">{{ detailInfo.workTime }}</view>
</view>
</view>
<!-- <view class="product-item">预计生产日期{{ detailInfo.startTime }} {{ detailInfo.entTime }}</view> -->
<view class="finish" v-if="isShowStart && detailInfo.procedureStatus !== 2 && detailInfo.totalWorkTime"
@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="no-data" v-if="!historyList.length">
无数据...
</view>
<template v-else>
<view class="item" v-for="(item, index) in historyList" :key="item.id">
<view class="product-row">
<view class="row-item">
<view class="label">报工人:</view>
<view class="val high-color">{{ item.userName }}</view>
</view>
</view>
<view class="product-item">报工时间:{{ item.bgTime }}~{{item.entTime}}</view>
<!-- <view class="product-item">生产结束时间:{{ item.endTimeStr }}</view> -->
<view class="product-row">
<view class="row-item">
<view class="label">报工工时:</view>
<view class="val high-color">{{ item.workTime }}</view>
</view>
<view class="row-item">
<view class="label">报工数量:</view>
<view class="val high-color">{{ item.amount }}</view>
</view>
</view>
<view class="tip-index">
<image src="/static/images/productionReport-detail-index.png" class="icon-status" mode="scaleToFit">
</image>
<view class="text">{{historyList.length - index}}</view>
</view>
</view>
</template>
</view>
</view>
<view class="action" v-if="detailInfo.pgType !== 1">
<view class="action-item start" v-if="detailInfo.active != 'START'" @click="handleStart">开始报工</view>
<view class="action-item stop" v-if="detailInfo.active == 'START'" @click="handleStop">结束报工</view>
<!-- <view class="action-item start" v-if="detailInfo.pgType !== 1" @click="handleStart">终检报工</view>
<view class="action-item stop" v-if="isShowEnd" @click="handleStop">结束生产</view> -->
</view>
</template>
<view class="loading-text" v-else>加载中..</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="cont">
<!-- <view class="item">
<view class="label">终检开始时间:</view>
<view class="val">{{ formObj.startTime }}</view>
</view>
<view class="item">
<view class="label">终检结束时间:</view>
<view class="val">{{ formObj.endTime }}</view>
</view> -->
<view class="item">
<view class="label"><span class="star">*</span>本次报工工时:</view>
<uni-easyinput class="val" type="digit" v-model="workTime" placeholder="请输入本次报工工时"></uni-easyinput>
<view class="unit">小时</view>
</view>
<view class="item">
<view class="label"><span class="star">*</span>本次报工数量:</view>
<uni-easyinput class="val" type="number" v-model="amount" placeholder="请输入本次报工数量"></uni-easyinput>
<view class="unit"> {{ detailInfo.unit }}</view>
</view>
</view>
<view class="ok" @click="handleOk">确定</view>
</uni-popup>
</view>
</template>
<style lang="scss">
// 订单列表
.data-detail {
border-radius: 10rpx;
padding-bottom: 200rpx;
.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;
&.start {
background: linear-gradient(157deg, #2EACE6 -3%, #356899 90%);
}
&.stop {
background: linear-gradient(167deg, #FEA97B -2%, #F75E40 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>