过程检app报工界面增加;过程检报工和终检报工作废功能添加

This commit is contained in:
think 2025-01-14 11:10:12 +08:00
parent bd08ec06c7
commit d6b7f2316f
11 changed files with 1437 additions and 18 deletions

View File

@ -101,6 +101,8 @@ public interface ErrorCodeConstants {
ErrorCode TASK_REPORT_PARAMS_ERRORS = new ErrorCode(1_009_007, "报工数量超出派工数量");
ErrorCode TASK_REPORT_PARAMS_ERRORSZF = new ErrorCode(1_009_008, "已经报工不允许作废");
ErrorCode TASK_REPORT_PARAMS_ERRORBG = new ErrorCode(1_009_009, "开始报工和结束报工操作人员不同,无法报工");
ErrorCode TASK_REPORT_PARAMS_ERRORJD = new ErrorCode(1_009_010, "报工进度不能超过100%");
ErrorCode TASK_REPORT_PARAMS_ERRORSJBG = new ErrorCode(1_009_011, "报工进度不能小于上次报工进度");
ErrorCode TASK_DISPATCH_TASK_NOT_EXISTS = new ErrorCode(1_009_004, "任务不存在或已完成");
ErrorCode TASK_DISPATCH_TASK_NO_PERMISSION_FOR_OPERATE = new ErrorCode(1_009_005, "任务不满足操作条件");
ErrorCode TASK_DISPATCH_TASK_REPORT_AMOUNT_EXCESS = new ErrorCode(1_009_006, "无法超额报工");

View File

@ -88,4 +88,7 @@ public class ProcessDesignPageReqVO extends PageParam {
@Schema(description = "未完成设计")
private Boolean uncompletedDesign;
@Schema(description = "是否完成")
private Integer pgType;
}

View File

@ -74,8 +74,13 @@ public interface ProcessDesignMapper extends BaseMapperX<ProcessDesignDO> {
.or()
.apply("u5.id = {0} and t.process_design_type = {1}", reqVO.getOwner(), ProcessDesignTypeEnum.BLUEPRINT_3D.name()));
}
if(reqVO.getUncompletedDesign() != null && reqVO.getUncompletedDesign()){
/*if(reqVO.getUncompletedDesign() != null && reqVO.getUncompletedDesign()){
query.and(QueryWrapper -> QueryWrapper.apply("COALESCE(z.progress, 0) < {0}", 100).ne(PlanDO::getStatus, ProjectPlanStatusEnum.TERMINATE.getCode()));
}*/
if(reqVO.getPgType()==0){
query.and(QueryWrapper -> QueryWrapper.apply("z.progress < {0}" , 100).or().apply("z.progress is null"));
}else{
query.and(QueryWrapper -> QueryWrapper.apply("z.progress >= {0}" , 100));
}
return selectPage(reqVO, query);

View File

@ -18,9 +18,11 @@ public interface ProcessDesignProgressMapper extends BaseMapperX<ProcessDesignPr
default ProcessDesignProgressDO selectSumJinDu(Long processDesignId) {
MPJLambdaWrapper<ProcessDesignProgressDO> query = new MPJLambdaWrapper<>();
query.select("SUM(progress) as progress")
.eq(ProcessDesignProgressDO::getProcessDesignId, processDesignId);
query.select("progress as progress")
.eq(ProcessDesignProgressDO::getProcessDesignId, processDesignId)
.orderByDesc(ProcessDesignProgressDO::getId)
.last("LIMIT 1")
;
return selectOne(query);
}

View File

@ -28,8 +28,7 @@ import java.util.Comparator;
import java.util.List;
import static com.chanko.yunxi.mes.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.chanko.yunxi.mes.module.heli.enums.ErrorCodeConstants.PROCESS_DESIGN_NOT_EXISTS;
import static com.chanko.yunxi.mes.module.heli.enums.ErrorCodeConstants.*;
/**
* 工艺设计 Service 实现类
*
@ -48,24 +47,20 @@ public class ProcessDesignServiceImpl implements ProcessDesignService {
public Long updateBaoGong(Long zid, BigDecimal progress, String imageLink){
//先取出主ID下的所有报工百分比判断不能报工不能超过100
ProcessDesignProgressDO processDesignProgressDOS = processDesignProgressMapper.selectSumJinDu(zid);
BigDecimal value1 = progress;
BigDecimal threshold = new BigDecimal("100");
if(processDesignProgressDOS != null){
//相加判断是否大于100大于时返回前端并给用户提示
BigDecimal value1 = progress;
BigDecimal value2 = processDesignProgressDOS.getProgress();
BigDecimal sum = value1.add(value2);
BigDecimal threshold = new BigDecimal("100");
if (sum.compareTo(threshold) > 0) {
//大于100时不执行
if (value1.compareTo(threshold) > 0) {
//大于100时不执行,并返回给用户提示设计进度不能超过100
throw exception(TASK_REPORT_PARAMS_ERRORJD);
} else {
//反之插入数据库数据
ProcessDesignProgressDO processDesignProgressDO = new ProcessDesignProgressDO();
processDesignProgressDO.setProcessDesignId(zid);
processDesignProgressDO.setProgress(progress);
processDesignProgressDO.setBlueprintLink(imageLink);
processDesignProgressMapper.insert(processDesignProgressDO);
}
if(processDesignProgressDOS.getProgress().compareTo(value1)>0){
throw exception(TASK_REPORT_PARAMS_ERRORSJBG);
}else{
//反之插入数据库数据
ProcessDesignProgressDO processDesignProgressDO = new ProcessDesignProgressDO();
@ -74,6 +69,20 @@ public class ProcessDesignServiceImpl implements ProcessDesignService {
processDesignProgressDO.setBlueprintLink(imageLink);
processDesignProgressMapper.insert(processDesignProgressDO);
}
}
}else{
if(value1.compareTo(threshold) > 0){
throw exception(TASK_REPORT_PARAMS_ERRORJD);
}else{
//反之插入数据库数据
ProcessDesignProgressDO processDesignProgressDO = new ProcessDesignProgressDO();
processDesignProgressDO.setProcessDesignId(zid);
processDesignProgressDO.setProgress(progress);
processDesignProgressDO.setBlueprintLink(imageLink);
processDesignProgressMapper.insert(processDesignProgressDO);
}
}

View File

@ -51,6 +51,13 @@ const categoryList = ref([
imgUrl: "/static/images/zhongjian.png",
defaultImgUrl: "/static/images/assembleReport-default.png"
},
{
path: "moJuSheJiReport",
name: "进度上报",
auth: true,
imgUrl: "/static/images/mojusheji.png",
defaultImgUrl: "/static/images/assembleReport-default.png"
},
])
const loginStore = useLoginStore()
const isLogin = computed(() => {

View File

@ -0,0 +1,493 @@
<script setup lang="ts">
import { onMounted, computed, ref } from 'vue'
import { onLoad, onShow } from '@dcloudio/uni-app'
import { getListAPI, getDictAPI,postOperateAPIZF,updateBaoGong } from '@/services/moJuSheJiReport'
import { useLoginStore } from '@/stores/modules/login'
import { formatDate } from '@/utils/index'
import popup from './popup.vue';
const userStore = useLoginStore()
const userId = userStore.userInfo.userId
//
const isFinish = ref(false)
//
const isTriggered = ref(false)
const selectedId = ref(null); // selectedId
// porps
const props = defineProps<{
orderState: string
}>()
const statusText = computed(() => {
const text = props.orderState == '0' ? '上报进度' : '查看'
return text
})
//
const isLoading = ref(false)
//
const queryParams: Required<any> = {
pageNo: 1,
pageSize: 5,
owner: userId,
//
procedureStatusList: props.orderState,
//
dispatchType: "ASSEMBLE",
//
isReport: 1,
pgType: 0,
}
const dataList = ref([])
const showPopup = ref(false);
const onPopupClose = (progress, imageLink) => {
//
showPopup.value = false;
const zid = selectedId.value;
callApi(zid,progress,imageLink)
/* */
};
const callApi = async (zid: Number,progress :Number,imageLink: String) => {
console.log(progress);
if(progress>0){
//id
await updateBaoGong(zid,progress,imageLink);
isFinish.value = false;
isLoading.value = false;
queryParams.pageNo = 1;
dataList.value = [];
await getListData();
}else{
uni.showToast({
title: '设计进度填写时不能为0%,请重新填写后提交!',
icon: 'none', // iconnone
duration: 2000
});
}
}
const getListData = async () => {
queryParams.pgType = props.orderState;
// 退
if (isLoading.value) return
if (isFinish.value === true) {
return uni.showToast({ icon: 'none', title: '没有更多数据~' })
}
isLoading.value = true
//
const data = await getListAPI(queryParams)
isLoading.value = false
data.list.forEach((e) => {
e.twoDimDate = formatDate(e.twoDimDate, "YYYY-MM-DD");
e.threeDimDate = formatDate(e.threeDimDate, "YYYY-MM-DD");
e.endTime = formatDate(e.endTime, "YYYY-MM-DD");
})
//
dataList.value.push(...data.list)
//
if (queryParams.pageNo < data.total) {
//
queryParams.pageNo++
} else {
//
isFinish.value = true
}
}
onMounted(async () => {
await getListData()
})
onShow(async () => {
isFinish.value = false
isLoading.value = false
queryParams.pageNo = 1
dataList.value = []
await getListData()
})
const handleDetail = (item) => {
showPopup.value = true;
selectedId.value = item.id; // selectedId
/* const url = `/pages/zjPgMaster/zjPgMaster-detail?id=${item.id}`
uni.navigateTo({ url }) */
}
/* const viewClick = (item) => {
const params = {
id: item.id
}
const data = await postOperateAPIZF(params);
await getListData();
} */
//
const viewClick = async (item) => {
const params = {
id: item.id
};
const data = await postOperateAPIZF(params);
if(data >0){
const url = `/pages/zjPgMaster/zjPgMaster`
uni.navigateTo({ url })
}
};
//
const onRefresherrefresh = async () => {
//
isTriggered.value = true
//
queryParams.pageNo = 1
dataList.value = []
isFinish.value = false
//
await getListData()
//
isTriggered.value = false
}
// const searchVal = ref('')
// const dataListDefault = ref([])
// const handleSearch = async () => {
// const code = searchVal.value
// if (code) {
// dataListDefault.value = dataList.value
// dataList.value = dataList.value.filter((e) => {
// return e.code == code
// })
// } else {
// dataList.value = dataListDefault.value
// }
// }
</script>
<template>
<view class="cont">
<!-- <view class="search" v-if="dataList.length > 5">
<view class="title"></view>
<input class="uni-input" v-model="searchVal" @change="handleSearch" placeholder="根据编号搜索" />
</view> -->
<scroll-view enable-back-to-top scroll-y class="data-list" refresher-enabled :refresher-triggered="isTriggered"
@refresherrefresh="onRefresherrefresh" @scrolltolower="getListData">
<view class="item" v-for="item in dataList" :key="item.id" >
<view class="hd">
<view class="num">项目编号</view>
<view class="statusLabel"> {{item.projectCode}} </view>
<view class="statusTexthd" v-if="item.processDesignType == 'BLUEPRINT_2D'"> 2D设计 </view>
<view class="statusTexthd" v-else-if ="item.processDesignType == 'BLUEPRINT_3D'"> 3D设计 </view>
<view class="statusTexthd" v-else-if="item.processDesignType == 'BLUEPRINT_WORKBLANK'"> 毛坯设计 </view>
<view class="statusTexthd" v-else-if="item.processDesignType == 'BLUEPRINT_FOUNDRY_TECHNOLOGY'"> 铸造设计 </view>
</view>
<view class="md">
<view class="product-item">项目{{ item.projectName }}</view>
<view class="product-item">子项目{{ item.projectSubCode || "" }}</view>
<view class="product-item">客户名称{{ item.customerName }}</view>
<view class="product-item">工艺起止日期{{item.twoDimDate}} {{item.threeDimDate}} </view>
<view class="product-item">最新进度{{item.progress}}%</view>
<!-- <view class="product-item">预计生产日期{{ item.startTime }} {{ item.entTime }}</view> -->
</view>
<view class="statusText" @click="handleDetail(item)">{{ statusText }}</view>
</view>
<!-- 底部提示文字 -->
<view class="loading-text" :style="{ paddingBottom: safeAreaInsets?.bottom + 'px' }">
{{ isFinish ? '没有更多数据~' : '正在加载...' }}
</view>
</scroll-view>
<!-- <popup :show="showPopup" :progress="0.0" :imageLink="''" @close="onPopupClose" /> -->
<popup :showPopup="showPopup" :progress="0.0" :imageLink="''" @close="onPopupClose" />
</view>
</template>
<style lang="scss">
//
.search {
padding: 4rpx;
width: 80%;
margin: 30rpx auto;
.uni-input {
border: 1px solid #D1D6DB;
height: 60rpx;
line-height: 60rpx;
padding: 4rpx 10rpx;
font-size: 32rpx;
border-radius: 6rpx;
}
}
.data-list {
height: 90vh;
.item {
position: relative;
padding: 20rpx 0;
margin: 20rpx 20rpx;
border-radius: 10rpx;
background-color: #fff;
.hd {
padding: 10rpx;
font-size: 28rpx;
display: flex;
.statusLabel {
font-size: 24rpx;
color: #737D88;
}
.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;
}
}
.md {
position: relative;
padding: 10rpx;
min-height: 100rpx;
font-size: 28rpx;
border-top: 2rpx solid #F2F2F2;
.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
}
}
}
}
}
.statusText {
position: absolute;
right: 30rpx;
top: 100rpx;
border-radius: 10rpx;
font-size: 24rpx;
padding: 10rpx 30rpx;
border-radius: 10rpx;
font-size: 24rpx;
background: linear-gradient(149deg, #d4e62d 4%, #c5ab1a 98%);
color: #fff;
}
.statusTexthd {
position: absolute;
right: 30rpx;
top: 13rpx;
border-radius: 10rpx;
font-size: 24rpx;
padding: 10rpx 30rpx;
border-radius: 10rpx;
font-size: 24rpx;
background: #2d9ce6;
color: #fff;
}
&:last-child {
padding-bottom: 40rpx;
}
}
.status {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 28rpx;
color: #999;
margin-bottom: 15rpx;
.date {
color: #666;
flex: 1;
}
.primary {
color: #ff9240;
}
.icon-delete {
line-height: 1;
margin-left: 10rpx;
padding-left: 10rpx;
border-left: 1rpx solid #e3e3e3;
}
}
.goods {
display: flex;
margin-bottom: 20rpx;
.cover {
width: 170rpx;
height: 170rpx;
margin-right: 20rpx;
border-radius: 10rpx;
overflow: hidden;
position: relative;
.image {
width: 170rpx;
height: 170rpx;
}
}
.quantity {
position: absolute;
bottom: 0;
right: 0;
line-height: 1;
padding: 6rpx 4rpx 6rpx 8rpx;
font-size: 24rpx;
color: #fff;
border-radius: 10rpx 0 0 0;
background-color: rgba(0, 0, 0, 0.6);
}
.meta {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
.name {
height: 80rpx;
font-size: 26rpx;
color: #444;
}
.type {
line-height: 1.8;
padding: 0 15rpx;
margin-top: 10rpx;
font-size: 24rpx;
align-self: flex-start;
border-radius: 4rpx;
color: #888;
background-color: #f7f7f8;
}
.more {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
font-size: 22rpx;
color: #333;
}
}
.payment {
display: flex;
justify-content: flex-end;
align-items: center;
line-height: 1;
padding: 20rpx 0;
text-align: right;
color: #999;
font-size: 28rpx;
border-bottom: 1rpx solid #eee;
.quantity {
font-size: 24rpx;
margin-right: 16rpx;
}
.amount {
color: #444;
margin-left: 6rpx;
}
.symbol {
font-size: 20rpx;
}
}
.action {
display: flex;
justify-content: flex-end;
align-items: center;
padding-top: 20rpx;
.button {
width: 180rpx;
height: 60rpx;
display: flex;
justify-content: center;
align-items: center;
margin-left: 20rpx;
border-radius: 60rpx;
border: 1rpx solid #ccc;
font-size: 26rpx;
color: #444;
}
.secondary {
color: #3775F6;
border-color: #3775F6;
}
.primary {
color: #fff;
background-color: #3775F6;
border-color: #3775F6;
}
}
.loading-text {
text-align: center;
font-size: 28rpx;
color: #666;
padding: 20rpx 0;
}
}
</style>import type { stringify } from 'querystring';

View File

@ -0,0 +1,73 @@
<template>
<view class="popup-container" v-if="showPopup">
<view class="popup-mask" @click="onMaskClick"></view>
<view class="popup-content">
<input type="number" class="progress-info" v-model="progress" placeholder="请输入进度">
<input type="text" class="image-info" v-model="imageLink" placeholder="请输入图片链接">
<button @click="onClose">关闭弹窗</button>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue';
const props = defineProps({
showPopup: {
type: Boolean,
default: false
}
});
const progress = ref(0.0);
const imageLink = ref('');
const emit = defineEmits(['close']);
const onMaskClick = () => {
onClose();
};
const onClose = () => {
emit('close', progress.value, imageLink.value);
};
</script>
<style scoped>
.popup-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999;
}
.popup-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
}
.popup-content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #fff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
}
.progress-info {
margin-bottom: 10px;
}
.image-info {
margin-bottom: 10px;
}
</style>

View File

@ -0,0 +1,592 @@
<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) => {
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,
})
}
//
const handleStart = async () => {
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 () => {
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-raduis: 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>

View File

@ -0,0 +1,151 @@
<script setup lang="ts">
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import dataItem from './components/dataItem.vue'
// porps
const props = defineProps<{
state: string
}>()
// tabs
const orderTabs = ref([
{ orderState: "0", title: "未完成", isRender: false },
{ orderState: "2", title: "已完成", isRender: false }
])
//
const activeIndex = ref(0)
const handleIndexChange = (index: any) => {
orderTabs.value.forEach((e) => {
e.isRender = false
})
activeIndex.value = index
orderTabs.value[index].isRender = true
}
onLoad(async (options) => {
if (options.state) {
//
orderTabs.value.forEach((e, index) => {
e.isRender = e.orderState == options.state
if (e.isRender) {
activeIndex.value = index
}
})
} else {
orderTabs.value.forEach((e, index) => {
e.isRender = e.orderState == '0'
if (e.isRender) {
activeIndex.value = index
}
})
}
})
</script>
<template>
<view class="viewport">
<view class="tabs">
<text class="item" :class="{ active: activeIndex == index }" v-for="(item, index) in orderTabs" :key="item.title"
@tap="handleIndexChange(index)">
{{ item.title }}
</text>
<!-- 游标 -->
<view class="cursor" :style="{ left: activeIndex ? '65%' : '14%' }"></view>
</view>
<!-- 滑动容器 -->
<swiper class="swiper" :current="activeIndex" @change="handleIndexChange($event.detail.current)">
<!-- 滑动项 -->
<swiper-item v-for="item in orderTabs" :key="item.title">
<dataItem v-if="item.isRender" :order-state="item.orderState" />
</swiper-item>
</swiper>
</view>
</template>
<style lang="scss">
page {
height: 100%;
}
.viewport {
height: 100%;
display: flex;
flex-direction: column;
// background-color: #3775F6;
.navbar {
width: 750rpx;
color: #000;
position: fixed;
top: 0;
left: 0;
z-index: 9;
/* background-color: #f8f8f8; */
background-color: #3775f6;
.wrap {
position: relative;
background-color: #3775f6;
.title {
height: 44px;
display: flex;
justify-content: center;
align-items: center;
font-size: 32rpx;
/* color: #000; */
color: #fff;
}
.back {
position: absolute;
left: 0;
height: 44px;
width: 44px;
font-size: 44rpx;
display: flex;
align-items: center;
justify-content: center;
/* color: #000; */
color: #fff;
}
}
}
.tabs {
display: flex;
justify-content: space-around;
line-height: 60rpx;
position: relative;
z-index: 9;
width: 100%;
.item {
flex: 1;
text-align: center;
padding: 20rpx;
font-size: 28rpx;
color: #1D2129;
&.active {
color: #356899;
}
}
.cursor {
position: absolute;
left: 13%;
bottom: 0;
width: 20%;
height: 6rpx;
padding: 0 50rpx;
background-color: #356899;
/* 过渡效果 */
transition: all 0.4s;
}
}
// swiper
.swiper {
background-color: #f7f7f8;
}
}
</style>

View File

@ -0,0 +1,82 @@
/*
* @Author:
* @Date: 2024-01-04 12:54:56
* @LastEditors:
* @LastEditTime: 2024-03-29 15:44:53
* @FilePath: /app-nx-personal/src/services/home.ts
* @Description: ,`customMade`, koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { http } from '@/utils/http'
// 获取工序分页
export const getListAPI = (data: Object) => {
return http<any[]>({
method: 'GET',
url: "/heli/process-design/page",
data,
})
}
/**
* ///
*/
export const updateBaoGong = (zid: String,progress: String,imageLink:String) => {
const data = {
zid: zid,
progress: progress,
imageLink: imageLink
};
return http<any[]>({
method: 'POST',
url: "/heli/process-design/updateBaoGong",
data,
})
}
// 报工记录分页查询
export const getTaskRepotPageAPI = (data: Object) => {
return http<any[]>({
method: 'GET',
url: "/heli/task-report/page",
data,
})
}
// 派工任务详情
export const getTaskDetailAPI = (data: Object) => {
return http<any[]>({
method: 'GET',
url: "/heli/task-dispatch/task-dispatch-detail/get",
data,
})
}
/**
*
*/
export const postOperateAPI = (data: Object) => {
return http<any[]>({
method: 'POST',
url: "/heli/task-dispatch/task-dispatch-detail/operate",
data,
})
}
/**
*
*/
export const postOperateAPIEnd = (data: Object) => {
return http<any[]>({
method: 'POST',
url: '/heli/bg-master-line/endBg',
data,
})
}
/**
* -
*/
export const postOperateAPIZF = (data: Object) => {
return http<any[]>({
method: 'POST',
url: '/heli/pg-master/zfPgMaster',
data,
})
}