<template>
|
<view class="invoice-add">
|
<!-- 使用通用页面头部组件 -->
|
<PageHeader title="生产报工"
|
@back="goBack" />
|
<!-- 表单内容 -->
|
<u-form @submit="submitForm"
|
ref="formRef"
|
label-width="110"
|
input-align="right"
|
error-message-align="right">
|
<!-- 基本信息 -->
|
<view class="form-section">
|
<u-form-item label="待生产数量"
|
prop="planQuantity"
|
required>
|
<u-input v-model="form.planQuantity"
|
placeholder="自动填充"
|
disabled />
|
</u-form-item>
|
<u-form-item label="生产合格数量"
|
prop="quantity"
|
required>
|
<u-input v-model="form.quantity"
|
placeholder="请输入"
|
type="number" />
|
</u-form-item>
|
<u-form-item label="报废数量"
|
prop="scrapQty">
|
<u-input v-model="form.scrapQty"
|
placeholder="请输入"
|
type="number" />
|
</u-form-item>
|
<u-form-item label="班组信息"
|
prop="schedulingUserId"
|
required>
|
<u-input v-model="form.userName"
|
placeholder="请选择生产人"
|
readonly
|
@click="openProducerPicker"
|
suffix-icon="arrow-down" />
|
</u-form-item>
|
<!-- 工时 -->
|
<u-form-item label="工时"
|
v-if="form.type == 0"
|
prop="workHour">
|
<u-input v-model="form.workHour"
|
placeholder="请输入工时"
|
type="number" />
|
<text class="param-unit">h</text>
|
</u-form-item>
|
</view>
|
<!-- 动态参数区域 -->
|
<view class="form-section"
|
v-if="params.length > 0">
|
<view class="section-title">工序参数</view>
|
<u-form-item v-for="param in params"
|
:key="param.id"
|
:label="param.paramName"
|
:label-width="110"
|
:required="param.required === '1'">
|
<!-- 数字类型 -->
|
<template v-if="param.paramType == '1'">
|
<u-input v-model="form.paramGroups[param.id]"
|
type="number"
|
:placeholder="'请输入' + param.paramName"
|
:key="param.id" />
|
<text v-if="param.unit && param.unit != '/'"
|
class="param-unit">{{ param.unit }}</text>
|
</template>
|
<!-- 文本类型 -->
|
<template v-else-if="param.paramType == '2'">
|
<u-input v-model="form.paramGroups[param.id]"
|
:placeholder="'请输入' + param.paramName"
|
:key="param.id" />
|
<text v-if="param.unit && param.unit != '/'"
|
class="param-unit">{{ param.unit }}</text>
|
</template>
|
<!-- 选择类型 -->
|
<template v-else-if="param.paramType == '3'">
|
<u-input v-model="form.paramGroups[param.id]"
|
readonly
|
:placeholder="'请选择' + param.paramName"
|
@click="openParamSelect(param)"
|
suffix-icon="arrow-down" />
|
</template>
|
<!-- 日期类型 -->
|
<template v-else-if="param.paramType == '4'">
|
<u-input v-model="form.paramGroups[param.id]"
|
readonly
|
:placeholder="'请选择' + param.paramName"
|
@click="openDateParamPicker(param)"
|
suffix-icon="arrow-down" />
|
<text v-if="param.unit && param.unit != '/'"
|
class="param-unit">{{ param.unit }}</text>
|
</template>
|
<!-- 默认文本 -->
|
<template v-else>
|
<u-input v-model="form.paramGroups[param.id]"
|
:placeholder="'请输入' + param.paramName"
|
:key="param.id" />
|
</template>
|
</u-form-item>
|
</view>
|
<!-- 使用FooterButtons组件 -->
|
<FooterButtons @cancel="goBack"
|
@confirm="submitForm"
|
:loading="submitting" />
|
<!-- 为底部按钮留出空间 -->
|
<view style="height: 80px;"></view>
|
</u-form>
|
<!-- 生产人选择器 -->
|
<up-action-sheet :show="showProducerPicker"
|
:actions="producerList"
|
title="选择生产人"
|
@select="onProducerConfirm"
|
@close="showProducerPicker = false" />
|
<!-- 参数选择器 -->
|
<up-action-sheet :show="showParamSelect"
|
:actions="paramOptions"
|
:title="currentParam?.paramName || '选择'"
|
@select="onParamConfirm"
|
@close="showParamSelect = false" />
|
<!-- 日期选择器 -->
|
<up-datetime-picker :show="showDatePicker"
|
v-model="datePickerValue"
|
:mode="datePickerMode"
|
@confirm="onDateConfirm"
|
@cancel="showDatePicker = false" />
|
</view>
|
</template>
|
|
<script setup>
|
import { ref, nextTick } from "vue";
|
import { onLoad } from "@dcloudio/uni-app";
|
import FooterButtons from "@/components/FooterButtons.vue";
|
|
const showToast = message => {
|
uni.showToast({
|
title: message,
|
icon: "none",
|
});
|
};
|
import { addProductMain } from "@/api/productionManagement/productionReporting";
|
import { getInfo } from "@/api/login";
|
import { userListNoPageByTenantId } from "@/api/system/user";
|
import {
|
findProcessParamListOrder,
|
listMaterialPickingDetail,
|
} from "@/api/productionManagement/productionOrder.js";
|
import { getDicts } from "@/api/system/dict/data";
|
import { formatDateToYMD, parseTime } from "@/utils/ruoyi";
|
|
const formRef = ref();
|
|
let form = ref({
|
planQuantity: "",
|
quantity: "",
|
scrapQty: "",
|
userName: "",
|
workOrderId: "",
|
userId: "",
|
schedulingUserId: "",
|
reportWork: "",
|
productionOrderRoutingOperationId: "",
|
productionOrderId: "",
|
workHour: 0,
|
type: null,
|
paramGroups: {},
|
});
|
|
const showProducerPicker = ref(false);
|
const producerList = ref([]);
|
|
const params = ref([]);
|
const dictOptions = ref({});
|
const showParamSelect = ref(false);
|
const currentParam = ref(null);
|
const paramOptions = ref([]);
|
|
const showDatePicker = ref(false);
|
const datePickerValue = ref(Date.now());
|
const datePickerMode = ref("date");
|
const currentDateParam = ref(null);
|
|
const openProducerPicker = async () => {
|
if (producerList.value.length === 0) {
|
try {
|
const res = await userListNoPageByTenantId();
|
const users = res.data || [];
|
producerList.value = users.map(user => ({
|
name: user.nickName || user.userName,
|
value: user.userId,
|
}));
|
} catch (error) {
|
console.error("加载用户列表失败:", error);
|
showToast("加载用户列表失败");
|
return;
|
}
|
}
|
showProducerPicker.value = true;
|
};
|
|
const onProducerConfirm = e => {
|
form.value.schedulingUserId = e.value;
|
form.value.userName = e.name;
|
form.value.userId = e.value;
|
showProducerPicker.value = false;
|
};
|
|
const openParamSelect = async param => {
|
currentParam.value = param;
|
if (param.paramType == "3" && param.paramFormat) {
|
const options = await getDictOptions(param.paramFormat);
|
paramOptions.value = options.map(opt => ({
|
name: opt.dictLabel,
|
value: opt.dictLabel,
|
}));
|
}
|
showParamSelect.value = true;
|
};
|
|
const onParamConfirm = e => {
|
if (currentParam.value) {
|
form.value.paramGroups[currentParam.value.id] = e.value;
|
}
|
showParamSelect.value = false;
|
};
|
|
const openDateParamPicker = param => {
|
currentDateParam.value = param;
|
const currentValue = form.value.paramGroups[param.id];
|
datePickerValue.value = currentValue
|
? new Date(currentValue).getTime()
|
: Date.now();
|
// 参照 PC 端逻辑:如果格式是 yyyy-MM-dd 则为 date 模式,否则为 datetime 模式
|
datePickerMode.value =
|
param.paramFormat === "yyyy-MM-dd" ? "date" : "datetime";
|
showDatePicker.value = true;
|
};
|
|
const onDateConfirm = e => {
|
if (currentDateParam.value) {
|
const format =
|
currentDateParam.value.paramFormat === "yyyy-MM-dd"
|
? "{y}-{m}-{d}"
|
: "{y}-{m}-{d} {h}:{i}:{s}";
|
form.value.paramGroups[currentDateParam.value.id] = parseTime(
|
e.value,
|
format
|
);
|
}
|
showDatePicker.value = false;
|
};
|
|
const getDictOptions = async dictType => {
|
if (!dictType) return [];
|
if (dictOptions.value[dictType]) return dictOptions.value[dictType];
|
try {
|
const res = await getDicts(dictType);
|
if (res.code === 200) {
|
dictOptions.value[dictType] = res.data;
|
return res.data;
|
}
|
return [];
|
} catch (error) {
|
console.error("获取字典数据失败:", error);
|
return [];
|
}
|
};
|
|
const loadParams = (productionOrderRoutingOperationId, productionOrderId) => {
|
findProcessParamListOrder({
|
productionOrderRoutingOperationId,
|
productionOrderId,
|
})
|
.then(res => {
|
if (res.code === 200) {
|
console.log(res.data, "res.data========");
|
|
const paramList = res.data || [];
|
params.value = paramList;
|
form.value.paramGroups = {};
|
paramList.forEach(param => {
|
if (!form.value.paramGroups[param.id]) {
|
form.value.paramGroups[param.id] = "";
|
}
|
if (param.paramType == "3" && param.paramFormat) {
|
getDictOptions(param.paramFormat);
|
}
|
});
|
}
|
})
|
.catch(err => {
|
console.error("获取工序参数失败:", err);
|
});
|
};
|
|
const submitting = ref(false);
|
|
const goBack = () => {
|
uni.navigateBack();
|
};
|
|
const submitForm = async () => {
|
submitting.value = true;
|
|
if (!form.value.quantity) {
|
submitting.value = false;
|
showToast("请输入生产合格数量");
|
return;
|
}
|
|
if (!form.value.schedulingUserId) {
|
submitting.value = false;
|
showToast("请选择生产人");
|
return;
|
}
|
|
const quantity = Number(form.value.quantity) || 0;
|
const scrapQty = Number(form.value.scrapQty) || 0;
|
const planQuantity = Number(form.value.planQuantity);
|
|
if (quantity < 0) {
|
submitting.value = false;
|
showToast("生产合格数量必须大于等于0");
|
return;
|
}
|
|
// if (quantity + scrapQty > planQuantity) {
|
// submitting.value = false;
|
// showToast("生产数量和报废数量的和不能超过待生产数量");
|
// return;
|
// }
|
|
if (scrapQty < 0) {
|
submitting.value = false;
|
showToast("报废数量不能小于0");
|
return;
|
}
|
|
// if (scrapQty > quantity) {
|
// submitting.value = false;
|
// showToast("报废数量不能大于本次生产数量");
|
// return;
|
// }
|
|
const productionOperationParamList = params.value.map(param => ({
|
...param,
|
inputValue: form.value.paramGroups[param.id] ?? "",
|
}));
|
|
const submitData = {
|
quantity: quantity,
|
scrapQty: scrapQty,
|
userId: form.value.userId,
|
userName: form.value.userName,
|
productionOperationTaskId: form.value.workOrderId,
|
reportWork: form.value.reportWork,
|
productionOrderRoutingOperationId:
|
form.value.productionOrderRoutingOperationId,
|
productionOrderId: form.value.productionOrderId,
|
workHour: form.value.workHour,
|
productionOperationParamList: productionOperationParamList,
|
};
|
|
console.log(submitData, "submitData");
|
|
addProductMain(submitData)
|
.then(res => {
|
if (res.code === 200) {
|
showToast("报工成功");
|
submitting.value = false;
|
setTimeout(() => {
|
goBack();
|
}, 1000);
|
} else {
|
showToast(res.msg || "报工失败");
|
submitting.value = false;
|
}
|
})
|
.catch(() => {
|
showToast("报工失败");
|
submitting.value = false;
|
});
|
};
|
|
onLoad(async options => {
|
console.log(options, "options");
|
if (!options.orderRow) {
|
console.log("从首页跳转,无订单数据");
|
getInfo().then(res => {
|
form.value.userId = res.user.userId;
|
form.value.userName = res.user.nickName || res.user.userName;
|
form.value.schedulingUserId = res.user.userId;
|
});
|
return;
|
}
|
try {
|
const orderRow = JSON.parse(decodeURIComponent(options.orderRow));
|
console.log("构造的orderRow:", orderRow);
|
|
// 参照 PC 端逻辑:未领料无法报工
|
if (orderRow.productionOrderId) {
|
try {
|
const res = await listMaterialPickingDetail(orderRow.productionOrderId);
|
const records = Array.isArray(res.data)
|
? res.data
|
: res.data?.records || [];
|
if (res.code === 200 && records.length === 0) {
|
uni.showModal({
|
title: "提示",
|
content: "未领料无法报工",
|
showCancel: false,
|
success: () => {
|
goBack();
|
},
|
});
|
return;
|
}
|
} catch (error) {
|
console.error("查询领料详情失败:", error);
|
}
|
}
|
|
const planQuantity = Number(orderRow.planQuantity || 0);
|
const completeQuantity = Number(orderRow.completeQuantity || 0);
|
form.value.planQuantity = String(
|
Math.max(0, planQuantity - completeQuantity)
|
);
|
form.value.workOrderId = orderRow.id || "";
|
form.value.reportWork = orderRow.reportWork || "";
|
form.value.productionOrderRoutingOperationId =
|
orderRow.productionOrderRoutingOperationId || "";
|
form.value.productionOrderId = orderRow.productionOrderId || "";
|
form.value.type = orderRow.type;
|
|
if (orderRow.type == 0) {
|
form.value.workHour = orderRow.workHour || 0;
|
} else {
|
form.value.workHour = 0;
|
}
|
|
getInfo().then(res => {
|
form.value.userId = res.user.userId;
|
form.value.userName = res.user.nickName || res.user.userName;
|
form.value.schedulingUserId = res.user.userId;
|
});
|
console.log(orderRow, "orderRow=====");
|
|
if (
|
orderRow.productionOrderRoutingOperationId &&
|
orderRow.productionOrderId
|
) {
|
nextTick(() => {
|
loadParams(
|
orderRow.productionOrderRoutingOperationId,
|
orderRow.productionOrderId
|
);
|
});
|
}
|
|
nextTick(() => {
|
console.log("form.value after assignment:", form.value);
|
});
|
} catch (error) {
|
console.error("订单解析失败:", error);
|
showToast("订单解析失败");
|
goBack();
|
}
|
});
|
</script>
|
|
<style scoped lang="scss">
|
@import "@/static/scss/form-common.scss";
|
|
.form-section {
|
background: #fff;
|
margin-bottom: 12px;
|
padding: 0 16px;
|
}
|
|
.section-title {
|
font-size: 28rpx;
|
font-weight: bold;
|
color: #303133;
|
padding: 24rpx 0 16rpx;
|
border-bottom: 1px solid #f0f0f0;
|
}
|
|
.param-unit {
|
margin-left: 8rpx;
|
color: #909399;
|
font-size: 24rpx;
|
}
|
</style>
|