<template>
|
<up-popup
|
v-model:show="show"
|
mode="bottom"
|
:round="20"
|
:safeAreaInsetBottom="true"
|
@close="handleClose"
|
@open="handleOpen"
|
>
|
<view class="dispatch-modal">
|
<!-- 头部 -->
|
<view class="modal-header">
|
<text class="modal-title">生产派工</text>
|
<view class="close-btn" @click="handleClose">
|
<up-icon name="close" size="20" color="#999"></up-icon>
|
</view>
|
</view>
|
|
<!-- 表单内容 -->
|
<view class="modal-content">
|
<up-form
|
:model="form"
|
ref="formRef"
|
:rules="rules"
|
labelWidth="120"
|
>
|
<!-- 项目基本信息 -->
|
<view class="form-section">
|
<text class="section-title">项目信息</text>
|
<up-form-item label="项目名称" prop="projectName">
|
<up-input
|
v-model="form.projectName"
|
disabled
|
placeholder="项目名称"
|
/>
|
</up-form-item>
|
<up-form-item label="产品大类" prop="productCategory">
|
<up-input
|
v-model="form.productCategory"
|
disabled
|
placeholder="产品大类"
|
/>
|
</up-form-item>
|
</view>
|
|
<!-- 数量信息 -->
|
<view class="form-section">
|
<text class="section-title">数量信息</text>
|
<up-form-item label="总数量" prop="quantity">
|
<up-input
|
v-model="form.quantity"
|
disabled
|
placeholder="总数量"
|
/>
|
</up-form-item>
|
<up-form-item label="待排产数量" prop="pendingQuantity">
|
<up-input
|
v-model="form.pendingQuantity"
|
disabled
|
placeholder="待排产数量"
|
/>
|
</up-form-item>
|
<up-form-item label="本次排产数量" prop="schedulingNum" required>
|
<up-number-box
|
v-model="form.schedulingNum"
|
:min="0"
|
:max="form.pendingQuantity"
|
:step="0.1"
|
:precision="2"
|
@change="handleNumChange"
|
/>
|
</up-form-item>
|
</view>
|
|
<!-- 派工信息 -->
|
<view class="form-section">
|
<text class="section-title">派工信息</text>
|
<up-form-item label="派工人" prop="schedulingUserId" required>
|
<up-input
|
v-model="selectedUserName"
|
placeholder="请选择派工人"
|
readonly
|
@click="showUserPicker = true"
|
suffixIcon="arrow-down"
|
/>
|
</up-form-item>
|
<up-form-item label="派工日期" prop="schedulingDate" required>
|
<up-input
|
v-model="form.schedulingDate"
|
placeholder="请选择派工日期"
|
readonly
|
@click="showDatePicker = true"
|
suffixIcon="calendar"
|
/>
|
</up-form-item>
|
</view>
|
</up-form>
|
</view>
|
|
<!-- 底部按钮 -->
|
<view class="modal-footer">
|
<up-button
|
@click="handleClose"
|
text="取消"
|
type="info"
|
plain
|
:customStyle="{ marginRight: '12px', flex: 1 }"
|
/>
|
<up-button
|
@click="handleConfirm"
|
text="确认派工"
|
type="primary"
|
:customStyle="{ flex: 1 }"
|
:loading="submitting"
|
/>
|
</view>
|
</view>
|
|
<!-- 人员选择器 -->
|
<up-picker
|
v-model="showUserPicker"
|
:columns="userColumns"
|
@confirm="handleUserSelect"
|
@cancel="showUserPicker = false"
|
/>
|
|
<!-- 日期选择器 -->
|
<up-datetime-picker
|
v-model="showDatePicker"
|
mode="date"
|
@confirm="handleDateSelect"
|
@cancel="showDatePicker = false"
|
/>
|
</up-popup>
|
</template>
|
|
<script setup>
|
import { ref, reactive, computed, getCurrentInstance } from 'vue';
|
import { userListNoPageByTenantId } from "@/api/system/user.js";
|
import { productionDispatch } from "@/api/productionManagement/productionOrder.js";
|
import useUserStore from "@/store/modules/user";
|
import dayjs from "dayjs";
|
|
const { proxy } = getCurrentInstance();
|
const userStore = useUserStore();
|
const emit = defineEmits(['confirm']);
|
|
// 弹窗显示状态
|
const show = ref(false);
|
const submitting = ref(false);
|
|
// 选择器显示状态
|
const showUserPicker = ref(false);
|
const showDatePicker = ref(false);
|
|
// 用户列表
|
const userList = ref([]);
|
const userColumns = computed(() => [
|
userList.value.map(user => ({
|
label: user.nickName,
|
value: user.userId
|
}))
|
]);
|
|
// 选中的用户名称(用于显示)
|
const selectedUserName = computed(() => {
|
const user = userList.value.find(u => u.userId === form.schedulingUserId);
|
return user ? user.nickName : '';
|
});
|
|
// 表单数据
|
const form = reactive({
|
projectName: "",
|
productCategory: "",
|
quantity: "",
|
schedulingNum: 0,
|
schedulingUserId: "",
|
schedulingDate: "",
|
pendingQuantity: 0,
|
id: "" // 原始记录ID
|
});
|
|
// 表单验证规则
|
const rules = reactive({
|
schedulingNum: [
|
{ required: true, message: "请输入排产数量", trigger: "blur" }
|
],
|
schedulingUserId: [
|
{ required: true, message: "请选择派工人", trigger: "change" }
|
],
|
schedulingDate: [
|
{ required: true, message: "请选择派工日期", trigger: "change" }
|
]
|
});
|
|
// 表单引用
|
const formRef = ref();
|
|
// 打开弹窗
|
const open = async (rowData) => {
|
try {
|
// 加载用户列表
|
const res = await userListNoPageByTenantId();
|
userList.value = res.data || [];
|
|
// 填充表单数据
|
Object.assign(form, {
|
...rowData,
|
schedulingNum: 0,
|
schedulingUserId: userStore.id,
|
schedulingDate: dayjs().format("YYYY-MM-DD")
|
});
|
|
show.value = true;
|
} catch (error) {
|
uni.showToast({
|
title: '加载用户列表失败',
|
icon: 'error'
|
});
|
}
|
};
|
|
// 处理数量变化
|
const handleNumChange = (value) => {
|
if (value > form.pendingQuantity) {
|
form.schedulingNum = form.pendingQuantity;
|
uni.showToast({
|
title: '排产数量不可大于待排产数量',
|
icon: 'none'
|
});
|
}
|
};
|
|
// 处理用户选择
|
const handleUserSelect = (params) => {
|
if (params.value && params.value.length > 0) {
|
form.schedulingUserId = params.value[0];
|
}
|
showUserPicker.value = false;
|
};
|
|
// 处理日期选择
|
const handleDateSelect = (params) => {
|
if (params.value) {
|
form.schedulingDate = dayjs(params.value).format("YYYY-MM-DD");
|
}
|
showDatePicker.value = false;
|
};
|
|
// 确认派工
|
const handleConfirm = async () => {
|
try {
|
// 表单验证
|
const valid = await formRef.value?.validate();
|
if (!valid) return;
|
|
if (form.schedulingNum <= 0) {
|
uni.showToast({
|
title: '排产数量必须大于0',
|
icon: 'none'
|
});
|
return;
|
}
|
|
submitting.value = true;
|
|
// 提交派工数据
|
await productionDispatch(form);
|
|
uni.showToast({
|
title: '派工成功',
|
icon: 'success'
|
});
|
|
handleClose();
|
emit('confirm');
|
|
} catch (error) {
|
uni.showToast({
|
title: '派工失败',
|
icon: 'error'
|
});
|
} finally {
|
submitting.value = false;
|
}
|
};
|
|
// 弹窗打开事件
|
const handleOpen = () => {
|
// 弹窗打开时的处理
|
};
|
|
// 关闭弹窗
|
const handleClose = () => {
|
show.value = false;
|
showUserPicker.value = false;
|
showDatePicker.value = false;
|
|
// 重置表单
|
Object.assign(form, {
|
projectName: "",
|
productCategory: "",
|
quantity: "",
|
schedulingNum: 0,
|
schedulingUserId: "",
|
schedulingDate: "",
|
pendingQuantity: 0,
|
id: ""
|
});
|
};
|
|
// 暴露方法
|
defineExpose({
|
open
|
});
|
</script>
|
|
<style scoped lang="scss">
|
.dispatch-modal {
|
background: #ffffff;
|
border-radius: 20px 20px 0 0;
|
max-height: 80vh;
|
overflow: hidden;
|
display: flex;
|
flex-direction: column;
|
}
|
|
.modal-header {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
padding: 20px 20px 0 20px;
|
border-bottom: 1px solid #f0f0f0;
|
padding-bottom: 16px;
|
margin-bottom: 20px;
|
}
|
|
.modal-title {
|
font-size: 18px;
|
font-weight: 600;
|
color: #333;
|
}
|
|
.close-btn {
|
padding: 4px;
|
|
&:active {
|
opacity: 0.7;
|
}
|
}
|
|
.modal-content {
|
flex: 1;
|
padding: 0 20px;
|
overflow-y: auto;
|
}
|
|
.form-section {
|
margin-bottom: 24px;
|
}
|
|
.section-title {
|
display: block;
|
font-size: 16px;
|
font-weight: 600;
|
color: #333;
|
margin-bottom: 16px;
|
padding-left: 8px;
|
border-left: 3px solid #2979ff;
|
}
|
|
.modal-footer {
|
display: flex;
|
gap: 12px;
|
padding: 20px;
|
border-top: 1px solid #f0f0f0;
|
background: #fafafa;
|
}
|
|
// uView 组件样式调整
|
:deep(.up-form-item) {
|
margin-bottom: 20px;
|
}
|
|
:deep(.up-input) {
|
background: #f8f9fa;
|
border-radius: 8px;
|
}
|
|
:deep(.up-input--disabled) {
|
background: #f0f0f0;
|
color: #999;
|
}
|
|
:deep(.up-number-box) {
|
background: #f8f9fa;
|
border-radius: 8px;
|
}
|
</style>
|