同步项目变更

This commit is contained in:
Developer
2026-06-27 09:02:07 +08:00
parent 99c7077865
commit 137e276340
16 changed files with 8028 additions and 22 deletions

BIN
dist.7z

Binary file not shown.

BIN
dist.zip

Binary file not shown.

477
part-modification-plan.html Normal file
View File

@@ -0,0 +1,477 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>零件改制功能设计方案</title>
<style>
@page { size: A4; margin: 18mm 16mm; }
body {
font-family: "Microsoft YaHei", "SimSun", Arial, sans-serif;
color: #1f2933;
font-size: 13px;
line-height: 1.65;
}
h1 {
font-size: 26px;
text-align: center;
margin: 0 0 24px;
padding-bottom: 12px;
border-bottom: 2px solid #2f80ed;
}
h2 {
font-size: 19px;
margin: 24px 0 10px;
padding-left: 8px;
border-left: 4px solid #2f80ed;
page-break-after: avoid;
}
h3 {
font-size: 16px;
margin: 18px 0 8px;
page-break-after: avoid;
}
p { margin: 7px 0; }
ul { margin: 6px 0 10px 22px; padding: 0; }
li { margin: 3px 0; }
table {
width: 100%;
border-collapse: collapse;
margin: 10px 0 16px;
page-break-inside: avoid;
}
th, td {
border: 1px solid #cbd5e1;
padding: 6px 8px;
text-align: left;
vertical-align: top;
word-break: break-word;
}
th {
background: #eef4ff;
font-weight: 600;
}
code {
font-family: Consolas, "Microsoft YaHei", monospace;
background: #f3f4f6;
padding: 1px 4px;
border-radius: 3px;
}
pre {
background: #f8fafc;
border: 1px solid #d8dee9;
padding: 10px;
overflow-wrap: break-word;
white-space: pre-wrap;
page-break-inside: avoid;
}
figure {
margin: 14px 0 20px;
page-break-inside: avoid;
}
figure img {
display: block;
width: 100%;
max-width: 100%;
height: auto;
border: 1px solid #d8dee9;
}
figcaption {
margin-top: 6px;
color: #64748b;
font-size: 12px;
text-align: center;
}
</style>
</head>
<body>
<h1>零件改制功能设计方案</h1>
<h2>0. 需求背景</h2>
<h3>0.1 需求提出</h3>
<p>本需求由罗总牵头,组织技术中心、精工车间、仓储等相关部门讨论后提出。</p>
<h3>0.2 提出原因</h3>
<p>当前现场存在零件改制业务,但改制过程尚未完整纳入系统管理。由于现场计件、派工生产、完工入库和后续统计都需要明确的数据来源,原有线下记录或零散流转方式无法满足计件核算、过程追溯和部门协同要求。</p>
<p>因此,需要在系统内补充零件改制订单流程,将改制订单从技术中心发起、精工车间派工生产到完工入库的全过程纳入系统管理。</p>
<h3>0.3 应用场景</h3>
<p>本功能主要应用于以下场景:</p>
<ul><li>技术中心根据现场或订单需求发起零件改制订单。</li><li>精工车间根据改制订单制定工艺、派工生产。</li><li>改制订单涉及非毛坯物料时,由系统生成领料单并交由仓库出库。</li><li>改制加工完成后,按现有流程办理入库。</li><li>现场计件、生产统计、入库记录和后续追溯均以系统内改制订单数据为依据。</li></ul>
<h2>1. 需求目标</h2>
<p>基于项目现有精工车间生产流程,新增“零件改制”业务。</p>
<p>本次方案调整为:</p>
<ul><li>在技术中心新增组件发起改制订单。</li><li>改制订单生成后进入现有精工车间生产任务流程。</li><li>精工车间生产任务查询组件可以查看改制订单。</li><li>车间派工组件可以查看改制订单并继续派工。</li><li>新增改制记录查询,用于查看改制订单的发起、生产、派工、领料和完工状态。</li><li>领料时根据改制订单和物料来源判断是否生成领料单。</li></ul>
<p>核心原则:</p>
<ul><li>技术中心负责发起改制订单。</li><li>精工车间复用现有生产任务、工艺、派工、加工流程。</li><li>仓储只在需要额外领用非毛坯物料时介入。</li><li>改制记录独立查询,但状态关联现有生产任务状态。</li></ul>
<h2>2. 现有流程承接关系</h2>
<p>根据项目现有页面,改制订单应承接以下流程:</p>
<table>
<thead><tr><th>流程节点</th><th>现有承接页面</th><th>说明</th></tr></thead>
<tbody>
<tr><td>技术发起</td><td>技术中心新增页面</td><td>发起改制订单,填写改制要求</td></tr>
<tr><td>生成任务</td><td>精工车间生产任务查询</td><td>改制订单进入生产任务列表</td></tr>
<tr><td>制定工艺</td><td>精工车间制定工艺</td><td>可复用或复制原工艺后调整</td></tr>
<tr><td>车间派工</td><td>精工车间车间派工</td><td>工艺完成后派工</td></tr>
<tr><td>领料判断</td><td>领料/仓储出库流程</td><td>根据物料类型决定是否生成领料单</td></tr>
<tr><td>加工执行</td><td>精工车间现有加工流程</td><td>扫码、报工、质检等复用现有逻辑</td></tr>
<tr><td>入库</td><td>仓储入库流程</td><td>改制完工后按现有流程办理入库</td></tr>
<tr><td>记录查询</td><td>改制记录查询</td><td>查看改制全流程</td></tr>
</tbody>
</table>
<figure><img src="零件改制流程图.svg" alt="零件改制业务流程图"><figcaption>零件改制业务流程图</figcaption></figure>
<h2>3. 页面设计</h2>
<h3>3.1 技术中心新增页面:改制订单发起</h3>
<p>建议路径:</p>
<pre><code>src/views/TechnologyCenter/PartModificationOrder/index.vue</code></pre>
<p>页面名称:</p>
<pre><code>改制订单发起</code></pre>
<p>归属模块:</p>
<pre><code>技术中心</code></pre>
<p>主要功能:</p>
<ul><li>查询需要改制的原订单、原零件或原自制件。</li><li>发起改制订单。</li><li>填写改制后零件信息、改制数量、改制原因、技术要求。</li><li>指定是否使用原件改制、毛坯改制或其他物料改制。</li><li>提交后生成改制订单,并进入精工车间生产任务查询。</li></ul>
<h3>3.2 精工车间修改页面:生产任务查询</h3>
<p>现有路径:</p>
<pre><code>src/views/SeikoWorkshop/ProductionTaskQuery/index.vue</code></pre>
<p>需要支持:</p>
<ul><li>查询改制订单生成的生产任务。</li><li>增加任务类型筛选。</li><li>增加任务类型列。</li><li>改制任务显示 <code>改制</code> 标识。</li><li>改制任务继续使用现有 <code>工艺</code><code>派工</code> 按钮。</li></ul>
<h3>3.3 精工车间修改页面:车间派工</h3>
<p>现有路径:</p>
<pre><code>src/views/SeikoWorkshop/WorkshopAssignment/index.vue</code></pre>
<p>需要支持:</p>
<ul><li>查询改制订单对应的待派工任务。</li><li>增加任务类型筛选。</li><li>增加任务类型列。</li><li>复用现有已派工查询、待派工工序查询、派工、取消派工逻辑。</li></ul>
<h3>3.4 新增页面:改制记录查询</h3>
<p>建议路径:</p>
<pre><code>src/views/TechnologyCenter/PartModificationRecord/index.vue</code></pre>
<p>也可以放在精工车间模块,建议最终按业务归属确认。</p>
<p>页面名称:</p>
<pre><code>改制记录查询</code></pre>
<p>主要功能:</p>
<ul><li>查询改制订单记录。</li><li>查看改制订单状态。</li><li>查看是否生成领料单。</li><li>查看仓库是否已出库。</li><li>查看精工生产任务、工艺、派工、完工状态。</li><li>支持跳转生产任务查询、车间派工、零件追溯。</li></ul>
<h2>4. 改制订单类型</h2>
<p>改制订单需要明确物料来源,建议增加字段:</p>
<pre><code>改制来源类型</code></pre>
<p>建议枚举:</p>
<table>
<thead><tr><th>改制来源类型</th><th>说明</th><th>是否生成领料单</th></tr></thead>
<tbody>
<tr><td>原现自制订单</td><td>使用原现有自制订单零件进行改制</td><td></td></tr>
<tr><td>毛坯改制</td><td>直接使用已有毛坯进行改制</td><td></td></tr>
<tr><td>非毛坯物料改制</td><td>使用仓库其他物料、半成品或成品改制</td><td></td></tr>
</tbody>
</table>
<p>说明:</p>
<ul><li>“原现自制订单”指当前已经存在的自制订单或自制零件,改制时不需要额外从仓库领料。</li><li>“毛坯改制”指直接使用毛坯进行改制,不额外生成领料单。</li><li>“非毛坯物料改制”指改制需要领用库存中的非毛坯物料,需要生成领料单并由仓库出库。</li></ul>
<h2>5. 领料规则</h2>
<h3>5.1 领料判断条件</h3>
<p>领料时增加判断:</p>
<pre><code>如果是改制订单,并且使用的物料不是毛坯,则生成领料单,由仓库物料出库。
如果是原现自制订单改制,或者直接使用毛坯改制,则不生成领料单。</code></pre>
<p>规则可表达为:</p>
<pre><code>是否生成领料单 =
是否改制订单 === 1
且 改制来源类型 === 非毛坯物料改制
且 是否毛坯 !== 1</code></pre>
<h3>5.2 生成领料单场景</h3>
<p>以下场景需要生成领料单:</p>
<ul><li>改制订单使用库存半成品。</li><li>改制订单使用库存成品。</li><li>改制订单使用其他非毛坯物料。</li><li>改制订单指定的物料需要仓库出库。</li></ul>
<p>生成后流程:</p>
<p>1. 技术中心发起改制订单。 2. 系统判断需要领料。 3. 生成领料单。 4. 仓库根据领料单出库。 5. 出库完成后,精工车间继续生产、工艺、派工。</p>
<h3>5.3 不生成领料单场景</h3>
<p>以下场景不生成领料单:</p>
<ul><li>原现自制订单改制。</li><li>直接使用毛坯改制。</li><li>改制对象已经在精工车间现场,不需要仓库出库。</li></ul>
<p>不生成领料单时:</p>
<ul><li>改制订单直接进入精工生产任务。</li><li>生产任务查询可查看。</li><li>车间派工可查看并派工。</li></ul>
<h3>5.4 领料状态字段</h3>
<p>建议改制订单增加以下字段:</p>
<table>
<thead><tr><th>字段名</th><th>说明</th></tr></thead>
<tbody>
<tr><td>是否需要领料</td><td>1 是0 否</td></tr>
<tr><td>是否已生成领料单</td><td>1 是0 否</td></tr>
<tr><td>领料单号</td><td>生成的领料单编号</td></tr>
<tr><td>领料状态</td><td>未生成、待出库、已出库、已取消</td></tr>
<tr><td>出库日期</td><td>仓库出库日期</td></tr>
<tr><td>出库人</td><td>仓库操作人</td></tr>
</tbody>
</table>
<h2>6. 业务流程</h2>
<h3>6.1 技术中心发起改制订单</h3>
<p>用户进入技术中心“改制订单发起”页面。</p>
<p>查询原始数据:</p>
<ul><li>订单编号</li><li>产品/部件名称</li><li>零件名称</li><li>图号</li><li>原自制订单</li><li>库存物料</li><li>毛坯物料</li></ul>
<p>发起改制时填写:</p>
<ul><li>改制订单号</li><li>原订单编号</li><li>原零件名称</li><li>原零件图号</li><li>改制零件名称</li><li>改制零件图号</li><li>改制数量</li><li>改制来源类型</li><li>是否毛坯</li><li>物料编号</li><li>物料名称</li><li>改制原因</li><li>改制要求</li><li>技术备注</li><li>精工期限</li></ul>
<p>提交时校验:</p>
<ul><li>改制数量必须大于 0。</li><li>改制来源类型不能为空。</li><li>改制原因不能为空。</li><li>改制要求不能为空。</li><li>精工期限不能为空。</li><li>如果来源类型为非毛坯物料改制,必须选择物料编号。</li></ul>
<h3>6.2 后端生成改制订单</h3>
<p>提交后,后端需要同时处理:</p>
<ul><li>写入改制订单主记录。</li><li>根据改制来源类型判断是否生成领料单。</li><li>生成精工车间生产任务。</li><li>写入任务类型为 <code>改制</code></li><li>关联改制订单号和新工艺计划流水号。</li></ul>
<h3>6.3 进入精工车间生产任务查询</h3>
<p>改制订单生成后,应能在现有接口中查到:</p>
<pre><code>精工车间_生成任务_查询数据</code></pre>
<p>建议返回字段增加:</p>
<ul><li>任务类型</li><li>是否改制</li><li>改制订单号</li><li>改制来源类型</li><li>是否需要领料</li><li>领料状态</li><li>改制原因</li><li>改制要求</li></ul>
<p>生产任务查询页面显示:</p>
<ul><li><code>任务类型 = 改制</code></li><li><code>是否需要领料 = 1</code><code>领料状态 !== 已出库</code>,可显示领料状态提示。</li></ul>
<p>是否允许工艺/派工,需要按业务决定:</p>
<ul><li>如果非毛坯物料改制必须先出库,建议未出库前允许制定工艺,但不允许派工。</li><li>如果现场允许先派工后补出库,则只做提示,不阻断派工。</li></ul>
<p>建议采用更稳妥规则:</p>
<pre><code>需要领料且未出库:允许制定工艺,不允许派工。
不需要领料:正常工艺、派工。
需要领料且已出库:正常工艺、派工。</code></pre>
<h3>6.4 制定工艺</h3>
<p>改制订单在生产任务查询中点击 <code>工艺</code>,进入现有:</p>
<pre><code>/SeikoWorkshop/DevelopProcess</code></pre>
<p>工艺规则:</p>
<ul><li>改制订单必须生成新的工艺计划流水号。</li><li>不覆盖原自制订单或原零件工艺。</li><li>可支持从原工艺复制后调整。</li><li>工艺保存后,任务状态进入 <code>工艺完成</code></li></ul>
<h3>6.5 车间派工</h3>
<p>工艺完成后进入现有车间派工页面:</p>
<pre><code>src/views/SeikoWorkshop/WorkshopAssignment/index.vue</code></pre>
<p>现有查询接口:</p>
<pre><code>精工车间_车间派工_查询</code></pre>
<p>改制订单派工前判断:</p>
<ul><li>不需要领料:允许派工。</li><li>需要领料且已出库:允许派工。</li><li>需要领料但未出库:禁止派工,并提示“改制订单物料未出库,不能派工”。</li></ul>
<p>派工明细继续复用现有接口:</p>
<pre><code>车间生产管理工艺_零件工序_已派工查询
车间生产管理工艺_零件工序_派工_工序查询
车间生产管理工艺_零件工序_派工
车间生产管理工艺_零件工序_取消派工</code></pre>
<h3>6.6 仓库出库</h3>
<p>当改制订单需要领料时,系统生成领料单。</p>
<p>仓库根据领料单完成出库后,需要回写:</p>
<ul><li>领料状态 = 已出库</li><li>出库日期</li><li>出库人</li><li>出库数量</li></ul>
<p>出库完成后,精工车间派工限制解除。</p>
<h3>6.7 加工和完工</h3>
<p>改制订单派工后,继续走现有精工车间加工流程:</p>
<ul><li>工序派工</li><li>扫码加工</li><li>完工报工</li><li>质检</li><li>零件追溯</li><li>工时统计</li></ul>
<p>完工后改制记录状态同步为:</p>
<pre><code>已完成</code></pre>
<h2>7. 数据字段设计</h2>
<h3>7.1 改制订单主记录字段</h3>
<table>
<thead><tr><th>字段名</th><th>说明</th></tr></thead>
<tbody>
<tr><td>改制订单号</td><td>改制业务编号</td></tr>
<tr><td>原订单编号</td><td>原订单编号</td></tr>
<tr><td>原订单流水号</td><td>原订单流水号</td></tr>
<tr><td>原组件流水号</td><td>原组件流水号</td></tr>
<tr><td>原基本件流水号</td><td>原零件流水号</td></tr>
<tr><td>原工艺计划流水号</td><td>原工艺计划流水号</td></tr>
<tr><td>原零件名称</td><td>改制前零件名称</td></tr>
<tr><td>原零件图号</td><td>改制前零件图号</td></tr>
<tr><td>原数量</td><td>原数量</td></tr>
<tr><td>改制零件名称</td><td>改制后零件名称</td></tr>
<tr><td>改制零件图号</td><td>改制后零件图号</td></tr>
<tr><td>改制数量</td><td>改制数量</td></tr>
<tr><td>改制来源类型</td><td>原现自制订单、毛坯改制、非毛坯物料改制</td></tr>
<tr><td>是否毛坯</td><td>1 是0 否</td></tr>
<tr><td>物料编号</td><td>使用物料编号</td></tr>
<tr><td>物料名称</td><td>使用物料名称</td></tr>
<tr><td>物料流水号</td><td>使用物料流水号</td></tr>
<tr><td>是否需要领料</td><td>1 是0 否</td></tr>
<tr><td>是否已生成领料单</td><td>1 是0 否</td></tr>
<tr><td>领料单号</td><td>领料单编号</td></tr>
<tr><td>领料状态</td><td>未生成、待出库、已出库、已取消</td></tr>
<tr><td>改制原因</td><td>改制原因</td></tr>
<tr><td>改制要求</td><td>改制要求</td></tr>
<tr><td>技术备注</td><td>技术备注</td></tr>
<tr><td>精工期限</td><td>精工完工期限</td></tr>
<tr><td>新基本件流水号</td><td>改制任务生成的新零件流水号</td></tr>
<tr><td>新工艺计划流水号</td><td>改制任务生成的新工艺计划流水号</td></tr>
<tr><td>发起人</td><td>当前用户 ID</td></tr>
<tr><td>发起日期</td><td>发起时间</td></tr>
<tr><td>状态</td><td>改制订单状态</td></tr>
<tr><td>是否启用</td><td>逻辑删除标识</td></tr>
</tbody>
</table>
<h3>7.2 改制订单状态</h3>
<table>
<thead><tr><th>状态</th><th>说明</th></tr></thead>
<tbody>
<tr><td>待领料</td><td>需要领料,领料单未出库</td></tr>
<tr><td>待工艺</td><td>不需要领料或已出库,等待制定工艺</td></tr>
<tr><td>工艺完成</td><td>工艺已保存,等待派工</td></tr>
<tr><td>待派工</td><td>工艺完成且满足派工条件</td></tr>
<tr><td>加工中</td><td>已派工或已开始加工</td></tr>
<tr><td>已完成</td><td>改制任务完工</td></tr>
<tr><td>已取消</td><td>改制订单取消</td></tr>
</tbody>
</table>
<p>说明:</p>
<ul><li>如果不需要领料,提交后可直接进入 <code>待工艺</code></li><li>如果需要领料,提交后进入 <code>待领料</code></li><li>仓库出库后从 <code>待领料</code> 转为 <code>待工艺</code> 或保持生产任务状态,由查询时关联显示。</li></ul>
<h2>8. API 设计</h2>
<p>项目请求继续使用:</p>
<pre><code>this.CreateData(type, name, param, pageSize, pageCurrent)
this.ExecDatabase(Data)</code></pre>
<h3>8.1 技术中心查询可改制对象</h3>
<pre><code>var Data = this.CreateData('11', '技术中心_改制订单_可改制对象_查询', param, this.pageSize, this.pageCurrent)</code></pre>
<h3>8.2 技术中心发起改制订单</h3>
<pre><code>var Data = this.CreateData('12', '技术中心_改制订单_发起改制', param)</code></pre>
<p>参数建议:</p>
<table>
<thead><tr><th>参数名</th><th>说明</th></tr></thead>
<tbody>
<tr><td>原订单流水号</td><td>原订单流水号</td></tr>
<tr><td>原组件流水号</td><td>原组件流水号</td></tr>
<tr><td>原基本件流水号</td><td>原基本件流水号</td></tr>
<tr><td>原工艺计划流水号</td><td>原工艺计划流水号</td></tr>
<tr><td>原订单编号</td><td>原订单编号</td></tr>
<tr><td>原零件名称</td><td>原零件名称</td></tr>
<tr><td>原零件图号</td><td>原零件图号</td></tr>
<tr><td>改制零件名称</td><td>改制零件名称</td></tr>
<tr><td>改制零件图号</td><td>改制零件图号</td></tr>
<tr><td>改制数量</td><td>改制数量</td></tr>
<tr><td>改制来源类型</td><td>原现自制订单、毛坯改制、非毛坯物料改制</td></tr>
<tr><td>是否毛坯</td><td>是否毛坯</td></tr>
<tr><td>物料流水号</td><td>使用物料流水号</td></tr>
<tr><td>物料编号</td><td>物料编号</td></tr>
<tr><td>物料名称</td><td>物料名称</td></tr>
<tr><td>改制原因</td><td>改制原因</td></tr>
<tr><td>改制要求</td><td>改制要求</td></tr>
<tr><td>技术备注</td><td>技术备注</td></tr>
<tr><td>精工期限</td><td>精工期限</td></tr>
<tr><td>发起人</td><td>当前用户 ID</td></tr>
</tbody>
</table>
<p>后端处理结果:</p>
<ul><li>生成改制订单。</li><li>判断是否生成领料单。</li><li>生成精工生产任务。</li><li>返回 <code>result</code><code>改制订单号</code><code>领料单号</code><code>是否需要领料</code></li></ul>
<h3>8.3 改制记录查询</h3>
<pre><code>var Data = this.CreateData('11', '技术中心_改制订单_记录_查询', param, this.pageSize, this.pageCurrent)</code></pre>
<h3>8.4 改制订单详情</h3>
<pre><code>var Data = this.CreateData('11', '技术中心_改制订单_详情_查询', param)</code></pre>
<h3>8.5 取消改制订单</h3>
<pre><code>var Data = this.CreateData('12', '技术中心_改制订单_取消', param)</code></pre>
<p>取消前后端需要校验:</p>
<ul><li>未派工可以取消。</li><li>已派工未加工,需要先取消派工。</li><li>已加工、已有质检记录或已完成,不允许取消。</li><li>已生成领料单且已出库,不允许直接取消,需要走退料或异常处理。</li></ul>
<h2>9. 现有接口扩展</h2>
<h3>9.1 生产任务查询接口</h3>
<p>现有接口:</p>
<pre><code>精工车间_生成任务_查询数据</code></pre>
<p>新增查询参数:</p>
<table>
<thead><tr><th>参数名</th><th>说明</th></tr></thead>
<tbody>
<tr><td>任务类型\_check</td><td>是否按任务类型过滤</td></tr>
<tr><td>任务类型</td><td>全部、正常、改制、报废补投</td></tr>
<tr><td>领料状态\_check</td><td>是否按领料状态过滤</td></tr>
<tr><td>领料状态</td><td>待出库、已出库、不需要领料</td></tr>
</tbody>
</table>
<p>新增返回字段:</p>
<table>
<thead><tr><th>字段名</th><th>说明</th></tr></thead>
<tbody>
<tr><td>任务类型</td><td>正常、改制、报废补投</td></tr>
<tr><td>是否改制</td><td>1 是0 否</td></tr>
<tr><td>改制订单号</td><td>改制订单编号</td></tr>
<tr><td>改制来源类型</td><td>原现自制订单、毛坯改制、非毛坯物料改制</td></tr>
<tr><td>是否需要领料</td><td>1 是0 否</td></tr>
<tr><td>领料状态</td><td>未生成、待出库、已出库、已取消</td></tr>
<tr><td>领料单号</td><td>领料单号</td></tr>
<tr><td>改制原因</td><td>改制原因</td></tr>
<tr><td>改制要求</td><td>改制要求</td></tr>
</tbody>
</table>
<h3>9.2 车间派工查询接口</h3>
<p>现有接口:</p>
<pre><code>精工车间_车间派工_查询</code></pre>
<p>新增查询参数:</p>
<table>
<thead><tr><th>参数名</th><th>说明</th></tr></thead>
<tbody>
<tr><td>任务类型\_check</td><td>是否按任务类型过滤</td></tr>
<tr><td>任务类型</td><td>全部、正常、改制、报废补投</td></tr>
</tbody>
</table>
<p>新增返回字段:</p>
<table>
<thead><tr><th>字段名</th><th>说明</th></tr></thead>
<tbody>
<tr><td>任务类型</td><td>正常、改制、报废补投</td></tr>
<tr><td>是否改制</td><td>1 是0 否</td></tr>
<tr><td>改制订单号</td><td>改制订单编号</td></tr>
<tr><td>改制来源类型</td><td>改制来源类型</td></tr>
<tr><td>是否需要领料</td><td>1 是0 否</td></tr>
<tr><td>领料状态</td><td>领料状态</td></tr>
<tr><td>领料单号</td><td>领料单号</td></tr>
</tbody>
</table>
<p>派工前端限制:</p>
<pre><code>如果 是否改制 = 1 且 是否需要领料 = 1 且 领料状态 != 已出库,则不允许派工。</code></pre>
<h2>10. 前端交互调整</h2>
<h3>10.1 技术中心改制订单发起页面</h3>
<p>查询条件:</p>
<ul><li>订单编号</li><li>零件名称</li><li>图号</li><li>物料编号</li><li>物料名称</li><li>改制来源类型</li></ul>
<p>表格列:</p>
<ul><li>订单编号</li><li>产品/部件名称</li><li>零件名称</li><li>零件图号</li><li>数量</li><li>当前状态</li><li>来源类型</li><li>物料编号</li><li>物料名称</li><li>操作</li></ul>
<p>操作:</p>
<ul><li>发起改制</li><li>图纸</li><li>PLM传入工艺</li><li>追溯</li></ul>
<p>发起改制弹窗:</p>
<ul><li>原订单编号</li><li>原零件名称</li><li>原零件图号</li><li>改制零件名称</li><li>改制零件图号</li><li>改制数量</li><li>改制来源类型</li><li>是否毛坯</li><li>物料编号</li><li>物料名称</li><li>改制原因</li><li>改制要求</li><li>技术备注</li><li>精工期限</li></ul>
<h3>10.2 生产任务查询页面</h3>
<p>新增筛选:</p>
<pre><code>任务类型:全部 / 正常 / 改制 / 报废补投
领料状态:全部 / 不需要领料 / 待出库 / 已出库</code></pre>
<p>新增列:</p>
<ul><li>任务类型</li><li>改制订单号</li><li>改制来源类型</li><li>领料状态</li></ul>
<p>显示建议:</p>
<pre><code>&lt;el-tag type="warning" size="mini"&gt;改制&lt;/el-tag&gt;
&lt;el-tag type="danger" size="mini"&gt;待出库&lt;/el-tag&gt;
&lt;el-tag type="success" size="mini"&gt;已出库&lt;/el-tag&gt;
&lt;el-tag type="info" size="mini"&gt;不需要领料&lt;/el-tag&gt;</code></pre>
<h3>10.3 车间派工页面</h3>
<p>新增筛选:</p>
<pre><code>任务类型:全部 / 正常 / 改制 / 报废补投</code></pre>
<p>新增列:</p>
<ul><li>任务类型</li><li>改制订单号</li><li>领料状态</li></ul>
<p>派工按钮或派工操作前增加判断:</p>
<pre><code>if (Number(row.是否改制) === 1 &amp;&amp; Number(row.是否需要领料) === 1 &amp;&amp; row.领料状态 !== '已出库') {
this.$message.warning('改制订单物料未出库,不能派工')
return
}</code></pre>
<h3>10.4 改制记录查询页面</h3>
<p>查询条件:</p>
<ul><li>改制订单号</li><li>原订单编号</li><li>零件名称或图号</li><li>改制来源类型</li><li>领料状态</li><li>改制状态</li><li>发起日期</li><li>发起人</li></ul>
<p>表格列:</p>
<ul><li>改制订单号</li><li>状态</li><li>原订单编号</li><li>原零件名称</li><li>原零件图号</li><li>改制零件名称</li><li>改制零件图号</li><li>改制数量</li><li>改制来源类型</li><li>是否需要领料</li><li>领料单号</li><li>领料状态</li><li>改制原因</li><li>发起人</li><li>发起日期</li><li>精工期限</li><li>完成日期</li><li>操作</li></ul>
<p>操作:</p>
<ul><li>详情</li><li>生产任务</li><li>派工</li><li>追溯</li><li>取消</li></ul>
<h2>11. 菜单配置</h2>
<p>建议后端菜单配置:</p>
<pre><code>技术中心
改制订单发起
改制记录查询</code></pre>
<p>组件路径:</p>
<pre><code>TechnologyCenter/PartModificationOrder/index
TechnologyCenter/PartModificationRecord/index</code></pre>
<p>精工车间不新增发起入口,只扩展现有页面:</p>
<pre><code>SeikoWorkshop/ProductionTaskQuery/index
SeikoWorkshop/WorkshopAssignment/index</code></pre>
<h2>12. 实施顺序</h2>
<p>建议按以下顺序实施:</p>
<p>1. 后端新增改制订单主记录表。 2. 后端新增技术中心发起改制订单接口。 3. 后端在发起接口中加入领料判断规则。 4. 后端按规则生成或不生成领料单。 5. 后端生成标准精工生产任务,并标记 <code>任务类型 = 改制</code>。 6. 扩展生产任务查询接口,返回改制和领料字段。 7. 扩展车间派工查询接口,返回改制和领料字段。 8. 前端新增技术中心改制订单发起页面。 9. 前端新增改制记录查询页面。 10. 前端修改生产任务查询页面,增加任务类型和领料状态显示。 11. 前端修改车间派工页面,增加改制任务显示和派工前领料状态校验。 12. 联调从技术中心发起、领料判断、仓库出库、精工工艺、车间派工、加工完工、记录查询的完整流程。</p>
<h2>13. 风险点</h2>
<h3>13.1 领料判断风险</h3>
<p>改制订单是否生成领料单,必须以后端判断为准。</p>
<p>前端可以显示和提示,但不能只依赖前端判断,避免绕过仓库出库流程。</p>
<h3>13.2 派工前物料状态风险</h3>
<p>如果改制订单需要仓库出库,但尚未出库,直接派工会导致车间无物料加工。</p>
<p>建议车间派工接口或派工保存接口再次校验:</p>
<pre><code>需要领料且未出库,不允许派工。</code></pre>
<h3>13.3 原任务数据覆盖风险</h3>
<p>改制订单必须生成新的生产任务和新的工艺计划流水号。</p>
<p>不能直接覆盖原自制订单或原零件工艺,否则会影响原订单追溯、工时和质量记录。</p>
<h3>13.4 取消改制风险</h3>
<p>已生成领料单、已出库、已派工或已加工的改制订单取消规则需要严格控制。</p>
<p>建议:</p>
<ul><li>未出库、未派工:允许取消。</li><li>已出库:需要退料后取消。</li><li>已派工未加工:先取消派工再取消。</li><li>已加工:不允许取消,只能走异常处理。</li></ul>
<h3>13.5 统计口径风险</h3>
<p>改制订单进入精工生产任务后,会影响生产任务数量、工时统计、完工统计。</p>
<p>建议所有统计接口增加任务类型维度:</p>
<pre><code>正常
改制
报废补投</code></pre>
<h2>14. 总结</h2>
<p>本方案采用:</p>
<pre><code>技术中心发起改制订单,精工车间承接生产,仓库按需出库,改制记录统一查询。</code></pre>
<p>关键规则:</p>
<ul><li>技术中心新增组件发起改制订单。</li><li>改制订单生成后进入精工车间生产任务查询。</li><li>改制订单工艺和派工复用现有精工流程。</li><li>领料时如果是改制订单,并且使用物料不是毛坯,则生成领料单,由仓库物料出库。</li><li>如果是原现自制订单改制,或者直接使用毛坯改制,则不生成领料单。</li><li>改制记录查询独立展示全流程状态。</li></ul>
</body>
</html>

BIN
part-modification-plan.pdf Normal file

Binary file not shown.

BIN
src.zip Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,570 @@
<template>
<div class="app-container">
<el-card style="height: 850px">
<div style="margin-top: 7px; margin-bottom: 7px">
<el-input v-model="consignee" style="width: 100px" size="small" clearable placeholder="收货人"/>
<el-input v-model="orderValue" style="width: 200px" size="small" clearable placeholder="买方/订单号"/>
<el-input v-model="logistics" style="width: 150px" size="small" clearable placeholder="物流单号"/>
<span style="font-size: 13px;color: black">发货日期</span>
<el-date-picker
v-model="dateRange"
size="small"
type="daterange"
align="center"
style="width: 240px;"
value-format="yyyy-MM-dd"
format="yyyy-MM-dd"
range-separator=""
clearable
start-placeholder="开始日期"
end-placeholder="结束日期"
@change="pageCurrent = 1;pageSize = 100;searchTable()"/>
<el-select v-model="deliveryStateValue" style="width:100px;margin-left: 10px" placeholder="发货状态" size="small" filterable clearable @change="pageCurrent = 1;pageSize = 100;searchTable()">
<el-option
v-for="item in deliveryState"
:key="item.value"
:label="item.label"
:value="item.value"/>
</el-select>
<el-button icon="el-icon-search" type="primary" plain size="small" style="margin-left: 10px" @click="pageCurrent = 1;pageSize = 100;searchTable()">查询</el-button>
</div>
<el-col style="margin-top: 10px;width: 891px">
<el-table
v-loading="loading"
ref="table"
:data="tableData"
:summary-method="getSummaries"
highlight-current-row
show-summary
border
stripe
size="small"
style="width: 891px"
height="740px"
@row-click="searchTable1">
<el-table-column :width="setColumnWidth('状态')" label="发货状态" align="center">
<template slot-scope="scope">
<el-tag v-if="scope.row.发货状态==='未审核'" type="info" size="small" style="margin: 0px">未审核</el-tag>
<el-tag v-if="scope.row.发货状态==='待审核'" type="primary" size="small" style="margin: 0px">待审核</el-tag>
<el-tag v-if="scope.row.发货状态==='已审核'" type="warning" size="small" style="margin: 0px">已审核</el-tag>
<el-tag v-if="scope.row.发货状态==='已发货'" type="success" size="small" style="margin: 0px">已发货</el-tag>
</template>
</el-table-column>
<el-table-column width="120px" label="发货单号" align="center" show-overflow-tooltip>
<template slot-scope="scope">
{{ scope.row.发货单号 }}
</template>
</el-table-column>
<el-table-column width="87px" label="发货日期" align="center" show-overflow-tooltip>
<template slot-scope="scope">
{{ scope.row.发货日期 }}
</template>
</el-table-column>
<el-table-column width="60px" label="收货人" align="center">
<template slot-scope="scope">
{{ scope.row.收货人 }}
</template>
</el-table-column>
<el-table-column label="收货地址" align="center">
<template slot-scope="scope">
{{ scope.row.收货地址 }}
</template>
</el-table-column>
<el-table-column width="102px" label="物流单号" align="center">
<template slot-scope="scope">
{{ scope.row.物流单号 }}
</template>
</el-table-column>
<el-table-column width="87px" label="发货金额" align="center" prop="发货金额">
<template slot-scope="scope">
{{ Number(scope.row.发货金额).toFixed(2) }}
</template>
</el-table-column>
<el-table-column width="90px" label="发货备注" show-overflow-tooltip align="center">
<template slot-scope="scope">
{{ scope.row.发货备注 }}
</template>
</el-table-column>
<el-table-column width="117px" label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" icon="el-icon-top" size="mini" @click="uploadPicture(scope.row)">照片</el-button>
<el-button v-show="Number(token)===8 || Number(token)===2" :disabled="scope.row.发货状态==='已发货'" size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"/>
<el-button type="text" icon="el-icon-edit" size="mini" @click="handleEdit(scope.row)"/>
<el-button size="mini" type="text" icon="el-icon-picture-outline" @click="handlePicture(scope.row)"/>
<el-tooltip :open-delay="500" effect="dark" content="退回发货单" placement="top">
<el-button :disabled="scope.row.发货状态==='未确认'" type="text" icon="el-icon-back" @click="confirmReturn(scope.row)"/>
</el-tooltip>
<el-button :disabled="scope.row.审核状态 > 0" size="mini" type="text" @click="review(scope.row)">审核</el-button>
</template>
</el-table-column>
</el-table>
<div class="block" style="margin-top: 10px;">
<el-pagination
:current-page="pageCurrent"
:page-sizes="[10, 20, 30, 40, 100]"
:page-size="pageSize"
:total="total"
:pager-count="5"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChanges"
@current-change="handleCurrentChanges"/>
</div>
</el-col>
<el-col style="margin-top: 10px;margin-left: 20px;width: 751px">
<el-table ref="table1" :data="tableData1" :header-cell-style="{background: '#2283D4',color: 'white'}" highlight-current-row border stripe size="small" style="width: 751px" height="740px">
<el-table-column :width="setColumnWidth('序号')" label="序号" type="index" align="center"/>
<el-table-column :width="setColumnWidth('订单号')" label="订单号" align="center" show-overflow-tooltip>
<template slot-scope="scope">
{{ scope.row.订单号 }}
</template>
</el-table-column>
<el-table-column label="买方名称" align="center" show-overflow-tooltip>
<template slot-scope="scope">
{{ scope.row.买方名称 }}
</template>
</el-table-column>
<el-table-column :width="setColumnWidth('产品名称')" label="产品名称" align="center" show-overflow-tooltip>
<template slot-scope="scope">
{{ scope.row.产品名称 }}
</template>
</el-table-column>
<el-table-column :width="setColumnWidth('数量')" label="发货数量" align="center" prop="发货数量">
<template slot-scope="scope">
{{ scope.row.发货数量 ? scope.row.发货数量 : scope.row.查询实际发量 }}
</template>
</el-table-column>
<el-table-column :width="setColumnWidth('单价')" label="单价" align="center" prop="单价">
<template slot-scope="scope">
{{ Number(scope.row.单价).toFixed(2) }}
</template>
</el-table-column>
<el-table-column width="110px" label="金额" align="center" prop="金额">
<template slot-scope="scope">
{{ Number((scope.row.发货数量 ? scope.row.发货数量 : scope.row.查询实际发量) * scope.row.单价).toFixed(2) }}
</template>
</el-table-column>
<el-table-column :width="setColumnWidth('数量')" label="订单数" align="center" prop="订单数">
<template slot-scope="scope">
{{ scope.row.订单数 }}
</template>
</el-table-column>
</el-table>
</el-col>
</el-card>
<el-dialog v-el-drag-dialog :visible.sync="dialogFormVisible" title="图片" center style="" width="600px">
<el-image v-for="url in urls" :key="url" :src="url" :preview-src-list="urls" lazy style="width: 500px; height: 500px"/>
</el-dialog>
<el-dialog v-el-drag-dialog :visible.sync="dialogFormVisible1" title="编辑发货信息" center width="360px">
<el-form ref="form" :model="form" :rules="rules" label-position="center" label-width="100px" class="demo-ruleForm">
<el-form-item label="物流单号" prop="物流单号">
<el-input v-model="form.物流单号" style="width:200px;" placeholder="物流单号" size="small" clearable/>
</el-form-item>
<el-form-item label="收货人" prop="收货人">
<el-input v-model="form.收货人" style="width:200px;" placeholder="收货人" size="small" clearable/>
</el-form-item>
<el-form-item label="收货地址" prop="收货地址">
<el-input v-model="form.收货地址" :rows="4" type="textarea" style="width:200px;" placeholder="收货地址" size="small" clearable/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size="small" @click="callOff('form')">取消</el-button>
<el-button type="distribution" size="small" @click="submitUpdate('form')">确定</el-button>
</div>
</el-dialog>
<el-dialog v-el-drag-dialog :visible.sync="dialogFormVisible2" title="上传图片" center width="320px">
<el-upload
id="invoiceScan"
ref="upload"
:multiple="true"
:auto-upload="false"
:on-success="uploadSuccess"
:on-exceed="warningExceed"
:limit="limit"
:data="Data"
:action="upload"
style="margin-left: 60px"
list-type="picture-card">
<i class="el-icon-plus"/>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button size="small" @click="dialogFormVisible2=false">取消</el-button>
<el-button type="distribution" size="small" @click="submit2('form')">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import { url, MESUploadFileNew, MESDownloadFileNew, MESUploadFileNew_BasePath } from '@/utils/request'
import axios from 'axios'
export default {
data() {
return {
Data: {},
limit: 1000,
upload: url,
dialogFormVisible1: false,
dialogFormVisible2: false,
listValue: '',
form: {
物流单号: '',
收货人: '',
收货地址: ''
},
rules: {
物流单号: [{ required: true, message: '请输入物流单号', trigger: 'blur' }],
收货人: [{ required: true, message: '请输入收货人', trigger: 'blur' }],
收货地址: [{ required: true, message: '请输入收货地址', trigger: 'change' }]
},
dialogFormVisible: false,
urls: [],
consignee: '', // 收货人
logistics: '', // 物流单号
orderValue: '', // 订单号
dateRange: '', // 发货日期
deliveryStateValue: '', // 发货状态
deliveryState: [{
value: 0,
label: '未确认'
}, {
value: 1,
label: '已发货'
}], // 发货状态数组
loading: false, // 数据加载
total: 0, // 分页总数
tableData: [], // 订单信息表
tableData1: [], // 产品信息表
pageCurrent: 1, // 分页当前页
pageSize: 100, // 分页每页显示条数
deliveryMxValue: [],
deliveryNum: [],
orderName: '', // 排序列名
order: '' // 排序方式
}
},
computed: {
...mapGetters([
'id',
'token'
])
},
updated() {
this.$nextTick(() => {
this.$refs['table'].doLayout()
this.$refs['table1'].doLayout()
})
},
created() {
this.searchTable()
},
methods: {
review(row) {
this.$confirm('是否通知审核?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
var param1 = []
param1[0] = ['发货单流水号', row.发货单流水号]
var Data1 = this.CreateData('12', '发货查询_发货单_通知审核', param1)
this.ExecDatabase(Data1).then(response => {
if (response.data[0].result === '1') {
this.$message.success('通知成功')
this.searchTable()
} else {
this.$message.error('通知失败')
}
})
}).catch(() => {
this.$message({
type: 'info',
message: '已取消'
})
})
},
warningExceed() {
this.$message.error('仅可上传五张照片')
},
uploadSuccess(res, file) { // 上传成功回调
// 生成文件保存路径: 基础路径/DeliveryRecord/年月日时分秒毫秒.后缀
const now = new Date()
const timestamp = now.getFullYear().toString() +
(now.getMonth() + 1).toString().padStart(2, '0') +
now.getDate().toString().padStart(2, '0') +
now.getHours().toString().padStart(2, '0') +
now.getMinutes().toString().padStart(2, '0') +
now.getSeconds().toString().padStart(2, '0') +
now.getMilliseconds().toString().padStart(3, '0')
const suffix = file.name.split('.').pop() || 'jpg'
const lastDotIndex = file.name.lastIndexOf('.')
const fileName = lastDotIndex > -1 ? file.name.slice(0, lastDotIndex) : file.name
const sqlFileName = fileName.replace(/'/g, "''")
const sqlSuffix = suffix.replace(/'/g, "''")
const uniqueCode = Math.random().toString(36).slice(2, 8)
const savePath = MESUploadFileNew_BasePath + '\\DeliveryRecord\\' + timestamp + '-' + this.listValue + '-' + uniqueCode + '.' + suffix
// 构造SQL语句清空文件内容更新文件路径
const sqlStatement = `update 发货管理_发货单_图片 set 文件内容 = NULL, 文件路径 = N'${savePath}' where id = (select top 1 id from 发货管理_发货单_图片 where 发货单流水号 = ${this.listValue} and 文件名称 = N'${sqlFileName}' and 文件后缀 = N'${sqlSuffix}' and 文件路径 is null order by 操作时间 desc, id desc); IF @@ROWCOUNT <> 1 RAISERROR(N'图片路径回填失败', 16, 1)`
// 调用新接口保存文件到磁盘
const formData = new FormData()
formData.append('file', file.raw)
formData.append('savePath', savePath)
formData.append('sqlStatement', sqlStatement)
axios.post(MESUploadFileNew, formData, {
headers: { 'Content-Type': 'multipart/form-data' }
}).then(response => {
if (response.data && response.data[0] && response.data[0].result === '1') {
console.log('文件保存成功:', savePath)
} else {
console.error('文件保存失败:', response.data)
}
}).catch(err => {
console.error('文件保存异常:', err)
})
this.dialogFormVisible2 = false
this.$refs.upload.clearFiles()
},
submit2() {
var param = []
param[0] = ['发货单流水号', this.listValue]
param[1] = ['文件名称', '']
param[2] = ['文件后缀', '']
param[3] = ['文件内容', null]
var Data1 = this.CreateData('15', '发货管理_发货单_上传图片', param)
this.Data.param = Data1
this.$refs.upload.submit()
this.dialogFormVisible2 = false
this.$nextTick(() => {
this.searchTable()
})
},
uploadPicture(row) {
this.dialogFormVisible2 = true
this.listValue = row.发货单流水号
},
submitUpdate(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
var param1 = []
param1[0] = ['发货单流水号', this.form.发货单流水号]
param1[1] = ['物流单号', this.form.物流单号]
param1[2] = ['收货人', this.form.收货人]
param1[3] = ['收货地址', this.form.收货地址]
var Data1 = this.CreateData('12', '发货查询_发货单_编辑', param1)
this.ExecDatabase(Data1).then(response => {
if (response.data[0].result === '1') {
this.$message.success('编辑成功')
this.searchTable()
this.dialogFormVisible1 = false
} else {
this.$message.error('编辑失败')
}
})
}
})
},
callOff(formName) {
this.form.物流单号 = ''
this.form.收货人 = ''
this.form.收货地址 = ''
this.dialogFormVisible1 = false
this.$refs[formName].resetFields()
},
handleEdit(row) {
if (this.$refs['form'] !== undefined) {
this.$refs['form'].resetFields()
}
this.title = '编辑物料'
this.form.物流单号 = row.物流单号
this.form.发货单流水号 = row.发货单流水号
this.form.收货人 = row.收货人
this.form.收货地址 = row.收货地址
this.dialogFormVisible1 = true
},
searchTable() {
console.log(this.token)
this.tableData1 = []
let consignee_check, dateRange_check, deliveryStateValue_check, logistics_check, orderValue_check
this.consignee ? consignee_check = 1 : consignee_check = 0
this.logistics ? logistics_check = 1 : logistics_check = 0
this.orderValue ? orderValue_check = 1 : orderValue_check = 0
this.dateRange ? dateRange_check = 1 : (dateRange_check = 0, this.dateRange = '')
if (this.deliveryStateValue === 0) {
deliveryStateValue_check = 1
} else if (this.deliveryStateValue) {
deliveryStateValue_check = 1
} else {
deliveryStateValue_check = 0
}
var param = []
param[0] = ['收货人_check', consignee_check]
param[1] = ['收货人', this.consignee]
param[2] = ['发货状态_check', deliveryStateValue_check]
param[3] = ['发货状态', this.deliveryStateValue]
param[4] = ['订单号_check', orderValue_check]
param[5] = ['订单号', this.orderValue]
param[6] = ['物流单号_check', logistics_check]
param[7] = ['物流单号', this.logistics]
param[8] = ['时间_check', dateRange_check]
param[9] = ['开始时间', this.dateRange[0]]
param[10] = ['结束时间', this.dateRange[1]]
param[11] = ['排序名称', '']
param[12] = ['排序方式', '']
var Data = this.CreateData('11', '产品发货_发货单_查询数据', param, this.pageSize, this.pageCurrent)
this.ExecDatabase(Data).then(response => {
this.tableData = response.data.rows
this.total = response.data.total
})
},
searchTable1(row) {
var param = []
param[0] = ['发货单流水号', row.发货单流水号]
param[1] = ['已发', 0]
var Data = this.CreateData('11', '产品发货_发货单明细_查询数据新', param)
this.ExecDatabase(Data).then(response => {
this.tableData1 = response.data
})
},
handlePicture(row) {
this.dialogFormVisible = true
this.urls = []
var param = []
param[0] = ['发货单流水号', row.发货单流水号]
var Data = this.CreateData('11', '发货单_图片_查询数据', param)
this.ExecDatabase(Data).then(response => {
for (let i = 0; i < response.data.length; i++) {
const item = response.data[i]
// 优先使用文件路径(新方式),否则使用数据库内容(旧方式)
if (item.文件路径) {
// 从文件系统读取
axios.get(MESDownloadFileNew, {
params: { filePath: item.文件路径 }
}).then(res => {
if (res.data && res.data[0] && res.data[0].文件内容) {
this.urls.push('data:image/png;base64,' + res.data[0].文件内容)
}
}).catch(err => {
console.error('图片加载失败:', err)
})
} else if (item.文件内容 !== null) {
// 兼容旧数据直接使用数据库中的base64
this.urls.push('data:image/png;base64,' + item.文件内容)
}
}
})
},
handleDelete(row) {
this.$confirm('是否删除?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
var param = []
param[0] = ['发货单流水号', row.发货单流水号]
var Data = this.CreateData('12', '产品发货_发货单_删除', param)
this.ExecDatabase(Data).then(response => {
if (response.data[0].result === '1') {
this.$message.success('删除成功')
this.searchTable()
} else {
this.$message.error('删除失败')
}
})
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
})
})
},
confirmReturn(row) {
this.$confirm('是否退回?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.deliveryMxValue = []
this.deliveryNum = []
for (let i = 0; i < this.tableData1.length; i++) {
this.deliveryMxValue.push(this.tableData1[i].发货单明细流水号)
if (isNaN(this.tableData1[i].发货数量) === false) {
if (this.tableData1[i].发货数量 !== '' && this.tableData1[i].发货数量 !== '0' && this.tableData1[i].发货数量 !== null) {
this.deliveryNum.push(this.tableData1[i].发货数量)
} else {
this.$message.error('已发数量不能为0或空')
break
}
} else {
this.$message.error('已发数量必须为数值')
break
}
}
var param = []
param[0] = ['发货单流水号', row.发货单流水号]
param[1] = ['发货单明细流水号组', this.deliveryMxValue]
param[2] = ['已发数量组', this.deliveryNum]
var Data = this.CreateData('12', '产品查询_发货单_退回发货', param)
this.ExecDatabase(Data).then(response => {
if (response.data[0].result === '1') {
this.$message.success('退回成功')
this.searchTable()
// this.searchTable1()
this.tableData1 = []
} else {
this.$message.success('退回失败')
}
})
}).catch(() => {
this.$message({
type: 'info',
message: '已取消'
})
})
},
getSummaries(param) {
const { columns, data } = param
const sums = []
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = '合计'
return
} else if (index === 6) {
const values = data.map(item => Number(item['发货金额']))
if (!values.every(value => isNaN(value))) {
sums[index] = values.reduce((prev, curr) => {
const value = Number(curr)
if (!isNaN(value)) {
return prev + curr
} else {
return prev
}
}, 0)
sums[index] = sums[index].toFixed(2)
} else {
sums[index] = 'N/A'
}
}
})
return sums
},
handleSizeChanges(val) {
this.pageCurrent = 1
this.pageSize = val
this.searchTable()
},
handleCurrentChanges(val) {
this.pageCurrent = val
this.searchTable()
}
}
}
</script>
<style>
.ziduan {
width: 50px!important;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -7,6 +7,7 @@
<el-input v-model="specificationsModel" style="width: 150px " size="small" clearable placeholder="图号或型号"/> <el-input v-model="specificationsModel" style="width: 150px " size="small" clearable placeholder="图号或型号"/>
<el-input v-model="LocationName" style="width: 100px " size="small" clearable placeholder="库位"/> <el-input v-model="LocationName" style="width: 100px " size="small" clearable placeholder="库位"/>
<el-button style="margin-left: 7px;width: 80px" type="primary" plain size="small" @click="pageCurrent=1;searchTable()">查询</el-button> <el-button style="margin-left: 7px;width: 80px" type="primary" plain size="small" @click="pageCurrent=1;searchTable()">查询</el-button>
<el-button type="primary" plain icon="el-icon-upload2" size="small" style="margin-left: 7px" @click="handleExcel()">导入查询</el-button>
<el-button v-if="Number(token) === 2" type="success" plain icon="el-icon-download" size="small" style="margin-left: 7px" @click="exportExcel()">导出</el-button> <el-button v-if="Number(token) === 2" type="success" plain icon="el-icon-download" size="small" style="margin-left: 7px" @click="exportExcel()">导出</el-button>
<el-button type="distribution" size="small" @click="addMaterial()">增加物料存货</el-button> <el-button type="distribution" size="small" @click="addMaterial()">增加物料存货</el-button>
<el-button type="primary" icon="el-icon-printer" style="margin-left: 20px" plain size="small" @click="Pronters()">批量打印</el-button> <el-button type="primary" icon="el-icon-printer" style="margin-left: 20px" plain size="small" @click="Pronters()">批量打印</el-button>
@@ -162,6 +163,22 @@
<el-button type="primary" size="small" @click="submitMaterialChange">确定</el-button> <el-button type="primary" size="small" @click="submitMaterialChange">确定</el-button>
</div> </div>
</el-dialog> </el-dialog>
<el-dialog
v-el-drag-dialog
:visible.sync="dialogFormVisibleExcel"
title="导入查询"
center
width="720px">
<upload-excel-component @on-selected-file="selected"/>
<div style="margin: 10px 0 0 45px">
<span v-show="worksheet.length > 1" style="cursor: pointer;width: 50px;" @click="removeAll"><i class="el-icon-close"/></span>
<el-upload :on-remove="handleRemove" :file-list="itemFile" style="width: 260px" action=""/>
</div>
<div slot="footer" class="dialog-footer">
<el-button size="small" @click="dialogFormVisibleExcel=false">取消</el-button>
<el-button type="primary" size="small" icon="el-icon-search" @click="importExcelSearch">查询</el-button>
</div>
</el-dialog>
<el-dialog v-el-drag-dialog :visible.sync="dialogFormVisible" title="增加产品" center width="390px"> <el-dialog v-el-drag-dialog :visible.sync="dialogFormVisible" title="增加产品" center width="390px">
<el-form ref="form" :model="form" :rules="rules" label-position="left" label-width="100px" class="demo-ruleForm" style="margin: auto"> <el-form ref="form" :model="form" :rules="rules" label-position="left" label-width="100px" class="demo-ruleForm" style="margin: auto">
<el-row> <el-row>
@@ -200,11 +217,14 @@
import { ExecDatabase } from '@/main' import { ExecDatabase } from '@/main'
import { wsuri } from '@/utils/request' import { wsuri } from '@/utils/request'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import UploadExcelComponent from '@/views/TechnologyCenter/ImportBOM/UploadExcel/index.vue'
export default { export default {
components: { UploadExcelComponent },
data() { data() {
return { return {
dialogFormVisible: false, dialogFormVisible: false,
dialogFormVisible1: false, dialogFormVisible1: false,
dialogFormVisibleExcel: false,
title: '', title: '',
materialName: '', materialName: '',
materialSpec: '', materialSpec: '',
@@ -223,6 +243,8 @@ export default {
productName: [], productName: [],
editorialStaff: [], editorialStaff: [],
multipleSelection: [], multipleSelection: [],
itemFile: [],
worksheet: [],
rules: { rules: {
入库数: [{ required: true, message: '请输入入库数' }], 入库数: [{ required: true, message: '请输入入库数' }],
产品名称: [{ required: true, message: '请选择产品名称' }] 产品名称: [{ required: true, message: '请选择产品名称' }]
@@ -362,6 +384,157 @@ export default {
} }
}) })
}, },
handleExcel() {
this.dialogFormVisibleExcel = true
},
selected(data) {
this.worksheet = data.worksheet
this.itemFile = data.itemFile
},
handleRemove(file) {
for (let i = 0; i < this.itemFile.length; i++) {
if (this.itemFile[i].name === file.name) {
this.worksheet.splice(i, 1)
this.itemFile.splice(i, 1)
}
}
},
removeAll() {
this.worksheet = []
this.itemFile = []
},
getExcelCellValue(sheet, col, row) {
var cell = sheet[col + row]
if (!cell || cell.v === undefined || cell.v === null) {
return ''
}
return String(cell.v).trim()
},
getImportColumns(sheet) {
var cols = [
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
]
var result = {
headerRow: 1,
nameCol: 'B',
drawingCol: 'A'
}
for (let row = 1; row <= 10; row++) {
let nameCol = ''
let drawingCol = ''
for (let i = 0; i < cols.length; i++) {
var title = this.getExcelCellValue(sheet, cols[i], row).replace(/\s/g, '')
if (title === '物料名称' || title === '名称' || title === '零件名称') {
nameCol = cols[i]
}
if (title === '图号' || title === '图号型号' || title === '图号或型号' || title === '图号/型号' || title === '规格型号') {
drawingCol = cols[i]
}
}
if (nameCol || drawingCol) {
result.headerRow = row
result.nameCol = nameCol || result.nameCol
result.drawingCol = drawingCol || result.drawingCol
return result
}
}
return result
},
getImportDetail() {
var detail = []
for (let j = 0; j < this.worksheet.length; j++) {
var sheet = this.worksheet[j]
var columns = this.getImportColumns(sheet)
var emptyCount = 0
for (let row = columns.headerRow + 1; row <= 2000; row++) {
var materialName = this.getExcelCellValue(sheet, columns.nameCol, row)
var specificationsModel = this.getExcelCellValue(sheet, columns.drawingCol, row)
if (!materialName && !specificationsModel) {
emptyCount++
if (emptyCount >= 20) {
break
}
continue
}
emptyCount = 0
detail.push({
物料名称: materialName,
图号或型号: specificationsModel
})
}
}
return detail
},
getImportConditionList(detail) {
var conditionMap = {}
var conditionList = []
for (let i = 0; i < detail.length; i++) {
var materialName = String(detail[i].物料名称 || '').trim()
var drawing = String(detail[i].图号或型号 || '').trim()
var condition = materialName + '^' + drawing
if ((materialName || drawing) && !conditionMap[condition]) {
conditionMap[condition] = true
conditionList.push(condition)
}
}
return conditionList.join(',')
},
setTableData(rows) {
this.tableData = []
for (let i = 0; i < rows.length; i++) {
this.tableData.push({
物料编码: rows[i].物料编码,
物料名称: rows[i].物料名称,
图号或型号: rows[i].图号或型号,
物料与货位流水号: rows[i].物料与货位流水号,
类型: rows[i].类型,
单位: rows[i].单位,
库存: rows[i].库存,
货位流水号: rows[i].货位流水号,
货位名称: rows[i].货位名称,
批次编号: rows[i].批次编号,
编辑人: rows[i].编辑人,
编辑时间: rows[i].编辑时间,
库存_before: rows[i].库存,
货位流水号_before: rows[i].货位流水号,
货位名称_before: rows[i].货位名称,
打印条码数: 1,
edit: false
})
}
},
importExcelSearch() {
var detail = this.getImportDetail()
if (detail.length === 0) {
this.$message.warning('请导入包含物料名称或图号的表格')
return
}
let LocationName_check
this.LocationName ? LocationName_check = 1 : LocationName_check = 0
var param = []
param[0] = ['物料名称_check', 0]
param[1] = ['物料名称', '']
param[2] = ['图号或型号_check', 1]
param[3] = ['图号或型号', this.getImportConditionList(detail)]
param[4] = ['库位_check', LocationName_check]
param[5] = ['库位', this.LocationName]
param[6] = ['排序名称', this.orderName]
param[7] = ['排序方式', this.order]
this.pageCurrent = 1
var Data = this.CreateData('11', '仓储管理_库存盘点_查询', param, this.pageSize, this.pageCurrent)
this.loading = true
this.ExecDatabase(Data).then(response => {
var rows = response.data.rows || response.data || []
this.setTableData(rows)
this.total = response.data.total || rows.length
this.dialogFormVisibleExcel = false
this.loading = false
this.$message.success('导入查询完成')
}).catch(() => {
this.loading = false
})
},
exportExcel() { exportExcel() {
if (this.tableData.length === 0) { if (this.tableData.length === 0) {
this.$message.warning('暂无数据') this.$message.warning('暂无数据')
@@ -403,28 +576,7 @@ export default {
ExecDatabase(Data).then(response => { ExecDatabase(Data).then(response => {
// console.log(response.data) // console.log(response.data)
if (response.data.rows.length !== 0) { if (response.data.rows.length !== 0) {
for (let i = 0; i < response.data.rows.length; i++) { this.setTableData(response.data.rows)
this.tableData.push({
// 表示将从数据库中查询到的数据,分别对应填充到表格中
物料编码: response.data.rows[i].物料编码,
物料名称: response.data.rows[i].物料名称,
图号或型号: response.data.rows[i].图号或型号,
物料与货位流水号: response.data.rows[i].物料与货位流水号,
类型: response.data.rows[i].类型,
单位: response.data.rows[i].单位,
库存: response.data.rows[i].库存,
货位流水号: response.data.rows[i].货位流水号,
货位名称: response.data.rows[i].货位名称,
批次编号: response.data.rows[i].批次编号,
编辑人: response.data.rows[i].编辑人,
编辑时间: response.data.rows[i].编辑时间,
库存_before: response.data.rows[i].库存,
货位流水号_before: response.data.rows[i].货位流水号,
货位名称_before: response.data.rows[i].货位名称,
打印条码数: 1,
edit: false
})
}
} }
this.total = response.data.total this.total = response.data.total
this.loading = false this.loading = false

View File

@@ -0,0 +1,541 @@
# 库存盘点组件库存调拨功能设计方案
## 0. 需求背景
当前库存盘点页面 `src/views/WarehouseManagement/InventoryCheck/index.vue` 已支持查询物料库存、编辑库存数、选择库位,并已存在新增物料货位数量的相关接口。现场盘点时,经常会发现同一物料的实际库存需要从原库位拆分到另一个库位,例如:
- 盘点发现物料实际摆放到了新库位。
- 原库位库存数量过多,需要拆一部分到新库位。
- 系统中还没有目标库位,需要现场一键新建库位后立即调拨。
- 需要保留原库位库存,只把输入的调拨数量从原库位扣掉,并增加到目标库位。
因此本次功能不设计完整调拨单流程,而是在“库存盘点”组件内增加轻量级库存调拨能力:选择一行库存,输入调拨数量,选择或新建目标库位,提交后直接完成原库位库存扣减和目标库位库存增加。
## 1. 设计目标
本功能面向库存盘点页面,核心目标如下:
- 在库存盘点表格行上增加“调拨”操作。
- 调拨弹窗中自动带出当前物料、原库位、原库存数。
- 支持选择已有目标库位。
- 支持一键新建目标库位,并自动回填为调入库位。
- 输入调拨数量后,提交时从原库位库存数中减掉该调拨数量。
- 如果目标库位已有同物料库存,则目标库位库存数增加调拨数量。
- 如果目标库位没有同物料库存,则新增一条物料与货位数量记录。
- 调拨后刷新库存盘点列表,保持页面显示与数据库一致。
## 2. 功能范围
本次只处理库存盘点组件内的库位库存调整,不新增独立“库存调拨单”页面。
包含:
- 盘点列表行内调拨。
- 一键新增库位。
- 原库位扣减库存。
- 目标库位增加库存。
- 调拨操作记录。
不包含:
- 调拨单主表和明细表。
- 调出确认、调入确认两段式流程。
- 审批流程。
- 跨仓库复杂调拨。
- 打印调拨单。
- 外协调拨。
## 3. 页面改造位置
现有页面:
```text
src/views/WarehouseManagement/InventoryCheck/index.vue
```
当前页面已有相关字段和接口:
- 表格字段:`库存``货位流水号``货位名称``物料与货位流水号`
- 库位下拉查询:`仓储管理_库位_查询`
- 盘点查询:`仓储管理_库存盘点_查询`
- 库存编辑:`仓储管理_库存盘点_货位数量_编辑数据`
- 新增物料货位数量验证:`仓储管理_库存盘点_物料货位数量_增加数据_验证是否存在`
- 新增物料货位数量:`仓储管理_库存盘点_物料货位数量_增加数据`
## 4. 前端交互设计
### 4.1 表格增加操作按钮
在库存盘点表格操作列增加:
```text
调拨
```
按钮显示规则:
- 当前行 `物料与货位流水号` 存在时显示。
- 当前行 `库存 > 0` 时允许点击。
- 如果库存为 0按钮禁用或点击提示“当前库位库存为0不能调拨”。
建议按钮:
```html
<el-button type="text" size="mini" @click="openTransfer(scope.row)">调拨</el-button>
```
### 4.2 调拨弹窗
新增 `el-dialog`
```text
库存调拨
```
弹窗字段:
| 字段 | 控件 | 说明 |
| --- | --- | --- |
| 物料名称 | 文本 | 当前行带出,只读 |
| 图号或型号 | 文本 | 当前行带出,只读 |
| 原库位 | 文本 | 当前行 `货位名称`,只读 |
| 原库存数 | 文本 | 当前行 `库存`,只读 |
| 目标库位 | el-select | 选择已有库位 |
| 新库位名称 | el-input | 一键新建库位时填写 |
| 调拨数量 | el-input-number | 需要从原库位调出的数量 |
| 调拨备注 | el-input | 可选 |
弹窗按钮:
- 新建库位
- 确定调拨
- 取消
### 4.3 一键新建库位
在调拨弹窗中增加“新建库位”小区域:
```text
新库位名称 + 新建按钮
```
用户输入新库位名称后点击“新建库位”:
1. 校验库位名称不能为空。
2. 调用后端新增库位接口。
3. 新增成功后重新查询库位下拉。
4. 将新库位流水号自动赋值给 `transferForm.目标货位流水号`
5. 提示“库位新增成功”。
接口建议:
```js
var Data = this.CreateData('12', '仓储管理_库位_增加', param)
```
参数建议:
| 参数名 | 说明 |
| --- | --- |
| 货位名称 | 新库位名称 |
| UserID | 当前用户 |
| ModularID | 当前路由 |
如果后端已有通用库位新增接口,应优先复用现有接口,不重复新增存储过程。
## 5. 调拨业务规则
### 5.1 数量规则
调拨数量必须满足:
```text
0 < 调拨数量 <= 原库存数
```
前端校验:
```js
if (Number(this.transferForm.调拨数量) <= 0) {
this.$message.warning('调拨数量必须大于0')
return
}
if (Number(this.transferForm.调拨数量) > Number(this.transferForm.原库存数)) {
this.$message.warning('调拨数量不能大于原库存数')
return
}
```
后端也必须重复校验,避免多人同时操作导致库存被扣成负数。
### 5.2 库位规则
目标库位必须满足:
- 目标库位不能为空。
- 目标库位不能等于原库位。
- 新建库位名称不能与已有库位重复。
### 5.3 库存更新规则
提交调拨后,后端一次性完成两个动作:
```text
原库位库存 = 原库位库存 - 调拨数量
目标库位库存 = 目标库位库存 + 调拨数量
```
如果目标库位不存在该物料库存记录:
```text
新增 物料 + 目标库位 的库存记录,库存数 = 调拨数量
```
如果目标库位已存在该物料库存记录:
```text
更新目标库位库存数,库存数 = 原目标库位库存数 + 调拨数量
```
### 5.4 原库位库存为 0 的处理
调拨后如果原库位库存变为 0建议保留该物料货位记录并显示库存为 0。
原因:
- 便于追溯原库位曾经存在该物料。
- 避免删除记录影响历史盘点记录。
- 与当前盘点页面“库存数可为 0”的逻辑一致。
如果现场明确要求隐藏 0 库存,可以在查询接口中过滤,不建议物理删除。
## 6. 数据字段设计
### 6.1 前端弹窗对象
建议新增:
```js
transferForm: {
物料与货位流水号: '',
物料流水号: '',
物料名称: '',
图号或型号: '',
原货位流水号: '',
原货位名称: '',
原库存数: 0,
目标货位流水号: '',
目标货位名称: '',
新货位名称: '',
调拨数量: 1,
调拨备注: ''
}
```
### 6.2 后端调拨接口参数
建议新增一个原子接口,避免前端连续调用两个编辑接口导致只扣不加或只加不扣。
接口:
```js
var Data = this.CreateData('12', '仓储管理_库存盘点_库存调拨', param)
```
参数:
| 参数名 | 说明 |
| --- | --- |
| 物料与货位流水号 | 原库存记录流水号 |
| 物料流水号 | 当前物料流水号 |
| 原货位流水号 | 原库位流水号 |
| 目标货位流水号 | 目标库位流水号 |
| 调拨数量 | 本次调拨数量 |
| 原库存数 | 页面带出的原库存数,仅用于校验参考 |
| 调拨备注 | 调拨备注 |
| 操作人 | UserID |
后端处理必须放在同一个事务中:
1. 查询原库存记录,并锁定或重新校验当前库存。
2. 校验当前库存是否大于等于调拨数量。
3. 扣减原库位库存。
4. 查询目标库位是否已有同物料记录。
5. 有则累加目标库位库存。
6. 无则新增目标库位库存记录。
7. 写入库存调拨记录。
8. 返回成功。
## 7. 调拨记录设计
建议新增轻量级调拨记录表,便于盘点后追溯谁把多少库存从哪个库位调到哪个库位。
字段建议:
| 字段名 | 说明 |
| --- | --- |
| 库存调拨流水号 | 主键 |
| 物料流水号 | 物料流水号 |
| 物料名称 | 冗余名称,便于查询 |
| 图号或型号 | 冗余图号 |
| 原物料与货位流水号 | 原库存记录 |
| 原货位流水号 | 原库位 |
| 原货位名称 | 原库位名称 |
| 目标物料与货位流水号 | 目标库存记录 |
| 目标货位流水号 | 目标库位 |
| 目标货位名称 | 目标库位名称 |
| 调拨数量 | 调拨数量 |
| 调拨前原库存 | 扣减前原库位库存 |
| 调拨后原库存 | 扣减后原库位库存 |
| 调拨前目标库存 | 增加前目标库位库存 |
| 调拨后目标库存 | 增加后目标库位库存 |
| 调拨备注 | 备注 |
| 操作人 | UserID |
| 操作时间 | 调拨时间 |
查询接口建议:
```js
var Data = this.CreateData('11', '仓储管理_库存盘点_库存调拨记录_查询', param, this.pageSize, this.pageCurrent)
```
第一版可以不新增独立页面,只在库存盘点页面增加“调拨记录”按钮或弹窗。
## 8. API 设计
### 8.1 查询库位
沿用现有:
```js
var Data = this.CreateData('11', '仓储管理_库位_查询', param)
```
### 8.2 新增库位
建议新增或复用:
```js
var Data = this.CreateData('12', '仓储管理_库位_增加', param)
```
参数:
| 参数名 | 说明 |
| --- | --- |
| 货位名称 | 新库位名称 |
| 备注 | 可选 |
| UserID | 当前用户 |
返回:
| 字段 | 说明 |
| --- | --- |
| result | 是否成功 |
| 货位流水号 | 新增库位流水号 |
| 货位名称 | 新增库位名称 |
### 8.3 库存调拨
建议新增:
```js
var Data = this.CreateData('12', '仓储管理_库存盘点_库存调拨', param)
```
这是本功能最核心接口,必须由后端事务保证扣减和增加同时成功或同时失败。
### 8.4 调拨记录查询
建议新增:
```js
var Data = this.CreateData('11', '仓储管理_库存盘点_库存调拨记录_查询', param, this.pageSize, this.pageCurrent)
```
查询参数:
| 参数名 | 说明 |
| --- | --- |
| 物料名称_check | 是否按物料名称查询 |
| 物料名称 | 物料名称 |
| 图号或型号_check | 是否按图号查询 |
| 图号或型号 | 图号或型号 |
| 原货位流水号_check | 是否按原库位查询 |
| 原货位流水号 | 原库位 |
| 目标货位流水号_check | 是否按目标库位查询 |
| 目标货位流水号 | 目标库位 |
| 操作时间_check | 是否按时间查询 |
| 开始时间 | 开始时间 |
| 结束时间 | 结束时间 |
## 9. 前端方法设计
### 9.1 打开调拨弹窗
```js
openTransfer(row) {
if (Number(row.库存) <= 0) {
this.$message.warning('当前库位库存为0不能调拨')
return
}
this.transferForm.物料与货位流水号 = row.物料与货位流水号
this.transferForm.物料流水号 = row.物料流水号
this.transferForm.物料名称 = row.物料名称
this.transferForm.图号或型号 = row.图号或型号
this.transferForm.原货位流水号 = row.货位流水号
this.transferForm.原货位名称 = row.货位名称
this.transferForm.原库存数 = Number(row.库存)
this.transferForm.目标货位流水号 = ''
this.transferForm.目标货位名称 = ''
this.transferForm.新货位名称 = ''
this.transferForm.调拨数量 = 1
this.transferForm.调拨备注 = ''
this.transferDialogVisible = true
}
```
### 9.2 新建库位
```js
addTransferLocation() {
if (!this.transferForm.新货位名称) {
this.$message.warning('请输入新库位名称')
return
}
var param = []
param[0] = ['货位名称', this.transferForm.新货位名称]
var Data = this.CreateData('12', '仓储管理_库位_增加', param)
this.ExecDatabase(Data).then(response => {
if (response.data && response.data.length > 0) {
this.getStorageLocation()
this.transferForm.目标货位流水号 = response.data[0].货位流水号
this.$message.success('库位新增成功')
}
})
}
```
说明:具体返回结构以现有后端为准,若只返回成功标识,则新增后通过库位名称重新查询并回填。
### 9.3 提交调拨
```js
submitTransfer() {
if (!this.transferForm.目标货位流水号) {
this.$message.warning('请选择目标库位')
return
}
if (this.transferForm.目标货位流水号 === this.transferForm.原货位流水号) {
this.$message.warning('目标库位不能与原库位相同')
return
}
if (Number(this.transferForm.调拨数量) <= 0) {
this.$message.warning('调拨数量必须大于0')
return
}
if (Number(this.transferForm.调拨数量) > Number(this.transferForm.原库存数)) {
this.$message.warning('调拨数量不能大于原库存数')
return
}
var param = []
param[0] = ['物料与货位流水号', this.transferForm.物料与货位流水号]
param[1] = ['物料流水号', this.transferForm.物料流水号]
param[2] = ['原货位流水号', this.transferForm.原货位流水号]
param[3] = ['目标货位流水号', this.transferForm.目标货位流水号]
param[4] = ['调拨数量', this.transferForm.调拨数量]
param[5] = ['原库存数', this.transferForm.原库存数]
param[6] = ['调拨备注', this.transferForm.调拨备注]
var Data = this.CreateData('12', '仓储管理_库存盘点_库存调拨', param)
this.ExecDatabase(Data).then(response => {
this.$message.success('调拨成功')
this.transferDialogVisible = false
this.searchTable()
})
}
```
## 10. 后端事务逻辑
后端存储过程建议逻辑:
```text
开始事务
查询原物料货位库存记录
如果不存在,返回“原库存记录不存在”
如果当前库存 < 调拨数量,返回“库存不足”
如果原货位流水号 = 目标货位流水号,返回“目标库位不能与原库位相同”
更新原库位库存 = 当前库存 - 调拨数量
查询目标货位是否存在同物料库存记录
如果存在:
更新目标库位库存 = 当前目标库存 + 调拨数量
如果不存在:
新增目标货位库存记录,库存 = 调拨数量
写入库存调拨记录
提交事务
```
任何一步失败必须回滚,避免库存只扣不加。
## 11. 与现有编辑库存功能的关系
当前库存盘点页面已有“编辑库存数”和“编辑库位”的能力:
```js
var Data = this.CreateData('12', '仓储管理_库存盘点_货位数量_编辑数据', param)
```
新调拨功能不建议复用前端两次调用该接口来完成扣减和增加,因为:
- 两次请求中间失败会造成库存不一致。
- 多人并发时容易出现负库存。
- 目标库位不存在同物料记录时还需要新增记录。
因此建议新增一个后端原子接口:
```text
仓储管理_库存盘点_库存调拨
```
该接口内部统一完成扣减、增加、新增目标记录、写调拨记录。
## 12. 实施步骤
1. 后端新增或确认库位新增接口:`仓储管理_库位_增加`
2. 后端新增库存调拨接口:`仓储管理_库存盘点_库存调拨`
3. 后端新增库存调拨记录表。
4. 后端新增库存调拨记录查询接口。
5. 前端 `InventoryCheck/index.vue` 增加“调拨”按钮。
6. 前端增加调拨弹窗和 `transferForm`
7. 前端增加“一键新建库位”方法。
8. 前端增加“确定调拨”方法。
9. 调拨成功后调用 `searchTable()` 刷新盘点列表。
10. 联调库存扣减、目标库位增加、目标库位不存在时新增记录。
## 13. 风险点
### 13.1 并发扣减风险
盘点期间多人可能同时调拨同一库位库存。后端必须以数据库当前库存为准,不能只相信前端传入的 `原库存数`
### 13.2 目标库位重复风险
一键新建库位时需要校验 `货位名称` 是否已存在。若已存在,应直接提示或返回已有库位,不应重复新增同名库位。
### 13.3 只扣不加风险
调拨不能由前端拆成“编辑原库存”和“新增目标库存”两个独立请求。必须由一个后端事务接口完成。
### 13.4 数据追溯风险
虽然不做完整调拨单,也必须保留调拨记录,记录调拨前后库存、原库位、目标库位、操作人和时间。
## 14. 总结
本方案将库存调拨限定在库存盘点组件内,采用“行内调拨弹窗 + 一键新建库位 + 后端事务扣减/增加库存”的轻量设计。用户在盘点时选择一行库存,输入调拨数量和目标库位,系统直接将调拨数量从原库位库存中减掉,并增加到目标库位库存中。
关键点是新增一个原子后端接口 `仓储管理_库存盘点_库存调拨`,避免前端多次请求造成库存不一致。同时保留调拨记录,满足后续盘点追溯。

Binary file not shown.

View File

@@ -0,0 +1,521 @@
# 车间派工移动端自适应设计方案
## 1. 需求目标
需求:车间需求一个车间派工组件的移动端功能,车间内及时操作
本次方案包含两部分:
1. 将现有车间派工组件复制并改造为移动端自适应页面。
2. 移动端用户登录系统后,首页只显示该自适应派工页面,不显示桌面端首页、侧边栏、顶部导航和标签栏。
总体原则:
- 不影响现有 PC 端车间派工页面。
- 不修改后端接口和参数格式。
- 移动端只改交互和布局,业务逻辑尽量复用现有页面。
- 保持 Vue 2 + Element UI + Options API 写法。
## 2. 当前代码基础
现有车间派工页面:
```text
src/views/SeikoWorkshop/WorkshopAssignment/index.vue
```
现有登录后首页:
```text
src/views/dashboard/index.vue
```
现有主布局:
```text
src/views/layout/Layout.vue
src/views/layout/components/AppMain.vue
```
现有动态路由生成:
```text
src/router/getRouter.js
src/permission.js
```
现有设备判断逻辑:
```text
src/views/layout/mixin/ResizeHandler.js
src/store/modules/app.js
```
项目中已有类似移动端/滑动版页面命名示例:
```text
src/views/AssemblyManagement/AssemblyExecutionSliding/index.vue
src/views/AssemblyManagement/ReceiveAssemblyTaskSliding/index.vue
src/views/AssemblyManagement/ReplenishmentOrdersSliding/index.vue
```
因此本次建议采用“新增独立移动端页面”的方式,而不是直接改造现有 PC 页面。
## 3. 总体设计
新增移动端页面:
```text
src/views/SeikoWorkshop/WorkshopAssignmentMobile/index.vue
```
新增移动端空布局:
```text
src/views/layout/MobileLayout.vue
```
新增设备判断工具:
```text
src/utils/device.js
```
修改路由配置:
```text
src/router/index.js
```
修改登录后跳转逻辑:
```text
src/permission.js
```
移动端访问路径建议为:
```text
/mobile/workshop-assignment
```
PC 端继续使用现有动态菜单路径:
```text
/SeikoWorkshop/WorkshopAssignment
```
## 4. 移动端页面结构设计
现有 PC 页面是左右两栏布局:
- 左侧:订单/零件待派工列表。
- 右侧:选中零件后的工序派工列表。
移动端不适合继续使用左右两栏和大表格,建议改为纵向流程。
### 4.1 顶部筛选区
移动端顶部展示查询条件:
- 订单号
- 产品/零件名称
- 名称或图号
- 查询按钮
- 查看图纸按钮
- 加急/取消加急按钮
- 手动报废结单按钮,按原权限控制
布局方式:
- 筛选项纵向排列。
- 输入框、下拉框宽度 `100%`
- 操作按钮使用两列或满宽布局。
- 顶部筛选区可固定,也可随页面滚动。第一版建议随页面滚动,避免遮挡内容。
### 4.2 待派工零件列表
将 PC 端左侧 `el-table` 改为卡片列表。
每张卡片展示核心字段:
- 订单号
- 产品名称
- 零件图号
- 零件名称
- 数量
- 毛坯库存
- 下达日期
- 完工期限
- 订单备注
- 技术备注
交互:
- 点击卡片后调用现有行点击逻辑,加载该零件的工序列表。
- 当前选中卡片需要有明显选中态。
- 列表底部保留分页,移动端分页建议简化为“上一页 / 下一页 / 当前页”。
### 4.3 工序派工列表
将 PC 端右侧工序表格改为工序卡片列表。
每张工序卡片展示:
- 工序顺序
- 工序名称
- 投产数
- 完成数
- 操作者
- 报废数量
- 加工设备
- 派工状态
卡片操作按钮:
- 编辑
- 派工
- 取消派工
按钮禁用条件沿用现有 PC 页面判断逻辑。
### 4.4 派工编辑区
移动端保留人员和设备选择:
- 操作者
- 设备
- 派工数量
- 计划完成日期
建议使用 `el-dialog` 或底部弹层形式。
Element UI 项目中现有弹窗较多,第一版建议继续使用 `el-dialog`,移动端适配如下:
```vue
<el-dialog :visible.sync="dialogVisible" width="94%" top="5vh">
```
表单布局:
- `el-form-item` 纵向排列。
- `el-select``el-input``el-date-picker``el-input-number` 宽度统一 `100%`
- 底部按钮固定为“取消 / 确定”。
### 4.5 文件和图纸查看
现有页面中图纸、文件查看逻辑继续保留。
移动端展示方式:
- 文件使用纵向列表。
- 每个文件展示图标、文件名。
- 点击后沿用现有下载/预览地址。
- 弹窗宽度 `94%`
## 5. 业务接口复用
移动端页面不新增后端接口,复用现有车间派工页面中的请求。
主要请求包括:
```text
精工车间_车间派工_查询
车间生产管理工艺_零件工序_已派工查询
车间生产管理工艺_零件工序_派工_工序查询
车间生产管理工艺_零件工序_派工
车间生产管理工艺_零件工序_取消派工
车间生产管理工艺_零件工序_派工_修改数量
车间生产管理工艺_零件工序_派工_设置计划完成日期
人事档案管理_人员_部门与人员_派工_查询数据_根据部门编号
车间派工_手动报废结单_查询信息
车间派工_手动报废结单
```
请求规范继续遵守项目约定:
- 统一 POST 到 `MESCommonBase.ashx`
- `url` 字段留空。
- 使用 `CreateData` 构建请求。
- 使用 `ExecDatabase` 或现有全局工具方法发送请求。
- 参数继续使用 `key=value&key2=value2` 字符串。
- 字段名继续使用后端返回的中文字段。
## 6. 路由设计
### 6.1 新增移动端空布局
新增文件:
```text
src/views/layout/MobileLayout.vue
```
职责:
- 不显示侧边栏。
- 不显示顶部导航。
- 不显示标签栏。
- 只渲染当前移动端页面。
结构示例:
```vue
<template>
<section class="mobile-main">
<router-view/>
</section>
</template>
<script>
export default {
name: 'MobileLayout'
}
</script>
<style scoped>
.mobile-main {
min-height: 100vh;
width: 100%;
background: #f5f7fa;
overflow-x: hidden;
}
</style>
```
### 6.2 新增静态隐藏路由
修改:
```text
src/router/index.js
```
新增:
```js
import MobileLayout from '../views/layout/MobileLayout'
```
`constantRouterMap` 中增加:
```js
{
path: '/mobile',
component: MobileLayout,
hidden: true,
children: [{
path: 'workshop-assignment',
component: () => import('@/views/SeikoWorkshop/WorkshopAssignmentMobile/index'),
meta: { title: '车间派工' }
}]
}
```
最终移动端首页路径:
```text
/mobile/workshop-assignment
```
## 7. 移动端登录后首页跳转设计
新增工具:
```text
src/utils/device.js
```
内容:
```js
export function isMobileDevice() {
if (!document || !document.body) {
return false
}
return document.body.getBoundingClientRect().width < 1024
}
```
修改:
```text
src/permission.js
```
在已登录逻辑中增加判断:
- 用户已登录。
- 当前目标路径是 `/``/dashboard`
- 当前设备为移动端。
- 自动跳转 `/mobile/workshop-assignment`
设计示例:
```js
import { isMobileDevice } from '@/utils/device'
// beforeEach 内部,已登录分支中
if ((to.path === '/' || to.path === '/dashboard') && isMobileDevice()) {
next({ path: '/mobile/workshop-assignment', replace: true })
NProgress.done()
return
}
```
这样移动端登录后不会进入桌面首页,而是直接进入移动端派工页。
## 8. 样式设计
移动端页面样式建议:
- 根节点使用 `.mobile-assignment-page`
- 页面最小高度 `100vh`
- 主背景使用浅灰色。
- 卡片使用白底、细边框、轻阴影。
- 卡片圆角控制在 `6px``8px`
- 字号保持可读,不使用随视口缩放的字体。
- 所有按钮、输入框高度适合触摸操作。
- 避免横向滚动。
建议结构:
```scss
.mobile-assignment-page {
min-height: 100vh;
padding: 10px;
background: #f5f7fa;
}
.mobile-filter {
background: #fff;
border-radius: 6px;
padding: 10px;
margin-bottom: 10px;
}
.assignment-card {
background: #fff;
border: 1px solid #ebeef5;
border-radius: 6px;
padding: 10px;
margin-bottom: 10px;
}
.assignment-card.is-active {
border-color: #409EFF;
}
.card-title {
font-size: 15px;
font-weight: bold;
color: #303133;
}
.card-row {
display: flex;
justify-content: space-between;
line-height: 24px;
font-size: 13px;
}
.card-label {
color: #909399;
}
.card-value {
color: #303133;
text-align: right;
}
```
## 9. 实施步骤
1. 新建 `src/views/SeikoWorkshop/WorkshopAssignmentMobile/index.vue`
2.`WorkshopAssignment/index.vue` 复制业务数据、方法和接口调用。
3. 将模板改为移动端筛选区、零件卡片列表、工序卡片列表。
4. 将弹窗宽度、表单布局和按钮布局改为移动端适配。
5. 新建 `src/views/layout/MobileLayout.vue`
6. 新建 `src/utils/device.js`
7. 修改 `src/router/index.js`,增加 `/mobile/workshop-assignment` 静态隐藏路由。
8. 修改 `src/permission.js`,移动端登录后访问 `/``/dashboard` 时跳转移动端派工页。
9. 本地运行项目,分别验证 PC 和移动端宽度。
## 10. 验收标准
PC 端:
- 原车间派工页面正常访问。
- 原首页正常显示。
- 原动态菜单不受影响。
移动端:
- 登录后自动进入 `/mobile/workshop-assignment`
- 页面不显示侧边栏、顶部导航、标签栏。
- 页面只显示移动端车间派工自适应页面。
- 查询条件可正常使用。
- 零件列表可正常加载和分页。
- 点击零件后可加载工序列表。
- 派工、取消派工、编辑数量、设置计划完成日期功能正常。
- 查看图纸和文件功能正常。
- 权限按钮显示逻辑与 PC 端一致。
- 页面无明显横向滚动、文字重叠、按钮遮挡。
## 11. 风险与控制
### 11.1 现有页面体量较大
风险:
- 直接抽公共逻辑可能引入 PC 页面回归问题。
控制:
- 第一版复制现有页面业务逻辑,只重写移动端模板。
- 待移动端稳定后,再考虑抽公共 mixin。
### 11.2 移动端首页跳转时机
风险:
- `Layout` 中的设备判断发生较晚,登录跳转时可能还未写入 Vuex。
控制:
-`permission.js` 中直接使用 DOM 宽度判断,不依赖 Vuex 中的 `device`
### 11.3 动态菜单权限
风险:
- 移动端隐藏路由如果依赖后端菜单,可能因为菜单未配置导致无法访问。
控制:
- 将移动端派工路由注册为静态隐藏路由。
- 登录后仍经过 token 校验,但不依赖菜单显示。
### 11.4 手机端表格不可用
风险:
- 继续使用大表格会产生横向滚动,操作困难。
控制:
- 移动端核心列表统一改为卡片式展示。
- 表格只在确实需要多列批量选择时使用,并控制宽度。
## 12. 推荐结论
建议第一版采用“独立移动端页面 + 移动端空布局 + 登录后设备重定向”的实现方式。
该方案改动边界清晰:
- PC 端页面不动。
- 后端接口不动。
- 权限体系基本不动。
- 移动端首页可直接进入派工工作流。
后续如果移动端使用稳定,再将 PC 和移动端共用的派工请求、字段处理、校验逻辑抽成公共 mixin减少长期维护成本。

View File

@@ -0,0 +1,477 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>零件改制功能设计方案</title>
<style>
@page { size: A4; margin: 18mm 16mm; }
body {
font-family: "Microsoft YaHei", "SimSun", Arial, sans-serif;
color: #1f2933;
font-size: 13px;
line-height: 1.65;
}
h1 {
font-size: 26px;
text-align: center;
margin: 0 0 24px;
padding-bottom: 12px;
border-bottom: 2px solid #2f80ed;
}
h2 {
font-size: 19px;
margin: 24px 0 10px;
padding-left: 8px;
border-left: 4px solid #2f80ed;
page-break-after: avoid;
}
h3 {
font-size: 16px;
margin: 18px 0 8px;
page-break-after: avoid;
}
p { margin: 7px 0; }
ul { margin: 6px 0 10px 22px; padding: 0; }
li { margin: 3px 0; }
table {
width: 100%;
border-collapse: collapse;
margin: 10px 0 16px;
page-break-inside: avoid;
}
th, td {
border: 1px solid #cbd5e1;
padding: 6px 8px;
text-align: left;
vertical-align: top;
word-break: break-word;
}
th {
background: #eef4ff;
font-weight: 600;
}
code {
font-family: Consolas, "Microsoft YaHei", monospace;
background: #f3f4f6;
padding: 1px 4px;
border-radius: 3px;
}
pre {
background: #f8fafc;
border: 1px solid #d8dee9;
padding: 10px;
overflow-wrap: break-word;
white-space: pre-wrap;
page-break-inside: avoid;
}
figure {
margin: 14px 0 20px;
page-break-inside: avoid;
}
figure img {
display: block;
width: 100%;
max-width: 100%;
height: auto;
border: 1px solid #d8dee9;
}
figcaption {
margin-top: 6px;
color: #64748b;
font-size: 12px;
text-align: center;
}
</style>
</head>
<body>
<h1>零件改制功能设计方案</h1>
<h2>0. 需求背景</h2>
<h3>0.1 需求提出</h3>
<p>本需求由罗总牵头,组织技术中心、精工车间、仓储等相关部门讨论后提出。</p>
<h3>0.2 提出原因</h3>
<p>当前现场存在零件改制业务,但改制过程尚未完整纳入系统管理。由于现场计件、派工生产、完工入库和后续统计都需要明确的数据来源,原有线下记录或零散流转方式无法满足计件核算、过程追溯和部门协同要求。</p>
<p>因此,需要在系统内补充零件改制订单流程,将改制订单从技术中心发起、精工车间派工生产到完工入库的全过程纳入系统管理。</p>
<h3>0.3 应用场景</h3>
<p>本功能主要应用于以下场景:</p>
<ul><li>技术中心根据现场或订单需求发起零件改制订单。</li><li>精工车间根据改制订单制定工艺、派工生产。</li><li>改制订单涉及非毛坯物料时,由系统生成领料单并交由仓库出库。</li><li>改制加工完成后,按现有流程办理入库。</li><li>现场计件、生产统计、入库记录和后续追溯均以系统内改制订单数据为依据。</li></ul>
<h2>1. 需求目标</h2>
<p>基于项目现有精工车间生产流程,新增“零件改制”业务。</p>
<p>本次方案调整为:</p>
<ul><li>在技术中心新增组件发起改制订单。</li><li>改制订单生成后进入现有精工车间生产任务流程。</li><li>精工车间生产任务查询组件可以查看改制订单。</li><li>车间派工组件可以查看改制订单并继续派工。</li><li>新增改制记录查询,用于查看改制订单的发起、生产、派工、领料和完工状态。</li><li>领料时根据改制订单和物料来源判断是否生成领料单。</li></ul>
<p>核心原则:</p>
<ul><li>技术中心负责发起改制订单。</li><li>精工车间复用现有生产任务、工艺、派工、加工流程。</li><li>仓储只在需要额外领用非毛坯物料时介入。</li><li>改制记录独立查询,但状态关联现有生产任务状态。</li></ul>
<h2>2. 现有流程承接关系</h2>
<p>根据项目现有页面,改制订单应承接以下流程:</p>
<table>
<thead><tr><th>流程节点</th><th>现有承接页面</th><th>说明</th></tr></thead>
<tbody>
<tr><td>技术发起</td><td>技术中心新增页面</td><td>发起改制订单,填写改制要求</td></tr>
<tr><td>生成任务</td><td>精工车间生产任务查询</td><td>改制订单进入生产任务列表</td></tr>
<tr><td>制定工艺</td><td>精工车间制定工艺</td><td>可复用或复制原工艺后调整</td></tr>
<tr><td>车间派工</td><td>精工车间车间派工</td><td>工艺完成后派工</td></tr>
<tr><td>领料判断</td><td>领料/仓储出库流程</td><td>根据物料类型决定是否生成领料单</td></tr>
<tr><td>加工执行</td><td>精工车间现有加工流程</td><td>扫码、报工、质检等复用现有逻辑</td></tr>
<tr><td>入库</td><td>仓储入库流程</td><td>改制完工后按现有流程办理入库</td></tr>
<tr><td>记录查询</td><td>改制记录查询</td><td>查看改制全流程</td></tr>
</tbody>
</table>
<figure><img src="零件改制流程图.svg" alt="零件改制业务流程图"><figcaption>零件改制业务流程图</figcaption></figure>
<h2>3. 页面设计</h2>
<h3>3.1 技术中心新增页面:改制订单发起</h3>
<p>建议路径:</p>
<pre><code>src/views/TechnologyCenter/PartModificationOrder/index.vue</code></pre>
<p>页面名称:</p>
<pre><code>改制订单发起</code></pre>
<p>归属模块:</p>
<pre><code>技术中心</code></pre>
<p>主要功能:</p>
<ul><li>查询需要改制的原订单、原零件或原自制件。</li><li>发起改制订单。</li><li>填写改制后零件信息、改制数量、改制原因、技术要求。</li><li>指定是否使用原件改制、毛坯改制或其他物料改制。</li><li>提交后生成改制订单,并进入精工车间生产任务查询。</li></ul>
<h3>3.2 精工车间修改页面:生产任务查询</h3>
<p>现有路径:</p>
<pre><code>src/views/SeikoWorkshop/ProductionTaskQuery/index.vue</code></pre>
<p>需要支持:</p>
<ul><li>查询改制订单生成的生产任务。</li><li>增加任务类型筛选。</li><li>增加任务类型列。</li><li>改制任务显示 <code>改制</code> 标识。</li><li>改制任务继续使用现有 <code>工艺</code><code>派工</code> 按钮。</li></ul>
<h3>3.3 精工车间修改页面:车间派工</h3>
<p>现有路径:</p>
<pre><code>src/views/SeikoWorkshop/WorkshopAssignment/index.vue</code></pre>
<p>需要支持:</p>
<ul><li>查询改制订单对应的待派工任务。</li><li>增加任务类型筛选。</li><li>增加任务类型列。</li><li>复用现有已派工查询、待派工工序查询、派工、取消派工逻辑。</li></ul>
<h3>3.4 新增页面:改制记录查询</h3>
<p>建议路径:</p>
<pre><code>src/views/TechnologyCenter/PartModificationRecord/index.vue</code></pre>
<p>也可以放在精工车间模块,建议最终按业务归属确认。</p>
<p>页面名称:</p>
<pre><code>改制记录查询</code></pre>
<p>主要功能:</p>
<ul><li>查询改制订单记录。</li><li>查看改制订单状态。</li><li>查看是否生成领料单。</li><li>查看仓库是否已出库。</li><li>查看精工生产任务、工艺、派工、完工状态。</li><li>支持跳转生产任务查询、车间派工、零件追溯。</li></ul>
<h2>4. 改制订单类型</h2>
<p>改制订单需要明确物料来源,建议增加字段:</p>
<pre><code>改制来源类型</code></pre>
<p>建议枚举:</p>
<table>
<thead><tr><th>改制来源类型</th><th>说明</th><th>是否生成领料单</th></tr></thead>
<tbody>
<tr><td>原现自制订单</td><td>使用原现有自制订单零件进行改制</td><td></td></tr>
<tr><td>毛坯改制</td><td>直接使用已有毛坯进行改制</td><td></td></tr>
<tr><td>非毛坯物料改制</td><td>使用仓库其他物料、半成品或成品改制</td><td></td></tr>
</tbody>
</table>
<p>说明:</p>
<ul><li>“原现自制订单”指当前已经存在的自制订单或自制零件,改制时不需要额外从仓库领料。</li><li>“毛坯改制”指直接使用毛坯进行改制,不额外生成领料单。</li><li>“非毛坯物料改制”指改制需要领用库存中的非毛坯物料,需要生成领料单并由仓库出库。</li></ul>
<h2>5. 领料规则</h2>
<h3>5.1 领料判断条件</h3>
<p>领料时增加判断:</p>
<pre><code>如果是改制订单,并且使用的物料不是毛坯,则生成领料单,由仓库物料出库。
如果是原现自制订单改制,或者直接使用毛坯改制,则不生成领料单。</code></pre>
<p>规则可表达为:</p>
<pre><code>是否生成领料单 =
是否改制订单 === 1
且 改制来源类型 === 非毛坯物料改制
且 是否毛坯 !== 1</code></pre>
<h3>5.2 生成领料单场景</h3>
<p>以下场景需要生成领料单:</p>
<ul><li>改制订单使用库存半成品。</li><li>改制订单使用库存成品。</li><li>改制订单使用其他非毛坯物料。</li><li>改制订单指定的物料需要仓库出库。</li></ul>
<p>生成后流程:</p>
<p>1. 技术中心发起改制订单。 2. 系统判断需要领料。 3. 生成领料单。 4. 仓库根据领料单出库。 5. 出库完成后,精工车间继续生产、工艺、派工。</p>
<h3>5.3 不生成领料单场景</h3>
<p>以下场景不生成领料单:</p>
<ul><li>原现自制订单改制。</li><li>直接使用毛坯改制。</li><li>改制对象已经在精工车间现场,不需要仓库出库。</li></ul>
<p>不生成领料单时:</p>
<ul><li>改制订单直接进入精工生产任务。</li><li>生产任务查询可查看。</li><li>车间派工可查看并派工。</li></ul>
<h3>5.4 领料状态字段</h3>
<p>建议改制订单增加以下字段:</p>
<table>
<thead><tr><th>字段名</th><th>说明</th></tr></thead>
<tbody>
<tr><td>是否需要领料</td><td>1 是0 否</td></tr>
<tr><td>是否已生成领料单</td><td>1 是0 否</td></tr>
<tr><td>领料单号</td><td>生成的领料单编号</td></tr>
<tr><td>领料状态</td><td>未生成、待出库、已出库、已取消</td></tr>
<tr><td>出库日期</td><td>仓库出库日期</td></tr>
<tr><td>出库人</td><td>仓库操作人</td></tr>
</tbody>
</table>
<h2>6. 业务流程</h2>
<h3>6.1 技术中心发起改制订单</h3>
<p>用户进入技术中心“改制订单发起”页面。</p>
<p>查询原始数据:</p>
<ul><li>订单编号</li><li>产品/部件名称</li><li>零件名称</li><li>图号</li><li>原自制订单</li><li>库存物料</li><li>毛坯物料</li></ul>
<p>发起改制时填写:</p>
<ul><li>改制订单号</li><li>原订单编号</li><li>原零件名称</li><li>原零件图号</li><li>改制零件名称</li><li>改制零件图号</li><li>改制数量</li><li>改制来源类型</li><li>是否毛坯</li><li>物料编号</li><li>物料名称</li><li>改制原因</li><li>改制要求</li><li>技术备注</li><li>精工期限</li></ul>
<p>提交时校验:</p>
<ul><li>改制数量必须大于 0。</li><li>改制来源类型不能为空。</li><li>改制原因不能为空。</li><li>改制要求不能为空。</li><li>精工期限不能为空。</li><li>如果来源类型为非毛坯物料改制,必须选择物料编号。</li></ul>
<h3>6.2 后端生成改制订单</h3>
<p>提交后,后端需要同时处理:</p>
<ul><li>写入改制订单主记录。</li><li>根据改制来源类型判断是否生成领料单。</li><li>生成精工车间生产任务。</li><li>写入任务类型为 <code>改制</code></li><li>关联改制订单号和新工艺计划流水号。</li></ul>
<h3>6.3 进入精工车间生产任务查询</h3>
<p>改制订单生成后,应能在现有接口中查到:</p>
<pre><code>精工车间_生成任务_查询数据</code></pre>
<p>建议返回字段增加:</p>
<ul><li>任务类型</li><li>是否改制</li><li>改制订单号</li><li>改制来源类型</li><li>是否需要领料</li><li>领料状态</li><li>改制原因</li><li>改制要求</li></ul>
<p>生产任务查询页面显示:</p>
<ul><li><code>任务类型 = 改制</code></li><li><code>是否需要领料 = 1</code><code>领料状态 !== 已出库</code>,可显示领料状态提示。</li></ul>
<p>是否允许工艺/派工,需要按业务决定:</p>
<ul><li>如果非毛坯物料改制必须先出库,建议未出库前允许制定工艺,但不允许派工。</li><li>如果现场允许先派工后补出库,则只做提示,不阻断派工。</li></ul>
<p>建议采用更稳妥规则:</p>
<pre><code>需要领料且未出库:允许制定工艺,不允许派工。
不需要领料:正常工艺、派工。
需要领料且已出库:正常工艺、派工。</code></pre>
<h3>6.4 制定工艺</h3>
<p>改制订单在生产任务查询中点击 <code>工艺</code>,进入现有:</p>
<pre><code>/SeikoWorkshop/DevelopProcess</code></pre>
<p>工艺规则:</p>
<ul><li>改制订单必须生成新的工艺计划流水号。</li><li>不覆盖原自制订单或原零件工艺。</li><li>可支持从原工艺复制后调整。</li><li>工艺保存后,任务状态进入 <code>工艺完成</code></li></ul>
<h3>6.5 车间派工</h3>
<p>工艺完成后进入现有车间派工页面:</p>
<pre><code>src/views/SeikoWorkshop/WorkshopAssignment/index.vue</code></pre>
<p>现有查询接口:</p>
<pre><code>精工车间_车间派工_查询</code></pre>
<p>改制订单派工前判断:</p>
<ul><li>不需要领料:允许派工。</li><li>需要领料且已出库:允许派工。</li><li>需要领料但未出库:禁止派工,并提示“改制订单物料未出库,不能派工”。</li></ul>
<p>派工明细继续复用现有接口:</p>
<pre><code>车间生产管理工艺_零件工序_已派工查询
车间生产管理工艺_零件工序_派工_工序查询
车间生产管理工艺_零件工序_派工
车间生产管理工艺_零件工序_取消派工</code></pre>
<h3>6.6 仓库出库</h3>
<p>当改制订单需要领料时,系统生成领料单。</p>
<p>仓库根据领料单完成出库后,需要回写:</p>
<ul><li>领料状态 = 已出库</li><li>出库日期</li><li>出库人</li><li>出库数量</li></ul>
<p>出库完成后,精工车间派工限制解除。</p>
<h3>6.7 加工和完工</h3>
<p>改制订单派工后,继续走现有精工车间加工流程:</p>
<ul><li>工序派工</li><li>扫码加工</li><li>完工报工</li><li>质检</li><li>零件追溯</li><li>工时统计</li></ul>
<p>完工后改制记录状态同步为:</p>
<pre><code>已完成</code></pre>
<h2>7. 数据字段设计</h2>
<h3>7.1 改制订单主记录字段</h3>
<table>
<thead><tr><th>字段名</th><th>说明</th></tr></thead>
<tbody>
<tr><td>改制订单号</td><td>改制业务编号</td></tr>
<tr><td>原订单编号</td><td>原订单编号</td></tr>
<tr><td>原订单流水号</td><td>原订单流水号</td></tr>
<tr><td>原组件流水号</td><td>原组件流水号</td></tr>
<tr><td>原基本件流水号</td><td>原零件流水号</td></tr>
<tr><td>原工艺计划流水号</td><td>原工艺计划流水号</td></tr>
<tr><td>原零件名称</td><td>改制前零件名称</td></tr>
<tr><td>原零件图号</td><td>改制前零件图号</td></tr>
<tr><td>原数量</td><td>原数量</td></tr>
<tr><td>改制零件名称</td><td>改制后零件名称</td></tr>
<tr><td>改制零件图号</td><td>改制后零件图号</td></tr>
<tr><td>改制数量</td><td>改制数量</td></tr>
<tr><td>改制来源类型</td><td>原现自制订单、毛坯改制、非毛坯物料改制</td></tr>
<tr><td>是否毛坯</td><td>1 是0 否</td></tr>
<tr><td>物料编号</td><td>使用物料编号</td></tr>
<tr><td>物料名称</td><td>使用物料名称</td></tr>
<tr><td>物料流水号</td><td>使用物料流水号</td></tr>
<tr><td>是否需要领料</td><td>1 是0 否</td></tr>
<tr><td>是否已生成领料单</td><td>1 是0 否</td></tr>
<tr><td>领料单号</td><td>领料单编号</td></tr>
<tr><td>领料状态</td><td>未生成、待出库、已出库、已取消</td></tr>
<tr><td>改制原因</td><td>改制原因</td></tr>
<tr><td>改制要求</td><td>改制要求</td></tr>
<tr><td>技术备注</td><td>技术备注</td></tr>
<tr><td>精工期限</td><td>精工完工期限</td></tr>
<tr><td>新基本件流水号</td><td>改制任务生成的新零件流水号</td></tr>
<tr><td>新工艺计划流水号</td><td>改制任务生成的新工艺计划流水号</td></tr>
<tr><td>发起人</td><td>当前用户 ID</td></tr>
<tr><td>发起日期</td><td>发起时间</td></tr>
<tr><td>状态</td><td>改制订单状态</td></tr>
<tr><td>是否启用</td><td>逻辑删除标识</td></tr>
</tbody>
</table>
<h3>7.2 改制订单状态</h3>
<table>
<thead><tr><th>状态</th><th>说明</th></tr></thead>
<tbody>
<tr><td>待领料</td><td>需要领料,领料单未出库</td></tr>
<tr><td>待工艺</td><td>不需要领料或已出库,等待制定工艺</td></tr>
<tr><td>工艺完成</td><td>工艺已保存,等待派工</td></tr>
<tr><td>待派工</td><td>工艺完成且满足派工条件</td></tr>
<tr><td>加工中</td><td>已派工或已开始加工</td></tr>
<tr><td>已完成</td><td>改制任务完工</td></tr>
<tr><td>已取消</td><td>改制订单取消</td></tr>
</tbody>
</table>
<p>说明:</p>
<ul><li>如果不需要领料,提交后可直接进入 <code>待工艺</code></li><li>如果需要领料,提交后进入 <code>待领料</code></li><li>仓库出库后从 <code>待领料</code> 转为 <code>待工艺</code> 或保持生产任务状态,由查询时关联显示。</li></ul>
<h2>8. API 设计</h2>
<p>项目请求继续使用:</p>
<pre><code>this.CreateData(type, name, param, pageSize, pageCurrent)
this.ExecDatabase(Data)</code></pre>
<h3>8.1 技术中心查询可改制对象</h3>
<pre><code>var Data = this.CreateData('11', '技术中心_改制订单_可改制对象_查询', param, this.pageSize, this.pageCurrent)</code></pre>
<h3>8.2 技术中心发起改制订单</h3>
<pre><code>var Data = this.CreateData('12', '技术中心_改制订单_发起改制', param)</code></pre>
<p>参数建议:</p>
<table>
<thead><tr><th>参数名</th><th>说明</th></tr></thead>
<tbody>
<tr><td>原订单流水号</td><td>原订单流水号</td></tr>
<tr><td>原组件流水号</td><td>原组件流水号</td></tr>
<tr><td>原基本件流水号</td><td>原基本件流水号</td></tr>
<tr><td>原工艺计划流水号</td><td>原工艺计划流水号</td></tr>
<tr><td>原订单编号</td><td>原订单编号</td></tr>
<tr><td>原零件名称</td><td>原零件名称</td></tr>
<tr><td>原零件图号</td><td>原零件图号</td></tr>
<tr><td>改制零件名称</td><td>改制零件名称</td></tr>
<tr><td>改制零件图号</td><td>改制零件图号</td></tr>
<tr><td>改制数量</td><td>改制数量</td></tr>
<tr><td>改制来源类型</td><td>原现自制订单、毛坯改制、非毛坯物料改制</td></tr>
<tr><td>是否毛坯</td><td>是否毛坯</td></tr>
<tr><td>物料流水号</td><td>使用物料流水号</td></tr>
<tr><td>物料编号</td><td>物料编号</td></tr>
<tr><td>物料名称</td><td>物料名称</td></tr>
<tr><td>改制原因</td><td>改制原因</td></tr>
<tr><td>改制要求</td><td>改制要求</td></tr>
<tr><td>技术备注</td><td>技术备注</td></tr>
<tr><td>精工期限</td><td>精工期限</td></tr>
<tr><td>发起人</td><td>当前用户 ID</td></tr>
</tbody>
</table>
<p>后端处理结果:</p>
<ul><li>生成改制订单。</li><li>判断是否生成领料单。</li><li>生成精工生产任务。</li><li>返回 <code>result</code><code>改制订单号</code><code>领料单号</code><code>是否需要领料</code></li></ul>
<h3>8.3 改制记录查询</h3>
<pre><code>var Data = this.CreateData('11', '技术中心_改制订单_记录_查询', param, this.pageSize, this.pageCurrent)</code></pre>
<h3>8.4 改制订单详情</h3>
<pre><code>var Data = this.CreateData('11', '技术中心_改制订单_详情_查询', param)</code></pre>
<h3>8.5 取消改制订单</h3>
<pre><code>var Data = this.CreateData('12', '技术中心_改制订单_取消', param)</code></pre>
<p>取消前后端需要校验:</p>
<ul><li>未派工可以取消。</li><li>已派工未加工,需要先取消派工。</li><li>已加工、已有质检记录或已完成,不允许取消。</li><li>已生成领料单且已出库,不允许直接取消,需要走退料或异常处理。</li></ul>
<h2>9. 现有接口扩展</h2>
<h3>9.1 生产任务查询接口</h3>
<p>现有接口:</p>
<pre><code>精工车间_生成任务_查询数据</code></pre>
<p>新增查询参数:</p>
<table>
<thead><tr><th>参数名</th><th>说明</th></tr></thead>
<tbody>
<tr><td>任务类型\_check</td><td>是否按任务类型过滤</td></tr>
<tr><td>任务类型</td><td>全部、正常、改制、报废补投</td></tr>
<tr><td>领料状态\_check</td><td>是否按领料状态过滤</td></tr>
<tr><td>领料状态</td><td>待出库、已出库、不需要领料</td></tr>
</tbody>
</table>
<p>新增返回字段:</p>
<table>
<thead><tr><th>字段名</th><th>说明</th></tr></thead>
<tbody>
<tr><td>任务类型</td><td>正常、改制、报废补投</td></tr>
<tr><td>是否改制</td><td>1 是0 否</td></tr>
<tr><td>改制订单号</td><td>改制订单编号</td></tr>
<tr><td>改制来源类型</td><td>原现自制订单、毛坯改制、非毛坯物料改制</td></tr>
<tr><td>是否需要领料</td><td>1 是0 否</td></tr>
<tr><td>领料状态</td><td>未生成、待出库、已出库、已取消</td></tr>
<tr><td>领料单号</td><td>领料单号</td></tr>
<tr><td>改制原因</td><td>改制原因</td></tr>
<tr><td>改制要求</td><td>改制要求</td></tr>
</tbody>
</table>
<h3>9.2 车间派工查询接口</h3>
<p>现有接口:</p>
<pre><code>精工车间_车间派工_查询</code></pre>
<p>新增查询参数:</p>
<table>
<thead><tr><th>参数名</th><th>说明</th></tr></thead>
<tbody>
<tr><td>任务类型\_check</td><td>是否按任务类型过滤</td></tr>
<tr><td>任务类型</td><td>全部、正常、改制、报废补投</td></tr>
</tbody>
</table>
<p>新增返回字段:</p>
<table>
<thead><tr><th>字段名</th><th>说明</th></tr></thead>
<tbody>
<tr><td>任务类型</td><td>正常、改制、报废补投</td></tr>
<tr><td>是否改制</td><td>1 是0 否</td></tr>
<tr><td>改制订单号</td><td>改制订单编号</td></tr>
<tr><td>改制来源类型</td><td>改制来源类型</td></tr>
<tr><td>是否需要领料</td><td>1 是0 否</td></tr>
<tr><td>领料状态</td><td>领料状态</td></tr>
<tr><td>领料单号</td><td>领料单号</td></tr>
</tbody>
</table>
<p>派工前端限制:</p>
<pre><code>如果 是否改制 = 1 且 是否需要领料 = 1 且 领料状态 != 已出库,则不允许派工。</code></pre>
<h2>10. 前端交互调整</h2>
<h3>10.1 技术中心改制订单发起页面</h3>
<p>查询条件:</p>
<ul><li>订单编号</li><li>零件名称</li><li>图号</li><li>物料编号</li><li>物料名称</li><li>改制来源类型</li></ul>
<p>表格列:</p>
<ul><li>订单编号</li><li>产品/部件名称</li><li>零件名称</li><li>零件图号</li><li>数量</li><li>当前状态</li><li>来源类型</li><li>物料编号</li><li>物料名称</li><li>操作</li></ul>
<p>操作:</p>
<ul><li>发起改制</li><li>图纸</li><li>PLM传入工艺</li><li>追溯</li></ul>
<p>发起改制弹窗:</p>
<ul><li>原订单编号</li><li>原零件名称</li><li>原零件图号</li><li>改制零件名称</li><li>改制零件图号</li><li>改制数量</li><li>改制来源类型</li><li>是否毛坯</li><li>物料编号</li><li>物料名称</li><li>改制原因</li><li>改制要求</li><li>技术备注</li><li>精工期限</li></ul>
<h3>10.2 生产任务查询页面</h3>
<p>新增筛选:</p>
<pre><code>任务类型:全部 / 正常 / 改制 / 报废补投
领料状态:全部 / 不需要领料 / 待出库 / 已出库</code></pre>
<p>新增列:</p>
<ul><li>任务类型</li><li>改制订单号</li><li>改制来源类型</li><li>领料状态</li></ul>
<p>显示建议:</p>
<pre><code>&lt;el-tag type="warning" size="mini"&gt;改制&lt;/el-tag&gt;
&lt;el-tag type="danger" size="mini"&gt;待出库&lt;/el-tag&gt;
&lt;el-tag type="success" size="mini"&gt;已出库&lt;/el-tag&gt;
&lt;el-tag type="info" size="mini"&gt;不需要领料&lt;/el-tag&gt;</code></pre>
<h3>10.3 车间派工页面</h3>
<p>新增筛选:</p>
<pre><code>任务类型:全部 / 正常 / 改制 / 报废补投</code></pre>
<p>新增列:</p>
<ul><li>任务类型</li><li>改制订单号</li><li>领料状态</li></ul>
<p>派工按钮或派工操作前增加判断:</p>
<pre><code>if (Number(row.是否改制) === 1 &amp;&amp; Number(row.是否需要领料) === 1 &amp;&amp; row.领料状态 !== '已出库') {
this.$message.warning('改制订单物料未出库,不能派工')
return
}</code></pre>
<h3>10.4 改制记录查询页面</h3>
<p>查询条件:</p>
<ul><li>改制订单号</li><li>原订单编号</li><li>零件名称或图号</li><li>改制来源类型</li><li>领料状态</li><li>改制状态</li><li>发起日期</li><li>发起人</li></ul>
<p>表格列:</p>
<ul><li>改制订单号</li><li>状态</li><li>原订单编号</li><li>原零件名称</li><li>原零件图号</li><li>改制零件名称</li><li>改制零件图号</li><li>改制数量</li><li>改制来源类型</li><li>是否需要领料</li><li>领料单号</li><li>领料状态</li><li>改制原因</li><li>发起人</li><li>发起日期</li><li>精工期限</li><li>完成日期</li><li>操作</li></ul>
<p>操作:</p>
<ul><li>详情</li><li>生产任务</li><li>派工</li><li>追溯</li><li>取消</li></ul>
<h2>11. 菜单配置</h2>
<p>建议后端菜单配置:</p>
<pre><code>技术中心
改制订单发起
改制记录查询</code></pre>
<p>组件路径:</p>
<pre><code>TechnologyCenter/PartModificationOrder/index
TechnologyCenter/PartModificationRecord/index</code></pre>
<p>精工车间不新增发起入口,只扩展现有页面:</p>
<pre><code>SeikoWorkshop/ProductionTaskQuery/index
SeikoWorkshop/WorkshopAssignment/index</code></pre>
<h2>12. 实施顺序</h2>
<p>建议按以下顺序实施:</p>
<p>1. 后端新增改制订单主记录表。 2. 后端新增技术中心发起改制订单接口。 3. 后端在发起接口中加入领料判断规则。 4. 后端按规则生成或不生成领料单。 5. 后端生成标准精工生产任务,并标记 <code>任务类型 = 改制</code>。 6. 扩展生产任务查询接口,返回改制和领料字段。 7. 扩展车间派工查询接口,返回改制和领料字段。 8. 前端新增技术中心改制订单发起页面。 9. 前端新增改制记录查询页面。 10. 前端修改生产任务查询页面,增加任务类型和领料状态显示。 11. 前端修改车间派工页面,增加改制任务显示和派工前领料状态校验。 12. 联调从技术中心发起、领料判断、仓库出库、精工工艺、车间派工、加工完工、记录查询的完整流程。</p>
<h2>13. 风险点</h2>
<h3>13.1 领料判断风险</h3>
<p>改制订单是否生成领料单,必须以后端判断为准。</p>
<p>前端可以显示和提示,但不能只依赖前端判断,避免绕过仓库出库流程。</p>
<h3>13.2 派工前物料状态风险</h3>
<p>如果改制订单需要仓库出库,但尚未出库,直接派工会导致车间无物料加工。</p>
<p>建议车间派工接口或派工保存接口再次校验:</p>
<pre><code>需要领料且未出库,不允许派工。</code></pre>
<h3>13.3 原任务数据覆盖风险</h3>
<p>改制订单必须生成新的生产任务和新的工艺计划流水号。</p>
<p>不能直接覆盖原自制订单或原零件工艺,否则会影响原订单追溯、工时和质量记录。</p>
<h3>13.4 取消改制风险</h3>
<p>已生成领料单、已出库、已派工或已加工的改制订单取消规则需要严格控制。</p>
<p>建议:</p>
<ul><li>未出库、未派工:允许取消。</li><li>已出库:需要退料后取消。</li><li>已派工未加工:先取消派工再取消。</li><li>已加工:不允许取消,只能走异常处理。</li></ul>
<h3>13.5 统计口径风险</h3>
<p>改制订单进入精工生产任务后,会影响生产任务数量、工时统计、完工统计。</p>
<p>建议所有统计接口增加任务类型维度:</p>
<pre><code>正常
改制
报废补投</code></pre>
<h2>14. 总结</h2>
<p>本方案采用:</p>
<pre><code>技术中心发起改制订单,精工车间承接生产,仓库按需出库,改制记录统一查询。</code></pre>
<p>关键规则:</p>
<ul><li>技术中心新增组件发起改制订单。</li><li>改制订单生成后进入精工车间生产任务查询。</li><li>改制订单工艺和派工复用现有精工流程。</li><li>领料时如果是改制订单,并且使用物料不是毛坯,则生成领料单,由仓库物料出库。</li><li>如果是原现自制订单改制,或者直接使用毛坯改制,则不生成领料单。</li><li>改制记录查询独立展示全流程状态。</li></ul>
</body>
</html>

View File

@@ -0,0 +1,841 @@
# 零件改制功能设计方案
## 0. 需求背景
### 0.1 需求提出
本需求由罗总牵头,组织技术中心、精工车间、仓储等相关部门讨论后提出。
### 0.2 提出原因
当前现场存在零件改制业务,但改制过程尚未完整纳入系统管理。由于现场计件、派工生产、完工入库和后续统计都需要明确的数据来源,原有线下记录或零散流转方式无法满足计件核算、过程追溯和部门协同要求。
因此,需要在系统内补充零件改制订单流程,将改制订单从技术中心发起、精工车间派工生产到完工入库的全过程纳入系统管理。
### 0.3 应用场景
本功能主要应用于以下场景:
- 技术中心根据现场或订单需求发起零件改制订单。
- 精工车间根据改制订单制定工艺、派工生产。
- 改制订单涉及非毛坯物料时,由系统生成领料单并交由仓库出库。
- 改制加工完成后,按现有流程办理入库。
- 现场计件、生产统计、入库记录和后续追溯均以系统内改制订单数据为依据。
## 1. 需求目标
基于项目现有精工车间生产流程,新增“零件改制”业务。
本次方案调整为:
- 在技术中心新增组件发起改制订单。
- 改制订单生成后进入现有精工车间生产任务流程。
- 精工车间生产任务查询组件可以查看改制订单。
- 车间派工组件可以查看改制订单并继续派工。
- 新增改制记录查询,用于查看改制订单的发起、生产、派工、领料和完工状态。
- 领料时根据改制订单和物料来源判断是否生成领料单。
核心原则:
- 技术中心负责发起改制订单。
- 精工车间复用现有生产任务、工艺、派工、加工流程。
- 仓储只在需要额外领用非毛坯物料时介入。
- 改制记录独立查询,但状态关联现有生产任务状态。
## 2. 现有流程承接关系
根据项目现有页面,改制订单应承接以下流程:
| 流程节点 | 现有承接页面 | 说明 |
| ---- | ---------- | --------------- |
| 技术发起 | 技术中心新增页面 | 发起改制订单,填写改制要求 |
| 生成任务 | 精工车间生产任务查询 | 改制订单进入生产任务列表 |
| 制定工艺 | 精工车间制定工艺 | 可复用或复制原工艺后调整 |
| 车间派工 | 精工车间车间派工 | 工艺完成后派工 |
| 领料判断 | 领料/仓储出库流程 | 根据物料类型决定是否生成领料单 |
| 加工执行 | 精工车间现有加工流程 | 扫码、报工、质检等复用现有逻辑 |
| 入库 | 仓储入库流程 | 改制完工后按现有流程办理入库 |
| 记录查询 | 改制记录查询 | 查看改制全流程 |
![零件改制业务流程图](零件改制流程图.svg)
## 3. 页面设计
### 3.1 技术中心新增页面:改制订单发起
建议路径:
```text
src/views/TechnologyCenter/PartModificationOrder/index.vue
```
页面名称:
```text
改制订单发起
```
归属模块:
```text
技术中心
```
主要功能:
- 查询需要改制的原订单、原零件或原自制件。
- 发起改制订单。
- 填写改制后零件信息、改制数量、改制原因、技术要求。
- 指定是否使用原件改制、毛坯改制或其他物料改制。
- 提交后生成改制订单,并进入精工车间生产任务查询。
### 3.2 精工车间修改页面:生产任务查询
现有路径:
```text
src/views/SeikoWorkshop/ProductionTaskQuery/index.vue
```
需要支持:
- 查询改制订单生成的生产任务。
- 增加任务类型筛选。
- 增加任务类型列。
- 改制任务显示 `改制` 标识。
- 改制任务继续使用现有 `工艺``派工` 按钮。
### 3.3 精工车间修改页面:车间派工
现有路径:
```text
src/views/SeikoWorkshop/WorkshopAssignment/index.vue
```
需要支持:
- 查询改制订单对应的待派工任务。
- 增加任务类型筛选。
- 增加任务类型列。
- 复用现有已派工查询、待派工工序查询、派工、取消派工逻辑。
### 3.4 新增页面:改制记录查询
建议路径:
```text
src/views/TechnologyCenter/PartModificationRecord/index.vue
```
也可以放在精工车间模块,建议最终按业务归属确认。
页面名称:
```text
改制记录查询
```
主要功能:
- 查询改制订单记录。
- 查看改制订单状态。
- 查看是否生成领料单。
- 查看仓库是否已出库。
- 查看精工生产任务、工艺、派工、完工状态。
- 支持跳转生产任务查询、车间派工、零件追溯。
## 4. 改制订单类型
改制订单需要明确物料来源,建议增加字段:
```text
改制来源类型
```
建议枚举:
| 改制来源类型 | 说明 | 是否生成领料单 |
| ------- | ----------------- | ------- |
| 原现自制订单 | 使用原现有自制订单零件进行改制 | 否 |
| 毛坯改制 | 直接使用已有毛坯进行改制 | 否 |
| 非毛坯物料改制 | 使用仓库其他物料、半成品或成品改制 | 是 |
说明:
- “原现自制订单”指当前已经存在的自制订单或自制零件,改制时不需要额外从仓库领料。
- “毛坯改制”指直接使用毛坯进行改制,不额外生成领料单。
- “非毛坯物料改制”指改制需要领用库存中的非毛坯物料,需要生成领料单并由仓库出库。
## 5. 领料规则
### 5.1 领料判断条件
领料时增加判断:
```text
如果是改制订单,并且使用的物料不是毛坯,则生成领料单,由仓库物料出库。
如果是原现自制订单改制,或者直接使用毛坯改制,则不生成领料单。
```
规则可表达为:
```text
是否生成领料单 =
是否改制订单 === 1
且 改制来源类型 === 非毛坯物料改制
且 是否毛坯 !== 1
```
### 5.2 生成领料单场景
以下场景需要生成领料单:
- 改制订单使用库存半成品。
- 改制订单使用库存成品。
- 改制订单使用其他非毛坯物料。
- 改制订单指定的物料需要仓库出库。
生成后流程:
1. 技术中心发起改制订单。
2. 系统判断需要领料。
3. 生成领料单。
4. 仓库根据领料单出库。
5. 出库完成后,精工车间继续生产、工艺、派工。
### 5.3 不生成领料单场景
以下场景不生成领料单:
- 原现自制订单改制。
- 直接使用毛坯改制。
- 改制对象已经在精工车间现场,不需要仓库出库。
不生成领料单时:
- 改制订单直接进入精工生产任务。
- 生产任务查询可查看。
- 车间派工可查看并派工。
### 5.4 领料状态字段
建议改制订单增加以下字段:
| 字段名 | 说明 |
| -------- | --------------- |
| 是否需要领料 | 1 是0 否 |
| 是否已生成领料单 | 1 是0 否 |
| 领料单号 | 生成的领料单编号 |
| 领料状态 | 未生成、待出库、已出库、已取消 |
| 出库日期 | 仓库出库日期 |
| 出库人 | 仓库操作人 |
## 6. 业务流程
### 6.1 技术中心发起改制订单
用户进入技术中心“改制订单发起”页面。
查询原始数据:
- 订单编号
- 产品/部件名称
- 零件名称
- 图号
- 原自制订单
- 库存物料
- 毛坯物料
发起改制时填写:
- 改制订单号
- 原订单编号
- 原零件名称
- 原零件图号
- 改制零件名称
- 改制零件图号
- 改制数量
- 改制来源类型
- 是否毛坯
- 物料编号
- 物料名称
- 改制原因
- 改制要求
- 技术备注
- 精工期限
提交时校验:
- 改制数量必须大于 0。
- 改制来源类型不能为空。
- 改制原因不能为空。
- 改制要求不能为空。
- 精工期限不能为空。
- 如果来源类型为非毛坯物料改制,必须选择物料编号。
### 6.2 后端生成改制订单
提交后,后端需要同时处理:
- 写入改制订单主记录。
- 根据改制来源类型判断是否生成领料单。
- 生成精工车间生产任务。
- 写入任务类型为 `改制`
- 关联改制订单号和新工艺计划流水号。
### 6.3 进入精工车间生产任务查询
改制订单生成后,应能在现有接口中查到:
```text
精工车间_生成任务_查询数据
```
建议返回字段增加:
- 任务类型
- 是否改制
- 改制订单号
- 改制来源类型
- 是否需要领料
- 领料状态
- 改制原因
- 改制要求
生产任务查询页面显示:
- `任务类型 = 改制`
-`是否需要领料 = 1``领料状态 !== 已出库`,可显示领料状态提示。
是否允许工艺/派工,需要按业务决定:
- 如果非毛坯物料改制必须先出库,建议未出库前允许制定工艺,但不允许派工。
- 如果现场允许先派工后补出库,则只做提示,不阻断派工。
建议采用更稳妥规则:
```text
需要领料且未出库:允许制定工艺,不允许派工。
不需要领料:正常工艺、派工。
需要领料且已出库:正常工艺、派工。
```
### 6.4 制定工艺
改制订单在生产任务查询中点击 `工艺`,进入现有:
```text
/SeikoWorkshop/DevelopProcess
```
工艺规则:
- 改制订单必须生成新的工艺计划流水号。
- 不覆盖原自制订单或原零件工艺。
- 可支持从原工艺复制后调整。
- 工艺保存后,任务状态进入 `工艺完成`
### 6.5 车间派工
工艺完成后进入现有车间派工页面:
```text
src/views/SeikoWorkshop/WorkshopAssignment/index.vue
```
现有查询接口:
```text
精工车间_车间派工_查询
```
改制订单派工前判断:
- 不需要领料:允许派工。
- 需要领料且已出库:允许派工。
- 需要领料但未出库:禁止派工,并提示“改制订单物料未出库,不能派工”。
派工明细继续复用现有接口:
```text
车间生产管理工艺_零件工序_已派工查询
车间生产管理工艺_零件工序_派工_工序查询
车间生产管理工艺_零件工序_派工
车间生产管理工艺_零件工序_取消派工
```
### 6.6 仓库出库
当改制订单需要领料时,系统生成领料单。
仓库根据领料单完成出库后,需要回写:
- 领料状态 = 已出库
- 出库日期
- 出库人
- 出库数量
出库完成后,精工车间派工限制解除。
### 6.7 加工和完工
改制订单派工后,继续走现有精工车间加工流程:
- 工序派工
- 扫码加工
- 完工报工
- 质检
- 零件追溯
- 工时统计
完工后改制记录状态同步为:
```text
已完成
```
## 7. 数据字段设计
### 7.1 改制订单主记录字段
| 字段名 | 说明 |
| -------- | ------------------- |
| 改制订单号 | 改制业务编号 |
| 原订单编号 | 原订单编号 |
| 原订单流水号 | 原订单流水号 |
| 原组件流水号 | 原组件流水号 |
| 原基本件流水号 | 原零件流水号 |
| 原工艺计划流水号 | 原工艺计划流水号 |
| 原零件名称 | 改制前零件名称 |
| 原零件图号 | 改制前零件图号 |
| 原数量 | 原数量 |
| 改制零件名称 | 改制后零件名称 |
| 改制零件图号 | 改制后零件图号 |
| 改制数量 | 改制数量 |
| 改制来源类型 | 原现自制订单、毛坯改制、非毛坯物料改制 |
| 是否毛坯 | 1 是0 否 |
| 物料编号 | 使用物料编号 |
| 物料名称 | 使用物料名称 |
| 物料流水号 | 使用物料流水号 |
| 是否需要领料 | 1 是0 否 |
| 是否已生成领料单 | 1 是0 否 |
| 领料单号 | 领料单编号 |
| 领料状态 | 未生成、待出库、已出库、已取消 |
| 改制原因 | 改制原因 |
| 改制要求 | 改制要求 |
| 技术备注 | 技术备注 |
| 精工期限 | 精工完工期限 |
| 新基本件流水号 | 改制任务生成的新零件流水号 |
| 新工艺计划流水号 | 改制任务生成的新工艺计划流水号 |
| 发起人 | 当前用户 ID |
| 发起日期 | 发起时间 |
| 状态 | 改制订单状态 |
| 是否启用 | 逻辑删除标识 |
### 7.2 改制订单状态
| 状态 | 说明 |
| ---- | ---------------- |
| 待领料 | 需要领料,领料单未出库 |
| 待工艺 | 不需要领料或已出库,等待制定工艺 |
| 工艺完成 | 工艺已保存,等待派工 |
| 待派工 | 工艺完成且满足派工条件 |
| 加工中 | 已派工或已开始加工 |
| 已完成 | 改制任务完工 |
| 已取消 | 改制订单取消 |
说明:
- 如果不需要领料,提交后可直接进入 `待工艺`
- 如果需要领料,提交后进入 `待领料`
- 仓库出库后从 `待领料` 转为 `待工艺` 或保持生产任务状态,由查询时关联显示。
## 8. API 设计
项目请求继续使用:
```js
this.CreateData(type, name, param, pageSize, pageCurrent)
this.ExecDatabase(Data)
```
### 8.1 技术中心查询可改制对象
```js
var Data = this.CreateData('11', '技术中心_改制订单_可改制对象_查询', param, this.pageSize, this.pageCurrent)
```
### 8.2 技术中心发起改制订单
```js
var Data = this.CreateData('12', '技术中心_改制订单_发起改制', param)
```
参数建议:
| 参数名 | 说明 |
| -------- | ------------------- |
| 原订单流水号 | 原订单流水号 |
| 原组件流水号 | 原组件流水号 |
| 原基本件流水号 | 原基本件流水号 |
| 原工艺计划流水号 | 原工艺计划流水号 |
| 原订单编号 | 原订单编号 |
| 原零件名称 | 原零件名称 |
| 原零件图号 | 原零件图号 |
| 改制零件名称 | 改制零件名称 |
| 改制零件图号 | 改制零件图号 |
| 改制数量 | 改制数量 |
| 改制来源类型 | 原现自制订单、毛坯改制、非毛坯物料改制 |
| 是否毛坯 | 是否毛坯 |
| 物料流水号 | 使用物料流水号 |
| 物料编号 | 物料编号 |
| 物料名称 | 物料名称 |
| 改制原因 | 改制原因 |
| 改制要求 | 改制要求 |
| 技术备注 | 技术备注 |
| 精工期限 | 精工期限 |
| 发起人 | 当前用户 ID |
后端处理结果:
- 生成改制订单。
- 判断是否生成领料单。
- 生成精工生产任务。
- 返回 `result``改制订单号``领料单号``是否需要领料`
### 8.3 改制记录查询
```js
var Data = this.CreateData('11', '技术中心_改制订单_记录_查询', param, this.pageSize, this.pageCurrent)
```
### 8.4 改制订单详情
```js
var Data = this.CreateData('11', '技术中心_改制订单_详情_查询', param)
```
### 8.5 取消改制订单
```js
var Data = this.CreateData('12', '技术中心_改制订单_取消', param)
```
取消前后端需要校验:
- 未派工可以取消。
- 已派工未加工,需要先取消派工。
- 已加工、已有质检记录或已完成,不允许取消。
- 已生成领料单且已出库,不允许直接取消,需要走退料或异常处理。
## 9. 现有接口扩展
### 9.1 生产任务查询接口
现有接口:
```text
精工车间_生成任务_查询数据
```
新增查询参数:
| 参数名 | 说明 |
| ----------- | ------------- |
| 任务类型\_check | 是否按任务类型过滤 |
| 任务类型 | 全部、正常、改制、报废补投 |
| 领料状态\_check | 是否按领料状态过滤 |
| 领料状态 | 待出库、已出库、不需要领料 |
新增返回字段:
| 字段名 | 说明 |
| ------ | ------------------- |
| 任务类型 | 正常、改制、报废补投 |
| 是否改制 | 1 是0 否 |
| 改制订单号 | 改制订单编号 |
| 改制来源类型 | 原现自制订单、毛坯改制、非毛坯物料改制 |
| 是否需要领料 | 1 是0 否 |
| 领料状态 | 未生成、待出库、已出库、已取消 |
| 领料单号 | 领料单号 |
| 改制原因 | 改制原因 |
| 改制要求 | 改制要求 |
### 9.2 车间派工查询接口
现有接口:
```text
精工车间_车间派工_查询
```
新增查询参数:
| 参数名 | 说明 |
| ----------- | ------------- |
| 任务类型\_check | 是否按任务类型过滤 |
| 任务类型 | 全部、正常、改制、报废补投 |
新增返回字段:
| 字段名 | 说明 |
| ------ | ---------- |
| 任务类型 | 正常、改制、报废补投 |
| 是否改制 | 1 是0 否 |
| 改制订单号 | 改制订单编号 |
| 改制来源类型 | 改制来源类型 |
| 是否需要领料 | 1 是0 否 |
| 领料状态 | 领料状态 |
| 领料单号 | 领料单号 |
派工前端限制:
```text
如果 是否改制 = 1 且 是否需要领料 = 1 且 领料状态 != 已出库,则不允许派工。
```
## 10. 前端交互调整
### 10.1 技术中心改制订单发起页面
查询条件:
- 订单编号
- 零件名称
- 图号
- 物料编号
- 物料名称
- 改制来源类型
表格列:
- 订单编号
- 产品/部件名称
- 零件名称
- 零件图号
- 数量
- 当前状态
- 来源类型
- 物料编号
- 物料名称
- 操作
操作:
- 发起改制
- 图纸
- PLM传入工艺
- 追溯
发起改制弹窗:
- 原订单编号
- 原零件名称
- 原零件图号
- 改制零件名称
- 改制零件图号
- 改制数量
- 改制来源类型
- 是否毛坯
- 物料编号
- 物料名称
- 改制原因
- 改制要求
- 技术备注
- 精工期限
### 10.2 生产任务查询页面
新增筛选:
```text
任务类型:全部 / 正常 / 改制 / 报废补投
领料状态:全部 / 不需要领料 / 待出库 / 已出库
```
新增列:
- 任务类型
- 改制订单号
- 改制来源类型
- 领料状态
显示建议:
```html
<el-tag type="warning" size="mini">改制</el-tag>
<el-tag type="danger" size="mini">待出库</el-tag>
<el-tag type="success" size="mini">已出库</el-tag>
<el-tag type="info" size="mini">不需要领料</el-tag>
```
### 10.3 车间派工页面
新增筛选:
```text
任务类型:全部 / 正常 / 改制 / 报废补投
```
新增列:
- 任务类型
- 改制订单号
- 领料状态
派工按钮或派工操作前增加判断:
```js
if (Number(row.是否改制) === 1 && Number(row.是否需要领料) === 1 && row.领料状态 !== '已出库') {
this.$message.warning('改制订单物料未出库,不能派工')
return
}
```
### 10.4 改制记录查询页面
查询条件:
- 改制订单号
- 原订单编号
- 零件名称或图号
- 改制来源类型
- 领料状态
- 改制状态
- 发起日期
- 发起人
表格列:
- 改制订单号
- 状态
- 原订单编号
- 原零件名称
- 原零件图号
- 改制零件名称
- 改制零件图号
- 改制数量
- 改制来源类型
- 是否需要领料
- 领料单号
- 领料状态
- 改制原因
- 发起人
- 发起日期
- 精工期限
- 完成日期
- 操作
操作:
- 详情
- 生产任务
- 派工
- 追溯
- 取消
## 11. 菜单配置
建议后端菜单配置:
```text
技术中心
改制订单发起
改制记录查询
```
组件路径:
```text
TechnologyCenter/PartModificationOrder/index
TechnologyCenter/PartModificationRecord/index
```
精工车间不新增发起入口,只扩展现有页面:
```text
SeikoWorkshop/ProductionTaskQuery/index
SeikoWorkshop/WorkshopAssignment/index
```
## 12. 实施顺序
建议按以下顺序实施:
1. 后端新增改制订单主记录表。
2. 后端新增技术中心发起改制订单接口。
3. 后端在发起接口中加入领料判断规则。
4. 后端按规则生成或不生成领料单。
5. 后端生成标准精工生产任务,并标记 `任务类型 = 改制`
6. 扩展生产任务查询接口,返回改制和领料字段。
7. 扩展车间派工查询接口,返回改制和领料字段。
8. 前端新增技术中心改制订单发起页面。
9. 前端新增改制记录查询页面。
10. 前端修改生产任务查询页面,增加任务类型和领料状态显示。
11. 前端修改车间派工页面,增加改制任务显示和派工前领料状态校验。
12. 联调从技术中心发起、领料判断、仓库出库、精工工艺、车间派工、加工完工、记录查询的完整流程。
## 13. 风险点
### 13.1 领料判断风险
改制订单是否生成领料单,必须以后端判断为准。
前端可以显示和提示,但不能只依赖前端判断,避免绕过仓库出库流程。
### 13.2 派工前物料状态风险
如果改制订单需要仓库出库,但尚未出库,直接派工会导致车间无物料加工。
建议车间派工接口或派工保存接口再次校验:
```text
需要领料且未出库,不允许派工。
```
### 13.3 原任务数据覆盖风险
改制订单必须生成新的生产任务和新的工艺计划流水号。
不能直接覆盖原自制订单或原零件工艺,否则会影响原订单追溯、工时和质量记录。
### 13.4 取消改制风险
已生成领料单、已出库、已派工或已加工的改制订单取消规则需要严格控制。
建议:
- 未出库、未派工:允许取消。
- 已出库:需要退料后取消。
- 已派工未加工:先取消派工再取消。
- 已加工:不允许取消,只能走异常处理。
### 13.5 统计口径风险
改制订单进入精工生产任务后,会影响生产任务数量、工时统计、完工统计。
建议所有统计接口增加任务类型维度:
```text
正常
改制
报废补投
```
## 14. 总结
本方案采用:
```text
技术中心发起改制订单,精工车间承接生产,仓库按需出库,改制记录统一查询。
```
关键规则:
- 技术中心新增组件发起改制订单。
- 改制订单生成后进入精工车间生产任务查询。
- 改制订单工艺和派工复用现有精工流程。
- 领料时如果是改制订单,并且使用物料不是毛坯,则生成领料单,由仓库物料出库。
- 如果是原现自制订单改制,或者直接使用毛坯改制,则不生成领料单。
- 改制记录查询独立展示全流程状态。

Binary file not shown.

85
零件改制流程图.svg Normal file
View File

@@ -0,0 +1,85 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1180" height="1080" viewBox="0 0 1180 1080">
<defs>
<style>
.title { font: 700 30px "Microsoft YaHei", "SimSun", Arial, sans-serif; fill: #1f2933; }
.label { font: 600 18px "Microsoft YaHei", "SimSun", Arial, sans-serif; fill: #1f2933; }
.small { font: 15px "Microsoft YaHei", "SimSun", Arial, sans-serif; fill: #475569; }
.node { fill: #ffffff; stroke: #2f80ed; stroke-width: 2; rx: 10; }
.tech { fill: #eef6ff; stroke: #2f80ed; }
.seiko { fill: #f0fdf4; stroke: #16a34a; }
.warehouse { fill: #fff7ed; stroke: #f97316; }
.record { fill: #f8fafc; stroke: #64748b; }
.decision { fill: #fff7ed; stroke: #f59e0b; stroke-width: 2; }
.line { stroke: #64748b; stroke-width: 2; fill: none; marker-end: url(#arrow); }
.yesno { font: 600 14px "Microsoft YaHei", "SimSun", Arial, sans-serif; fill: #334155; }
</style>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,6 L9,3 z" fill="#64748b" />
</marker>
</defs>
<rect x="0" y="0" width="1180" height="1080" fill="#ffffff"/>
<text x="590" y="48" text-anchor="middle" class="title">零件改制业务流程图</text>
<rect x="70" y="90" width="1040" height="90" class="node tech"/>
<text x="590" y="126" text-anchor="middle" class="label">技术中心:改制订单发起</text>
<text x="590" y="154" text-anchor="middle" class="small">选择原订单/零件/物料,填写改制数量、来源类型、原因、要求、精工期限</text>
<path d="M590 180 L590 225" class="line"/>
<polygon points="590,225 755,305 590,385 425,305" class="decision"/>
<text x="590" y="292" text-anchor="middle" class="label">是否改制订单</text>
<text x="590" y="322" text-anchor="middle" class="small">且使用物料不是毛坯?</text>
<path d="M755 305 L900 305 L900 365" class="line"/>
<text x="820" y="292" class="yesno"></text>
<rect x="760" y="365" width="280" height="88" class="node warehouse"/>
<text x="900" y="400" text-anchor="middle" class="label">生成领料单</text>
<text x="900" y="428" text-anchor="middle" class="small">仓库按领料单物料出库</text>
<path d="M900 453 L900 515 L670 515" class="line"/>
<text x="918" y="488" class="yesno">已出库</text>
<path d="M425 305 L280 305 L280 515 L510 515" class="line"/>
<text x="320" y="292" class="yesno"></text>
<text x="118" y="384" class="small">原现自制订单改制</text>
<text x="118" y="410" class="small">或直接毛坯改制</text>
<text x="118" y="436" class="small">不生成领料单</text>
<rect x="510" y="475" width="160" height="80" class="node seiko"/>
<text x="590" y="508" text-anchor="middle" class="label">生成精工</text>
<text x="590" y="535" text-anchor="middle" class="small">生产任务</text>
<path d="M590 555 L590 602" class="line"/>
<rect x="390" y="602" width="400" height="80" class="node seiko"/>
<text x="590" y="636" text-anchor="middle" class="label">精工车间:生产任务查询</text>
<text x="590" y="662" text-anchor="middle" class="small">显示任务类型=改制、领料状态、改制订单号</text>
<path d="M590 682 L590 728" class="line"/>
<rect x="390" y="728" width="400" height="80" class="node seiko"/>
<text x="590" y="762" text-anchor="middle" class="label">制定工艺</text>
<text x="590" y="788" text-anchor="middle" class="small">生成新工艺计划,可复制原工艺后调整</text>
<path d="M590 808 L590 854" class="line"/>
<rect x="390" y="854" width="400" height="80" class="node seiko"/>
<text x="590" y="888" text-anchor="middle" class="label">车间派工与加工完工</text>
<text x="590" y="914" text-anchor="middle" class="small">需要领料且未出库时禁止派工,出库后正常派工</text>
<path d="M590 934 L590 980" class="line"/>
<rect x="390" y="980" width="400" height="70" class="node warehouse"/>
<text x="590" y="1010" text-anchor="middle" class="label">仓储入库</text>
<text x="590" y="1036" text-anchor="middle" class="small">改制完工后按现有流程办理入库并回写状态</text>
<path d="M790 1015 L970 1015 L970 215 L720 215" class="line"/>
<rect x="820" y="188" width="300" height="54" class="node record"/>
<text x="970" y="222" text-anchor="middle" class="label">改制记录查询贯穿全流程</text>
<path d="M390 1015 L210 1015 L210 215 L460 215" class="line"/>
<rect x="60" y="188" width="300" height="54" class="node record"/>
<text x="210" y="222" text-anchor="middle" class="label">状态回写与追溯关联</text>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB