| | |
| | | <div class="card-body"> |
| | | <!-- <div class="process-name">{{ process.name }}</div> --> |
| | | <div class="process-desc">{{ process.remark || '暂无描述' }}</div> |
| | | <div class="process-device">关联设备: {{ deviceOptions.find(item => item.id === Number(process.deviceLedgerId))?.deviceName|| '未关联' }}</div> |
| | | <div class="process-device">关联设备: {{ (deviceOptions.find(item => item.id === Number(process.deviceLedgerId))?.deviceName) || '未关联' }}</div> |
| | | </div> |
| | | <div class="card-footer"> |
| | | <div class="status-tag"> |
| | |
| | | :type="process.isQuality ? 'warning' : 'info'"> |
| | | {{ process.isQuality ? '质检' : '非质检' }} |
| | | </el-tag> |
| | | <el-tag v-if="process.type !== null && process.type !== undefined" |
| | | size="small" |
| | | :type="process.type == 1 ? 'primary' : 'success'" |
| | | style="margin-left: 8px"> |
| | | {{ process.type == 0 ? '计时' : '计件' }} |
| | | <el-tag size="small" |
| | | style="margin-left: 8px" |
| | | :type="process.isProduction ? 'warning' : 'info'"> |
| | | {{ process.isProduction ? '生产' : '不生产' }} |
| | | </el-tag> |
| | | </div> |
| | | <span class="param-count">工资定额: ¥{{ process.salaryQuota || 0 }}</span> |
| | | <span class="param-count">计划工时: {{ process.salaryQuota || 0 }}小时</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | </div> |
| | | </div> |
| | | <!-- 工序新增/编辑对话框 --> |
| | | <el-dialog v-model="processDialogVisible" |
| | | :title="isProcessEdit ? '编辑工序' : '新增工序'" |
| | | width="500px"> |
| | | <FormDialog v-model="processDialogVisible" |
| | | :title="isProcessEdit ? '编辑部件' : '新增部件'" |
| | | width="600" |
| | | @confirm="handleProcessSubmit" |
| | | @cancel="processDialogVisible = false"> |
| | | <el-form :model="processForm" |
| | | :rules="processRules" |
| | | ref="processFormRef" |
| | | label-width="100px"> |
| | | <el-form-item label="工序编码" |
| | | prop="no"> |
| | | <el-input v-model="processForm.no" |
| | | placeholder="请输入工序编码" /> |
| | | </el-form-item> |
| | | <el-form-item label="工序名称" |
| | | label-width="120px"> |
| | | <el-form-item label="部件名称" |
| | | prop="name"> |
| | | <el-input v-model="processForm.name" |
| | | placeholder="请输入工序名称" /> |
| | | placeholder="请输入部件名称" /> |
| | | </el-form-item> |
| | | <el-form-item label="工资定额" |
| | | <el-form-item label="部件编号" |
| | | prop="no"> |
| | | <el-input v-model="processForm.no" |
| | | placeholder="请输入部件编号" /> |
| | | </el-form-item> |
| | | <el-form-item label="部件类型" |
| | | prop="processType"> |
| | | <el-select v-model="processForm.processType" |
| | | placeholder="请选择部件类型" |
| | | style="width: 100%"> |
| | | <el-option v-for="item in processTypeOptions" |
| | | :key="item" |
| | | :label="item" |
| | | :value="item" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="计划工时(小时)" |
| | | prop="salaryQuota"> |
| | | <el-input v-model="processForm.salaryQuota" |
| | | type="number" |
| | | :step="0.001" /> |
| | | :step="0.5" |
| | | placeholder="请输入计划工时" /> |
| | | </el-form-item> |
| | | <el-form-item label="计划人员" |
| | | prop="planPerson"> |
| | | <el-select v-model="processForm.planPerson" |
| | | placeholder="请选择计划人员" |
| | | clearable |
| | | filterable |
| | | style="width: 100%"> |
| | | <el-option v-for="item in employeeOptions" |
| | | :key="item.id" |
| | | :label="item.staffName" |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="计划执行人员" |
| | | prop="executor"> |
| | | <el-select v-model="processForm.executor" |
| | | placeholder="请选择计划执行人员" |
| | | clearable |
| | | filterable |
| | | style="width: 100%"> |
| | | <el-option v-for="item in employeeOptions" |
| | | :key="item.id" |
| | | :label="item.staffName" |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="是否质检" |
| | | prop="isQuality"> |
| | | <el-switch v-model="processForm.isQuality" /> |
| | | </el-form-item> |
| | | <el-form-item label="计费类型" |
| | | prop="type"> |
| | | <el-radio-group v-model="processForm.type"> |
| | | <el-radio :label="0">计时</el-radio> |
| | | <el-radio :label="1">计件</el-radio> |
| | | </el-radio-group> |
| | | <el-form-item label="是否生产" |
| | | prop="isProduction"> |
| | | <el-switch v-model="processForm.isProduction" /> |
| | | </el-form-item> |
| | | <el-form-item label="关联设备" |
| | | prop="deviceLedgerId"> |
| | |
| | | placeholder="请输入工序描述" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="processDialogVisible = false">取消</el-button> |
| | | <el-button type="primary" |
| | | @click="handleProcessSubmit">确定</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | </FormDialog> |
| | | <!-- 选择参数对话框 --> |
| | | <el-dialog v-model="paramDialogVisible" |
| | | title="选择参数" |
| | | width="1000px"> |
| | | <FormDialog v-model="paramDialogVisible" |
| | | title="选择参数" |
| | | width="1000px"> |
| | | <div class="param-select-container"> |
| | | <!-- 左侧参数列表 --> |
| | | <div class="param-list-area"> |
| | |
| | | </el-form-item> |
| | | <el-form-item label="标准值"> |
| | | <el-input v-model="selectedParam.standardValue" |
| | | @input="val => onStandardValueInput(val, selectedParam)" |
| | | placeholder="请输入默认值" /> |
| | | </el-form-item> |
| | | </el-form> |
| | |
| | | </div> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="paramDialogVisible = false">取消</el-button> |
| | | <el-button type="primary" |
| | | :disabled="!selectedParam" |
| | | @click="handleParamSubmit">确定</el-button> |
| | | <el-button @click="paramDialogVisible = false">取消</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | </FormDialog> |
| | | <!-- 编辑参数对话框 --> |
| | | <el-dialog v-model="editParamDialogVisible" |
| | | title="编辑参数" |
| | |
| | | <el-form-item label="标准值" |
| | | prop="standardValue"> |
| | | <el-input v-model="editParamForm.standardValue" |
| | | @input="val => onStandardValueInput(val, editParamForm)" |
| | | placeholder="请输入标准值" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="editParamDialogVisible = false">取消</el-button> |
| | | <el-button type="primary" |
| | | @click="handleEditParamSubmit">确定</el-button> |
| | | <el-button @click="editParamDialogVisible = false">取消</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted } from "vue"; |
| | | import { ref, reactive, computed, onMounted } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { Plus, Edit, Delete, Search } from "@element-plus/icons-vue"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | |
| | | } from "@/api/productionManagement/productionProcess.js"; |
| | | import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; |
| | | import { getBaseParamList } from "@/api/basicData/parameterMaintenance.js"; |
| | | import { staffOnJobListPage } from "@/api/personnelManagement/staffOnJob.js"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | |
| | | // 部件类型下拉选项(写死) |
| | | const processTypeOptions = [ |
| | | "机加工", |
| | | "刮板冷芯制作", |
| | | "管路组对", |
| | | "罐体连接及调试", |
| | | "测试打压", |
| | | "其他", |
| | | ]; |
| | | |
| | | // 工序列表数据 |
| | | const processValueList = ref([]); |
| | |
| | | const processLoading = ref(false); |
| | | const deviceOptions = ref([]); |
| | | |
| | | // 参数列表数据 |
| | | const paramList = ref([]); |
| | | // 工序已选参数表格分页(接口一次返回全量) |
| | | const paramPage2 = ref({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0, |
| | | }); |
| | | const paramListRaw = ref([]); |
| | | const paramList = computed(() => { |
| | | const all = paramListRaw.value; |
| | | const { current, size } = paramPage2.value; |
| | | const start = (current - 1) * size; |
| | | return all.slice(start, start + size); |
| | | }); |
| | | const paramLoading = ref(false); |
| | | |
| | | // 数据字典 |
| | | const dictTypes = ref([]); |
| | | |
| | | // 员工列表(计划人员、计划执行人员下拉用) |
| | | const employeeOptions = ref([]); |
| | | |
| | | // 工序对话框 |
| | | const processDialogVisible = ref(false); |
| | |
| | | name: "", |
| | | salaryQuota: null, |
| | | isQuality: false, |
| | | isProduction: false, |
| | | remark: "", |
| | | deviceLedgerId: null, |
| | | type: 0, |
| | | processType: "", |
| | | planPerson: null, |
| | | executor: null, |
| | | }); |
| | | const processRules = { |
| | | no: [{ required: true, message: "请输入工序编码", trigger: "blur" }], |
| | | name: [{ required: true, message: "请输入工序名称", trigger: "blur" }], |
| | | no: [{ required: true, message: "请输入部件编码", trigger: "blur" }], |
| | | name: [{ required: true, message: "请输入部件名称", trigger: "blur" }], |
| | | salaryQuota: [ |
| | | { |
| | | required: false, |
| | | message: "请输入工资定额", |
| | | trigger: "blur", |
| | | validator: (rule, value, callback) => { |
| | | if (isNaN(value) || value < 0) { |
| | | callback(new Error("工资定额必须是非负数字")); |
| | | if (value !== null && value !== undefined && value !== "" && (isNaN(value) || Number(value) < 0)) { |
| | | callback(new Error("计划工时必须是非负数字")); |
| | | } else { |
| | | callback(); |
| | | } |
| | |
| | | deviceLedgerId: [ |
| | | { required: false, message: "请选择设备", trigger: "change" }, |
| | | ], |
| | | type: [{ required: false, message: "请选择计费类型", trigger: "change" }], |
| | | processType: [{ required: true, message: "请选择部件类型", trigger: "change" }], |
| | | }; |
| | | |
| | | // 参数对话框 |
| | |
| | | technologyParamId: null, |
| | | paramName: "", |
| | | standardValue: null, |
| | | paramType: null, |
| | | }); |
| | | |
| | | const onStandardValueInput = (val, target) => { |
| | | const data = target.value || target; |
| | | const type = data.paramType; |
| | | if (type === 1) { |
| | | // 数值格式:不能输入中文或英文字符 |
| | | data.standardValue = val.replace(/[a-zA-Z\u4e00-\u9fa5]/g, ""); |
| | | } |
| | | }; |
| | | |
| | | const editParamRules = { |
| | | standardValue: [ |
| | | { |
| | |
| | | if (value === null || value === undefined || value === "") { |
| | | callback(new Error("请输入标准值")); |
| | | } else { |
| | | const type = editParamForm.paramType; |
| | | if (type === 1 && value) { |
| | | if (/[a-zA-Z\u4e00-\u9fa5]/.test(value)) { |
| | | return callback(new Error("数值格式不能包含中英文字符")); |
| | | } |
| | | } |
| | | callback(); |
| | | } |
| | | }, |
| | |
| | | } |
| | | }; |
| | | |
| | | const paramPage2 = ref({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0, |
| | | }); |
| | | |
| | | // 获取参数列表 |
| | | const getParamList = processId => { |
| | | paramLoading.value = true; |
| | | console.log(paramPage2.value, "paramPage2.value"); |
| | | getProcessParamList({ technologyOperationId: processId }) |
| | | .then(res => { |
| | | console.log(res, "res"); |
| | | paramList.value = res.data || []; |
| | | paramPage2.value.total = 0; |
| | | const list = res.data || []; |
| | | paramListRaw.value = Array.isArray(list) ? list : []; |
| | | paramPage2.value.total = paramListRaw.value.length; |
| | | const maxPage = Math.max( |
| | | 1, |
| | | Math.ceil(paramPage2.value.total / paramPage2.value.size) || 1 |
| | | ); |
| | | if (paramPage2.value.current > maxPage) { |
| | | paramPage2.value.current = maxPage; |
| | | } |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.error("获取参数列表失败"); |
| | |
| | | // 选择工序 |
| | | const selectProcess = process => { |
| | | selectedProcess.value = process; |
| | | paramPage2.value.current = 1; |
| | | getParamList(process.id); |
| | | }; |
| | | |
| | |
| | | processForm.name = ""; |
| | | processForm.salaryQuota = null; |
| | | processForm.isQuality = false; |
| | | processForm.isProduction = false; |
| | | processForm.remark = ""; |
| | | processForm.deviceLedgerId = null; |
| | | processForm.type = 0; |
| | | processForm.processType = ""; |
| | | processForm.planPerson = null; |
| | | processForm.executor = null; |
| | | processDialogVisible.value = true; |
| | | }; |
| | | |
| | |
| | | processForm.name = process.name; |
| | | processForm.salaryQuota = process.salaryQuota; |
| | | processForm.isQuality = !!process.isQuality; |
| | | processForm.isProduction = !!process.isProduction; |
| | | processForm.remark = process.remark || ""; |
| | | processForm.deviceLedgerId = Number(process.deviceLedgerId); |
| | | processForm.type = process.type; |
| | | // 如果设备 ID 为 0 或者在设备列表中找不到,则回显为空(null) |
| | | const deviceId = Number(process.deviceLedgerId); |
| | | const hasDevice = deviceOptions.value.some(item => item.id === deviceId); |
| | | processForm.deviceLedgerId = deviceId && hasDevice ? deviceId : null; |
| | | processForm.processType = process.processType || ""; |
| | | processForm.planPerson = process.planPerson || null; |
| | | processForm.executor = process.executor || null; |
| | | processDialogVisible.value = true; |
| | | }; |
| | | |
| | |
| | | getProcessList(); |
| | | if (selectedProcess.value?.id === process.id) { |
| | | selectedProcess.value = null; |
| | | paramList.value = []; |
| | | paramListRaw.value = []; |
| | | paramPage2.value.total = 0; |
| | | } |
| | | }) |
| | | .catch(() => { |
| | |
| | | editParamForm.technologyParamId = row.technologyParamId; |
| | | editParamForm.paramName = row.paramName; |
| | | editParamForm.standardValue = row.standardValue; |
| | | editParamForm.paramType = row.paramType; |
| | | editParamDialogVisible.value = true; |
| | | }; |
| | | |
| | |
| | | }; |
| | | |
| | | const handleParamPagination = obj => { |
| | | console.log(obj, "obj"); |
| | | paramPage2.value.current = obj.page; |
| | | paramPage2.value.size = obj.limit; |
| | | getParamList(selectedProcess.value.id); |
| | | }; |
| | | |
| | | // 获取数据字典 |
| | |
| | | }); |
| | | }; |
| | | |
| | | const loadEmployees = async () => { |
| | | try { |
| | | const res = await staffOnJobListPage({ current: -1, size: -1, staffState: 1 }); |
| | | employeeOptions.value = res.data?.records || []; |
| | | } catch (error) { |
| | | console.error("加载员工列表失败", error); |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | loadDeviceName(); |
| | | getProcessList(); |
| | | getDictTypes(); |
| | | loadEmployees(); |
| | | }); |
| | | </script> |
| | | |