evoToK3Cloud-vue/src/views/system/route/index.vue
2026-10-27 17:40:10 +08:00

2486 lines
89 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form :model="queryParams">
<el-form-item label="项目令号" prop="routeDescription">
<el-select v-model="queryParams.routeDescription" filterable remote :remote-method="handleQuery1"
placeholder="请输入令号" clearable :loading="loading">
<el-option v-for="item in projectCodes" :key="item" :label="item" :value="item"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-form>
<div class="route-toolbar">
<div class="route-toolbar__left">
<el-button type="primary" plain icon="el-icon-download" size="mini" @click="handleExport"
v-hasPermi="['system:route:export']">导出
</el-button>
<el-button type="success" plain icon="el-icon-upload" size="mini" @click="handleImport"
:disabled="uploadRouteStatusLocked" :title="uploadRouteStatusLockMsg || ''"
v-hasPermi="['system:route:importRoute']">导入工艺
</el-button>
<el-button type="warning" plain icon="el-icon-time" size="mini" @click="handleImportTime"
v-hasPermi="['system:route:importDataTime']">导入时间
</el-button>
<el-button type="info" plain icon="el-icon-share" size="mini" @click="pushRouteBom"
:disabled="jsyyBlocked || pushRouteStatusLocked"
:title="(jsyyBlocked ? jsyyDenyMsg : '') || pushRouteStatusLockMsg || ''"
v-hasPermi="['system:route:pushRouteBom']">推送工艺
</el-button>
<el-button type="warning" plain icon="el-icon-share" size="mini" @click="pushSelectedMaterialRoute"
:disabled="jsyyBlocked || pushRouteStatusLocked || !ids.length"
:title="(jsyyBlocked ? jsyyDenyMsg : '') || pushRouteStatusLockMsg || (!ids.length ? '请先勾选物料' : '')"
v-hasPermi="['system:route:pushRouteBom']">推送单个工艺
</el-button>
<el-button type="primary" plain icon="el-icon-check" size="mini" @click="approveRoute"
v-hasPermi="['system:route:approveRoute']">审核通过
</el-button>
<el-input
class="route-toolbar__group"
v-model="routeGroupName"
placeholder="请输入推送分组"
size="mini"
clearable
/>
<el-button type="danger" plain icon="el-icon-edit" size="mini" :disabled="multiple" @click="updateProcessPlan"
v-hasPermi="['system:route:updateProcessPlan']">更新计划时间
</el-button>
<el-button type="success" plain icon="el-icon-setting" size="mini" @click="updateProcesTime"
v-hasPermi="['system:route:updateProcesTime']">更新生产订单
</el-button>
<el-button type="primary" plain icon="el-icon-document" size="mini" @click="generatePDFs1"
:loading="generatingAllPdf"
v-hasPermi="['system:route:generatePDFs']">生成PDF
</el-button>
<el-button type="danger" plain icon="el-icon-warning" size="mini" @click="getKindeeExcel"
v-hasPermi="['system:route:getKindeeExcel']">获取标准工艺
</el-button>
<el-button type="danger" plain icon="el-icon-warning" size="mini" @click="getAllRouteAndUse"
v-hasPermi="['system:route:getAllRouteAndUse']">获取全部工艺
</el-button>
</div>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</div>
<el-form :inline="true" :model="form" ref="ruleForm" size="mini" :rules="rules">
<el-table v-if="showtable" v-loading="loading" row-key="id" ref="tree" v-drag:[config]="form.routeList"
:tree-props="{ children: 'children' }" :data="form.routeList" stripe :row-class-name="tableRowClassName" border
max-height="680px" @cell-click="cellhand" :default-expand-all="true" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<!-- <el-table-column label="主键ID" align="center" prop="id" v-if="true"/>-->
<el-table-column label="操作" width="55" align="center">
<template slot-scope="props">
<!-- <el-button type="text" icon="el-icon-check" v-if="scope.row.id < 0" @click="onSaveChild()" /> -->
<!-- <fromed v-if="props.row.parentId" /> -->
<!-- {{props.row.materialCode}} -->
<el-button v-if="props.row.parentId" size="mini" class="handle" icon="el-icon el-icon-rank" />
</template>
</el-table-column>
<!-- <el-table-column label="项目令号" align="center">
<template slot-scope="scope">升降台
<router-link :to="'/route1/' + scope.row.routeDescription" type="primary" :underline="false">{{
scope.row.routeDescription }}</router-link>
</template>
</el-table-column> -->
<el-table-column label="物料编码" width="140" align="center" prop="materialCode" fixed="left" />
<el-table-column label="名称" width="120" align="center" prop="materialName" fixed="left" />
<el-table-column label="材质" width="80" align="center" prop="material" />
<el-table-column label="单重" width="60" align="center" prop="discWeight" />
<el-table-column label="单台数" width="60" align="center" prop="unitQuantity">
<template slot-scope="scope">
<span :style="{
color: scope.row.firstBatchQuantity > 0 ? 'green' : 'red',
fontWeight: 'bold'
}">
{{ scope.row.firstBatchQuantity }}
</span>
</template>
</el-table-column>
<el-table-column label="本批数" width="60" align="center" prop="batchQuantity" />
<el-table-column label="重要程度" width="80" align="center" prop="stateImportance" />
<el-table-column label="工序号" width="60" align="center" prop="processNo" />
<el-table-column label="工作中心" width="96" align="center">
<template slot-scope="scope">
<el-form-item v-if="scope.row.isEdit" :prop="'routeList.' + scope.$index + '.workCenter'">
<el-select v-model="scope.row.workCenter" placeholder="请选择工作中心" clearable>
<el-option v-for="dict in dict.type.work_center" :key="dict.value" :label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
<span v-else>
<dict-tag :options="dict.type.work_center" :value="scope.row.workCenter" />
</span>
</template>
</el-table-column>
<el-table-column label="工序名称" width="160" align="center">
<template slot-scope="scope">
<el-form-item v-if="scope.row.id < 0 || scope.row.isEdit"
:prop="'routeList.' + scope.$index + '.processName'">
<el-select v-model="scope.row.processName" filterable remote :remote-method="handleQuery3"
placeholder="请输入工序名称" clearable :loading="loading" @change="handleProcessNameChange(scope)">
<el-option v-for="item in processName" :key="item" :label="item" :value="item"></el-option>
</el-select>
</el-form-item>
<span v-else>{{ scope.row.processName }}</span>
</template>
</el-table-column>
<el-table-column label="序说明" width="300" align="center">
<template slot-scope="scope">
<el-form-item v-if="scope.row.id < 0 || scope.row.isEdit"
:prop="'routeList.' + scope.$index + '.processDescription'">
<el-input v-model="scope.row.processDescription"></el-input>
</el-form-item>
<span v-else>{{ scope.row.processDescription }}</span>
</template>
</el-table-column>
<!-- 工序控制列 -->
<el-table-column label="工序控制码" width="100" align="center">
<template slot-scope="scope">
<el-form-item v-if="scope.row.isEdit" :prop="'routeList.' + scope.$index + '.processControl'">
<el-select
v-model="scope.row.processControl"
placeholder="请选择工序控制码"
clearable
filterable
allow-create
default-first-option
>
<el-option
v-for="item in processControlOptions"
:key="item"
:label="item"
:value="item"
/>
</el-select>
</el-form-item>
<span v-else>{{ scope.row.processControl }}</span>
</template>
</el-table-column>
<el-table-column label="活动时长" align="center">
<template slot-scope="scope">
<el-form-item v-if="scope.row.id < 0 || scope.row.isEdit"
:prop="'routeList.' + scope.$index + '.activityDuration'">
<el-input v-model="scope.row.activityDuration"></el-input>
</el-form-item>
<span v-else>{{ scope.row.activityDuration }}</span>
</template>
</el-table-column>
<el-table-column label="活动单位" align="center" prop="activityUnit" />
<el-table-column label="序开始时间" align="center" prop="xuStartTime" width="100">
<template slot-scope="scope">
<el-form-item v-if="scope.row.id < 0 || scope.row.isEdit"
:prop="'routeList.' + scope.$index + '.xuStartTime'">
<el-date-picker v-model="scope.row.xuStartTime" type="date" placeholder="选择序开始时间"
value-format="yyyy-MM-dd" format="yyyy-MM-dd">
</el-date-picker>
</el-form-item>
<span v-else>{{ parseTime(scope.row.xuStartTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="序结束时间" align="center" prop="xuEndTime" width="100">
<template slot-scope="scope">
<el-form-item v-if="scope.row.id < 0 || scope.row.isEdit"
:prop="'routeList.' + scope.$index + '.xuEndTime'">
<el-date-picker v-model="scope.row.xuEndTime" type="date" placeholder="选择序结束时间" value-format="yyyy-MM-dd"
format="yyyy-MM-dd">
</el-date-picker>
</el-form-item>
<span v-else>{{ parseTime(scope.row.xuEndTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="计划开始时间" align="center" prop="planStartTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.planStartTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="计划结束时间" align="center" prop="planEndTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.planEndTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column class="maxWidth" label="操作" width="250" fixed="right" align="center"
class-name="small-padding fixed-width">
<template slot-scope="scope">
<div class="route-row-ops">
<el-button class="btn" size="mini" @click="onAddChild(scope)" v-if="!scope.row.parentId">
添加工艺
</el-button>
<el-dropdown
v-if="rowMoreVisible(scope.row)"
trigger="click"
@command="command => handleRowMore(scope.row, command)"
>
<el-button class="btn" size="mini">
更多<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
v-hasPermi="['system:route:pushRouteBom']"
command="push"
:disabled="jsyyBlocked || pushRouteStatusLocked || pushingMaterialCode === scope.row.materialCode"
>{{ pushingMaterialCode === scope.row.materialCode ? '推送中…' : '推送该物料工艺' }}</el-dropdown-item>
<el-dropdown-item
v-hasPermi="['system:route:generatePDFs']"
command="pdf"
:disabled="downloadingPdfCode === scope.row.materialCode"
>{{ downloadingPdfCode === scope.row.materialCode ? '下载中…' : '下载PDF' }}</el-dropdown-item>
<template v-if="isPlmProject">
<el-dropdown-item
v-for="(fmt, index) in drawingModelFormats"
:key="fmt.type"
v-hasPermi="['system:route:downloadDrawingModel']"
:divided="index === 0"
:command="'model:' + fmt.type"
:disabled="downloadingDrawingCode === scope.row.materialCode"
>{{ fmt.label }}</el-dropdown-item>
</template>
</el-dropdown-menu>
</el-dropdown>
<el-button class="btn" size="mini" type="success" @click="onSave(scope)"
v-if="!scope.row.parentId && showParentSaveBtn === scope.row.id">
保存工艺
</el-button>
<template v-else-if="scope.row.parentId">
<template v-if="scope.row.isEdit">
<el-button class="btn" size="mini" type="success" @click="onSaveRow(scope)">
确定
</el-button>
<el-button class="btn" size="mini" type="info" @click="cancelEdit(scope)">
取消
</el-button>
</template>
<template v-else>
<template v-if="scope.row.id > 0">
<el-button class="btn" size="mini" type="primary" @click="handleRowEdit(scope)"
v-hasPermi="['system:route:edit']">
修改
</el-button>
<el-button class="btn" size="mini" type="danger" @click="handleDelete(scope)"
v-hasPermi="['system:route:remove']">
删除
</el-button>
</template>
<template v-else>
<el-button class="btn" size="mini" type="danger" @click="onDeleteUnsaved(scope)">
删除
</el-button>
</template>
</template>
</template>
</div>
</template>
</el-table-column>
</el-table>
</el-form>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
@pagination="getList" />
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<!-- 基本信息 -->
<el-row>
<el-col :span="12">
<el-form-item label="物料编码" prop="materialCode">
<el-input v-model="form.materialCode" placeholder="请输入物料编码" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="物料名称" prop="materialName">
<el-input v-model="form.materialName" placeholder="请输入物料名称" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="材质" prop="material">
<el-input v-model="form.material" placeholder="请输入材质" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="单重" prop="discWeight">
<el-input v-model="form.discWeight" placeholder="请输入单重" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="单位" prop="bomUnit">
<el-select v-model="form.bomUnit" placeholder="请选择单位">
<el-option label="件" value="件"></el-option>
<el-option label="套" value="套"></el-option>
<el-option label="个" value="个"></el-option>
<el-option label="米" value="米"></el-option>
<el-option label="千克" value="千克"></el-option>
<el-option label="吨" value="吨"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="单台数量" prop="unitQuantity">
<el-input-number v-model="form.unitQuantity" :min="0" placeholder="请输入单台数量" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="本批数量" prop="batchQuantity">
<el-input-number v-model="form.batchQuantity" :min="0" placeholder="请输入本批数量" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="首批数量" prop="firstBatchQuantity">
<el-input-number v-model="form.firstBatchQuantity" :min="0" placeholder="请输入首批数量" />
</el-form-item>
</el-col>
</el-row>
<!-- 工艺信息 -->
<el-row>
<el-col :span="12">
<el-form-item label="工作中心" prop="workCenter">
<el-select v-model="form.workCenter" placeholder="请选择工作中心" clearable>
<el-option label="机一工段" value="机一工段"></el-option>
<el-option label="机二工段" value="机二工段"></el-option>
<el-option label="焊接工段" value="焊接工段"></el-option>
<el-option label="装一工段" value="装一工段"></el-option>
<el-option label="装二工段" value="装二工段"></el-option>
<el-option label="下料工段" value="下料工段"></el-option>
<el-option label="电钳工段" value="电钳工段"></el-option>
<el-option label="委外中心" value="委外中心"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工序名称" prop="processName">
<el-select v-model="form.processName" filterable remote :remote-method="handleQuery3"
placeholder="请输入工序名称" clearable :loading="loading" @change="handleProcessNameChange">
<el-option v-for="item in processName" :key="item" :label="item" :value="item"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="工序说明" prop="processDescription">
<el-input type="textarea" v-model="form.processDescription" placeholder="请输入工序说明" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="工序控制" prop="processControl">
<el-select
v-model="form.processControl"
placeholder="请选择工序控制码"
clearable
filterable
allow-create
default-first-option
>
<el-option
v-for="item in processControlOptions"
:key="item"
:label="item"
:value="item"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="活动时长" prop="activityDuration">
<el-input v-model="form.activityDuration" placeholder="请输入活动时长" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="序开始时间" prop="xuStartTime">
<el-date-picker v-model="form.xuStartTime" type="date" placeholder="选择序开始时间" value-format="yyyy-MM-dd"
format="yyyy-MM-dd">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="序结束时间" prop="xuEndTime">
<el-date-picker v-model="form.xuEndTime" type="date" placeholder="选择序结束时间" value-format="yyyy-MM-dd"
format="yyyy-MM-dd">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
<!-- 导入导入对话框 -->
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
<el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :headers="upload.headers"
:action="importUploadAction" :disabled="upload.isUploading"
:on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip">
<div class="el-upload__tip" slot="tip">
<el-checkbox v-model="upload.updateSupport" />
是否更新已经存在的物料数据
</div>
<span>仅允许导入xls、xlsx格式文件。</span>
<!-- <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;"
@click="importTemplate">下载模板
</el-link>-->
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm">确 定</el-button>
<el-button @click="upload.open = false">取 消</el-button>
</div>
</el-dialog>
<el-dialog :title="timeUpload.title" :visible.sync="timeUpload.open" width="400px" append-to-body>
<el-upload ref="timeUpload" :limit="1" accept=".xlsx, .xls" :headers="timeUpload.headers" :action="timeUpload.url"
:disabled="timeUpload.isUploading" :on-progress="handleTimeFileUploadProgress"
:on-success="handleTimeFileSuccess" :auto-upload="false" drag>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip">
<span>仅允许导入xls、xlsx格式文件。</span>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitTimeFileForm">确 定</el-button>
<el-button @click="timeUpload.open = false">取 消</el-button>
</div>
</el-dialog>
<!-- 抽屉 -->
<el-drawer title="BOM信息" :visible.sync="BOMpop" :before-close="bomClose" :size="1100" :destroy-on-close="true"
:modal="false">
<div style="padding: 20px;">
<!-- BOM信息头部 -->
<div class="bom-header">
<el-descriptions :column="3" border>
<el-descriptions-item label="当前物料编码">{{ currentMaterial.materialCode }}</el-descriptions-item>
<el-descriptions-item label="当前物料名称">{{ currentMaterial.materialName }}</el-descriptions-item>
<el-descriptions-item label="生产令号">{{ currentMaterial.productionOrderNo }}</el-descriptions-item>
</el-descriptions>
</div>
<!-- 搜索和操作按钮 -->
<div class="table-operations" style="margin: 15px 0;">
<div class="right-operations">
<el-button-group>
<el-button type="primary" size="small" @click="handleBomAdd">
<i class="el-icon-plus"></i> 新增
</el-button>
<el-button type="primary" size="small" @click="handleBomRefresh">
<i class="el-icon-refresh"></i> 刷新
</el-button>
<el-button type="success" size="small" @click="handleBomExport">
<i class="el-icon-download"></i> 导出
</el-button>
</el-button-group>
</div>
</div>
<!-- BOM数据表格 -->
<el-table :data="filteredBomData" stripe max-height="400px" border v-loading="bomLoading"
@selection-change="handleBomSelectionChange" element-loading-text="加载中..."
element-loading-spinner="el-icon-loading">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="生产令号" width="150" align="center" prop="projectNumber" />
<el-table-column label="物料编码" width="200" align="center" prop="materialCode" show-overflow-tooltip />
<el-table-column label="物料名称" width="200" align="center" prop="materialName" show-overflow-tooltip />
<el-table-column label="材质" width="70" align="center" prop="materialType" />
<el-table-column label="库存" width="88" align="center" prop="singleWeight ">
<template slot-scope="scope">
<span>{{ scope.row.singleWeight || '0' }}</span>
</template>
</el-table-column>
<el-table-column label="用量" width="88" align="center" prop="quantity">
<template slot-scope="scope">
<span>{{ scope.row.quantity || '0' }}</span>
</template>
</el-table-column>
<el-table-column label="单位" width="88" align="center" prop="unit" />
<el-table-column label="操作" align="center" width="150">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleBomEdit(scope.row)">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleBomDelete(scope.row)">删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- BOM编辑对话框 -->
<el-dialog :title="bomDialogTitle" :visible.sync="bomDialogVisible" width="500px" append-to-body>
<el-form ref="bomForm" :model="bomForm" :rules="bomRules" label-width="100px">
<input type="hidden" v-model="bomForm.projectNumber">
<input type="hidden" v-model="bomForm.parentMaterialCode">
<input type="hidden" v-model="bomForm.parentMaterialName">
<!-- 物料名称 - 支持搜索或手动输入 -->
<el-form-item label="物料名称" prop="materialName">
<el-autocomplete v-model="bomForm.materialName" :fetch-suggestions="handleMaterialSearch"
:trigger-on-focus="false" @select="handleMaterialSelect" placeholder="请输入物料名称" clearable
popper-class="material-autocomplete-dropdown">
<template slot-scope="{ item }">
<div class="material-suggestion-item">
<div class="material-name">{{ item.materialName }}</div>
<div class="material-info">
<span>编码: {{ item.materialCode }}</span>
<span>材质: {{ item.materialType }}</span>
<span>单位: {{ item.classificationName }}</span>
<span>库存: {{ item.singleWeight || '0' }}</span>
</div>
</div>
</template>
</el-autocomplete>
</el-form-item>
<!-- 物料编码 - 允许手动输入 -->
<el-form-item label="物料编码" prop="materialCode">
<el-input v-model="bomForm.materialCode" placeholder="请输入物料编码"></el-input>
</el-form-item>
<!-- 材质 - 允许手动输入 -->
<el-form-item label="材质" prop="materialType">
<el-input v-model="bomForm.materialType" placeholder="请输入材质"></el-input>
</el-form-item>
<!-- 单位 -->
<el-form-item label="单位" prop="unit">
<el-select v-model="bomForm.unit" placeholder="请选择单位" clearable>
<el-option label="件" value="件"></el-option>
<el-option label="根" value="根"></el-option>
<el-option label="mm" value="mm"></el-option>
<el-option label="kg" value="kg"></el-option>
<el-option label="套" value="套"></el-option>
<el-option label="个" value="个"></el-option>
</el-select>
</el-form-item>
<!-- 当前库存 - 允许手动输入 -->
<el-form-item label="当前库存" prop="stock">
<el-input-number v-model="bomForm.stock" :min="0" :precision="2" placeholder="请输入库存"></el-input-number>
</el-form-item>
<!-- 用量 -->
<el-form-item label="用量" prop="quantity">
<el-input-number v-model="bomForm.quantity" :min="0" :precision="2" placeholder="请输入用量"></el-input-number>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitBomForm">确 定</el-button>
<el-button @click="bomDialogVisible = false">取 消</el-button>
</div>
</el-dialog>
<!-- 工艺路线信息部分 -->
<div class="section-title" style="margin: 20px 0 15px;">
<h3>工艺路线信息</h3>
</div>
<el-table :data="processRoutes" stripe border v-loading="processLoading">
<el-table-column label="工艺编号" prop="fnumber" width="120" align="center" />
<el-table-column label="项目令号" prop="project_code" width="180" align="center" />
<el-table-column label="物料编码" prop="materialCode" fixed="left" width="140" align="center" />
<el-table-column label="物料名称" prop="materialName" fixed="left" min-width="140" align="center" />
<el-table-column label="操作" width="120" align="center">
<template slot-scope="scope">
<el-button @click="handleViewRoute(scope.row)"
:type="selectedRouteId === scope.row.id ? 'success' : 'primary'">
{{ selectedRouteId === scope.row.id ? '查看中' : '查看' }}
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 选中的工艺路线工序信息 -->
<div v-if="selectedRoute" class="process-detail" style="margin-top: 15px;">
<div class="sub-title" style="margin-bottom: 10px;">
<h4>工序信息 - {{ selectedRoute.fnumber }}</h4>
</div>
<el-table :data="currentProcessList" stripe border max-height="300px">
<el-table-column label="工序号" prop="processNo" width="80" align="center" />
<el-table-column label="工作中心" prop="workCenter" width="120" align="center" />
<el-table-column label="工序名称" prop="processName" width="120" align="center" />
<el-table-column label="工序说明" prop="processDescription" min-width="200" show-overflow-tooltip />
<el-table-column label="工序控制" prop="processControl" width="120" align="center" />
<el-table-column label="活动时长" align="center" width="120">
<template slot-scope="scope">
{{ scope.row.activityDuration }} {{ scope.row.activityUnit }}
</template>
</el-table-column>
</el-table>
</div>
</div>
</el-drawer>
</div>
</template>
<script>
import {
listRoute,
getRoute,
delRoute,
addRoute,
updateRoute,
getDistinctProjectCodes,
updateProcessPlan, generatePDFs, downloadDrawingModel as requestDrawingModel, updateBom, addBom, deleteBom, getKindeeExcel, getAllRouteAndUse, updateProcesTime
} from "@/api/system/route";
import { getToken } from "../../../utils/auth";
import Fromed from './fromed'
import Bomfrom from './bomfrom'
import { getProcessInfoList, pushRouteBom, pushRouteBomByMaterial, approveRoute, onSave, getBomInfo, getProcessRouteList } from "@/api/system/route";
import { listMaterial } from "@/api/system/material";
import { blobValidate } from "@/utils/ruoyi";
import { checkPermi } from "@/utils/permission";
import dict from "@/utils/dict";
import DictData from "@/components/DictData";
import { isJsyyOrderNo, JSYY_DENY_MSG } from "@/utils/jsyyOrderNo";
import {
ProjectStatusAction,
denyIfProjectStatusLocked,
} from "@/utils/projectStatusLock";
import { listOrderPro } from "@/api/system/orderPro";
DictData.install();
export default {
name: "",
dicts: ['work_center'],
components: {
Fromed,
Bomfrom
},
props: {
params: {},
showdel: {
type: Boolean,
default: true
},
obj: {
type: Object,
default() {
return {}
}
}
},
data() {
return {
timeUpload: {
open: false,
title: "",
isUploading: false,
headers: { Authorization: "Bearer " + getToken() },
url: process.env.VUE_APP_BASE_API + "/system/route/importDataTime"
},
materialOptions: [], // 用于存储物料信息
processControlOptions: [
'汇报+免检',
'汇报+质量',
'委外+质量',
'委外+汇报'
],
showtable: true,
expand: true,
bomData: [],
bomLoading: false,
bomSearchKey: '',
currentMaterial: {
materialCode: '',
materialName: '',
productionOrderNo: ''
},
bomPagination: {
currentPage: 1,
pageSize: 10
},
totalBomCount: 0,
BOMpop: false,
bomList: [],
//expandRowKeys:[],
omdelData: '',
routeDescription: '', // 用于存储 productionOrderNo 的变量
/** 当前令号对应项目状态,用于状态锁 */
projectBomStatus: undefined,
/** 当前令号来源:手动 / PLM */
projectSource: undefined,
/** 正在下载图纸模型的物料编码 */
downloadingDrawingCode: "",
// 按钮loading
buttonLoading: false,
// 遮罩层
loading: true,
// 选中数组
ids: [],
selectedRows: [],
/** 正在下载 PDF 的物料编码,用于行内按钮 loading */
downloadingPdfCode: "",
/** 图纸模型文件服务支持的格式,propertyValue 传物料编码(图号) */
drawingModelFormats: [
{ type: "sldprt", label: "零件模型 sldprt" },
{ type: "sldasm", label: "装配模型 sldasm" },
{ type: "dwg", label: "DWG" },
{ type: "pdf", label: "PDF" },
{ type: "x_t", label: "x_t" }
],
/** 正在按物料推送工艺的物料编码 */
pushingMaterialCode: "",
/** 工具栏「生成PDF」整包 zip 的 loading */
generatingAllPdf: false,
// 非单禁用
single: true,
// 非多个禁用
multiple: false,
// 显示搜索条件
showSearch: true,
// 显示父级的保存工艺按钮
showParentSaveBtn: null,
// 总条数
total: 0,
form: {
// 工艺路线表格数据
routeList: [],
},
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 工序详情对话框显示状态
processDetailsVisible: false,
// 当前显示的工序列表
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 500,
routeDescription: [],
materialCode: undefined,
materialName: undefined,
stateImportance: undefined,
bomUnit: undefined,
processNo: undefined,
workCenter: undefined,
processName: undefined,
rawMaterialCode: undefined,
rawMaterialName: undefined,
discWeight: undefined,
discUsage: undefined,
firstBatchQuantity: undefined,
processDescription: undefined,
processControl: undefined,
activityDuration: undefined,
activityUnit: undefined,
},
// 对应关系映射:工序名称 -> 工作中心
processToWorkCenterMap: {
// 下料工段
'数控火焰下料': '下料工段',
'数控激光下料': '下料工段',
'数控切管下料': '下料工段',
'水虎鱼剪折冲': '下料工段',
'锯床下料': '下料工段',
'抛丸': '下料工段',
'组焊': '下料工段',
'普车': '机一工段',
'普铣': '机一工段',
'龙门铣': '机一工段',
'立磨': '机一工段',
'平磨': '机一工段',
'钻床': '机一工段',
'数车': '机二工段',
'数控外圆磨': '机二工段',
'走芯机': '机二工段',
'双主轴': '机二工段',
'车铣复合': '机二工段',
'线切割': '机二工段',
'卧加63': '焊接工段',
'5032龙门': '焊接工段',
'3018龙门': '焊接工段',
'2013龙门': '焊接工段',
'立加1370': '焊接工段',
'立加1177': '焊接工段',
'立加850': '焊接工段',
'数插5035': '焊接工段',
'装配1': '装一工段',
'装配2': '装二工段',
'电装': '电钳工段',
'正火': '委外中心',
'回火': '委外中心',
'调质': '委外中心',
'真空调质': '委外中心',
'整体淬火': '委外中心',
'表面淬火': '委外中心',
'真空淬火': '委外中心',
'渗碳淬火': '委外中心',
'渗氮': '委外中心',
'碳氮共渗': '委外中心',
'制齿': '委外中心',
'电火花': '委外中心',
'插床': '委外中心',
'按图订制': '委外中心',
'磷化处理': '委外中心',
'发蓝处理': '委外中心',
'QPQ处理': '委外中心',
'镀锌': '委外中心',
'镀硬铬': '委外中心',
'镀锌镍合金': '委外中心',
'阳极氧化': '委外中心',
'达克罗': '委外中心',
'喷漆': '委外中心',
'喷塑': '委外中心',
'喷砂': '委外中心',
'喷砂底漆': '委外中心'
},
// 表单参数
projectCodes: [], // 存储查询到的项令号
processName: [],
activeRows: [], // 转换为列表的数据
config: {
elementSeletor: "tbody", //元素选择
filter: ".filtered", // 过滤
onEnd: (event, oldValue, newValue) => {
// 找到父节点
const parentIndex = this.form.routeList.findIndex(item =>
item.children && item.children.some(child => child.id === newValue.id)
);
if (parentIndex !== -1) {
// 获取子节点列表
const children = this.form.routeList[parentIndex].children;
// 重新排序工序号
children.forEach((child, index) => {
child.processNo = (index + 1) * 10;
});
}
},
},
upload: {
// 是否显示弹出层
open: false,
// 弹出层标题
title: "",
// 是否禁用上传
isUploading: false,
// 是否更新已经存在的用户数据
updateSupport: 0,
// 设置上传的请求头部
headers: { Authorization: "Bearer " + getToken() },
// 上传的地址
url: process.env.VUE_APP_BASE_API + "/system/route/importData"
},
id: 0,//动态增加表格列的ID
// 表单校验
rules: {
id: [
{ required: true, message: "主键ID不能为空", trigger: "blur" }
],
routeDescription: [
{ required: true, message: "工艺路线描述不能为空", trigger: "blur" }
],
materialCode: [
{ required: true, message: "物料编码不能为空", trigger: "blur" }
],
materialName: [
{ required: true, message: "物料名称不能为空", trigger: "blur" }
],
processControl: [ // 添加工序控制码的验证
{ required: true, message: "工序控制码不能为空", trigger: "blur" }
],
processName: [ // 添加工序名称的验证
{ required: true, message: "工序名称不能为空", trigger: "blur" }
],
activityDuration: [ // 添加活动时长的验证
{ required: true, message: "活动时长不能为空", trigger: "blur" }
]
},
bomDialogVisible: false,
bomDialogTitle: '',
bomForm: {
id: undefined,
projectNumber: '', // 添加项目令号
materialCode: '',
materialName: '',
materialType: '',
quantity: 0,
unit: '',
stock: 0,
parentMaterialCode: '', // 添加父级物料编码
parentMaterialName: '', // 添加父级物料名称
},
bomRules: {
materialName: [
{ required: true, message: '请输入物料名称', trigger: 'blur' }
],
materialCode: [
{ required: true, message: '请输入物料编码', trigger: 'blur' }
],
materialType: [
{ required: true, message: '请选择材质', trigger: 'change' }
],
unit: [
{ required: true, message: '请选择单位', trigger: 'change' }
],
quantity: [
{ required: true, message: '请输入用量', trigger: 'blur' }
],
projectNumber: [
{ required: true, message: '项目令号不能为空', trigger: 'blur' }
],
parentMaterialCode: [
{ required: true, message: '父级物料编码不能为空', trigger: 'blur' }
],
parentMaterialName: [
{ required: true, message: '父级物料名称不能为空', trigger: 'blur' }
],
stock: [
{ required: true, message: '库存不能为空', trigger: 'blur' }
]
},
selectedBomRows: [],
materialSearchLoading: false,
materialQuery: '', // 当前搜索关键字
materialPagination: {
pageNum: 1,
pageSize: 10,
total: 0
},
materialLoading: false, // 加载更多状态
hasMoreMaterial: true, // 是否还有更多数据
activeTab: 'bom', // 当前激活的标签页
processRouteData: [], // 工艺路线数据
processLoading: false, // 工艺信息加载状态
processRoutes: [], // 所有工艺路线
selectedRouteId: null, // 当前选中的工艺路线ID
selectedRoute: null, // 当前选中的工艺路线完整信息
currentProcessList: [], // 当前显示的工序列表
dataList: [], // 存储获取到的数据
routeGroupName: ''
};
},
created() {
this.queryParams.routeDescription = "";
console.log(this.params)
if (this.params && this.params.productionOrderNo) {
this.queryParams.routeDescription = this.params.productionOrderNo;
}
// const productionOrderNo = this.params.productionOrderNo;
// if (productionOrderNo) {
// this.queryParams.routeDescription = productionOrderNo;
// } else {
// }
this.getList();
},
mounted() {
this.rowDrop();
},
computed: {
filteredBomData() {
if (!this.bomSearchKey) return this.bomData;
const searchKey = this.bomSearchKey.toLowerCase();
return this.bomData.filter(item => {
return Object.values(item).some(value =>
String(value).toLowerCase().includes(searchKey)
);
});
},
jsyyBlocked() {
const orderNo = (this.params && this.params.productionOrderNo) || this.queryParams.routeDescription;
return isJsyyOrderNo(orderNo);
},
/** 当前要导入的项目令号:抽屉传入优先,否则用页面所选令号 */
currentImportOrderNo() {
const fromParams = this.params && this.params.productionOrderNo;
const fromQuery = this.queryParams && this.queryParams.routeDescription;
return String(fromParams || fromQuery || "").trim();
},
/** 上传地址带上当前令号,后端据此与 Excel 内令号核对 */
importUploadAction() {
let url = this.upload.url + "?updateSupport=" + this.upload.updateSupport;
const orderNo = this.currentImportOrderNo;
if (orderNo) {
url += "&productionOrderNo=" + encodeURIComponent(orderNo);
}
return url;
},
jsyyDenyMsg() {
return JSYY_DENY_MSG;
},
resolvedBomStatus() {
if (this.params && this.params.bomStatus !== undefined && this.params.bomStatus !== null && this.params.bomStatus !== "") {
return this.params.bomStatus;
}
return this.projectBomStatus;
},
uploadRouteStatusLockMsg() {
return denyIfProjectStatusLocked(this.resolvedBomStatus, ProjectStatusAction.UPLOAD_ROUTE);
},
uploadRouteStatusLocked() {
return !!this.uploadRouteStatusLockMsg;
},
pushRouteStatusLockMsg() {
return denyIfProjectStatusLocked(this.resolvedBomStatus, ProjectStatusAction.PUSH_ROUTE);
},
pushRouteStatusLocked() {
return !!this.pushRouteStatusLockMsg;
},
isPlmProject() {
const source = (this.params && this.params.source) || this.projectSource;
return String(source || "").trim().toUpperCase() === "PLM";
},
},
watch: {
'$route.query.productionOrderNo': function (newVal) {
this.setTotalWeight();
this.getList();
if (newVal) {
this.queryParams.routeDescription = newVal;
}
},
"params.productionOrderNo": {
immediate: true,
handler(val) {
if (val) {
this.refreshProjectBomStatus(val);
}
},
},
"queryParams.routeDescription"(val) {
if (val) {
this.refreshProjectBomStatus(val);
}
},
},
methods: {
async refreshProjectBomStatus(orderNo) {
if (!orderNo) {
this.projectBomStatus = undefined;
this.projectSource = undefined;
return;
}
const hasParamStatus = this.params
&& this.params.bomStatus !== undefined
&& this.params.bomStatus !== null
&& this.params.bomStatus !== "";
if (hasParamStatus) {
this.projectBomStatus = this.params.bomStatus;
}
if (this.params && this.params.source) {
this.projectSource = this.params.source;
}
if (hasParamStatus && this.projectSource) {
return;
}
try {
const res = await listOrderPro({ productionOrderNo: orderNo, pageNum: 1, pageSize: 1 });
const row = (res.rows && res.rows[0]) || null;
if (!hasParamStatus) {
this.projectBomStatus = row ? row.bomStatus : undefined;
}
if (!(this.params && this.params.source)) {
this.projectSource = row ? row.source : undefined;
}
} catch (e) {
if (!hasParamStatus) {
this.projectBomStatus = undefined;
}
if (!(this.params && this.params.source)) {
this.projectSource = undefined;
}
}
},
// dict,
getKindeeExcel() {
// 显示加载状态
const loadingInstance = this.$loading({
lock: true,
text: '正在获取已投放的工艺数据...',
spinner: 'el-icon-loading',
background: 'rgba(255, 255, 255, 0.7)',
});
this.loading = true;
// 调用 reset 方法,重置表单或状态
this.reset();
// 获取生产订单号
const rooteProdet = this.params.productionOrderNo;
// 调用 getKindeeExcel 方法
getKindeeExcel(rooteProdet)
.then(data => {
// 处理返回的数据
this.$message.success('获取工艺成功!');
})
.catch(error => {
this.$message.error(error.message); // 显示错误消息
})
.finally(() => {
// 关闭加载状态
loadingInstance.close();
this.loading = false; // 关闭 loading 状态
});
this.handleBomRefresh();
},
getAllRouteAndUse() {
// 显示加载状态
const loadingInstance = this.$loading({
lock: true,
text: '正在获取全部工艺数据...',
spinner: 'el-icon-loading',
background: 'rgba(255, 255, 255, 0.7)',
});
this.loading = true;
// 调用 reset 方法,重置表单或状态
this.reset();
// 获取生产订单号
const rooteProdet = this.params.productionOrderNo;
// 调用 getAllRouteAndUse 方法
getAllRouteAndUse(rooteProdet)
.then(data => {
// 处理返回的数据
this.$message.success('获取全部工艺成功!');
})
.catch(error => {
this.$message.error(error.message); // 显示错误消息
})
.finally(() => {
// 关闭加载状态
loadingInstance.close();
this.loading = false; // 关闭 loading 状态
});
this.handleBomRefresh();
},
// 开始编辑行
handleRowEdit(scope) {
scope.row.originalData = JSON.parse(JSON.stringify(scope.row));
this.$set(scope.row, 'isEdit', true);
},
/** 导入时间按钮操作 */
handleImportTime() {
this.timeUpload.title = "导入时间";
this.timeUpload.open = true;
},
// 处理时间文件上传进度
handleTimeFileUploadProgress(event, file, fileList) {
this.timeUpload.isUploading = true;
},
// 处理时间文件上传成功
handleTimeFileSuccess(response, file, fileList) {
this.timeUpload.open = false;
this.timeUpload.isUploading = false;
this.$refs.timeUpload.clearFiles();
this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>"
+ response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
this.getList();
},
// 提交时间文件上传
submitTimeFileForm() {
this.$refs.timeUpload.submit();
},
rowDrop() {
const tbody = document.querySelector('.el-table__body-wrapper tbody');
const _this = this;
// Sortable.create(tbody, {
// onEnd({newIndex, oldIndex}) {
// const currRow = _this.form.routeList[oldIndex];
// // 只处理子工序
// if (currRow.parentId) {
// const parentIndex = _this.form.routeList.findIndex(item => item.id === currRow.parentId);
// if (parentIndex > -1) {
// const children = _this.form.routeList[parentIndex].children;
// // 移动数组元素
// const targetRow = children.splice(oldIndex, 1)[0];
// children.splice(newIndex, 0, targetRow);
// // 重新计算工序号
// children.forEach((item, index) => {
// item.processNo = (index + 1) * 10; // 按10、20、30...排序
// });
// }
// }
// },
// filter: ".filtered" // 过滤掉父节点
// });
},
reorderProcessNo() {
this.form.routeList.forEach(parent => {
if (parent.children && parent.children.length) {
parent.children.forEach((child, index) => {
child.processNo = index + 1; // 使用下标+1
});
}
});
},
// BOM抽屉相关方法
bomClose(done) {
// 直接清空数据并关闭
this.bomData = [];
this.currentMaterial = {
materialCode: '',
materialName: '',
productionOrderNo: ''
};
done();
},
handleBomSearch() {
this.bomPagination.currentPage = 1;
},
handleBomRefresh() {
this.fetchBomInfo().then(response => {
this.bomData = response || [];
this.totalBomCount = this.bomData.length;
}).catch(error => {
this.$message.error('获取BOM数据失败');
this.bomData = [];
}).finally(() => {
this.bomLoading = false;
});
},
handleBomExport() {
this.download('system/bom/export', {
materialCode: this.currentMaterial.materialCode,
materialName: this.currentMaterial.materialName,
productionOrderNo: this.currentMaterial.productionOrderNo
}, `bom_${new Date().getTime()}.xlsx`);
},
handleBomSizeChange(val) {
this.bomPagination.pageSize = val;
},
handleBomCurrentChange(val) {
this.bomPagination.currentPage = val;
},
handleProcessNameChange(scope) {
console.log(scope)
const selectedProcessName = scope.row.processName;
console.log(selectedProcessName)
if (this.processToWorkCenterMap[selectedProcessName]) {
scope.row.workCenter = this.processToWorkCenterMap[selectedProcessName];
} else {
scope.row.workCenter = '';
}
},
handleQuery3(query) {
if (query === '') {
this.processName = [];
return;
}
// 开始加载
this.loading = true;
// 调用后端接口获取匹配的项目令号
getProcessInfoList(query).then((response) => {
// 加载完成
this.loading = false;
this.processName = response;
}).catch(() => {
this.loading = false; // 加载失败
this.processName = []; // 如果请求失败,清空选项
});
},
// 控制表格可移动部分
tableRowClassName({ row, rowIndex }) {
// 过滤掉父节点
if (!row.parentId) {
return "filtered";
}
return "";
},
// 添加子集
onAddChild(props) {
// 是否为父级,返回父级所在下标
var index = this.form.routeList.findIndex(item => item.id === props.row.id);
// -1为未检索到,不为父级
if (index === -1) {
alert("刷新试试,为检索到此目录,可能不存在")
return;
}
var routeList = this.form.routeList[index].children;
var route = routeList.sort(function (a, b) {
return a.processNo - b.processNo
})[routeList.length - 1];
var processNo = !route ? 0 : route.processNo + 10;
//routeList.push({ id: --this.id, parentId: props.row.id, processNo: processNo, children: null });
//this.showParentSaveBtn = props.row.id;
const newRow = {
id: --this.id,
parentId: props.row.id,
processNo: processNo,
children: null
};
routeList.push(newRow);
this.showParentSaveBtn = props.row.id;
},
// 删除子集
onDelete(props) {
// 获取父级的所在下标
var index = this.form.routeList.findIndex(item => item.id === props.row.parentId);
// 获取子集的所在下标
var childrenIndex = this.form.routeList[index].children.findIndex(item => item.id === props.row.id);
// 找到子集并删除
this.form.routeList[index].children.splice(childrenIndex, 1);
// 修改其它子集的工序号
for (let i = 0; i < this.form.routeList[index].children.length; i++) {
// 修改子集中工序号
this.form.routeList[index].children[i].processNo = (i + 1) * 10;
}
},
// 修改现有的cellhand方法
cellhand(row, column) {
// 只在点击物料编码列时触发
if (column.property === 'materialCode') {
this.BOMpop = true;
this.bomLoading = true;
this.processLoading = true;
// 设置当前物料信息
this.currentMaterial = {
materialCode: row.materialCode,
materialName: row.materialName,
productionOrderNo: this.params.productionOrderNo
};
// 调用获取BOM信息的接口
getBomInfo(
row.materialCode,
row.materialName,
this.currentMaterial.productionOrderNo
)
.then(response => {
this.bomData = response || [];
this.totalBomCount = this.bomData.length;
})
.catch(error => {
console.error('获取BOM数据失败:', error);
this.$message.error('获取BOM数据失败');
this.bomData = [];
})
.finally(() => {
this.bomLoading = false;
});
// 获取工艺信息
this.getProcessRouteList();
}
},
setTotalWeight() {
const totalWeight = this.params.productionOrderNo;
if (totalWeight) {
this.queryParams.totalWeight = totalWeight;
}
},
/** 查询工艺路线列表 */
// 修改原有的 getList 方法,获取列表后自动刷新库存
async getList() {
this.loading = true;
try {
const response = await listRoute(this.queryParams);
this.form.routeList = response.rows;
this.total = response.total;
} catch (error) {
console.error('获取数据失败:', error);
} finally {
this.loading = false;
}
},
// 表单重置
reset() {
this.form = {
id: undefined,
// 物料信息
materialCode: undefined,
materialName: undefined,
material: undefined,
discWeight: undefined,
bomUnit: undefined,
unitQuantity: undefined,
batchQuantity: undefined,
firstBatchQuantity: undefined,
// 工艺信息
workCenter: undefined,
processName: undefined,
processDescription: undefined,
processControl: undefined,
activityDuration: undefined,
activityUnit: undefined,
xuStartTime: undefined,
xuEndTime: undefined
};
this.resetForm("form");
},
/** 导入钮操作 */
handleImport() {
if (this.uploadRouteStatusLocked) {
this.$modal.msgError(this.uploadRouteStatusLockMsg);
return;
}
// 未选令号则无法与文件核对,先拦住
if (!this.currentImportOrderNo) {
this.$modal.msgWarning("请先选择项目令号,再导入工艺");
return;
}
this.upload.title = "工艺导入(当前令号:" + this.currentImportOrderNo + ")";
this.upload.open = true;
},
/** 下载模板操作 */
importTemplate() {
this.download('system/route/importTemplate', {}, `route_template_${new Date().getTime()}.xlsx`)
},
// 文件上传中处理
handleFileUploadProgress(event, file, fileList) {
this.upload.isUploading = true;
},
// 文件上传成功处理
handleFileSuccess(response, file, fileList) {
this.upload.open = false;
this.upload.isUploading = false;
this.$refs.upload.clearFiles();
const msg = (response && response.msg) || "导入失败";
const ok = response && (response.code === 200 || response.code === 0);
this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>"
+ msg + "</div>", ok ? "导入结果" : "导入失败", { dangerouslyUseHTMLString: true });
if (ok) {
this.getList();
}
},
// 提交上传文件
submitFileForm() {
if (!this.currentImportOrderNo) {
this.$modal.msgWarning("请先选择项目令号,再导入工艺");
return;
}
this.$refs.upload.submit();
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
handleQuery1(query) {
if (query === '') {
this.projectCodes = []; // 如果没有输入任何关键字,清空选项
return;
}
// 开始加载
this.loading = true;
// 调用后端接口获取匹配的项目令号
getDistinctProjectCodes(query).then((response) => {
// 加载完成
this.loading = false;
this.projectCodes = response;
}).catch(() => {
this.loading = false; // 加载失败
this.projectCodes = []; // 如果请求失败,清空选项
});
},
//获取工序列表
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.selectedRows = selection || []
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加工艺路线";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.loading = true;
const id = row.id || this.ids;
getRoute(id).then(response => {
this.loading = false;
// 只提取工艺相关字段
const { workCenter, processName, processDescription, processControl, activityDuration } = response.data;
this.form = {
...this.form, // 保留现有数据
id: id,
workCenter,
processName,
processDescription,
processControl,
activityDuration
};
this.open = true;
this.title = "修改工艺信息";
}).catch(() => {
this.loading = false;
});
},
/** 推送工艺 / 按物料推送 共用逻辑 */
async executeRoutePush({ confirmMessage, loadingText, apiFn, errorTitle, successTitle, materialCodes }) {
const productionOrderNo = this.params.productionOrderNo;
if (!productionOrderNo) {
this.$modal.msgError("未获取到生产订单号,请检查!");
return;
}
if (isJsyyOrderNo(productionOrderNo)) {
this.$modal.msgError(this.jsyyDenyMsg);
return;
}
if (this.pushRouteStatusLocked) {
this.$modal.msgError(this.pushRouteStatusLockMsg);
return;
}
if (!this.routeGroupName || !this.routeGroupName.trim()) {
this.$modal.msgError("请填写分组名称!");
return;
}
let loading = null;
try {
await this.$confirm(confirmMessage, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
});
loading = this.$loading({
lock: true,
text: loadingText,
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
this.reset();
const timeout = 600000;
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => {
reject(new Error('推送操作超时,请检查后台处理状态'));
}, timeout);
});
const response = await Promise.race([
apiFn(productionOrderNo, this.routeGroupName.trim(), materialCodes),
timeoutPromise
]);
const result = (response && response.data) || {};
const duplicateRoutes = result.duplicateRoutes || [];
const failedRoutes = result.failedRoutes || [];
const successfulRoutes = result.successfulRoutes || [];
const duplicateCodes = duplicateRoutes.join(', ');
const failedInfo = failedRoutes.map(route =>
`${route.materialCode} (${route.errorMessage || '未知错误'})`
).join(', ');
const successfulCodes = successfulRoutes.map(route => route.materialCode).join(', ');
this.$alert(`
<div><strong>成功 (${successfulRoutes.length}):</strong></div>
<div style="margin-left: 20px;">${successfulCodes || '无'}</div>
<div><strong>失败 (${failedRoutes.length}):</strong></div>
<div style="margin-left: 20px;">${failedInfo || '无'}</div>
<div><strong>重复 (${duplicateRoutes.length}):</strong></div>
<div style="margin-left: 20px;">${duplicateCodes || '无'}</div>
`, successTitle || '推送完成', {
dangerouslyUseHTMLString: true,
confirmButtonText: '确定'
});
await this.getList();
} catch (error) {
if (error === 'cancel') {
return;
}
console.error(`[${errorTitle}]:`, error);
this.$notify({
title: errorTitle,
message: error.message || `${errorTitle},请重试!`,
type: 'error',
duration: 0,
showClose: true
});
} finally {
if (loading) {
loading.close();
}
this.loading = false;
}
},
collectSelectedMaterialCodes(rows) {
const codes = [];
const seen = new Set();
const source = rows || this.selectedRows || [];
source.forEach(row => {
const code = row && row.materialCode ? String(row.materialCode).trim() : "";
if (!code) {
return;
}
const key = code.toUpperCase();
if (seen.has(key)) {
return;
}
seen.add(key);
codes.push(code);
});
return codes;
},
/**推送工艺 */
pushRouteBom() {
return this.executeRoutePush({
confirmMessage: '推送工艺可能需要较长时间,请耐心等待。是否继续?',
loadingText: '正在推送工艺,请稍候...',
apiFn: pushRouteBom,
errorTitle: '推送工艺失败'
});
},
/** 勾选物料后单独推送金蝶 */
pushSelectedMaterialRoute() {
const codes = this.collectSelectedMaterialCodes();
if (!codes.length) {
this.$modal.msgError("请先勾选要推送的物料");
return;
}
return this.executeRoutePush({
confirmMessage: `将只推送所选物料(${codes.join('、')})的工艺到金蝶,不会整单推送、也不会改项目状态。是否继续?`,
loadingText: '正在推送所选物料工艺,请稍候...',
apiFn: pushRouteBomByMaterial,
errorTitle: '推送选中物料失败',
successTitle: '物料推送完成',
materialCodes: codes
});
},
/** 物料行单独推送 */
pushMaterialRoute(row) {
const code = row && row.materialCode ? String(row.materialCode).trim() : "";
if (!code) {
this.$modal.msgError("该行没有物料编码");
return;
}
this.pushingMaterialCode = code;
return this.executeRoutePush({
confirmMessage: `将只推送物料 ${code} 的工艺到金蝶,不会整单推送、也不会改项目状态。是否继续?`,
loadingText: `正在推送物料 ${code} 的工艺,请稍候...`,
apiFn: pushRouteBomByMaterial,
errorTitle: '推送该物料工艺失败',
successTitle: '物料推送完成',
materialCodes: [code]
}).finally(() => {
this.pushingMaterialCode = "";
});
},
/** 审核通过:更新状态并发送钉钉通知,不推送金蝶、不发送工艺计划表 */
async approveRoute() {
const productionOrderNo = this.params.productionOrderNo;
if (!productionOrderNo) {
this.$modal.msgError("未获取到生产订单号,请检查!");
return;
}
try {
await this.$confirm(
'将通过工艺审核并发送钉钉通知,不会推送金蝶。是否继续?',
'提示',
{ confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }
);
const loading = this.$loading({
lock: true,
text: '正在审核并发送通知...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
try {
const res = await approveRoute(productionOrderNo);
this.$modal.msgSuccess((res && res.msg) || '审核通过');
await this.getList();
} finally {
loading.close();
}
} catch (error) {
if (error !== 'cancel') {
this.$modal.msgError(error.message || '审核失败');
}
}
},
/** 更新计划时间间*/
updateProcessPlan(row) {
// 若未勾选任何行,则提示并返回
if (!this.ids || this.ids.length === 0) {
this.$modal.msgError("请先勾选至少一条数据再更新计划时间");
return;
}
// 显示加载状态
this.loading = true;
// 调用 reset 方法,重置表单或状态
this.reset();
// 获取生产订单号
const rooteProdet = this.params.productionOrderNo;
//获取物料编码
const materialCode = this.params.materialCode;
console.log(rooteProdet);
// 调用封装好的 API 方法(带勾选的 ids)
updateProcessPlan(rooteProdet, this.ids)
.then(response => {
// 假设后端返回的数据可以直接赋值给表单
this.form = response;
// 弹出成功消息
this.$modal.msgSuccess("更新" + rooteProdet + "工序计划时间成功");
// 调用方法更新列表
this.getList();
})
.catch(error => {
// 处理错误,弹出错误提示
this.$modal.msgError("更新,请重试!");
console.error('更新工序计划失败:', error);
})
.finally(() => {
// 隐藏加载状态
this.loading = false;
});
},
/** 更新生产订单时间*/
updateProcesTime(row) {
// 显示加载状态
this.loading = true;
// 调用 reset 方法,重置表单或状态
this.reset();
// 获取生产订单号
const rooteProdet = this.params.productionOrderNo;
console.log(rooteProdet);
// 调用封装好的 API 方法
updateProcesTime(rooteProdet)
.then(response => {
// 假设后端返回的数据可以直接赋值给表单
this.form = response;
// 弹出成功消息
this.$modal.msgSuccess("更新" + rooteProdet + "生产订单成功");
// 调用方法更新列表
this.getList();
})
.catch(error => {
// 处理错误,弹出错误提示
this.$modal.msgError("更新,请重试!");
console.error('更新生产订单失败:', error);
})
.finally(() => {
// 隐藏加载状态
this.loading = false;
});
},
/**
* 工具栏「生成PDF」:当前令号下全部工序计划单打 zip。
*/
generatePDFs1() {
const rooteProdet = (this.params && this.params.productionOrderNo)
|| this.queryParams.routeDescription
|| this.$route.query.productionOrderNo;
if (!rooteProdet) {
this.$modal.msgWarning("请先选择项目令号");
return;
}
this.generatingAllPdf = true;
const loading = this.$loading({
lock: true,
text: "正在生成全部工序计划单PDF,请稍候...",
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)"
});
generatePDFs(rooteProdet)
.then(async (response) => {
const isBlob = blobValidate(response);
if (!isBlob) {
const resText = await response.text();
const rspObj = JSON.parse(resText);
this.$modal.msgError((rspObj && rspObj.msg) || "生成PDF失败");
return;
}
const blob = new Blob([response], { type: "application/zip" });
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = rooteProdet + "_工序计划单.zip";
link.click();
URL.revokeObjectURL(url);
this.$modal.msgSuccess("生成" + rooteProdet + "的PDF成功");
})
.catch((error) => {
this.$modal.msgError("生成PDF失败,请重试!");
console.error("生成PDF失败:", error);
})
.finally(() => {
this.generatingAllPdf = false;
loading.close();
});
},
/**
* 物料行「下载PDF」:用当前令号 + 该行物料编码查金蝶生产订单,直接下单份 PDF。
*/
downloadMaterialPdf(row) {
const materialCode = row && row.materialCode ? String(row.materialCode).trim() : "";
const rooteProdet = (this.params && this.params.productionOrderNo)
|| this.queryParams.routeDescription
|| this.$route.query.productionOrderNo;
if (!rooteProdet) {
this.$modal.msgWarning("请先选择项目令号");
return;
}
if (!materialCode) {
this.$modal.msgWarning("该行没有物料编码");
return;
}
this.downloadingPdfCode = materialCode;
generatePDFs(rooteProdet, materialCode)
.then(async (response) => {
const isBlob = blobValidate(response);
if (!isBlob) {
const resText = await response.text();
const rspObj = JSON.parse(resText);
this.$modal.msgError((rspObj && rspObj.msg) || "下载PDF失败");
return;
}
const filename = `${rooteProdet}_${materialCode}_工序计划单.pdf`;
const blob = new Blob([response], { type: "application/pdf" });
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = filename;
link.click();
URL.revokeObjectURL(url);
this.$modal.msgSuccess(`已下载物料 ${materialCode} 的工序计划单`);
})
.catch((error) => {
this.$modal.msgError("下载PDF失败,请重试!");
console.error("下载PDF失败:", error);
})
.finally(() => {
this.downloadingPdfCode = "";
});
},
rowMoreVisible(row) {
if (!row || row.parentId || !row.materialCode) return false
return checkPermi(['system:route:pushRouteBom'])
|| checkPermi(['system:route:generatePDFs'])
|| checkPermi(['system:route:downloadDrawingModel'])
},
handleRowMore(row, command) {
if (!command) return
if (command === 'push') {
this.pushMaterialRoute(row)
return
}
if (command === 'pdf') {
this.downloadMaterialPdf(row)
return
}
if (String(command).indexOf('model:') === 0) {
this.downloadDrawingModel(row, String(command).slice(6))
}
},
/**
* 物料行「下载图纸模型」:仅 PLM 项目。前端请求本系统,由后端转发文件服务。
*/
downloadDrawingModel(row, fileType) {
const materialCode = row && row.materialCode ? String(row.materialCode).trim() : "";
const format = this.drawingModelFormats.find(item => item.type === fileType);
const productionOrderNo = (this.params && this.params.productionOrderNo)
|| this.queryParams.routeDescription
|| this.$route.query.productionOrderNo;
if (!this.isPlmProject) {
this.$modal.msgWarning("仅 PLM 来源项目可下载图纸模型");
return;
}
if (!productionOrderNo) {
this.$modal.msgWarning("请先选择项目令号");
return;
}
if (!materialCode) {
this.$modal.msgWarning("该行没有物料编码");
return;
}
if (!format) {
this.$modal.msgWarning("请选择图纸格式");
return;
}
this.downloadingDrawingCode = materialCode;
requestDrawingModel(productionOrderNo, materialCode, fileType)
.then(async (response) => {
const isBlob = blobValidate(response);
if (!isBlob) {
const resText = await response.text();
const rspObj = JSON.parse(resText);
this.$modal.msgError((rspObj && rspObj.msg) || "下载图纸模型失败");
return;
}
const filename = `${materialCode}.${fileType}`;
const blob = new Blob([response], { type: "application/octet-stream" });
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = filename;
link.click();
URL.revokeObjectURL(url);
this.$modal.msgSuccess(`已下载物料 ${materialCode} 的 ${format.label}`);
})
.catch((error) => {
this.$modal.msgError("下载图纸模型失败,请重试!");
console.error("下载图纸模型失败:", error);
})
.finally(() => {
this.downloadingDrawingCode = "";
});
},
/** 提交按钮 */
submitForm() {
this.$refs.form.validate(valid => {
if (valid) {
// 提交逻辑
this.buttonLoading = true;
if (this.form.id != null) {
updateRoute(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
}).finally(() => {
this.buttonLoading = false;
});
} else {
addRoute(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
}).finally(() => {
this.buttonLoading = false;
});
}
} else {
this.$message.error("请填写必填项");
}
});
},
/** 删除按钮操作 */
handleDelete(scope) {
const ids = [scope.row.id];
this.$modal.confirm('是否确认删除工艺路线编号为"' + ids + '"的数据项?').then(() => {
return delRoute(ids);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(error => {
if (error !== 'cancel') {
console.error('Delete error:', error);
this.$modal.msgError("删除失败:" + (error.message || "未知错误"));
}
});
},
/** 导出按钮操作 */
handleExport() {
this.download('system/route/export', {
...this.queryParams
}, `route_${new Date().getTime()}.xlsx`)
},
// BOM选择项改变
handleBomSelectionChange(selection) {
this.selectedBomRows = selection;
},
// 新增BOM
handleBomAdd() {
this.bomDialogTitle = '新增BOM';
this.bomForm = {
id: undefined,
projectNumber: this.currentMaterial.productionOrderNo, // 使用当<E794A8><E5BD93>的项目令号
materialCode: '',
materialName: '',
materialType: '',
quantity: 0,
unit: '',
stock: 0,
parentMaterialCode: this.currentMaterial.materialCode, // 使用当前物料作为父级
parentMaterialName: this.currentMaterial.materialName
};
this.bomDialogVisible = true;
},
// 修改BOM
handleBomEdit(row) {
this.bomDialogTitle = '修改BOM';
this.bomForm = JSON.parse(JSON.stringify(row));
this.bomDialogVisible = true;
},
// 删除BOM
handleBomDelete(row) {
this.$confirm('是否确认删除该BOM数据?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
return deleteBom(row.id);
}).then(() => {
this.$message.success('删除成功');
this.handleBomRefresh();
}).catch(() => {
});
},
// 提交BOM表单
submitBomForm() {
this.$refs.bomForm.validate((valid) => {
if (valid) {
const isUpdate = this.bomForm.id !== undefined;
const promise = isUpdate ? updateBom(this.bomForm) : addBom(this.bomForm);
promise.then(() => {
this.$message.success(isUpdate ? '修改成功' : '新增成功');
this.bomDialogVisible = false;
this.handleBomRefresh();
}).catch(() => {
this.$message.error(isUpdate ? '修改失败' : '新增失败');
});
}
});
},
fetchBomInfo() {
return getBomInfo(
this.currentMaterial.materialCode,
this.currentMaterial.materialName,
this.currentMaterial.productionOrderNo
);
},
// 处理物料搜
handleMaterialSearch(queryString, callback) {
if (queryString.length === 0) {
callback([]);
return;
}
this.materialSearchLoading = true;
listMaterial({
pageNum: 1,
pageSize: 10,
materialName: queryString
}).then(response => {
const suggestions = response.rows.map(item => ({
materialName: item.materialName,
materialCode: item.materialCode,
materialType: item.materialQuality,
classificationName: item.classificationName,
singleWeight: item.singleWeight || 0
}));
callback(suggestions);
}).catch(() => {
callback([]);
}).finally(() => {
this.materialSearchLoading = false;
});
},
// 处理物料选择
handleMaterialSelect(item) {
if (item) {
// 如果是从建议中选择
this.bomForm.materialName = item.materialName;
this.bomForm.materialCode = item.materialCode;
this.bomForm.materialType = item.materialType;
this.bomForm.stock = item.singleWeight;
this.bomForm.unit = item.classificationName;
}
},
// 取消编辑
cancelEdit(scope) {
// 恢复原始数据
Object.assign(scope.row, scope.row.originalData);
// 退出编辑状态
this.$set(scope.row, 'isEdit', false);
},
// 保存单行数据
onSaveRow(scope) {
// 显示加载状态
this.loading = true;
// 获取行数据并创建副本
const row = scope.row;
const saveData = {
id: row.id,
parentId: row.parentId,
routeDescription: row.routeDescription,
materialCode: row.materialCode,
materialName: row.materialName,
unit: row.unit,
processNo: row.processNo,
bomMaterial: row.bomMaterial,
workCenter: row.workCenter,
processName: row.processName,
rawMaterialCode: row.rawMaterialCode,
rawMaterialName: row.rawMaterialName,
discWeight: row.discWeight,
discUsage: row.discUsage,
processDescription: row.processDescription,
processControl: row.processControl,
activityDuration: row.activityDuration,
activityUnit: row.activityUnit,
material: row.material,
bomUnit: row.bomUnit,
unitQuantity: row.unitQuantity,
batchQuantity: row.batchQuantity,
firstBatchQuantity: row.firstBatchQuantity,
planStartTime: row.planStartTime,
planEndTime: row.planEndTime,
xuStartTime: row.xuStartTime,
xuEndTime: row.xuEndTime
};
// 显示加载状态
this.loading = true;
// 调用更新接口
updateRoute(saveData)
.then(response => {
this.$modal.msgSuccess("修改成功");
// 退出编辑状态
this.$set(row, 'isEdit', false);
// 刷新列表
this.getList();
})
.catch(error => {
this.$modal.msgError("修改失败:" + (error.message || "未知错误"));
})
.finally(() => {
this.loading = false;
});
},
// 同样修改整体保存方法
onSave(props) {
this.$confirm('确认保存工艺路线数据?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.loading = true;
var list = this.form.routeList.find(item => item.id === props.row.id);
var newChildrenList = list.children.filter(item => item.id < 0).map(v => ({
id: v.parentId,
routeDescription: list.routeDescription,
materialCode: list.materialCode,
materialName: list.materialName,
unit: list.unit,
processNo: v.processNo,
bomMaterial: list.bomMaterial,
workCenter: v.workCenter,
processName: v.processName,
rawMaterialCode: list.rawMaterialCode,
rawMaterialName: list.rawMaterialName,
discWeight: list.discWeight,
discUsage: list.discUsage,
processDescription: v.processDescription,
processControl: v.processControl,
activityDuration: v.activityDuration,
activityUnit: v.activityUnit,
material: list.material,
bomUnit: list.bomUnit,
unitQuantity: list.unitQuantity,
batchQuantity: list.batchQuantity,
firstBatchQuantity: list.firstBatchQuantity,
planStartTime: v.planStartTime,
planEndTime: v.planEndTime,
xuStartTime: v.xuStartTime || null,
xuEndTime: v.xuEndTime || null
}));
return onSave(newChildrenList);
}).then((response) => {
this.$modal.msgSuccess("工艺路线保存成功");
this.showParentSaveBtn = null;
this.getList();
}).catch((error) => {
if (error !== 'cancel') {
this.$modal.msgError(error.message || "工艺路线保存失败");
}
}).finally(() => {
this.loading = false;
});
},
// 删除未保存的工艺
onDeleteUnsaved(scope) {
const parentRow = this.form.routeList.find(item => item.id === scope.row.parentId);
if (parentRow && parentRow.children) {
const index = parentRow.children.findIndex(item => item === scope.row);
if (index > -1) {
// 删除当前行
parentRow.children.splice(index, 1);
// 重新排序剩余的工序号
parentRow.children.forEach((child, idx) => {
child.processNo = (idx + 1) * 10; // 按10、20、30...重新排序
});
}
}
},
// 获取工艺信息列表
getProcessRouteList() {
this.processLoading = true;
getProcessRouteList(
this.currentMaterial.materialCode,
this.currentMaterial.materialName,
this.currentMaterial.productionOrderNo
)
.then(response => {
this.processRoutes = response || [];
// 默认选中第一条工艺路线
if (this.processRoutes.length > 0) {
this.handleViewRoute(this.processRoutes[0]);
}
})
.catch(error => {
console.error('获取工艺路线数据失败:', error);
this.$message.error('获取工艺路线数据失败');
this.processRoutes = [];
this.resetRouteSelection();
})
.finally(() => {
this.processLoading = false;
});
},
// 查看工艺路线
handleViewRoute(route) {
this.selectedRouteId = route.id;
this.selectedRoute = route;
this.currentProcessList = route.processRouteDT || [];
},
// 重置工艺路线选择
resetRouteSelection() {
this.selectedRouteId = null;
this.selectedRoute = null;
this.currentProcessList = [];
}
},
// 处理工艺路线选择变化
handleRouteChange(routeId) {
const route = this.processRoutes.find(r => r.id === routeId);
if (route) {
this.selectedRoute = route;
this.currentProcessList = route.processRouteDT || [];
} else {
this.selectedRoute = null;
this.currentProcessList = [];
}
},
};
</script>
<style>
.route-toolbar {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
margin-bottom: 8px;
}
.route-toolbar__left {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px;
flex: 1;
min-width: 0;
}
.route-toolbar__left .el-button {
margin-left: 0;
}
.route-toolbar__group {
width: 160px;
}
.btn {
font-size: 12px;
padding: 7px 10px !important;
border-radius: 0;
}
.route-row-ops {
display: inline-flex;
align-items: center;
justify-content: center;
flex-wrap: nowrap;
gap: 6px;
white-space: nowrap;
}
.route-row-ops .el-button {
margin-left: 0;
}
.handle {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
font-size: 20px;
border: none;
background-color: #FAFAFA;
}
.bom-header {
margin-bottom: 15px;
}
.table-operations {
display: flex;
justify-content: space-between;
align-items: center;
}
.pagination-container {
display: flex;
justify-content: flex-end;
}
.table-operations {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.left-operations,
.right-operations {
display: flex;
align-items: center;
}
.right-operations .el-button {
margin-left: 8px;
}
.material-select-dropdown {
max-height: 300px !important;
}
.material-select-dropdown .el-select-dropdown__wrap {
max-height: 300px !important;
}
.material-autocomplete-dropdown {
min-width: 500px !important;
/* 设置下拉框最小宽度 */
}
.material-suggestion-item {
padding: 8px 10px;
border-bottom: 1px solid #eee;
}
.material-suggestion-item:last-child {
border-bottom: none;
}
.material-name {
font-size: 14px;
color: #303133;
margin-bottom: 4px;
}
.material-info {
font-size: 12px;
color: #909399;
}
.material-info span {
margin-right: 15px;
}
.material-info span:last-child {
margin-right: 0;
}
/* 调整输入框宽度 */
.el-form-item[label="物料名称"] .el-autocomplete {
width: 100%;
}
/* 可以添加一些提示样式 */
.el-select.is-disabled .el-input__inner {
background-color: #f5f7fa;
border-color: #e4e7ed;
color: #909399;
cursor: not-allowed;
}
</style>