addSample.vue 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360
  1. <template>
  2. <ele-modal
  3. :visible.sync="visible"
  4. :title="title"
  5. width="80%"
  6. append-to-body
  7. :maxable="true"
  8. @close="cancel"
  9. >
  10. <div class="switch" v-if="type == 'view'">
  11. <div class="switch_left">
  12. <ul>
  13. <li
  14. v-for="item in tabOptions"
  15. :key="item.key"
  16. :class="{ active: activeComp == item.key }"
  17. @click="activeComp = item.key"
  18. >
  19. {{ item.name }}
  20. </li>
  21. </ul>
  22. </div>
  23. </div>
  24. <el-form
  25. v-show="activeComp === 'main'"
  26. ref="form"
  27. :model="form"
  28. :rules="rules"
  29. label-width="120px"
  30. class="el-form-box"
  31. :disabled="type == 'view'"
  32. >
  33. <header-title title="基本信息"></header-title>
  34. <el-row>
  35. <el-col :span="8">
  36. <el-form-item label="检测工单编码:" prop="qualityWorkOrderCode">
  37. <el-input
  38. :disabled="!isSampleRecord || (isSampleRecord && type != 'add')"
  39. readonly
  40. v-model="form.qualityWorkOrderCode"
  41. placeholder=" "
  42. @click.native="$refs.inspectionWorkDialog.open()"
  43. />
  44. </el-form-item>
  45. </el-col>
  46. <el-col :span="8">
  47. <el-form-item label="检测工单名称:" prop="qualityWorkOrderName">
  48. <el-input
  49. disabled
  50. v-model="form.qualityWorkOrderName"
  51. placeholder=" "
  52. />
  53. </el-form-item>
  54. </el-col>
  55. <el-col :span="8">
  56. <el-form-item label="来源单号:" prop="sourceCode">
  57. <el-input
  58. disabled
  59. :value="form.qualityWorkOrderCode"
  60. placeholder=" "
  61. />
  62. </el-form-item>
  63. </el-col>
  64. <el-col :span="8">
  65. <el-form-item label="类型:" prop="qualityType">
  66. <DictSelection
  67. dictName="质检计划类型"
  68. v-model="form.qualityType"
  69. disabled
  70. ></DictSelection>
  71. </el-form-item>
  72. </el-col>
  73. <el-col :span="8">
  74. <el-form-item label="编码:" prop="productCode">
  75. <el-input disabled v-model="form.productCode" placeholder=" " />
  76. </el-form-item>
  77. </el-col>
  78. <el-col :span="8">
  79. <el-form-item label="名称:" prop="productName">
  80. <el-input disabled v-model="form.productName" placeholder=" " />
  81. </el-form-item>
  82. </el-col>
  83. <el-col :span="8">
  84. <el-form-item label="批次号:" prop="batchNo">
  85. <el-input disabled v-model="form.batchNo" placeholder=" " />
  86. </el-form-item>
  87. </el-col>
  88. <el-col :span="8">
  89. <el-form-item label="规格:" prop="specification">
  90. <el-input disabled v-model="form.specification" placeholder=" " />
  91. </el-form-item>
  92. </el-col>
  93. <el-col :span="8">
  94. <el-form-item label="型号:" prop="modelType">
  95. <el-input disabled v-model="form.modelType" placeholder=" " />
  96. </el-form-item>
  97. </el-col>
  98. <el-col :span="8">
  99. <el-form-item label="牌号:" prop="brandNo">
  100. <el-input disabled v-model="form.brandNo" placeholder=" " />
  101. </el-form-item>
  102. </el-col>
  103. <el-col :span="8">
  104. <el-form-item label="总数:" prop="total">
  105. <el-input disabled v-model="form.total" placeholder=" ">
  106. <template slot="append">
  107. {{ tableList[0]?.measureUnit }}
  108. </template>
  109. </el-input>
  110. </el-form-item>
  111. </el-col>
  112. <!-- <el-col :span="8">
  113. <el-form-item label="样品数:" prop="sampleQuantity">
  114. <el-input disabled v-model="form.sampleQuantity" placeholder=" ">
  115. <template slot="append">
  116. {{ form.qualityMode == 1 ? form.measureUnit : form.unit }}
  117. </template>
  118. </el-input>
  119. </el-form-item>
  120. </el-col> -->
  121. </el-row>
  122. <header-title title="来源清单"></header-title>
  123. <ele-pro-table
  124. ref="sourceTable"
  125. :columns="tableColumns"
  126. :datasource="tableList"
  127. :initLoad="false"
  128. :needPage="false"
  129. height="300px"
  130. full-height="calc(100vh - 120px)"
  131. :selection.sync="selection"
  132. >
  133. <template v-slot:toolbar>
  134. 累计请样数量:{{ workSampleQuantity
  135. }}{{ sampleList[0]?.measureUnit || form.measureUnit }}
  136. </template>
  137. </ele-pro-table>
  138. <header-title title="请样信息"> </header-title>
  139. <el-row>
  140. <el-col :span="8">
  141. <el-form-item label="请样目的:" prop="pleasePurpose">
  142. <el-input
  143. v-model="form.pleasePurpose"
  144. placeholder="请输入"
  145. ></el-input>
  146. </el-form-item>
  147. </el-col>
  148. <el-col :span="8">
  149. <el-form-item label="检测方式:" prop="qualityMode">
  150. <DictSelection
  151. dictName="取样类型"
  152. v-model="form.qualityMode"
  153. @change="handleQualityModeChange"
  154. :disabled="form.isFirstSampling != '1'"
  155. ></DictSelection>
  156. </el-form-item>
  157. </el-col>
  158. <el-col :span="8">
  159. <el-form-item label="记录方法:" prop="recordingMethod">
  160. <el-select
  161. style="width: 100%"
  162. v-model="form.recordingMethod"
  163. placeholder="请选择"
  164. :disabled="form.isFirstSampling != '1'"
  165. >
  166. <el-option
  167. v-for="item in recordingMethodList"
  168. :label="item.label"
  169. :value="item.value"
  170. :key="item.value"
  171. ></el-option>
  172. </el-select>
  173. </el-form-item>
  174. </el-col>
  175. </el-row>
  176. <el-row v-if="form.qualityMode == '2'">
  177. <el-col :span="8">
  178. <el-form-item label="请样类型:" prop="conditionType">
  179. <el-select
  180. style="width: 100%"
  181. v-model="form.conditionType"
  182. placeholder="请选择"
  183. :disabled="form.isFirstSampling != '1'"
  184. >
  185. <el-option
  186. v-for="item in sampleNumberList"
  187. :label="item.label"
  188. :value="item.value"
  189. :key="item.value"
  190. ></el-option>
  191. </el-select>
  192. </el-form-item>
  193. </el-col>
  194. <el-col :span="16">
  195. <el-row>
  196. <el-col :span="6" v-if="form.conditionType == 2">
  197. <el-form-item prop="quantity" label="数量">
  198. <el-input
  199. v-model="form.quantity"
  200. placeholder="请输入"
  201. ></el-input>
  202. </el-form-item>
  203. </el-col>
  204. <el-col :span="6" v-if="form.conditionType == 2">
  205. <el-form-item prop="unit" label-width="0">
  206. <DictSelection
  207. dictName="计量单位"
  208. clearable
  209. :disabled="form.isFirstSampling != '1'"
  210. v-model="form.unit"
  211. filter-placeholder="请输入计量单位搜索"
  212. ></DictSelection>
  213. </el-form-item>
  214. </el-col>
  215. <el-col :span="8" v-if="form.conditionType == 2">
  216. <el-form-item prop="portion" label="条数">
  217. <el-input
  218. v-model="form.portion"
  219. placeholder="请输入"
  220. ></el-input>
  221. </el-form-item>
  222. </el-col>
  223. <el-col :span="10" v-if="form.conditionType == 1">
  224. <el-form-item prop="portion" label="数量">
  225. <el-input
  226. v-model="form.portion"
  227. placeholder="请输入"
  228. ></el-input>
  229. </el-form-item>
  230. </el-col>
  231. <el-col :span="10" v-if="form.conditionType == 1">
  232. <el-form-item prop="packingUnit" label="单位">
  233. <el-select
  234. v-model="form.packingUnit"
  235. placeholder="请选择"
  236. :disabled="form.isFirstSampling != '1'"
  237. >
  238. <el-option
  239. v-for="item in packingSpecificationOption"
  240. :key="item.id"
  241. :label="item.conversionUnit"
  242. :value="item.id"
  243. @click.native="handlePackingUnitChange(item)"
  244. >
  245. </el-option>
  246. </el-select>
  247. </el-form-item>
  248. </el-col>
  249. <el-col
  250. :span="4"
  251. style="text-align: right"
  252. v-if="form.conditionType == 2 && type != 'view'"
  253. >
  254. <el-button
  255. type="primary"
  256. size="mini"
  257. @click="handleSampleSubmit"
  258. style="margin-right: 12px"
  259. >确认</el-button
  260. >
  261. </el-col>
  262. <el-col
  263. :span="4"
  264. style="text-align: right"
  265. v-if="form.conditionType == 1 && type != 'view'"
  266. >
  267. <el-button
  268. type="primary"
  269. size="mini"
  270. @click="handleSampleSubmit"
  271. style="margin-right: 12px"
  272. >确认</el-button
  273. >
  274. </el-col>
  275. </el-row>
  276. </el-col>
  277. </el-row>
  278. <header-title title="样品信息"></header-title>
  279. <ele-pro-table
  280. ref="showSampleListTable"
  281. :columns="tableColumns1"
  282. :datasource="sampleList"
  283. :needPage="false"
  284. height="400px"
  285. full-height="calc(100vh - 120px)"
  286. >
  287. <!-- <template>attachmentUrl</template> -->
  288. <template v-slot:attachmentUrl="{ row, $index }">
  289. <fileMain
  290. v-model="row.attachmentUrl"
  291. :directoryId="
  292. $store.state.user.info.clientEnvironmentId == 10
  293. ? '2065608790337171458'
  294. : ''
  295. "
  296. ></fileMain>
  297. </template>
  298. </ele-pro-table>
  299. </el-form>
  300. <bpmDetail
  301. v-if="activeComp == 'bpm' && form.processInstanceId"
  302. :id="form.processInstanceId"
  303. ></bpmDetail>
  304. <template v-slot:footer>
  305. <el-button
  306. type="primary"
  307. @click="save()"
  308. v-loading="loading"
  309. v-if="type != 'view'"
  310. >保存</el-button
  311. >
  312. <el-button
  313. type="primary"
  314. @click="save('submit')"
  315. v-loading="loading"
  316. v-if="type != 'view' && isSamplingApproval == 1"
  317. >提交</el-button
  318. >
  319. <el-button @click="cancel">关闭</el-button>
  320. </template>
  321. <inspectionWorkDialog
  322. ref="inspectionWorkDialog"
  323. @changeParent="changeParent"
  324. ></inspectionWorkDialog>
  325. <processSubmitDialog
  326. :processSubmitDialogFlag.sync="processSubmitDialogFlag"
  327. v-if="processSubmitDialogFlag"
  328. ref="processSubmitDialogRef"
  329. @reload="search"
  330. ></processSubmitDialog>
  331. </ele-modal>
  332. </template>
  333. <script>
  334. import processSubmitDialog from '@/components/processSubmitDialog/processSubmitDialog.vue';
  335. import { recordingMethodList } from '@/utils/util.js';
  336. const defForm = {
  337. code: '', //编码
  338. name: '', //名称
  339. conditionType: '',
  340. quantity: '',
  341. unit: '',
  342. portion: '',
  343. qualityMode: '',
  344. recordingMethod: 1,
  345. pleaseQuantity: '',
  346. pleasePurpose: '',
  347. pleaseUnit: '',
  348. sampleQuantity: '',
  349. qualityWorkOrderId: '',
  350. qualityWorkOrderCode: '',
  351. qualityWorkOrderName: '',
  352. isFirstSampling: ''
  353. };
  354. import {
  355. queryQualityInventory,
  356. queryQualityTempleContent
  357. } from '@/api/inspectionWork';
  358. import {
  359. samplingrecordSave,
  360. getById,
  361. samplingrecordUpdate,
  362. samplingRecordsPage
  363. } from '@/api/samplingRecords';
  364. import bpmDetail from '@/views/bpm/processInstance/detail.vue';
  365. import inspectionWorkDialog from '@/views/inspectionWork/components/inspectionWorkDialog.vue';
  366. import { getCodeList, getCode } from '@/api/login';
  367. import { parameterGetByCode } from '@/api/main/index';
  368. export default {
  369. components: { bpmDetail, inspectionWorkDialog, processSubmitDialog },
  370. props: {
  371. isSampleRecord: {
  372. default: false
  373. }
  374. },
  375. data() {
  376. return {
  377. recordingMethodList,
  378. processSubmitDialogFlag: false,
  379. form: { ...defForm },
  380. activeComp: 'main',
  381. tabOptions: [
  382. { key: 'main', name: '请样详情' },
  383. { key: 'bpm', name: '流程详情' }
  384. ],
  385. workSampleQuantity: 0,
  386. visible: false,
  387. loading: false,
  388. rules: {
  389. qualityWorkOrderCode: [
  390. { required: true, message: '请选择检测工单', trigger: 'change' }
  391. ],
  392. qualityMode: [
  393. { required: true, message: '请选择检测方式', trigger: 'change' }
  394. ],
  395. recordingMethod: [
  396. { required: true, message: '请选择记录方法', trigger: 'change' }
  397. ],
  398. conditionType: [
  399. { required: true, message: '请选择请样类型', trigger: 'change' }
  400. ],
  401. quantity: [{ required: true, message: '请输入', trigger: 'change' }],
  402. portion: [{ required: true, message: '请输入', trigger: 'change' }],
  403. unit: [{ required: true, message: '请选择', trigger: 'change' }],
  404. packingUnit: [
  405. { required: true, message: '请选择', trigger: 'change' }
  406. ]
  407. },
  408. sampleNumberList: [
  409. { label: '请整样', value: 1 },
  410. { label: '请小样', value: 2 }
  411. ],
  412. selection: [],
  413. tableColumns1: [
  414. {
  415. label: '样品编码',
  416. prop: 'sampleCode',
  417. width: '200',
  418. align: 'center',
  419. fixed: 'left'
  420. },
  421. {
  422. label: '编码',
  423. prop: 'categoryCode',
  424. align: 'center',
  425. fixed: 'left'
  426. },
  427. {
  428. label: '名称',
  429. prop: 'categoryName',
  430. align: 'center'
  431. },
  432. {
  433. label: '照片',
  434. prop: 'attachmentUrl',
  435. slot: 'attachmentUrl',
  436. width: 150,
  437. align: 'center'
  438. },
  439. { label: '批次号', prop: 'batchNo', align: 'center' },
  440. { label: '发货条码', prop: 'barcodes', align: 'center' },
  441. { label: '包装编码', prop: 'packageNo', align: 'center' },
  442. { label: '包装数量', prop: 'packingQuantity', align: 'center' },
  443. { label: '包装单位', prop: 'packingUnit', align: 'center' },
  444. { label: '计量数量', prop: 'measureQuantity', align: 'center' },
  445. { label: '计量单位', prop: 'measureUnit', align: 'center' },
  446. {
  447. label: '供应商名称',
  448. prop: 'supplierName',
  449. align: 'center',
  450. width: '120'
  451. },
  452. {
  453. label: '供应商代号',
  454. prop: 'supplierCode',
  455. align: 'center',
  456. width: '120'
  457. },
  458. {
  459. label: '物料代号',
  460. prop: 'materielDesignation',
  461. align: 'center',
  462. slot: 'materielDesignation',
  463. width: '120'
  464. },
  465. {
  466. label: '客户代号',
  467. prop: 'clientCode',
  468. align: 'center',
  469. slot: 'clientCode',
  470. width: '120'
  471. },
  472. {
  473. label: '刻码',
  474. prop: 'engrave',
  475. align: 'center',
  476. slot: 'engrave',
  477. width: '120'
  478. },
  479. {
  480. label: '机型',
  481. prop: 'modelKey',
  482. align: 'center',
  483. showOverflowTooltip: true
  484. },
  485. {
  486. label: '颜色',
  487. prop: 'colorKey',
  488. align: 'center',
  489. showOverflowTooltip: true
  490. },
  491. {
  492. label: '重量',
  493. prop: 'weight',
  494. align: 'center',
  495. slot: 'weight',
  496. width: '120'
  497. },
  498. {
  499. label: '重量单位',
  500. prop: 'weightUnit',
  501. align: 'center',
  502. width: 100
  503. },
  504. { label: '仓库', prop: 'warehouseName', align: 'center', width: 100 },
  505. { label: '货区', prop: 'areaName', align: 'center' },
  506. { label: '货架', prop: 'goodsShelfName', align: 'center' },
  507. { label: '货位', prop: 'goodsAllocationName', align: 'center' },
  508. { label: '生产日期', prop: 'productionDate', align: 'center' },
  509. { label: '采购日期', prop: 'purchaseDate', align: 'center' }
  510. ],
  511. tableColumns: [
  512. {
  513. columnKey: 'selection',
  514. type: 'selection',
  515. width: 45,
  516. align: 'center'
  517. },
  518. {
  519. columnKey: 'index',
  520. label: '序号',
  521. type: 'index',
  522. width: 55,
  523. align: 'center',
  524. fixed: 'left'
  525. },
  526. {
  527. label: '编码',
  528. prop: 'categoryCode',
  529. width: 150,
  530. align: 'center',
  531. showOverflowTooltip: true
  532. },
  533. {
  534. label: '名称',
  535. prop: 'categoryName',
  536. width: '150',
  537. align: 'center',
  538. width: 120,
  539. showOverflowTooltip: true
  540. },
  541. {
  542. label: '批次号',
  543. prop: 'batchNo',
  544. align: 'center',
  545. width: 120,
  546. showOverflowTooltip: true
  547. },
  548. {
  549. label: '发货条码',
  550. prop: 'barcodes',
  551. align: 'center',
  552. showOverflowTooltip: true
  553. },
  554. {
  555. label: '包装编码',
  556. prop: 'packageNo',
  557. align: 'center',
  558. width: 120,
  559. showOverflowTooltip: true
  560. },
  561. { label: '包装数量', prop: 'packingQuantity', align: 'center' },
  562. { label: '包装单位', prop: 'packingUnit', align: 'center' },
  563. { label: '计量数量', prop: 'measureQuantity', align: 'center' },
  564. { label: '计量单位', prop: 'measureUnit', align: 'center' },
  565. { label: '物料代号', prop: 'materielDesignation', align: 'center' },
  566. { label: '客户代号', prop: 'clientCode', align: 'center' },
  567. {
  568. label: '供应商名称',
  569. prop: 'supplierName',
  570. align: 'center',
  571. width: 120,
  572. showOverflowTooltip: true
  573. },
  574. {
  575. label: '供应商代号',
  576. prop: 'supplierCode',
  577. align: 'center',
  578. width: '120',
  579. showOverflowTooltip: true
  580. },
  581. { label: '刻码', prop: 'engrave', align: 'center' },
  582. {
  583. label: '机型',
  584. prop: 'modelKey',
  585. align: 'center',
  586. showOverflowTooltip: true
  587. },
  588. {
  589. label: '颜色',
  590. prop: 'colorKey',
  591. align: 'center',
  592. showOverflowTooltip: true
  593. },
  594. { label: '重量', prop: 'weight', align: 'center' },
  595. { label: '重量单位', prop: 'weightUnit', align: 'center' },
  596. {
  597. label: '仓库',
  598. prop: 'warehouseName',
  599. align: 'center',
  600. width: 120,
  601. showOverflowTooltip: true
  602. },
  603. { label: '货区', prop: 'areaName', align: 'center' },
  604. { label: '货架', prop: 'goodsShelfName', align: 'center' },
  605. { label: '货位', prop: 'goodsAllocationName', align: 'center' },
  606. {
  607. label: '生产日期',
  608. prop: 'productionDate',
  609. align: 'center',
  610. width: 120,
  611. showOverflowTooltip: true
  612. },
  613. {
  614. label: '采购日期',
  615. prop: 'purchaseDate',
  616. align: 'center',
  617. width: 120,
  618. showOverflowTooltip: true
  619. }
  620. ],
  621. packingSpecificationOption: [],
  622. sampleList: [],
  623. schemeList: [],
  624. tableList: [],
  625. type: 'add',
  626. title: '',
  627. isSamplingApproval: 0
  628. };
  629. },
  630. computed: {},
  631. created() {},
  632. methods: {
  633. handlePackingUnitChange(val) {
  634. this.$set(this.form, 'unit', val.conversionUnit);
  635. },
  636. async open(type, row) {
  637. this.activeComp = 'main';
  638. this.visible = true;
  639. this.type = type;
  640. this.parameterGetByCode();
  641. this.title =
  642. type == 'add' ? '请样' : type == 'edit' ? '修改请样' : '详情';
  643. if (type == 'add') {
  644. if (row) {
  645. this.init(row);
  646. }
  647. } else {
  648. this.getById(row.id);
  649. }
  650. },
  651. parameterGetByCode() {
  652. parameterGetByCode({
  653. code: 'sampling_approval'
  654. }).then((res) => {
  655. this.isSamplingApproval = res.value;
  656. });
  657. },
  658. async init(row) {
  659. let isPackingUnit = false;
  660. let data = await samplingRecordsPage({
  661. qualityWorkOrderId: row.id
  662. });
  663. let list = data.list.filter(
  664. (item) => item.status === 0 || item.status === 4
  665. );
  666. let list1 = data.list.filter((item) => item.status != 3);
  667. if (list?.length) {
  668. this.getById(list[0].id);
  669. this.type = 'edit';
  670. this.title = '修改请样';
  671. } else {
  672. row.sourceCode = row.qualityPlanCode || row.workOrderCode;
  673. this.form = JSON.parse(JSON.stringify(row));
  674. this.form.qualityWorkOrderId = row.id;
  675. this.form.qualityWorkOrderCode = row.code;
  676. this.form.qualityWorkOrderName = row.name;
  677. this.workSampleQuantity = Number(row.sampleQuantity) || 0;
  678. if (!list1?.length) {
  679. this.form.isFirstSampling = 1;
  680. isPackingUnit = true;
  681. if (this.form.conditionType == 1) {
  682. this.$set(this.form, 'packingUnit', '111');
  683. }
  684. } else {
  685. this.$set(this.form, 'unit', list1[0].unit);
  686. this.$set(this.form, 'measureUnit', list1[0].measureUnit);
  687. }
  688. await this.datasource(list1[0]?.unit, isPackingUnit);
  689. await this.queryQualityTempleContent(
  690. !list1.length && row.qualityMode == 1
  691. );
  692. if (
  693. this.$store.state.user.info.clientEnvironmentId == 10 &&
  694. this.form.qualityType == 3
  695. ) {
  696. this.form.qualityMode = 2;
  697. this.form.recordingMethod = 2;
  698. this.form.conditionType = 2;
  699. this.form.quantity = 1;
  700. this.form.portion = 1;
  701. await this.queryQualityTempleContent(true);
  702. this.save();
  703. }
  704. }
  705. },
  706. getById(id) {
  707. getById(id).then((res) => {
  708. this.workSampleQuantity =
  709. Number(res.qualityWorkOrderVO.sampleQuantity) || 0;
  710. [
  711. 'id',
  712. 'code',
  713. 'name',
  714. 'createTime',
  715. 'createUserId',
  716. 'status',
  717. 'approvalStatus',
  718. 'approvalUserId',
  719. 'sampleQuantity',
  720. 'processInstanceId'
  721. ].forEach((it) => {
  722. delete res.qualityWorkOrderVO[it];
  723. });
  724. this.form = { ...res, ...res.qualityWorkOrderVO };
  725. this.datasource(this.form.unit);
  726. this.queryQualityTempleContent();
  727. if (this.form.qualityMode == 2) {
  728. if (res.qualityWorkOrderVO.conditionType == 1) {
  729. // if (res.unit != res.qualitySampleList[0].measureUnit) {
  730. // this.$set(this.form, 'portion', res.qualitySampleList.length);
  731. // } else {
  732. // }
  733. this.$set(this.form, 'portion', res.quantity);
  734. this.$set(this.form, 'quantity', 0);
  735. } else {
  736. this.$set(this.form, 'portion', res.copies);
  737. // this.$set(this.form, 'quantity', res.quantity / res.copies);
  738. }
  739. }
  740. this.sampleList = res.qualitySampleList;
  741. });
  742. },
  743. /* 查询质检模板内容 */
  744. async queryQualityTempleContent(is) {
  745. const res = await queryQualityTempleContent({
  746. qualityWorkerId: this.form.qualityWorkOrderId,
  747. page: 1,
  748. size: 10000
  749. });
  750. this.schemeList = res.list;
  751. if (is) {
  752. await this.updatePackingList();
  753. }
  754. return;
  755. },
  756. cancel() {
  757. this.form = {
  758. ...defForm
  759. };
  760. this.schemeList = [];
  761. this.packingSpecificationOption = [];
  762. this.sampleList = [];
  763. this.tableList = [];
  764. this.visible = false;
  765. },
  766. changeParent(row) {
  767. this.init(row);
  768. },
  769. async datasource(unit, isPackingUnit) {
  770. const res = await queryQualityInventory({
  771. qualityWorkerId: this.form.qualityWorkOrderId,
  772. pageNum: 1,
  773. size: -1
  774. });
  775. let o = res.list[0];
  776. let listArr = [];
  777. if (o.measureUnit) {
  778. listArr.push({
  779. packageCellTotal: 1,
  780. conversionUnit: o.measureUnit,
  781. id: '111'
  782. });
  783. }
  784. if (o.packingUnit) {
  785. listArr.push({
  786. packageCellTotal: o.measureQuantity - 0,
  787. conversionUnit: o.packingUnit,
  788. id: '222'
  789. });
  790. }
  791. if (unit) {
  792. this.$set(
  793. this.form,
  794. 'packingUnit',
  795. listArr.find((item) => unit == item.conversionUnit)?.id
  796. );
  797. }
  798. if (isPackingUnit) {
  799. this.$set(this.form, 'unit', res.list[0]?.measureUnit);
  800. }
  801. this.form.pleaseUnit = res.list[0]?.measureUnit;
  802. res.list.map((el) => {
  803. el.weightProportion = el.weight
  804. ? (el.weight / el.measureQuantity).toFixed(4)
  805. : 0;
  806. el.weightProportion = el.weightProportion - 0;
  807. });
  808. this.packingSpecificationOption = listArr;
  809. this.tableList = res.list;
  810. this.selection = res.list;
  811. this.$nextTick(() => {
  812. this.$refs.sourceTable.toggleAllSelection();
  813. });
  814. return res;
  815. },
  816. handleSampleSubmit() {
  817. this.$refs.form.validate((valid) => {
  818. if (valid) {
  819. let params = {
  820. conditionType: this.form.conditionType,
  821. quantity: this.form.quantity,
  822. sampleUnit: this.form.unit,
  823. portion: this.form.portion
  824. };
  825. let specifications = this.packingSpecificationOption.find(
  826. (el) => el.id == this.form.packingUnit
  827. );
  828. this.sampleFn(params, specifications);
  829. }
  830. });
  831. },
  832. async sampleFn(data, specifications) {
  833. this.sampleList = [];
  834. if (!this.selection || this.selection.length == 0) {
  835. this.$message.warning('请先选择来源清单!');
  836. return;
  837. }
  838. const quantity = data.quantity || 1;
  839. const unit = data.sampleUnit;
  840. const sampleCount = Number(data.portion);
  841. try {
  842. // 2 取小样
  843. if (this.form.conditionType == 2) {
  844. if (!this.validateMeasureQuantity(quantity, unit, sampleCount))
  845. return; //取样数量验证
  846. if (unit === 'KG' && !this.validateWeight(quantity, sampleCount))
  847. return; // 若计量单位为重量,还需验证总重量是否足够
  848. await this.getNewFullSampleList(
  849. Math.ceil(sampleCount),
  850. // sampleCount,
  851. quantity,
  852. unit,
  853. specifications
  854. );
  855. } else {
  856. let isFlag = this.validateSampleQuantity(
  857. sampleCount,
  858. specifications
  859. );
  860. if (!isFlag) return;
  861. if (this.form.inspectionStandards == 1) {
  862. await this.getNewFullSampleList(
  863. Math.ceil(sampleCount),
  864. quantity,
  865. unit,
  866. specifications
  867. );
  868. } else {
  869. await this.handleWeightFullSample(sampleCount, specifications);
  870. }
  871. }
  872. } catch (error) {
  873. console.error('请样处理失败:', error);
  874. this.$message.error('请样处理失败');
  875. }
  876. },
  877. validateWeight(quantity, sampleCount) {
  878. let totalMaxPossible = 0;
  879. this.selection.forEach((item) => {
  880. totalMaxPossible += item.measureQuantity / quantity;
  881. });
  882. if (totalMaxPossible < sampleCount) {
  883. this.$message.info(`最大请样条数为${totalMaxPossible}`);
  884. return false;
  885. }
  886. let totalWeight = this.selection.reduce(
  887. (sum, item) => sum + item.weight,
  888. 0
  889. );
  890. const weightUnit = this.selection[0].weightUnit;
  891. if (weightUnit === 'G') totalWeight /= 1000;
  892. if (quantity * sampleCount > totalWeight) {
  893. this.$message.info('请样计量重量不能大于总计量重量');
  894. return false;
  895. }
  896. const invalidItem = this.selection.find((item) => {
  897. const weight =
  898. item.weightUnit === 'G' ? item.weight / 1000 : item.weight;
  899. return weight < quantity;
  900. });
  901. if (invalidItem) {
  902. this.$message.info('勾选条目重量小于请样重量');
  903. return false;
  904. }
  905. return true;
  906. },
  907. validateMeasureQuantity(quantity, unit, sampleCount) {
  908. if (quantity <= 0) {
  909. this.$message.info('请样计量数量必须大于0');
  910. return false;
  911. }
  912. const totalQuantity =
  913. this.selection.reduce((sum, item) => sum + item.measureQuantity, 0) -
  914. this.workSampleQuantity;
  915. if (
  916. this.selection[0].measureUnit === unit &&
  917. quantity * sampleCount > totalQuantity
  918. ) {
  919. this.$message.info('请样计量数量不能大于总计量数量');
  920. return false;
  921. }
  922. const invalidItem = this.selection.find(
  923. (item) => item.measureQuantity < quantity
  924. );
  925. if (invalidItem) {
  926. this.$message.info('条目计量数量小于请样计量数量');
  927. return false;
  928. }
  929. return true;
  930. },
  931. async handleWeightFullSample(sampleCount, specifications) {
  932. const dataList = [];
  933. let currentNum = sampleCount - this.selection.length;
  934. let currentNum1 = sampleCount;
  935. for (const item of this.selection) {
  936. const qualitySampleTemplateList = item.qualitySampleTemplateList
  937. ?.length
  938. ? JSON.parse(JSON.stringify(item.qualitySampleTemplateList))
  939. : JSON.parse(
  940. JSON.stringify(
  941. this.schemeList.map((item) => {
  942. item['qualityResults'] = 1;
  943. return item;
  944. })
  945. )
  946. );
  947. if (sampleCount >= this.selection.length) {
  948. dataList.push({
  949. ...item,
  950. measureQuantity: 1, //作为计量数量
  951. sampleCode: await getCode('sample_code'),
  952. qualitySampleTemplateList
  953. });
  954. } else {
  955. if (dataList.length < sampleCount) {
  956. dataList.push({
  957. ...item,
  958. measureQuantity: currentNum1 > 1 ? 1 : currentNum1, //作为计量数量
  959. sampleCode: await getCode('sample_code'),
  960. qualitySampleTemplateList
  961. });
  962. currentNum1 -= 1;
  963. }
  964. }
  965. }
  966. if (sampleCount > this.selection.length) {
  967. dataList.forEach((item) => {
  968. if (currentNum > 0) {
  969. let data = this.selection.find((val) => val.id == item.id);
  970. item['measureQuantity'] =
  971. data.measureQuantity - 1 - currentNum > 0
  972. ? currentNum + 1
  973. : data.measureQuantity;
  974. currentNum = currentNum - (data.measureQuantity - 1);
  975. }
  976. });
  977. }
  978. // 更改 从新计算 样品清单 取整样 数据
  979. if (specifications && specifications.id) {
  980. // let proportion = (obj.weight / obj.measureQuantity).toFixed(2);
  981. dataList.map((el) => {
  982. el.measureQuantity =
  983. el.measureQuantity * specifications.packageCellTotal;
  984. el.weight = this.formatNumber(
  985. el.measureQuantity,
  986. el.weightProportion
  987. );
  988. });
  989. }
  990. // 更改
  991. this.sampleList = dataList;
  992. this.getTotal();
  993. },
  994. // 小数点数据判断
  995. formatNumber(a, b, maxDecimals = 4) {
  996. if (a == 0 || b == 0 || !a || !b) {
  997. return 0;
  998. }
  999. // 计算乘积
  1000. const product = a * b;
  1001. // 转换为固定小数位数,然后转换为数字以去除末尾零
  1002. const rounded = Number(product.toFixed(maxDecimals));
  1003. // 转换为字符串检查是否需要显示小数部分
  1004. const str = rounded.toString();
  1005. // 如果包含小数点
  1006. if (str.indexOf('.') !== -1) {
  1007. // 移除末尾的零和小数点(如果后面没有数字了)
  1008. return str.replace(/\.?0+$/, '');
  1009. }
  1010. return str;
  1011. },
  1012. //从来源数组取样到目标数组
  1013. async getNewFullSampleList(
  1014. sampleCount,
  1015. sampleQuantity,
  1016. sampleUnit,
  1017. specifications
  1018. ) {
  1019. const sourceArray = this.selection;
  1020. // 检查单位是否匹配
  1021. const isUnitMismatch =
  1022. sourceArray.length > 0 && sourceArray[0].measureUnit !== sampleUnit;
  1023. // 创建副本并计算初始可取样数量
  1024. const items = sourceArray.map((item) => ({
  1025. ...item,
  1026. remainingQuantity: isUnitMismatch
  1027. ? Infinity
  1028. : item['measureQuantity'], // 剩余可取样数量
  1029. maxPossible: item['measureQuantity'] / sampleQuantity // 最大取样次数
  1030. }));
  1031. const result = [];
  1032. let remainingCount = sampleCount;
  1033. let count = Math.ceil(remainingCount);
  1034. const codeList = await this.batchCodes(count);
  1035. let codeIdx = 0;
  1036. // 尽可能均匀地从各条目取样
  1037. while (remainingCount > 0) {
  1038. // 按剩余可取样比例排序
  1039. items.sort(
  1040. (a, b) =>
  1041. b.remainingQuantity / b['measureQuantity'] -
  1042. a.remainingQuantity / a['measureQuantity']
  1043. );
  1044. let distributed = false;
  1045. for (const item of items) {
  1046. // let values = remainingCount > 1 ? 1 : remainingCount;
  1047. if (
  1048. !isUnitMismatch ||
  1049. (item.remainingQuantity >= sampleQuantity && remainingCount > 0)
  1050. ) {
  1051. let qualitySampleTemplateList = [];
  1052. if (
  1053. item.qualitySampleTemplateList == undefined ||
  1054. item.qualitySampleTemplateList == null ||
  1055. item.qualitySampleTemplateList.length == 0
  1056. ) {
  1057. qualitySampleTemplateList = JSON.parse(
  1058. JSON.stringify(this.schemeList)
  1059. );
  1060. } else {
  1061. qualitySampleTemplateList = item.qualitySampleTemplateList;
  1062. }
  1063. // 添加到结果数组
  1064. // let sampleCode = await this.getSampleCode();
  1065. let sampleCode = codeList[codeIdx];
  1066. if (
  1067. this.form.conditionType == 1 &&
  1068. this.form.inspectionStandards == 1
  1069. ) {
  1070. result.push({
  1071. ...item,
  1072. // measureQuantity: values,
  1073. measureQuantity: 1,
  1074. sampleCode,
  1075. qualitySampleTemplateList
  1076. });
  1077. } else if (this.form.conditionType == 2) {
  1078. let weight = (item.weight / item.maxPossible).toFixed(2);
  1079. result.push({
  1080. ...item,
  1081. measureQuantity: sampleQuantity,
  1082. measureUnit: sampleUnit,
  1083. sampleCode,
  1084. weight,
  1085. qualitySampleTemplateList
  1086. });
  1087. }
  1088. // 更新剩余数量
  1089. if (!isUnitMismatch) {
  1090. item.remainingQuantity -= sampleQuantity;
  1091. }
  1092. remainingCount = (remainingCount - 1).toFixed(2);
  1093. codeIdx++;
  1094. distributed = true;
  1095. }
  1096. }
  1097. // 如果没有分配任何取样
  1098. if (!distributed) {
  1099. break;
  1100. }
  1101. }
  1102. // 判断是不是取整样
  1103. if (
  1104. this.form.conditionType == 1 &&
  1105. specifications &&
  1106. specifications.id
  1107. ) {
  1108. result.map((el) => {
  1109. el.measureQuantity =
  1110. el.measureQuantity * specifications.packageCellTotal;
  1111. el.weight = this.formatNumber(
  1112. el.measureQuantity,
  1113. el.weightProportion
  1114. );
  1115. });
  1116. }
  1117. this.sampleList = result;
  1118. if (this.sampleList.length > sampleCount) {
  1119. this.sampleList = this.sampleList.splice(0, sampleCount);
  1120. }
  1121. this.getTotal();
  1122. },
  1123. // 当计量类型 是数量的时候 取整样 校验
  1124. validateSampleQuantity(sampleCount, specifications) {
  1125. let packingUnit = this.selection[0].packingUnit?.trim() || '';
  1126. let totalS = 0;
  1127. let measureQuantityCount = 0;
  1128. let labelKey =
  1129. packingUnit == specifications.conversionUnit.trim()
  1130. ? 'packingQuantity'
  1131. : 'measureQuantity';
  1132. let labelName = labelKey == 'packingQuantity' ? '包装数量' : '计量数量';
  1133. totalS = this.selection.reduce((total, el) => total + el[labelKey], 0);
  1134. let formTotalS = this.tableList.reduce(
  1135. (total, el) => total + el.measureQuantity,
  1136. 0
  1137. );
  1138. if (sampleCount > totalS) {
  1139. this.$message.info(
  1140. `所填的条目数量不能超过所选${labelName}总和${totalS}`
  1141. );
  1142. return false;
  1143. }
  1144. if (labelKey == 'packingQuantity') {
  1145. measureQuantityCount =
  1146. sampleCount * this.selection[0].measureQuantity;
  1147. } else {
  1148. measureQuantityCount = sampleCount;
  1149. }
  1150. if (measureQuantityCount > formTotalS - this.workSampleQuantity) {
  1151. this.$message.info(
  1152. `请样数量不能大于${formTotalS - this.workSampleQuantity} ${
  1153. this.selection[0].measureUnit
  1154. }`
  1155. );
  1156. return false;
  1157. }
  1158. return true;
  1159. },
  1160. handleQualityModeChange(val) {
  1161. if (val == 1) {
  1162. this.updatePackingList();
  1163. } else {
  1164. this.sampleList = [];
  1165. this.getTotal();
  1166. }
  1167. },
  1168. // 全检
  1169. async updatePackingList() {
  1170. let list = this.tableList;
  1171. let sampleCount = this.form.total;
  1172. const dataList = [];
  1173. let count = list ? list.length : 0;
  1174. console.log(count, 'count');
  1175. const codeList = await this.batchCodes(count);
  1176. for (const [index, item] of list.entries()) {
  1177. const qualitySampleTemplateList = item.qualitySampleTemplateList
  1178. ?.length
  1179. ? JSON.parse(JSON.stringify(item.qualitySampleTemplateList))
  1180. : JSON.parse(
  1181. JSON.stringify(
  1182. this.schemeList.map((item) => {
  1183. item['qualityResults'] = 1;
  1184. return item;
  1185. })
  1186. )
  1187. );
  1188. // if (sampleCount >= list.length) {
  1189. dataList.push({
  1190. ...item,
  1191. measureQuantity: item.measureQuantity, //作为计量数量
  1192. sampleCode: codeList[index],
  1193. attachmentUrl: [],
  1194. qualitySampleTemplateList
  1195. });
  1196. // }
  1197. }
  1198. console.log(dataList, 'dataList');
  1199. this.sampleList = dataList;
  1200. this.getTotal();
  1201. return
  1202. },
  1203. getTotal() {
  1204. this.form.sampleQuantity = this.sampleList
  1205. .reduce((total, el) => total + Number(el.measureQuantity), 0)
  1206. .toFixed(2);
  1207. this.form.sampleWeight = this.sampleList
  1208. .reduce((total, el) => total + Number(el.weight), 0)
  1209. .toFixed(2);
  1210. },
  1211. async batchCodes(count) {
  1212. if (count <= 0) return;
  1213. let params = { count };
  1214. const res = await getCodeList('sample_code', params);
  1215. return res;
  1216. },
  1217. /* 保存编辑 */
  1218. save(type) {
  1219. if (this.type == 'add') {
  1220. [
  1221. 'id',
  1222. 'code',
  1223. 'name',
  1224. 'createTime',
  1225. 'createUserId',
  1226. 'status',
  1227. 'approvalStatus',
  1228. 'approvalUserId'
  1229. ].forEach((key) => {
  1230. delete this.form[key];
  1231. });
  1232. }
  1233. let data = JSON.parse(JSON.stringify(this.form));
  1234. let api =
  1235. this.type == 'add' ? samplingrecordSave : samplingrecordUpdate;
  1236. this.$refs.form.validate((valid) => {
  1237. if (valid) {
  1238. if (!this.sampleList.length) {
  1239. this.$message.error('样品清单不能为空!');
  1240. return;
  1241. }
  1242. //抽检
  1243. if (data.qualityMode == 2) {
  1244. //取整样
  1245. if (data.conditionType == 1) {
  1246. data.quantity = data.portion;
  1247. } else {
  1248. data.copies = data.portion;
  1249. }
  1250. }
  1251. data.measureUnit = this.sampleList[0].measureUnit;
  1252. this.loading = true;
  1253. api({
  1254. ...data,
  1255. sampleList: this.sampleList
  1256. })
  1257. .then((res) => {
  1258. this.$message.success('操作成功');
  1259. if (type == 'submit') {
  1260. this.approvalSubmit(this.type == 'add' ? res : data.id);
  1261. } else {
  1262. this.cancel();
  1263. this.$emit('reload');
  1264. }
  1265. })
  1266. .finally(() => {
  1267. this.loading = false;
  1268. });
  1269. }
  1270. });
  1271. },
  1272. async approvalSubmit(id) {
  1273. const res = await getById(id);
  1274. this.processSubmitDialogFlag = true;
  1275. this.$nextTick(() => {
  1276. let params = {
  1277. businessId: res.id,
  1278. businessKey: 'sampling_approval_process',
  1279. formCreateUserId: res.createUserId,
  1280. variables: {
  1281. businessCode: res.code,
  1282. businessName: '请样',
  1283. businessType:
  1284. res.qualityWorkOrderVO.conditionType == 1 ? '整样' : '小样'
  1285. }
  1286. };
  1287. this.$refs.processSubmitDialogRef.init(params);
  1288. });
  1289. },
  1290. search() {
  1291. this.cancel();
  1292. this.$emit('reload');
  1293. }
  1294. }
  1295. };
  1296. </script>
  1297. <style lang="scss" scoped>
  1298. .basic-details-title {
  1299. margin: 10px 0;
  1300. }
  1301. .title {
  1302. font-size: 16px;
  1303. line-height: 45px;
  1304. }
  1305. .add-product {
  1306. width: 100%;
  1307. display: flex;
  1308. align-items: center;
  1309. justify-content: flex-end;
  1310. font-size: 30px;
  1311. color: #1890ff;
  1312. margin: 10px 0;
  1313. cursor: pointer;
  1314. }
  1315. </style>