| | |
| | | data: query, |
| | | }); |
| | | } |
| | | |
| | | // 查询损耗率 |
| | | export function getLossRate() { |
| | | return request({ |
| | | url: "/salesLedger/scheduling/loss", |
| | | method: "get", |
| | | }); |
| | | } |
| | | |
| | | // 新增损耗率 |
| | | export function addLossRate(data) { |
| | | return request({ |
| | | url: "/salesLedger/scheduling/addLoss", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // 修改损耗率 |
| | | export function updateLossRate(data) { |
| | | return request({ |
| | | url: "/salesLedger/scheduling/updateLoss", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | |
| | | }) |
| | | |
| | | const handleSizeChange = (val) => { |
| | | console.log('handleSizeChange', val) |
| | | if (currentPage.value * val > props.total) { |
| | | currentPage.value = 1 |
| | | } |
| | |
| | | } |
| | | |
| | | const handleCurrentChange = (val) => { |
| | | console.log('handleCurrentChange---', val) |
| | | emit('pagination', { page: val, limit: pageSize.value }) |
| | | if (props.autoScroll) { |
| | | scrollTo(0, 800) |
| | |
| | | {{ (department_type.find(i => i.value === String(scope.row.department)) || {}).label }} |
| | | </template> |
| | | </el-table-column> --> |
| | | <!-- <el-table-column prop="shiftType" label="班次类型" width="100"> |
| | | <el-table-column prop="shiftType" label="班次类型" width="120"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getShiftTagType(scope.row.shiftType)"> |
| | | {{ (shift_type.find(i => i.value === String(scope.row.shiftType)) || {}).label }} |
| | | {{ (shift_type.find(i => i.value === String(scope.row.shiftType)) || {}).label || '未知' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> --> |
| | | </el-table-column> |
| | | <!-- <el-table-column prop="workDate" label="工作日期" width="120"/> --> |
| | | <el-table-column prop="workStartTime" label="开始时间"/> |
| | | <el-table-column prop="workEndTime" label="结束时间"/> |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> --> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="班次类型:" prop="shiftType"> |
| | | <el-select v-model="scheduleForm.shiftType" placeholder="请选择班次类型" style="width: 100%"> |
| | | <el-option v-for="item in shift_type" :label="item.label" :value="item.value" :key="item.value"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | |
| | | staffIds: [], |
| | | // staffNo: '', |
| | | // department: '', |
| | | // shiftType: '', |
| | | shiftType: '', |
| | | // workDate: '', |
| | | workStartTime: '', |
| | | workEndTime: '', |
| | |
| | | const scheduleRules = reactive({ |
| | | staffIds: [{required: true, message: '请选择员工', trigger: 'change'}], |
| | | // department: [{required: true, message: '请选择部门', trigger: 'change'}], |
| | | // shiftType: [{required: true, message: '请选择班次类型', trigger: 'change'}], |
| | | shiftType: [{required: true, message: '请选择班次类型', trigger: 'change'}], |
| | | // workDate: [{required: true, message: '请选择工作日期', trigger: 'change'}], |
| | | workStartTime: [{required: true, message: '请选择开始时间', trigger: 'change'}], |
| | | workEndTime: [{required: true, message: '请选择结束时间', trigger: 'change'}], |
| | |
| | | // 设置其他必要字段的默认值 |
| | | staffNo: '', // 可以根据需要从personList中获取 |
| | | department: '', |
| | | shiftType: '', |
| | | shiftType: scheduleForm.shiftType, |
| | | workDate: '', |
| | | status: '', |
| | | remark: '' |
| | |
| | | > |
| | | <el-button type="primary" @click="addRow" style="margin-bottom: 10px;">新增</el-button> |
| | | <span style="font-size: 18px;margin-left: 10px">待排产数量:{{pendingNum}}</span> |
| | | <div style="margin-bottom: 10px; margin-left: 10px;"> |
| | | <el-form-item label="领用:" style="margin-bottom: 0;"> |
| | | <el-input v-model="receive" placeholder="请输入领用" style="width: 200px;" /> |
| | | </el-form-item> |
| | | </div> |
| | | <!-- <div style="margin-bottom: 10px; margin-left: 10px;">--> |
| | | <!-- <el-form-item label="领用:" style="margin-bottom: 0;">--> |
| | | <!-- <el-input v-model="receive" placeholder="请输入领用" style="width: 200px;" />--> |
| | | <!-- </el-form-item>--> |
| | | <!-- </div>--> |
| | | <el-table :data="tableData" border style="width: 100%" :summary-method="summarizeMainTable" show-summary :row-key="row => row.id"> |
| | | <el-table-column label="序号" width="60" align="center"> |
| | | <template #default="scope"> |
| | |
| | | clearable |
| | | style="width: 100%" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="损耗" prop="loss" width="150"> |
| | | <template #default="scope"> |
| | | <el-input v-model="scope.row.loss" placeholder="请输入损耗" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="工时定额" width="200" prop="workHours"> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {ref, getCurrentInstance} from "vue"; |
| | | import {userListNoPageByTenantId} from "@/api/system/user.js"; |
| | | import {processScheduling} from "@/api/productionManagement/operationScheduling.js"; |
| | | const { proxy } = getCurrentInstance() |
| | |
| | | |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref('') |
| | | const tableData = ref([ |
| | | { process: '', schedulingDate: '', schedulingNum: null, schedulingUserId: '', workHours: null, unit: '', remark: '', loss: '', type: '' } |
| | | ]); |
| | | const tableData = ref([]); |
| | | const unitFromRow = ref(''); |
| | | const idFromRow = ref(''); |
| | | const pendingNum = ref(''); |
| | | const specificationModelFromRow = ref(''); |
| | | const pendingNum = ref(0); |
| | | const userList = ref([]) |
| | | const receive = ref('') |
| | | |
| | |
| | | userListNoPageByTenantId().then((res) => { |
| | | userList.value = res.data; |
| | | }); |
| | | pendingNum.value = row.pendingNum |
| | | if (row && row.unit !== undefined) { |
| | | unitFromRow.value = row.unit; |
| | | idFromRow.value = row.id; |
| | | tableData.value.forEach(item => { |
| | | item.unit = row.unit; |
| | | item.id = row.id; |
| | | pendingNum.value = row?.pendingNum ?? 0; |
| | | unitFromRow.value = row?.unit ?? ''; |
| | | idFromRow.value = row?.id ?? ''; |
| | | specificationModelFromRow.value = row?.specificationModel ?? ''; |
| | | tableData.value = [createRow()]; |
| | | } |
| | | |
| | | const createRow = () => ({ |
| | | id: idFromRow.value, |
| | | process: '', |
| | | schedulingDate: '', |
| | | schedulingNum: null, |
| | | schedulingUserId: '', |
| | | workHours: null, |
| | | unit: unitFromRow.value, |
| | | remark: '', |
| | | type: specificationModelFromRow.value, |
| | | }); |
| | | } else { |
| | | unitFromRow.value = ''; |
| | | } |
| | | } |
| | | |
| | | const submitForm = () => { |
| | | // 1. 检查每一行是否填写完整 |
| | | for (let i = 0; i < tableData.value.length; i++) { |
| | |
| | | proxy.$modal.msgError('排产数量合计不能超过待排产数量'); |
| | | return; |
| | | } |
| | | // 3. 将 receive 字段添加到每条数据中 |
| | | const submitData = tableData.value.map(row => ({ |
| | | ...row, |
| | | // 3. 将 receive 字段添加到每条数据中,并移除 loss 字段 |
| | | const submitData = tableData.value.map(row => { |
| | | const { loss, ...rest } = row; |
| | | return { |
| | | ...rest, |
| | | receive: receive.value |
| | | })); |
| | | }; |
| | | }); |
| | | processScheduling(submitData).then((res) => { |
| | | proxy.$modal.msgSuccess("提交成功"); |
| | | closeDia(); |
| | |
| | | const closeDia = () => { |
| | | dialogFormVisible.value = false; |
| | | receive.value = ''; |
| | | tableData.value = []; |
| | | unitFromRow.value = ''; |
| | | idFromRow.value = ''; |
| | | specificationModelFromRow.value = ''; |
| | | pendingNum.value = 0; |
| | | emit('close') |
| | | }; |
| | | defineExpose({ |
| | |
| | | }); |
| | | |
| | | const addRow = () => { |
| | | tableData.value.push({ id: idFromRow.value, process: '', unit: unitFromRow.value, schedulingNum: null, workHours: null, schedulingDate: '', schedulingUserId: '', remark: '', loss: '', type: '' }); |
| | | tableData.value.push(createRow()); |
| | | }; |
| | | const removeRow = (index) => { |
| | | tableData.value.splice(index, 1); |
| | |
| | | <span>总量(kg):</span> |
| | | <el-input-number v-model="machineData[machine.name].workLoad" :min="0" :step="1" size="small" /> |
| | | </div> |
| | | <div><span>正在工作量(kg):</span><span>{{ machineData[machine.name].currentWorkLoad }}</span></div> |
| | | <div><span> 预计投入量(kg):</span><span>{{ machineData[machine.name].currentWorkLoad }}</span></div> |
| | | <div><span>空余工作量(kg):</span><span>{{ machineData[machine.name].vacant }}</span></div> |
| | | </div> |
| | | </div> |
| | | <div class="save-button-container"> |
| | | <div class="loss-rate-container"> |
| | | <span class="loss-rate-label">损耗率(%):</span> |
| | | <el-select v-model="rate" placeholder="请选择损耗率" style="width: 120px" size="small"> |
| | | <el-option label="6" :value="6" /> |
| | | <el-option label="7" :value="7" /> |
| | | <el-option label="8" :value="8" /> |
| | | <el-option label="9" :value="9" /> |
| | | <el-option label="10" :value="10" /> |
| | | </el-select> |
| | | </div> |
| | | <el-button type="primary" @click="saveMachineTotals" size="small">保存设置</el-button> |
| | | </div> |
| | | </div> |
| | |
| | | import FormDia from "@/views/productionManagement/productionDispatching/components/formDia.vue"; |
| | | import AutoDispatchDia from "@/views/productionManagement/productionDispatching/components/autoDispatchDia.vue"; |
| | | import dayjs from "dayjs"; |
| | | import {schedulingListPage, schedulingList, addSpeculatTrading, updateSpeculatTrading} from "@/api/productionManagement/productionOrder.js"; |
| | | import {schedulingListPage, schedulingList, addSpeculatTrading, updateSpeculatTrading, getLossRate, addLossRate, updateLossRate} from "@/api/productionManagement/productionOrder.js"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | |
| | | const data = reactive({ |
| | |
| | | |
| | | // 保存炒机总量设置 |
| | | const saveMachineTotals = () => { |
| | | // 验证损耗率是否已选择 |
| | | if (rate.value === null || rate.value === undefined || isNaN(rate.value)) { |
| | | proxy.$message.warning('请选择损耗率'); |
| | | return; |
| | | } |
| | | |
| | | // 构造保存数据数组,使用machines数组循环构建 |
| | | const saveData = machines.map(machine => { |
| | | const saveItem = { |
| | | name: machine.name, // 炒机名称 |
| | | workLoad: machineData[machine.name].workLoad, // 总量 |
| | | currentWorkLoad: machineData[machine.name].currentWorkLoad, // 正在工作量 |
| | | currentWorkLoad: machineData[machine.name].currentWorkLoad, // 预计投入量 |
| | | vacant: machineData[machine.name].vacant // 空余量 |
| | | }; |
| | | |
| | | // 如果是修改操作,需要传递id字段 |
| | | if (hasQueryData.value) { |
| | | // 这里需要从查询数据中获取对应的id |
| | | // 假设查询数据中每个炒机数据都有id字段 |
| | | const queryData = getMachineQueryData(machine.id); |
| | | if (queryData && queryData.id) { |
| | | saveItem.id = queryData.id; |
| | |
| | | return saveItem; |
| | | }); |
| | | |
| | | console.log('保存炒机设置数据:', saveData); |
| | | // 构造损耗率数据 |
| | | const rateData = { |
| | | rate: rate.value |
| | | }; |
| | | |
| | | // 如果有ID,说明是修改操作 |
| | | if (rateId.value) { |
| | | rateData.id = rateId.value; |
| | | } |
| | | |
| | | // 根据是否有查询数据决定调用新增接口还是修改接口 |
| | | const saveApi = hasQueryData.value ? updateSpeculatTrading : addSpeculatTrading; |
| | | const successMessage = hasQueryData.value ? '炒机设置修改成功' : '炒机设置新增成功'; |
| | | |
| | | console.log(`调用接口: ${hasQueryData.value ? '修改' : '新增'}`); |
| | | // 根据是否有ID决定调用新增接口还是修改接口 |
| | | const rateApi = rateId.value ? updateLossRate : addLossRate; |
| | | const rateSuccessMessage = rateId.value ? '损耗率修改成功' : '损耗率新增成功'; |
| | | |
| | | // 调用后端API保存 |
| | | saveApi(saveData).then(res => { |
| | | // 并行调用两个接口 |
| | | Promise.all([ |
| | | saveApi(saveData), |
| | | rateApi(rateData) |
| | | ]).then(([saveRes, rateRes]) => { |
| | | proxy.$message.success(successMessage); |
| | | console.log('保存成功:', res); |
| | | proxy.$message.success(rateSuccessMessage); |
| | | |
| | | // 保存成功后,设置hasQueryData为true,下次保存将调用修改接口 |
| | | if (!hasQueryData.value) { |
| | | hasQueryData.value = true; |
| | | } |
| | | |
| | | // 如果返回了ID,保存起来 |
| | | if (rateRes && rateRes.data && rateRes.data.id) { |
| | | rateId.value = rateRes.data.id; |
| | | } |
| | | |
| | | // 保存成功后重新调用查询页面 |
| | | getList(); |
| | | }).catch(err => { |
| | | proxy.$message.error('保存失败'); |
| | | console.error('保存失败:', err); |
| | |
| | | |
| | | // 是否有查询数据 |
| | | const hasQueryData = ref(false) |
| | | // 损耗率 |
| | | const rate = ref(6) |
| | | // 损耗率ID |
| | | const rateId = ref(null) |
| | | |
| | | // 获取炒机正在工作量数据 |
| | | const getMachineProductionData = () => { |
| | |
| | | machineData[machineName].vacant = machineData[machineName].workLoad - machineData[machineName].currentWorkLoad; |
| | | } |
| | | }); |
| | | |
| | | console.log('炒机数据初始化完成:', machineData); |
| | | console.log('炒机查询数据:', machineQueryData.value); |
| | | } |
| | | }).catch(err => { |
| | | console.error('获取炒机正在工作量数据失败:', err); |
| | |
| | | |
| | | // 同时获取炒机正在工作量数据 |
| | | getMachineProductionData(); |
| | | // 获取损耗率数据 |
| | | getLossRateData(); |
| | | }).catch(() => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | |
| | | // 获取损耗率数据 |
| | | const getLossRateData = () => { |
| | | getLossRate().then((res) => { |
| | | const data = res.data || res; |
| | | if (data && data.rate !== undefined && data.rate !== null) { |
| | | rate.value = Number(data.rate); // 确保转换为数字 |
| | | rateId.value = data.id || null; |
| | | } else { |
| | | rate.value = 6; |
| | | rateId.value = null; |
| | | } |
| | | }).catch(err => { |
| | | console.error('获取损耗率数据失败:', err); |
| | | rate.value = 6; |
| | | rateId.value = null; |
| | | }); |
| | | }; |
| | | // 表格选择数据 |
| | | const handleSelectionChange = (selection) => { |
| | |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | getLossRateData(); |
| | | }); |
| | | </script> |
| | | |
| | |
| | | grid-column: 1 / -1; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | gap: 16px; |
| | | margin-top: 16px; |
| | | padding-top: 16px; |
| | | border-top: 1px solid #e9ecef; |
| | | } |
| | | .loss-rate-container{ |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | .loss-rate-label{ |
| | | font-size: 14px; |
| | | color: #6c757d; |
| | | font-weight: 500; |
| | | white-space: nowrap; |
| | | } |
| | | </style> |
| | |
| | | </div> |
| | | <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" :row-key="(row) => row.id" show-summary style="width: 100%" |
| | | :summary-method="summarizeMainTable" @expand-change="expandChange" height="calc(100vh - 18.5em)"> |
| | | :summary-method="summarizeMainTable" @expand-change="expandChange" height="calc(100vh - 21em)"> |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column type="expand"> |
| | | <template #default="props"> |