InRequestForm.vue 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416
  1. <template>
  2. <div class="app-container">
  3. <div class="page-header">
  4. <div class="header-content">
  5. <!-- 按钮区域 -->
  6. <div class="header-buttons">
  7. <el-button
  8. type="primary"
  9. :loading="formLoading"
  10. plain
  11. size="mini"
  12. :disabled="isFormDisabled"
  13. @click="submitForm"
  14. >
  15. 保 存
  16. </el-button>
  17. <!-- 提交菜单 -->
  18. <el-dropdown class="ml-5" trigger="click">
  19. <el-button type="primary" size="mini" plain>
  20. 提交菜单
  21. <i class="el-icon-arrow-down el-icon--right" />
  22. </el-button>
  23. <el-dropdown-menu slot="dropdown">
  24. <el-dropdown-item
  25. :disabled="isButtonDisabled('commit')"
  26. @click.native="commit"
  27. >提交</el-dropdown-item
  28. >
  29. <el-dropdown-item
  30. :disabled="isButtonDisabled('cancel')"
  31. @click.native="cancel"
  32. >撤销</el-dropdown-item
  33. >
  34. </el-dropdown-menu>
  35. </el-dropdown>
  36. <!-- 审批菜单 -->
  37. <el-dropdown class="ml-5 mr-5" trigger="click">
  38. <el-button type="warning" size="mini" plain>
  39. 审批菜单
  40. <i class="el-icon-arrow-down el-icon--right" />
  41. </el-button>
  42. <el-dropdown-menu slot="dropdown">
  43. <el-dropdown-item
  44. :disabled="isButtonDisabled('audit')"
  45. @click.native="audit"
  46. >审核</el-dropdown-item
  47. >
  48. <el-dropdown-item
  49. :disabled="isButtonDisabled('antiAudit')"
  50. @click.native="antiAudit"
  51. >反审核</el-dropdown-item
  52. >
  53. </el-dropdown-menu>
  54. </el-dropdown>
  55. <!-- <el-button @click="reset" plain>重置</el-button> -->
  56. <el-button
  57. type="primary"
  58. size="mini"
  59. plain
  60. :disabled="isFormDisabled"
  61. @click="add()"
  62. >新增明细
  63. </el-button>
  64. <el-button plain size="mini" @click="handleCancel">返回</el-button>
  65. </div>
  66. </div>
  67. </div>
  68. <el-tabs v-model="activeName" @tab-click="handleClick">
  69. <el-tab-pane label="明细信息" name="detail">
  70. <el-form
  71. ref="formRef"
  72. v-loading="formLoading"
  73. :model="formData"
  74. :rules="dynamicFormRules"
  75. label-width="150px"
  76. class="form-container"
  77. >
  78. <el-row :gutter="20">
  79. <el-col :span="12"
  80. ><el-form-item label="业务类型" prop="businessType">
  81. <el-select
  82. v-model="formData.businessType"
  83. placeholder="请选择业务类型"
  84. :disabled="!isEditable"
  85. @change="changeBusinessType"
  86. >
  87. <el-option
  88. v-for="dict in getDictDatas('in_business_type')"
  89. :key="dict.value"
  90. :label="dict.label"
  91. :value="dict.value"
  92. />
  93. </el-select>
  94. </el-form-item>
  95. </el-col>
  96. <el-col :span="12">
  97. <el-form-item label="申请单号" prop="remark">
  98. <el-input
  99. v-model="formData.requestNo"
  100. :disabled="true"
  101. placeholder="保存后自动生成"
  102. /> </el-form-item
  103. ></el-col>
  104. <el-col :span="12">
  105. <el-form-item :label="getDeptLabel" prop="deptCode">
  106. <DepartMentSelect
  107. ref="departMentSelect"
  108. v-model="formData.deptCode"
  109. :disabled="isFormDisabled || formData.businessType == null"
  110. :placeholder="getDeptPlaceholder"
  111. clearable
  112. @change="selectDepart"
  113. />
  114. </el-form-item>
  115. </el-col>
  116. <el-col :span="12"
  117. ><el-form-item label="业务分类名称" prop="businessDescribe">
  118. <el-select
  119. v-model="formData.businessDescribe"
  120. :disabled="isFormDisabled || formData.businessType == null"
  121. placeholder="请选择业务类型"
  122. @change="changeBusinessDescribe"
  123. >
  124. <el-option
  125. v-for="dict in businessDescribeList"
  126. :key="dict.label"
  127. :label="dict.label"
  128. :value="dict.label"
  129. />
  130. </el-select> </el-form-item
  131. ></el-col>
  132. <el-col :span="12"
  133. ><el-form-item label="优先级" prop="priority">
  134. <el-select
  135. v-model="formData.priority"
  136. :disabled="isFormDisabled || formData.businessType == null"
  137. placeholder="请选择优先级"
  138. >
  139. <el-option
  140. v-for="dict in getDictDatas('priority')"
  141. :key="dict.value"
  142. :label="dict.label"
  143. :value="dict.value"
  144. />
  145. </el-select>
  146. </el-form-item>
  147. </el-col>
  148. <el-col :span="12">
  149. <el-form-item label="供应商编码" prop="supplierCode">
  150. <el-select
  151. v-model="formData.supplierCode"
  152. :disabled="isFormDisabled || formData.businessType == null"
  153. placeholder="请选择供应商编码"
  154. clearable
  155. filterable
  156. :filter-method="filterSupplier"
  157. >
  158. <el-option
  159. v-for="item in supplierOptions"
  160. :key="item.code"
  161. :label="`${item.code} ${item.name}`"
  162. :value="item.code"
  163. >
  164. <span style="display: inline-block; width: 120px">{{
  165. item.code
  166. }}</span>
  167. <span style="color: #8492a6; font-size: 13px">{{
  168. item.name
  169. }}</span>
  170. </el-option>
  171. </el-select>
  172. </el-form-item>
  173. </el-col>
  174. <el-col :span="12">
  175. <el-form-item label="客户编码" prop="customerCode">
  176. <el-select
  177. v-model="formData.customerCode"
  178. :disabled="isFormDisabled || formData.businessType == null"
  179. placeholder="请选择客户编码"
  180. clearable
  181. filterable
  182. >
  183. <el-option
  184. v-for="item in customerList"
  185. :key="item.erpId"
  186. :label="`${item.code} ${item.name || ''}`"
  187. :value="item.code"
  188. />
  189. <!-- <el-option
  190. v-for="item in customerList"
  191. :key="item.code"
  192. :value="item.code"
  193. >
  194. <span style="display: inline-block; width: 120px">{{
  195. item.code
  196. }}</span>
  197. <span>{{ item.name }}</span>
  198. </el-option> -->
  199. </el-select>
  200. </el-form-item>
  201. </el-col>
  202. <el-col :span="12">
  203. <el-form-item label="源单编号" prop="sourceOrderNo">
  204. <el-select
  205. v-model="formData.sourceOrderNo"
  206. filterable
  207. remote
  208. :disabled="isFormDisabled || formData.businessType == null"
  209. reserve-keyword
  210. placeholder="请输入源单编号"
  211. :remote-method="remoteMethod"
  212. :loading="loading"
  213. @change="changeSourceOrderNo"
  214. >
  215. <el-option
  216. v-for="item in sourceOrderNoList"
  217. :key="item.sourceOrderNo"
  218. :label="item.sourceOrderNo"
  219. :value="item.sourceOrderNo"
  220. />
  221. </el-select>
  222. </el-form-item>
  223. </el-col>
  224. <el-col v-if="formData.businessType === '9'" :span="12">
  225. <el-form-item label="扣料仓库" prop="originStockCode">
  226. <el-select
  227. v-model="formData.originStockCode"
  228. :disabled="isFormDisabled || formData.businessType == null"
  229. placeholder="请选择扣料仓库"
  230. clearable
  231. filterable
  232. >
  233. <el-option
  234. v-for="item in warehouseList"
  235. :key="item.erpId"
  236. :label="item.name"
  237. :value="item.code"
  238. />
  239. </el-select>
  240. </el-form-item>
  241. </el-col>
  242. <!-- <el-col v-if="formData.businessType === '9'" :span="12">
  243. <el-form-item label="委外发料单" prop="relatedOrder">
  244. <el-select
  245. v-model="formData.relatedOrder"
  246. filterable
  247. remote
  248. :disabled="isFormDisabled"
  249. reserve-keyword
  250. placeholder="请输入委外发料单号"
  251. :remote-method="remoteRelatedOrder"
  252. :loading="loading"
  253. >
  254. <el-option
  255. v-for="item in relatedOrderList"
  256. :key="item.requestNo"
  257. :label="item.requestNo"
  258. :value="item.requestNo"
  259. />
  260. </el-select>
  261. </el-form-item>
  262. </el-col> -->
  263. <!-- <el-col :span="12">
  264. <el-form-item label="源单编号" prop="sourceOrderNo">
  265. <el-select
  266. v-model="formData.sourceOrderNo"
  267. :disabled="isFormDisabled || formData.businessType == null"
  268. placeholder="请选择源单编号"
  269. clearable
  270. @change="changeSourceOrderNo"
  271. >
  272. <el-option
  273. v-for="item in sourceOrderNoList"
  274. :key="item.sourceOrderNo"
  275. :label="item.sourceOrderNo"
  276. :value="item.sourceOrderNo"
  277. />
  278. </el-select>
  279. </el-form-item>
  280. </el-col> -->
  281. <el-col :span="12">
  282. <el-form-item label="预计出入库时间" prop="expectedTime">
  283. <el-date-picker
  284. v-model="formData.expectedTime"
  285. :disabled="isFormDisabled || formData.businessType == null"
  286. clearable
  287. type="date"
  288. value-format="timestamp"
  289. placeholder="选择预计出入库时间"
  290. /> </el-form-item
  291. ></el-col>
  292. <el-col :span="12">
  293. <el-form-item label="实际出入库时间" prop="actualTime">
  294. <el-date-picker
  295. v-model="formData.actualTime"
  296. clearable
  297. :disabled="true"
  298. type="date"
  299. value-format="timestamp"
  300. placeholder="选择实际出入库时间"
  301. /> </el-form-item
  302. ></el-col>
  303. <el-col :span="12">
  304. <el-form-item label="备注" prop="remark">
  305. <el-input
  306. v-model="formData.remark"
  307. :disabled="isFormDisabled || formData.businessType == null"
  308. placeholder="请输入备注"
  309. /> </el-form-item
  310. ></el-col>
  311. <!-- 远程搜索版本 -->
  312. <!-- <el-col :span="12">
  313. <el-form-item label="存储地点" prop="warehouseId">
  314. <el-select
  315. v-model="formData.warehouseId"
  316. filterable
  317. remote
  318. :disabled="isFormDisabled || formData.businessType == null"
  319. reserve-keyword
  320. placeholder="请输入存储地点"
  321. :remote-method="remoteWarehouse"
  322. :loading="loading"
  323. >
  324. <el-option
  325. v-for="item in warehouseList"
  326. :key="item.erpId"
  327. :label="item.name"
  328. :value="item.erpId"
  329. />
  330. </el-select>
  331. </el-form-item>
  332. </el-col> -->
  333. <el-col :span="12">
  334. <el-form-item label="存储地点" prop="warehouseId">
  335. <el-select
  336. v-model="formData.warehouseId"
  337. :disabled="isFormDisabled || formData.businessType == null"
  338. placeholder="请选择存储地点"
  339. clearable
  340. filterable
  341. >
  342. <el-option
  343. v-for="item in warehouseList"
  344. :key="item.erpId"
  345. :label="item.name"
  346. :value="item.erpId"
  347. />
  348. </el-select>
  349. </el-form-item>
  350. </el-col>
  351. <el-col :span="12">
  352. <el-form-item label="状态" prop="status" aria-disabled="true">
  353. <el-select
  354. v-model="formData.status"
  355. disabled
  356. placeholder="请选择状态"
  357. >
  358. <el-option
  359. v-for="dict in getDictDatas('in_out_status')"
  360. :key="dict.value"
  361. :label="dict.label"
  362. :value="dict.value"
  363. />
  364. </el-select>
  365. </el-form-item>
  366. </el-col>
  367. <el-col :span="12">
  368. <el-form-item label="仓管员" prop="receivePerson">
  369. <el-select
  370. v-model="formData.receivePerson"
  371. filterable
  372. :disabled="isFormDisabled || formData.businessType == null"
  373. placeholder="请输入仓管员"
  374. clearable
  375. style="width: 100%"
  376. >
  377. <el-option
  378. v-for="item in users"
  379. :key="parseInt(item.id)"
  380. :label="`${item.nickname}(${item.deptName || ''} ${
  381. item.postName || ''
  382. })`"
  383. :value="parseInt(item.id)"
  384. />
  385. </el-select>
  386. </el-form-item>
  387. </el-col>
  388. <el-col :span="8" class="text-right">
  389. <el-button
  390. type="primary"
  391. plain
  392. style="width: 60%"
  393. icon="el-icon-upload2"
  394. @click="handleUpload"
  395. >附件上传</el-button
  396. >
  397. </el-col>
  398. </el-row>
  399. </el-form>
  400. <!-- <el-tabs v-model="activeName" @tab-click="handleClick">
  401. <el-tab-pane label="明细信息" name="detail"> -->
  402. <el-table :data="formData.list" border size="mini">
  403. <el-table-column
  404. label="源单编号"
  405. align="center"
  406. prop="sourceRequestId"
  407. width="160"
  408. show-overflow-tooltip
  409. />
  410. <el-table-column
  411. label="源单行号"
  412. align="center"
  413. prop="sourceLineNo"
  414. width="160"
  415. show-overflow-tooltip
  416. />
  417. <el-table-column
  418. label="物料编码"
  419. align="center"
  420. prop="materialNo"
  421. width="200"
  422. show-overflow-tooltip
  423. >
  424. <template v-slot="scope">
  425. <el-select
  426. v-model="scope.row.materialNo"
  427. filterable
  428. remote
  429. reserve-keyword
  430. placeholder="请选择物料编码"
  431. :remote-method="
  432. (query) => remoteMaterialSearch(query, 'code', scope.$index)
  433. "
  434. :loading="loading"
  435. @change="(value) => changeMaterial(value, scope.$index, 'code')"
  436. >
  437. <el-option
  438. v-for="item in materialNoList"
  439. :key="item.code"
  440. :label="item.code"
  441. :value="item.code"
  442. />
  443. </el-select>
  444. </template>
  445. </el-table-column>
  446. <el-table-column
  447. label="物料名称"
  448. align="center"
  449. prop="materialName"
  450. width="200"
  451. show-overflow-tooltip
  452. >
  453. <template v-slot="scope">
  454. <el-select
  455. v-model="scope.row.materialName"
  456. filterable
  457. remote
  458. reserve-keyword
  459. placeholder="请选择物料名称"
  460. :remote-method="
  461. (query) => remoteMaterialSearch(query, 'name', scope.$index)
  462. "
  463. :loading="loading"
  464. @change="(value) => changeMaterial(value, scope.$index, 'name')"
  465. >
  466. <el-option
  467. v-for="item in materialNameList"
  468. :key="item.code"
  469. :label="item.name"
  470. :value="item.name"
  471. />
  472. </el-select>
  473. </template>
  474. </el-table-column>
  475. <el-table-column
  476. label="客户编码"
  477. align="center"
  478. prop="customerCode"
  479. width="150"
  480. show-overflow-tooltip
  481. />
  482. <el-table-column
  483. label="客户名称"
  484. align="center"
  485. prop="customerName"
  486. width="160"
  487. show-overflow-tooltip
  488. />
  489. <el-table-column
  490. label="本次申请数量"
  491. align="center"
  492. prop="nowDeliveredQty"
  493. width="160"
  494. >
  495. <template slot-scope="scope">
  496. <el-input
  497. v-model="scope.row.nowDeliveredQty"
  498. :disabled="isFormDisabled"
  499. @change="deliverChange"
  500. />
  501. </template>
  502. </el-table-column>
  503. <el-table-column
  504. label="已入库数量"
  505. align="center"
  506. prop="completedQty"
  507. width="120"
  508. />
  509. <el-table-column
  510. label="源单计划数量"
  511. align="center"
  512. prop="planQty"
  513. width="120"
  514. />
  515. <el-table-column
  516. label="单位"
  517. align="center"
  518. prop="unitName"
  519. width="150"
  520. show-overflow-tooltip
  521. />
  522. <el-table-column
  523. label="行备注"
  524. align="center"
  525. prop="remark"
  526. width="200"
  527. >
  528. <template slot-scope="scope">
  529. <el-input v-model="scope.row.remark" :disabled="isFormDisabled" />
  530. </template>
  531. </el-table-column>
  532. <el-table-column
  533. label="操作"
  534. align="center"
  535. fixed="right"
  536. width="150px"
  537. class-name="small-padding fixed-width"
  538. >
  539. <template v-slot="scope">
  540. <el-button
  541. size="mini"
  542. type="text"
  543. icon="el-icon-delete"
  544. :disabled="isFormDisabled"
  545. @click="handleDelete(scope)"
  546. >删除</el-button
  547. >
  548. </template>
  549. </el-table-column>
  550. </el-table>
  551. </el-tab-pane>
  552. <el-tab-pane label="审批任务" name="approvalTask" lazy>
  553. <ApprovalTask
  554. v-if="
  555. activeName === 'approvalTask' &&
  556. formData.bpmInstanceId !== null &&
  557. formData.bpmInstanceId !== undefined
  558. "
  559. :id="formData.bpmInstanceId"
  560. :receive-person="formData.receivePerson"
  561. />
  562. <div v-else class="isNotApproval">暂未开启工作流</div>
  563. </el-tab-pane>
  564. </el-tabs>
  565. <!-- 附件上传 -->
  566. <AttachmentUpload ref="attachmentUpload" @files="getFileList" />
  567. </div>
  568. </template>
  569. <script>
  570. import * as InRequestApi from "@/api/wms/output/inrequest";
  571. import DepartMentSelect from "./components/DepartMentSelect.vue";
  572. import AttachmentUpload from "../../wms/incoming/register/components/AttachmentUpload.vue";
  573. // 审批任务
  574. import ApprovalTask from "../../wms/quality/iqcInspection/components/ApprovalTaskNew2.vue";
  575. import { getFilesById } from "@/api/wms/incoming/register";
  576. import { getUserList } from "@/api/system/user";
  577. export default {
  578. name: "InRequestForm",
  579. components: {
  580. DepartMentSelect,
  581. ApprovalTask,
  582. AttachmentUpload,
  583. },
  584. data() {
  585. return {
  586. activeName: "detail",
  587. materialNameList: [],
  588. materialNoList: [],
  589. sourceOrderNoList: [],
  590. allSourceOrderNoList: [],
  591. supplierList: [],
  592. supplierOptions: [],
  593. customerList: [],
  594. businessDescribeList: [],
  595. warehouseList: [],
  596. uploadFiles: [], // 上传的文件
  597. users: [],
  598. loading: false,
  599. relatedOrderList: [], // 委外发料单列表
  600. allRelatedOrderList: [], // 全部委外发料单(用于本地过滤)
  601. // 页面标题
  602. dialogTitle: "",
  603. // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
  604. formLoading: false,
  605. // 记录当前业务类型下选中的业务分类名称
  606. selectedBusinessDescribe: "",
  607. // 保存当前选中的业务类型整行字典数据
  608. currentBusinessTypeRow: null,
  609. // 保存当前选中的业务分类整行数据
  610. currentBusinessDescribeRow: null,
  611. // 表单参数
  612. formData: {
  613. relatedOrder: undefined, // 委外发料单号
  614. departmentNo: undefined,
  615. deptCode: undefined,
  616. deptName: undefined,
  617. id: undefined,
  618. requestNo: undefined,
  619. requestType: undefined,
  620. businessType: undefined,
  621. businessCategory: undefined,
  622. businessDescribe: undefined,
  623. businessSubType: undefined,
  624. status: undefined,
  625. originStockCode: undefined,
  626. priority: undefined,
  627. warehouseId: undefined,
  628. relatedWarehouseId: undefined,
  629. supplierCode: undefined,
  630. customerCode: undefined,
  631. sourceOrderNo: undefined,
  632. expectedTime: undefined,
  633. actualTime: undefined,
  634. totalQty: undefined,
  635. totalSku: undefined,
  636. totalLine: undefined,
  637. remark: undefined,
  638. extendInfo: undefined,
  639. submitter: undefined,
  640. submitTime: undefined,
  641. auditor: undefined,
  642. auditTime: undefined,
  643. erpWriteFlag: undefined,
  644. erpErrMsg: undefined,
  645. erpBackId: undefined,
  646. list: [],
  647. bpmInstanceId: undefined,
  648. },
  649. // 表单校验
  650. formRules: {
  651. businessType: [
  652. {
  653. required: true,
  654. message: "业务类型不能为空",
  655. trigger: "blur",
  656. },
  657. ],
  658. priority: [
  659. {
  660. required: true,
  661. message: "优先级不能为空",
  662. trigger: "blur",
  663. },
  664. ],
  665. expectedTime: [
  666. { required: true, message: "预计入库时间不能为空", trigger: "blur" },
  667. ],
  668. receivePerson: [
  669. {
  670. required: true,
  671. message: "仓管员不能为空",
  672. trigger: "blur",
  673. },
  674. ],
  675. },
  676. };
  677. },
  678. computed: {
  679. isFormDisabled() {
  680. // 当路径有id且status>=1时禁用表单
  681. const status = parseInt(this.formData.status || "0");
  682. return status >= 1;
  683. },
  684. // 计算属性判断修改状态下是否可编辑
  685. isEditable() {
  686. // 有 id 表示是编辑模式,不可编辑
  687. // 没有 id 表示是新增模式,可编辑
  688. return (
  689. this.formData.id === undefined ||
  690. this.formData.id === null ||
  691. this.formData.id === ""
  692. );
  693. },
  694. // 动态获取部门标签
  695. getDeptLabel() {
  696. const businessType = this.formData.businessType;
  697. if (businessType === "9") {
  698. // 委外入库
  699. return "收货部门";
  700. } else if (businessType === "8") {
  701. // 委外退料
  702. return "退货部门";
  703. } else if (businessType === "3") {
  704. // 生产退料
  705. return "发料部门";
  706. }
  707. return "部门";
  708. },
  709. // 动态获取部门占位符
  710. getDeptPlaceholder() {
  711. const businessType = this.formData.businessType;
  712. if (businessType === "9") {
  713. // 委外入库
  714. return "请选择收货部门";
  715. } else if (businessType === "8") {
  716. // 委外退料
  717. return "请选择退货部门";
  718. } else if (businessType === "3") {
  719. // 生产退料
  720. return "请选择发料部门";
  721. }
  722. return "请选择部门";
  723. },
  724. // 动态生成表单验证规则
  725. dynamicFormRules() {
  726. // 从原始规则中只保留业务类型、优先级、预计出入库时间、仓管员
  727. const baseRules = {
  728. businessType: this.formRules.businessType,
  729. priority: this.formRules.priority,
  730. expectedTime: this.formRules.expectedTime,
  731. receivePerson: this.formRules.receivePerson,
  732. };
  733. const rules = { ...baseRules };
  734. const businessType = this.formData.businessType;
  735. // 只有选择了业务类型后,才添加其他字段的验证规则
  736. if (businessType) {
  737. // 委外入库(9)和委外退料(8)需要的必填字段
  738. if (businessType === "9" || businessType === "8") {
  739. rules.deptCode = [
  740. {
  741. required: true,
  742. message: this.getDeptLabel + "不能为空",
  743. trigger: "blur",
  744. },
  745. ];
  746. rules.businessDescribe = [
  747. {
  748. required: true,
  749. message: "业务分类名称不能为空",
  750. trigger: "blur",
  751. },
  752. ];
  753. rules.supplierCode = [
  754. { required: true, message: "供应商不能为空", trigger: "blur" },
  755. ];
  756. rules.sourceOrderNo = [
  757. { required: true, message: "源单编号不能为空", trigger: "blur" },
  758. ];
  759. if (businessType === "9") {
  760. rules.originStockCode = [
  761. { required: true, message: "扣料仓库不能为空", trigger: "blur" },
  762. ];
  763. }
  764. // rules.relatedOrder = [
  765. // { required: true, message: "委外发料单不能为空", trigger: "blur" },
  766. // ];
  767. }
  768. // 生产退料(3)需要的必填字段
  769. else if (businessType === "3") {
  770. rules.deptCode = [
  771. {
  772. required: true,
  773. message: this.getDeptLabel + "不能为空",
  774. trigger: "blur",
  775. },
  776. ];
  777. rules.businessDescribe = [
  778. {
  779. required: true,
  780. message: "业务分类名称不能为空",
  781. trigger: "blur",
  782. },
  783. ];
  784. rules.sourceOrderNo = [
  785. { required: true, message: "源单编号不能为空", trigger: "blur" },
  786. ];
  787. }
  788. // 其他业务类型不需要必填部门字段
  789. else {
  790. // 移除部门字段的必填规则
  791. delete rules.deptCode;
  792. }
  793. }
  794. return rules;
  795. },
  796. },
  797. watch: {
  798. "$route.query.id": {
  799. immediate: true,
  800. handler(newId) {
  801. // 只有当前路由路径包含"/inStorageManage/in-request/InRequestForm"时才处理,避免标签跳转时错误调用API
  802. if (
  803. this.$route.path.includes("/inStorageManage/in-request/InRequestForm")
  804. ) {
  805. if (newId) {
  806. this.initData(newId);
  807. } else {
  808. this.reset();
  809. }
  810. }
  811. },
  812. },
  813. },
  814. created() {
  815. // 从路由参数获取ID
  816. const id = this.$route.query.id;
  817. // 一次性获取全部仓管员
  818. getUserList().then((response) => {
  819. this.users = response.data;
  820. });
  821. // 一次性获取全部仓库
  822. InRequestApi.getStockPage({ pageSize: 9999 }).then(({ data }) => {
  823. this.warehouseList = data.list || [];
  824. });
  825. // 一次性获取全部供应商
  826. InRequestApi.getSupplierPage({ pageSize: 9999 }).then(({ data }) => {
  827. this.supplierList = data.list || [];
  828. this.supplierOptions = this.supplierList;
  829. });
  830. // 一次性获取全部客户编码
  831. InRequestApi.getCustomerPage({ pageSize: 9999 }).then(({ data }) => {
  832. this.customerList = data.list || [];
  833. });
  834. if (id) {
  835. this.dialogTitle = "修改";
  836. // this.initData(id)
  837. } else {
  838. this.dialogTitle = "新增";
  839. }
  840. },
  841. methods: {
  842. // 通用的判断函数判断按钮是否可点击
  843. isButtonDisabled(buttonType) {
  844. const status = Number(this.formData.status);
  845. switch (buttonType) {
  846. case "commit":
  847. return status !== 0; // 提交,status=0时可点击
  848. case "cancel":
  849. return status !== 1; // 撤销,status=1时可点击
  850. case "audit":
  851. return status !== 1; // 审核,status=1时可点击
  852. case "antiAudit":
  853. return status < 2; // 反审核,status>=2时可点击
  854. default:
  855. return true;
  856. }
  857. },
  858. // 标签页切换处理
  859. handleClick(tab, event) {
  860. // 可以在这里添加标签切换时的逻辑
  861. console.log(tab, event);
  862. },
  863. handleDelete(row) {
  864. console.log(row);
  865. this.formData.list.splice(row.$index, 1);
  866. },
  867. selectDepart(item) {
  868. this.formData.deptCode = item.code;
  869. this.formData.deptName = item.name;
  870. },
  871. remoteMaterialSearch(query, type, index) {
  872. if (query !== "") {
  873. this.loading = true;
  874. setTimeout(async () => {
  875. this.loading = false;
  876. const params = {
  877. pageSize: 999,
  878. };
  879. // 根据搜索类型设置参数
  880. if (type === "code") {
  881. params.code = query;
  882. } else {
  883. params.name = query;
  884. }
  885. try {
  886. const {
  887. data: { list },
  888. } = await InRequestApi.getMaterialPage(params);
  889. // 每次搜索都重新赋值,保证列表始终是最新数据
  890. if (type === "code") {
  891. this.materialNoList = list || [];
  892. } else {
  893. this.materialNameList = list || [];
  894. }
  895. } catch (error) {
  896. console.error("搜索物料失败:", error);
  897. // 出错时清空列表
  898. if (type === "code") {
  899. this.materialNoList = [];
  900. } else {
  901. this.materialNameList = [];
  902. }
  903. }
  904. }, 200);
  905. } else {
  906. // 清空对应的列表
  907. if (type === "code") {
  908. this.materialNoList = [];
  909. } else {
  910. this.materialNameList = [];
  911. }
  912. }
  913. },
  914. async remoteRelatedOrder(query) {
  915. if (query !== "") {
  916. this.loading = true;
  917. try {
  918. const { data } = await InRequestApi.getInRequestPage({
  919. pageNo: 1,
  920. pageSize: 100,
  921. businessType: 7,
  922. requestNo: query,
  923. });
  924. this.relatedOrderList = data?.list || [];
  925. } finally {
  926. this.loading = false;
  927. }
  928. } else {
  929. this.relatedOrderList = this.allRelatedOrderList;
  930. }
  931. },
  932. remoteMethod(query) {
  933. if (query !== "") {
  934. this.sourceOrderNoList = this.allSourceOrderNoList.filter((item) =>
  935. item.sourceOrderNo.toLowerCase().includes(query.toLowerCase())
  936. );
  937. } else {
  938. this.sourceOrderNoList = this.allSourceOrderNoList;
  939. }
  940. },
  941. add() {
  942. if (!this.formData.businessType) {
  943. return this.$message.error("请先选择业务类型");
  944. }
  945. this.formData.list = this.formData.list || [];
  946. this.formData.list.push({});
  947. this.formData = { ...this.formData };
  948. },
  949. // remoteWarehouse(query) {
  950. // if (query !== "") {
  951. // const that = this;
  952. // this.loading = true;
  953. // setTimeout(async () => {
  954. // this.loading = false;
  955. // const {
  956. // data: { list },
  957. // } = await InRequestApi.getStockPage({
  958. // name: query,
  959. // pageSize: 999,
  960. // });
  961. // this.warehouseList = list || [];
  962. // }, 200);
  963. // } else {
  964. // this.warehouseList = [];
  965. // }
  966. // },
  967. changeSourceOrderNo(value) {
  968. this.sourceOrderNoList.map((v) => {
  969. if (v.sourceOrderNo == value) {
  970. this.formData.list = v.list;
  971. }
  972. });
  973. },
  974. changeMaterial(value, index, type) {
  975. // 根据选择的类型获取对应的列表
  976. const list =
  977. type === "code" ? this.materialNoList : this.materialNameList;
  978. // 查找选中的物料信息
  979. let selectedMaterial = null;
  980. if (type === "code") {
  981. selectedMaterial = list.find((item) => item.code === value);
  982. // 如果在当前列表找不到,尝试从另一个列表找
  983. if (!selectedMaterial) {
  984. selectedMaterial = this.materialNameList.find(
  985. (item) => item.code === value
  986. );
  987. }
  988. } else {
  989. selectedMaterial = list.find((item) => item.name === value);
  990. // 如果在当前列表找不到,尝试从另一个列表找
  991. if (!selectedMaterial) {
  992. selectedMaterial = this.materialNoList.find(
  993. (item) => item.name === value
  994. );
  995. }
  996. }
  997. if (selectedMaterial) {
  998. // 更新表单中的物料信息
  999. const newRow = {
  1000. ...this.formData.list[index],
  1001. materialNo: selectedMaterial.code,
  1002. materialName: selectedMaterial.name,
  1003. unitName: selectedMaterial.unit || "",
  1004. };
  1005. // 更新行数据
  1006. this.$set(this.formData.list, index, newRow);
  1007. // 强制更新列表,确保页面正常展示
  1008. this.formData.list = [...this.formData.list];
  1009. }
  1010. },
  1011. async changeBusinessDescribe(e) {
  1012. // 1. 找到并存储选中的业务分类整行数据
  1013. const selectedRow =
  1014. (this.businessDescribeList || []).find((v) => v.label === e) || {};
  1015. this.currentBusinessDescribeRow = selectedRow;
  1016. // 2. 设置业务分类值
  1017. if (selectedRow) {
  1018. this.formData.businessCategory = selectedRow.value;
  1019. }
  1020. // 3. 记录选中的名称
  1021. this.selectedBusinessDescribe = e;
  1022. // 4. 调用源单接口
  1023. if (this.formData.businessType && this.selectedBusinessDescribe) {
  1024. this.loading = true;
  1025. try {
  1026. const { data } = await InRequestApi.getSourceOrder({
  1027. businessType: this.formData.businessType,
  1028. businessDescribe: this.selectedBusinessDescribe,
  1029. businessCategory: selectedRow?.value,
  1030. pageSize: 999,
  1031. });
  1032. this.allSourceOrderNoList = data || [];
  1033. this.sourceOrderNoList = this.allSourceOrderNoList;
  1034. } finally {
  1035. this.loading = false;
  1036. }
  1037. }
  1038. },
  1039. async changeBusinessType(value) {
  1040. // 1. 先拿到业务类型对应的整条字典
  1041. const dictRow =
  1042. this.getDictDatas("in_business_type").find((d) => d.value === value) ||
  1043. {};
  1044. this.currentBusinessTypeRow = dictRow; // 整条数据存起来
  1045. // 2. 原有逻辑保持不变
  1046. this.formData.businessType = value;
  1047. this.formData.businessDescribe = "";
  1048. this.formData.businessCategory = "";
  1049. this.formData.sourceOrderNo = "";
  1050. this.formData.list = [];
  1051. this.sourceOrderNoList = [];
  1052. this.allSourceOrderNoList = [];
  1053. this.selectedBusinessDescribe = "";
  1054. this.currentBusinessDescribeRow = null; // 清空业务分类数据
  1055. this.$nextTick(() => this.$refs.formRef.clearValidate());
  1056. const { data } = await InRequestApi.getDictByOrderType({
  1057. orderType: value,
  1058. });
  1059. this.businessDescribeList = data;
  1060. // 委外入库时加载委外发料单列表
  1061. if (value === "9") {
  1062. this.loading = true;
  1063. try {
  1064. const { data } = await InRequestApi.getInRequestPage({
  1065. pageNo: 1,
  1066. pageSize: 100,
  1067. businessType: 7,
  1068. });
  1069. this.allRelatedOrderList = data?.list || [];
  1070. this.relatedOrderList = this.allRelatedOrderList;
  1071. } finally {
  1072. this.loading = false;
  1073. }
  1074. } else {
  1075. // 非委外入库时清空
  1076. this.allRelatedOrderList = [];
  1077. this.relatedOrderList = [];
  1078. this.formData.relatedOrder = undefined;
  1079. }
  1080. },
  1081. /** 初始化数据 */
  1082. async initData(id) {
  1083. this.formLoading = true;
  1084. try {
  1085. /* 1. 拿主表数据 */
  1086. const res = await InRequestApi.getRequest(id);
  1087. const data = res.data;
  1088. /* 2. 把 number 字段统一转字符串 */
  1089. data.businessType && (data.businessType = String(data.businessType));
  1090. data.businessDescribe &&
  1091. (data.businessDescribe = String(data.businessDescribe));
  1092. data.priority && (data.priority = String(data.priority));
  1093. data.status && (data.status = String(data.status));
  1094. data.receivePerson && (data.receivePerson = Number(data.receivePerson));
  1095. data.list = data.list || [];
  1096. /* 3. 补业务分类下拉数据 */
  1097. if (data.businessType) {
  1098. const { data: describeList } = await InRequestApi.getDictByOrderType({
  1099. orderType: data.businessType,
  1100. });
  1101. this.businessDescribeList = describeList || [];
  1102. }
  1103. /* 4. 关键:如果后端也返回了业务分类名称,顺手把源单列表拉回来 */
  1104. if (data.businessType && data.businessDescribe) {
  1105. // 找到当前分类整行,拿 value 字段
  1106. const row = this.businessDescribeList.find(
  1107. (v) => v.label === data.businessDescribe
  1108. );
  1109. this.currentBusinessDescribeRow = row || null;
  1110. this.loading = true;
  1111. try {
  1112. const { data: sourceList } = await InRequestApi.getSourceOrder({
  1113. businessType: data.businessType,
  1114. businessDescribe: data.businessDescribe,
  1115. businessCategory: row?.value,
  1116. id, // 当前单据 id
  1117. pageSize: 999,
  1118. });
  1119. this.allSourceOrderNoList = sourceList || [];
  1120. this.sourceOrderNoList = this.allSourceOrderNoList;
  1121. } finally {
  1122. this.loading = false;
  1123. }
  1124. }
  1125. /* 5. 回填表单 */
  1126. this.formData = data;
  1127. // 委外入库时加载委外发料单列表
  1128. if (data.businessType === "9") {
  1129. this.loading = true;
  1130. try {
  1131. const { data: relatedList } = await InRequestApi.getInRequestPage({
  1132. pageNo: 1,
  1133. pageSize: 100,
  1134. businessType: 7,
  1135. });
  1136. this.allRelatedOrderList = relatedList?.list || [];
  1137. this.relatedOrderList = this.allRelatedOrderList;
  1138. } finally {
  1139. this.loading = false;
  1140. }
  1141. } else {
  1142. this.allRelatedOrderList = [];
  1143. this.relatedOrderList = [];
  1144. }
  1145. /* 6. 附件列表 */
  1146. this.uploadFiles = data.filesListVos || [];
  1147. } finally {
  1148. this.formLoading = false;
  1149. }
  1150. },
  1151. /** 保存按钮 */
  1152. async submitForm() {
  1153. // 校验主表
  1154. await this.$refs["formRef"].validate();
  1155. this.formLoading = true;
  1156. try {
  1157. // /* 1. 深拷贝一份,避免污染页面数据 */
  1158. // const data = JSON.parse(JSON.stringify(this.formData));
  1159. // /* 2. 把仓管员转回字符串 */
  1160. // data.receivePerson =
  1161. // data.receivePerson != null ? String(data.receivePerson) : "";
  1162. const data = this.formData;
  1163. data.list = data.list
  1164. .filter((v) => v.nowDeliveredQty)
  1165. .map(
  1166. ({
  1167. completedQty,
  1168. actualQty,
  1169. stock_code,
  1170. area_code,
  1171. location_code,
  1172. status,
  1173. lineNo,
  1174. inventory_status,
  1175. ...rest
  1176. }) => rest
  1177. );
  1178. // 上传的附件拼接传给后端
  1179. const fileIds = (this.uploadFiles || [])
  1180. .map((item) => {
  1181. return item.id || item.name?.fileId;
  1182. })
  1183. .filter((id) => id && id !== "");
  1184. // 拼接文件ID
  1185. data.fileId = fileIds.join(",");
  1186. // 修改的提交
  1187. if (data.id) {
  1188. await InRequestApi.updateRequest(data);
  1189. this.$modal.msgSuccess("修改成功");
  1190. // 提交成功后刷新数据
  1191. await this.initData(data.id);
  1192. return;
  1193. }
  1194. // 添加的提交
  1195. await InRequestApi.createRequest(data);
  1196. this.$modal.msgSuccess("新增成功");
  1197. this.$router.push({
  1198. path: "/inStorageManage/in-request",
  1199. });
  1200. } finally {
  1201. this.formLoading = false;
  1202. }
  1203. },
  1204. /** 提交按钮 */
  1205. async commit() {
  1206. console.log("打印一下仓管员信息", this.formData.receivePerson);
  1207. if (!this.formData.receivePerson) {
  1208. this.$modal.msgWarning("请先添加仓管员");
  1209. return;
  1210. }
  1211. const menuId = this.$route.meta.id;
  1212. // 只提取需要的字段
  1213. const requestData = {
  1214. id: this.formData.id,
  1215. menuId: menuId,
  1216. };
  1217. // 接口调用
  1218. await InRequestApi.commitInRequest(requestData);
  1219. this.$modal.msgSuccess("提交成功");
  1220. // 提交成功后刷新数据
  1221. await this.initData(this.formData.id);
  1222. // 状态变化
  1223. this.$set(this.formData, "status", "1");
  1224. // 重新获取数据
  1225. const res = await InRequestApi.getRequest(this.formData.id);
  1226. this.formData.bpmInstanceId = res.data.bpmInstanceId;
  1227. },
  1228. /** 撤销按钮 */
  1229. async cancel() {
  1230. const data = this.formData;
  1231. // 接口调用
  1232. await InRequestApi.cancelInRequest(data);
  1233. this.$modal.msgSuccess("撤销成功");
  1234. // 状态变化
  1235. this.$set(this.formData, "status", "0");
  1236. // 跳转到明细信息tab
  1237. this.activeName = "detail";
  1238. // 刷新明细信息
  1239. await this.initData(this.formData.id);
  1240. },
  1241. /** 审核按钮 */
  1242. async audit() {
  1243. // 检查是否存在工作流实例ID
  1244. if (this.formData.bpmInstanceId) {
  1245. // 如果存在工作流实例,跳转到审批任务tab页
  1246. this.activeName = "approvalTask";
  1247. this.$modal.msgWarning("请在审批任务页面完成审核!");
  1248. return;
  1249. }
  1250. const data = this.formData;
  1251. // 接口调用
  1252. await InRequestApi.auditInRequest(data);
  1253. this.$modal.msgSuccess("审核成功");
  1254. // 状态变化
  1255. this.$set(this.formData, "status", "2");
  1256. },
  1257. /** 反审核按钮 */
  1258. async antiAudit() {
  1259. const data = this.formData;
  1260. // 接口调用
  1261. await InRequestApi.antiAuditInRequest(data);
  1262. this.$modal.msgSuccess("反审核成功");
  1263. // 状态变化
  1264. this.$set(this.formData, "status", "0");
  1265. // 跳转到明细信息tab
  1266. this.activeName = "detail";
  1267. // 刷新明细信息
  1268. await this.initData(this.formData.id);
  1269. },
  1270. /** 返回按钮 */
  1271. handleCancel() {
  1272. this.reset();
  1273. this.$router.push({
  1274. path: "/inStorageManage/in-request",
  1275. });
  1276. },
  1277. /** 表单重置 */
  1278. reset() {
  1279. this.formData = {
  1280. id: undefined,
  1281. // list: [],
  1282. originStockCode: undefined,
  1283. relatedOrder: undefined,
  1284. requestNo: undefined,
  1285. requestType: undefined,
  1286. businessType: undefined,
  1287. businessCategory: undefined,
  1288. businessDescribe: undefined,
  1289. businessSubType: undefined,
  1290. status: undefined,
  1291. priority: undefined,
  1292. warehouseId: undefined,
  1293. relatedWarehouseId: undefined,
  1294. supplierCode: undefined,
  1295. customerCode: undefined,
  1296. sourceOrderNo: undefined,
  1297. expectedTime: undefined,
  1298. actualTime: undefined,
  1299. totalQty: undefined,
  1300. totalSku: undefined,
  1301. totalLine: undefined,
  1302. remark: undefined,
  1303. extendInfo: undefined,
  1304. submitter: undefined,
  1305. submitTime: undefined,
  1306. auditor: undefined,
  1307. auditTime: undefined,
  1308. erpWriteFlag: undefined,
  1309. erpErrMsg: undefined,
  1310. erpBackId: undefined,
  1311. list: [],
  1312. };
  1313. this.resetForm("formRef");
  1314. },
  1315. deliverChange(val) {
  1316. // 这里可以写“本次出入数量”变化后的校验或计算逻辑
  1317. console.log("deliverChange", val);
  1318. },
  1319. // 附件上传
  1320. handleUpload() {
  1321. this.$refs.attachmentUpload.isUploadShow = -1;
  1322. this.$refs.attachmentUpload.title = "上传附件";
  1323. // 直接使用当前组件维护的 uploadFiles,而不是重新获取
  1324. this.$refs.attachmentUpload.fileList = this.uploadFiles || [];
  1325. this.$refs.attachmentUpload.visible = true;
  1326. },
  1327. // 获取上传的附件
  1328. getFileList(data) {
  1329. this.uploadFiles = data;
  1330. },
  1331. // 供应商编码过滤方法
  1332. filterSupplier(keyword) {
  1333. const key = (keyword || "").toLowerCase();
  1334. this.supplierOptions = this.supplierList.filter(
  1335. (item) =>
  1336. item.code.toLowerCase().includes(key) ||
  1337. (item.name && item.name.toLowerCase().includes(key))
  1338. );
  1339. },
  1340. },
  1341. };
  1342. </script>
  1343. <style scoped>
  1344. .page-header {
  1345. margin-bottom: 20px;
  1346. padding: 15px 0;
  1347. border-bottom: 1px solid #eee;
  1348. }
  1349. .header-content {
  1350. display: flex;
  1351. flex-direction: column;
  1352. align-items: flex-start;
  1353. }
  1354. .breadcrumb {
  1355. margin-bottom: 15px;
  1356. }
  1357. .header-buttons {
  1358. display: flex;
  1359. justify-content: flex-start;
  1360. align-items: center;
  1361. }
  1362. .header-buttons .el-button {
  1363. margin-right: 10px;
  1364. }
  1365. .form-container {
  1366. margin-bottom: 20px;
  1367. }
  1368. .app-container {
  1369. min-width: 900px;
  1370. margin: 0 auto;
  1371. overflow-x: auto;
  1372. }
  1373. </style>