outboundXTBG.vue 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393
  1. <!-- 协同办公使用 -->
  2. <template>
  3. <div>
  4. <el-card shadow="never">
  5. <header-title title="基本信息"></header-title>
  6. <el-form
  7. :model="formData"
  8. ref="formName"
  9. label-width="110px"
  10. :rules="rules"
  11. >
  12. <el-row :gutter="20">
  13. <el-col :span="6">
  14. <el-form-item label="出库场景" prop="bizType">
  15. <!-- <el-select
  16. filterable
  17. placeholder="请选择"
  18. v-model="formData.bizType"
  19. clearable
  20. @change="handleBizSceneChange"
  21. :disabled="!!(productList && productList.length)"
  22. >
  23. <el-option
  24. v-for="item in outputSceneState"
  25. :key="item.code"
  26. :value="item.code"
  27. :label="item.label"
  28. ></el-option>
  29. </el-select> -->
  30. <el-select
  31. filterable
  32. placeholder="请选择"
  33. v-model="formData.bizType"
  34. clearable
  35. @change="handleBizSceneChange"
  36. >
  37. <el-option
  38. v-for="item in outputSceneState"
  39. :key="item.code"
  40. :value="item.code"
  41. :label="item.label"
  42. ></el-option>
  43. </el-select> </el-form-item
  44. ></el-col>
  45. <el-col :span="6">
  46. <el-form-item label="单据来源" prop="documentSource">
  47. <el-input
  48. placeholder="请选择"
  49. disabled
  50. v-model="formData.sourceBizNo"
  51. @click.native="openDocumentSourceDialog"
  52. >
  53. </el-input>
  54. </el-form-item>
  55. </el-col>
  56. <el-col :span="6">
  57. <el-form-item label="出库物品类型" prop="extInfo.assetType">
  58. <el-select
  59. style="width: 100%"
  60. multiple
  61. v-model="formData.extInfo.assetType"
  62. placeholder="请选择"
  63. >
  64. <el-option
  65. v-for="item in goodsLists"
  66. :key="item.id"
  67. :label="item.name"
  68. :value="item.id"
  69. >
  70. </el-option>
  71. </el-select>
  72. <!-- <el-select
  73. style="width: 100%"
  74. multiple
  75. :disabled="!!(productList && productList.length)"
  76. v-model="formData.extInfo.assetType"
  77. placeholder="请选择"
  78. >
  79. <el-option
  80. v-for="item in goodsLists"
  81. :key="item.id"
  82. :label="item.name"
  83. :value="item.id"
  84. >
  85. </el-option>
  86. </el-select> -->
  87. </el-form-item>
  88. </el-col>
  89. <el-col :span="6">
  90. <el-form-item label="出库时间">
  91. <el-date-picker
  92. v-model="formData.storageTime"
  93. type="datetime"
  94. value-format="yyyy-MM-dd HH:mm:ss"
  95. placeholder="选择日期时间"
  96. >
  97. </el-date-picker></el-form-item
  98. ></el-col>
  99. <el-col :span="6">
  100. <el-form-item label="出库登记人">
  101. <el-input
  102. placeholder="登记人"
  103. disabled
  104. v-model="formData.extInfo.createUserName"
  105. clearable /></el-form-item
  106. ></el-col>
  107. <el-col :span="6">
  108. <el-form-item
  109. :label="this.bizType == 10 ? '申请人部门' : '领料人部门'"
  110. prop="extInfo.verifyDeptCode"
  111. >
  112. <selectTree
  113. ref="tree"
  114. class="form-ipt"
  115. size="medium"
  116. style="width: 100%"
  117. clearable
  118. :value="formData.extInfo.verifyDeptCode"
  119. :options="treeList"
  120. :props="{
  121. value: 'id',
  122. label: 'name',
  123. children: 'children'
  124. }"
  125. @getValue="auditorDeptClick"
  126. />
  127. </el-form-item>
  128. </el-col>
  129. <el-col :span="6">
  130. <el-form-item
  131. :label="this.bizType == 10 ? '申请人' : '领料人'"
  132. prop="fromId"
  133. >
  134. <el-select
  135. v-model="formData.fromId"
  136. filterable
  137. placeholder="请选择"
  138. >
  139. <el-option
  140. v-for="item in llrLsit"
  141. :key="item.id"
  142. :label="item.name"
  143. :value="item.id"
  144. @click.native="userSlected(item)"
  145. >
  146. </el-option>
  147. </el-select> </el-form-item
  148. ></el-col>
  149. <!-- <el-col :span="6">
  150. <el-form-item label="领料人联系方式" prop="fromUserPhone">
  151. <el-input
  152. placeholder="请输入"
  153. disabled
  154. v-model="formData.extInfo.fromUserPhone"
  155. clearable /></el-form-item
  156. ></el-col> -->
  157. <el-col :span="12">
  158. <el-form-item label="备注" prop="remark">
  159. <el-input
  160. v-model="formData.remark"
  161. placeholder="请详细说明"
  162. ></el-input>
  163. </el-form-item>
  164. </el-col>
  165. </el-row>
  166. </el-form>
  167. <div>
  168. <el-button
  169. style="margin-bottom: 20px; float: right; margin-right: 20px"
  170. type="primary"
  171. @click="addStock"
  172. >添加</el-button
  173. >
  174. </div>
  175. <div class="material">
  176. <div>
  177. <header-title title="物品清单"></header-title>
  178. <div class="mt10 form-table">
  179. <el-table
  180. ref="productListTable"
  181. :data="productList"
  182. tooltip-effect="dark"
  183. :max-height="300"
  184. :header-cell-style="rowClass"
  185. border
  186. >
  187. <el-table-column label="序号" type="index" width="50">
  188. </el-table-column>
  189. <el-table-column
  190. label="编码"
  191. prop="categoryCode"
  192. align="center"
  193. :show-overflow-tooltip="true"
  194. ></el-table-column>
  195. <el-table-column
  196. label="名称"
  197. align="center"
  198. prop="categoryName"
  199. :show-overflow-tooltip="true"
  200. ></el-table-column>
  201. <el-table-column
  202. v-if="clientEnvironmentId == 4"
  203. label="级别"
  204. prop="level"
  205. align="center"
  206. >
  207. </el-table-column>
  208. <el-table-column
  209. label="型号"
  210. align="center"
  211. prop="categoryModel"
  212. :show-overflow-tooltip="true"
  213. ></el-table-column>
  214. <el-table-column
  215. label="规格"
  216. align="center"
  217. prop="specification"
  218. :show-overflow-tooltip="true"
  219. ></el-table-column>
  220. <el-table-column
  221. label="牌号"
  222. align="center"
  223. prop="brandNum"
  224. :show-overflow-tooltip="true"
  225. ></el-table-column>
  226. <el-table-column
  227. v-for="(item, index) in newColumns"
  228. :label="item.label"
  229. :align="item.align"
  230. :key="item.prop"
  231. :prop="item.prop"
  232. :show-overflow-tooltip="item.showOverflowTooltip"
  233. ></el-table-column>
  234. <el-table-column
  235. label="批次号"
  236. prop="batchNo"
  237. align="center"
  238. :show-overflow-tooltip="true"
  239. >
  240. </el-table-column>
  241. <el-table-column
  242. label="包装数量"
  243. prop="packingQuantity"
  244. width="80"
  245. ></el-table-column>
  246. <el-table-column
  247. label="单位"
  248. prop="packingUnit"
  249. ></el-table-column>
  250. <el-table-column
  251. label="计量数量"
  252. prop="measureQuantity"
  253. :show-overflow-tooltip="true"
  254. ></el-table-column>
  255. <el-table-column
  256. label="计量单位"
  257. prop="measureUnit"
  258. ></el-table-column>
  259. <el-table-column
  260. label="重量"
  261. prop="weight"
  262. align="center"
  263. :show-overflow-tooltip="true"
  264. >
  265. </el-table-column>
  266. <el-table-column
  267. label="重量单位"
  268. prop="weightUnit"
  269. align="center"
  270. :show-overflow-tooltip="true"
  271. >
  272. </el-table-column>
  273. <el-table-column label="机型" prop="modelKey" width="200">
  274. </el-table-column>
  275. <el-table-column label="颜色" prop="colorKey" width="200">
  276. </el-table-column>
  277. <el-table-column label="锁定数量" prop="lockQuantity" width="100">
  278. </el-table-column>
  279. <el-table-column
  280. label="库存"
  281. prop="stockNum"
  282. align="center"
  283. :show-overflow-tooltip="true"
  284. >
  285. </el-table-column>
  286. <el-table-column
  287. label="单价"
  288. prop="price"
  289. align="center"
  290. v-if="isPrice == 1"
  291. >
  292. <template slot-scope="{ row }">
  293. <template>
  294. {{ row.price ? row.price : ' ' + '元' }}/{{
  295. row.measureUnit
  296. }}
  297. </template>
  298. </template>
  299. </el-table-column>
  300. <el-table-column
  301. label="金额"
  302. align="center"
  303. prop="totalMoney"
  304. :show-overflow-tooltip="true"
  305. v-if="isPrice == 1"
  306. >
  307. <template slot-scope="{ row, $index }">
  308. {{ row.totalMoney ? row.totalMoney : 0 }}
  309. </template>
  310. </el-table-column>
  311. <el-table-column
  312. v-if="clientEnvironmentId == 4"
  313. label="采购原因"
  314. align="center"
  315. prop="purpose"
  316. :show-overflow-tooltip="true"
  317. ></el-table-column>
  318. <el-table-column
  319. label="仓库"
  320. prop="warehouseName"
  321. :show-overflow-tooltip="true"
  322. >
  323. </el-table-column>
  324. <el-table-column
  325. prop="supplierName"
  326. label="供应商"
  327. min-width="200"
  328. :show-overflow-tooltip="true"
  329. ></el-table-column>
  330. <el-table-column
  331. prop="supplierCode"
  332. label="供应商代号"
  333. min-width="200"
  334. :show-overflow-tooltip="true"
  335. ></el-table-column>
  336. <el-table-column label="操作" width="120" align="center">
  337. <template slot="header" slot-scope="scope"> 操作 </template>
  338. <template slot-scope="{ row, $index }">
  339. <el-link type="danger" @click="deleteProductList(row, $index)"
  340. >删除</el-link
  341. >
  342. </template>
  343. </el-table-column>
  344. </el-table>
  345. </div>
  346. <header-title class="mt20" title="包装清单"></header-title>
  347. <div class="mt10 form-table">
  348. <el-table
  349. ref="showPackingListTable"
  350. :data="showPackingList"
  351. tooltip-effect="dark"
  352. :max-height="300"
  353. :row-class-name="tableRowClassName"
  354. :header-cell-style="rowClass"
  355. border
  356. v-el-table-infinite-scroll="pickingHandleScroll"
  357. >
  358. <el-table-column label="序号" type="index" width="50">
  359. </el-table-column>
  360. <el-table-column
  361. label="编码"
  362. prop="categoryCode"
  363. :show-overflow-tooltip="true"
  364. ></el-table-column>
  365. <el-table-column
  366. label="名称"
  367. prop="categoryName"
  368. :show-overflow-tooltip="true"
  369. ></el-table-column>
  370. <el-table-column
  371. label="批次号"
  372. prop="batchNo"
  373. :show-overflow-tooltip="true"
  374. ></el-table-column>
  375. <el-table-column
  376. label="发货条码"
  377. prop="barcodes"
  378. :show-overflow-tooltip="true"
  379. ></el-table-column>
  380. <el-table-column
  381. label="包装编码"
  382. prop="packageNo"
  383. :show-overflow-tooltip="true"
  384. ></el-table-column>
  385. <el-table-column
  386. label="包装数量"
  387. prop="packingQuantity"
  388. :show-overflow-tooltip="true"
  389. ></el-table-column>
  390. <el-table-column
  391. label="单位"
  392. prop="packingUnit"
  393. :show-overflow-tooltip="true"
  394. ></el-table-column>
  395. <el-table-column
  396. label="计量数量"
  397. prop="measureQuantity"
  398. :show-overflow-tooltip="true"
  399. ></el-table-column>
  400. <el-table-column
  401. label="计量单位"
  402. prop="measureUnit"
  403. :show-overflow-tooltip="true"
  404. ></el-table-column>
  405. <el-table-column
  406. label="物料代号"
  407. prop="materielDesignation"
  408. :show-overflow-tooltip="true"
  409. >
  410. </el-table-column>
  411. <el-table-column
  412. label="客户代号"
  413. prop="clientCode"
  414. :show-overflow-tooltip="true"
  415. >
  416. </el-table-column>
  417. <el-table-column
  418. label="刻码"
  419. prop="engrave"
  420. :show-overflow-tooltip="true"
  421. >
  422. </el-table-column>
  423. <el-table-column
  424. label="重量"
  425. prop="weight"
  426. :show-overflow-tooltip="true"
  427. >
  428. </el-table-column>
  429. <el-table-column
  430. label="重量单位"
  431. prop="weightUnit"
  432. :show-overflow-tooltip="true"
  433. >
  434. </el-table-column>
  435. <el-table-column label="机型" prop="modelKey" width="200">
  436. </el-table-column>
  437. <el-table-column label="颜色" prop="colorKey" width="200">
  438. </el-table-column>
  439. <el-table-column
  440. label="质检结果"
  441. prop="result"
  442. :show-overflow-tooltip="true"
  443. >
  444. <template slot-scope="{ row }">
  445. <span>{{ qualityResults[row.result] }}</span>
  446. </template>
  447. </el-table-column>
  448. <el-table-column
  449. label="质检状态"
  450. prop="status"
  451. :show-overflow-tooltip="true"
  452. >
  453. <template slot-scope="{ row }">
  454. <span>{{ qualityStatus[row.status] }}</span>
  455. </template>
  456. </el-table-column>
  457. <el-table-column
  458. label="生产日期"
  459. prop="productionDate"
  460. :show-overflow-tooltip="true"
  461. >
  462. </el-table-column>
  463. <el-table-column
  464. label="采购日期"
  465. prop="purchaseDate"
  466. :show-overflow-tooltip="true"
  467. >
  468. </el-table-column>
  469. <el-table-column
  470. prop="supplierName"
  471. label="供应商"
  472. min-width="200"
  473. :show-overflow-tooltip="true"
  474. ></el-table-column>
  475. <el-table-column
  476. prop="supplierCode"
  477. label="供应商代号"
  478. min-width="200"
  479. :show-overflow-tooltip="true"
  480. ></el-table-column>
  481. </el-table>
  482. </div>
  483. </div>
  484. <!-- <div class="mt20">
  485. <header-title class="mt20" title="物料明细"></header-title>
  486. <el-table ref="multipleTable" :data="showMaterialList" tooltip-effect="dark" :max-height="300"
  487. :row-class-name="tableRowClassName" :header-cell-style="rowClass" border style="width: 100%" stripe
  488. height="300px" v-el-table-infinite-scroll="materielHandleScroll">
  489. <el-table-column label="序号" type="index" width="50">
  490. </el-table-column>
  491. <el-table-column label="编码" prop="categoryCode" :show-overflow-tooltip="true"></el-table-column>
  492. <el-table-column label="名称" prop="categoryName" :show-overflow-tooltip="true"></el-table-column>
  493. <el-table-column label="批次号" prop="batchNo"></el-table-column>
  494. <el-table-column label="物料编码" prop="materialCode" :show-overflow-tooltip="true"></el-table-column>
  495. <el-table-column label="发货条码" prop="barcodes" :show-overflow-tooltip="true"></el-table-column>
  496. <el-table-column label="计量数量" prop="minPackingQuantity"></el-table-column>
  497. <el-table-column label="计量单位" prop="measureUnit"></el-table-column>
  498. <el-table-column label="物料代号" prop="materielDesignation">
  499. </el-table-column>
  500. <el-table-column label="客户代号" prop="clientCode">
  501. </el-table-column>
  502. <el-table-column label="刻码" prop="engrave"> </el-table-column>
  503. <el-table-column width="100" label="重量" prop="weight">
  504. </el-table-column>
  505. <el-table-column label="重量单位" prop="weightUnit">
  506. </el-table-column>
  507. <el-table-column label="质检结果" prop="result" width="120">
  508. <template slot-scope="{ row }">
  509. <span>{{ qualityResults[row.result] }}</span>
  510. </template>
  511. </el-table-column>
  512. <el-table-column label="质检状态" prop="status" width="120">
  513. <template slot-scope="{ row }">
  514. <span>{{ qualityStatus[row.status] }}</span>
  515. </template>
  516. </el-table-column>
  517. </el-table>
  518. </div> -->
  519. </div>
  520. </el-card>
  521. <AssetsDialog
  522. ref="assetsDialogRef"
  523. :treeIds="formData.extInfo?.assetType"
  524. @detailData="detailData"
  525. :productLists="this.productList"
  526. />
  527. </div>
  528. </template>
  529. <script>
  530. import storageApi from '@/api/warehouseManagement/index.js';
  531. import elTableInfiniteScroll from 'el-table-infinite-scroll';
  532. import warehouseDefinition from '@/api/warehouseManagement/warehouseDefinition';
  533. import { getTreeByGroup } from '@/api/classifyManage';
  534. import {
  535. outputSceneState,
  536. qualityResults,
  537. qualityStatus
  538. } from '@/utils/dict/index';
  539. import selectTree from '@/components/selectTree';
  540. import AssetsDialog from './components/AssetsDialog.vue';
  541. import { deepClone } from '@/components/FormGenerator/utils/index';
  542. import { mapGetters } from 'vuex';
  543. import { parameterGetByCode } from '@/api/main/index.js';
  544. export default {
  545. components: {
  546. selectTree,
  547. AssetsDialog
  548. },
  549. props: {
  550. form: { type: Object, default: {} },
  551. bizType: { type: Number, default: 1 },
  552. sourceBizNo: { type: String, default: '' },
  553. type: { type: String, default: '正常出库' },
  554. detailList: { type: Array, default: () => [] },
  555. saleProductList: { type: Array, default: () => [] },
  556. extractedList: { type: Array, default: () => [] },
  557. wwType: { type: Number, default: null }
  558. },
  559. directives: {
  560. 'el-table-infinite-scroll': elTableInfiniteScroll
  561. },
  562. data() {
  563. return {
  564. newColumns: [], // 动态表头
  565. goodsLists: [], // 商品列表
  566. productList: [], // 产品列表
  567. showPackingList: [], // 展示的包装列表
  568. packingList: [], // 包装列表
  569. showMaterialList: [], // 展示物料列表
  570. materialList: [], // 物料列表
  571. extInfo: {}, // 扩展信息
  572. pageSize: 20,
  573. pickingPageNum: 1,
  574. materielPageNum: 1,
  575. dimension: '3',
  576. outputSceneState,
  577. qualityStatus, // 质检状态
  578. qualityResults, // 质检结果
  579. treeList: [],
  580. formData: {
  581. storageTime: '',
  582. extInfo: {
  583. assetType: [], //物品类型id
  584. assetTypeName: '', //物品类型名称
  585. deptCode: '', //部门code
  586. deptName: '', //部门名称
  587. verifyDeptCode: '', //审核部门编码
  588. verifyDeptName: '', //审核部门名称
  589. deliveryName: '', //送货人名称
  590. fromUserPhone: '', //送货人电话
  591. sourceBizNo: '', //销售订单
  592. urgent: '', //紧急状态
  593. supplierId: '', //供应商ID
  594. supplierName: '', //供应商名称
  595. createUserName: '', //创建人名字
  596. contentImage: [] //图片数组
  597. },
  598. fromId: '', //领料人
  599. fromUser: '', //送货人
  600. bizType: '', //物品类型
  601. verifyId: '', //审核人Id
  602. verifyName: '', //审核人名称
  603. createUserId: '',
  604. remark: ''
  605. },
  606. rules: {
  607. bizType: {
  608. required: true,
  609. message: '请选择出库场景',
  610. trigger: 'change'
  611. },
  612. 'extInfo[verifyDeptCode]': {
  613. required: true,
  614. message: '请选择领料人部门',
  615. trigger: ['change', 'blur']
  616. },
  617. fromId: {
  618. required: true,
  619. message: '请选择',
  620. trigger: 'change'
  621. }
  622. },
  623. llrLsit: [],
  624. isPrice: 1
  625. };
  626. },
  627. computed: {
  628. ...mapGetters(['user']),
  629. clientEnvironmentId() {
  630. return this.$store.state.user.info.clientEnvironmentId;
  631. }
  632. },
  633. async created() {
  634. //仓库出入库是否显示金额(0:不显示 1:显示)
  635. parameterGetByCode({
  636. code: 'wms_price'
  637. }).then((res) => {
  638. this.isPrice = res.value;
  639. });
  640. this.getFieldModel();
  641. this.getListItems();
  642. this.initDeptData().then(() => {
  643. this.initFormData();
  644. this.getNowFormatDate();
  645. });
  646. },
  647. methods: {
  648. // 获取当前时间函数
  649. getNowDate() {
  650. let date = new Date(),
  651. obj = {
  652. year: date.getFullYear(), //获取当前月份(0-11,0代表1月)
  653. month: date.getMonth() + 1, //获取当前月份(0-11,0代表1月)
  654. strDate: date.getDate(), // 获取当前日(1-31)
  655. hour: date.getHours(), //获取当前小时(0 ~ 23)
  656. minute: date.getMinutes(), //获取当前分钟(0 ~ 59)
  657. second: date.getSeconds() //获取当前秒数(0 ~ 59)
  658. };
  659. Object.keys(obj).forEach((key) => {
  660. if (obj[key] < 10) obj[key] = `0${obj[key]}`;
  661. });
  662. return obj;
  663. },
  664. // 赋值入库时间
  665. getNowFormatDate() {
  666. const obj = this.getNowDate();
  667. const defaultTime = '00:00:00';
  668. const currentTime = `${obj.hour}:${obj.minute}:${obj.second}`;
  669. this.formData.storageTime = `${obj.year}-${obj.month}-${obj.strDate} ${currentTime}`;
  670. },
  671. // 获取动态表头
  672. getFieldModel() {
  673. storageApi.fieldModel({ fieldModel: 't_main_category' }).then((res) => {
  674. let newRes = res.map((m) => {
  675. return {
  676. prop: 'extField.' + m.prop,
  677. label: m.label,
  678. align: 'center',
  679. showOverflowTooltip: true
  680. };
  681. });
  682. this.newColumns = [...newRes];
  683. });
  684. },
  685. userSlected(data) {
  686. this.formData.fromId = data.id;
  687. this.formData.fromUser = data.name;
  688. this.formData.fromUserPhone = data.phone;
  689. },
  690. openDocumentSourceDialog() {
  691. console.log('打开单据来源弹窗');
  692. },
  693. clearDocumentSource() {
  694. console.log('清空');
  695. },
  696. pickingHandleScroll() {
  697. console.log('---------pickingHandleScroll------------');
  698. if (this.showPackingList.length < this.packingList.length) {
  699. if (this.packingList.length > this.pageSize) {
  700. this.pickingPageNum += 1;
  701. }
  702. this.pickingFetchData();
  703. }
  704. },
  705. pickingFetchData() {
  706. const start = (this.pickingPageNum - 1) * this.pageSize;
  707. const end = start + this.pageSize;
  708. this.showPackingList = this.showPackingList.concat(
  709. this.packingList.slice(start, end)
  710. );
  711. },
  712. materielHandleScroll() {
  713. console.log('---------materielHandleScroll------------');
  714. if (this.showMaterialList.length < this.materialList.length) {
  715. if (this.materialList.length > this.pageSize) {
  716. this.materielPageNum += 1;
  717. }
  718. this.materielFetchData();
  719. }
  720. },
  721. materielFetchData() {
  722. const start = (this.materielPageNum - 1) * this.pageSize;
  723. const end = start + this.pageSize;
  724. this.showMaterialList = this.showMaterialList.concat(
  725. this.materialList.slice(start, end)
  726. );
  727. console.log(this.showMaterialList);
  728. },
  729. // 获取物品列表
  730. async getListItems() {
  731. const { data } = await getTreeByGroup({});
  732. this.goodsLists = data;
  733. },
  734. // 打开单据来源弹窗
  735. openDocumentSourceDialog() {
  736. console.log('打开单据来源弹窗');
  737. },
  738. tableRowClassName({ row, rowIndex }) {
  739. console.log(row);
  740. if (row.result == 1) {
  741. return 'warning-row';
  742. } else {
  743. return '';
  744. }
  745. },
  746. detailData(data, dimension) {
  747. this.dimension = dimension;
  748. const mergedData = [...(this.formData.outInDetailList || []), ...data];
  749. this.formData.outInDetailList = mergedData;
  750. this.productList = data.map((productItem) => {
  751. return {
  752. ...productItem,
  753. outInDetailRecordRequestList:
  754. productItem.outInDetailRecordRequestList.map((packingItem) => {
  755. return {
  756. ...packingItem,
  757. workOrderId:
  758. this.type === '自选领用出库'
  759. ? this.form.detailList[0].workOrderId
  760. : '',
  761. pickOrderId:
  762. this.type === '自选领用出库'
  763. ? this.form.detailList[0].pickOrderId
  764. : '',
  765. taskId:
  766. this.type === '自选领用出库'
  767. ? this.form.detailList[0].taskId
  768. : '',
  769. categoryName: productItem.categoryName,
  770. categoryCode: productItem.categoryCode,
  771. supplierCode: productItem.supplierCode,
  772. supplierName: productItem.supplierName,
  773. materialDetailList: packingItem.materialDetailList.map(
  774. (materialItem) => {
  775. return {
  776. ...materialItem,
  777. categoryName: productItem.categoryName,
  778. categoryCode: productItem.categoryCode,
  779. supplierCode: productItem.supplierCode,
  780. supplierName: productItem.supplierName
  781. };
  782. }
  783. )
  784. };
  785. })
  786. };
  787. });
  788. const newProducts = mergedData.map((productItem) => ({
  789. ...productItem,
  790. outInDetailRecordRequestList:
  791. productItem.outInDetailRecordRequestList.map((packingItem) => ({
  792. ...packingItem,
  793. categoryName: productItem.categoryName,
  794. categoryCode: productItem.categoryCode,
  795. supplierCode: productItem.supplierCode,
  796. supplierName: productItem.supplierName,
  797. workOrderId:
  798. this.type === '自选领用出库'
  799. ? this.form.detailList[0].workOrderId
  800. : '',
  801. pickOrderId:
  802. this.type === '自选领用出库'
  803. ? this.form.detailList[0].pickOrderId
  804. : '',
  805. taskId:
  806. this.type === '自选领用出库'
  807. ? this.form.detailList[0].taskId
  808. : '',
  809. materialDetailList: packingItem.materialDetailList.map(
  810. (materialItem) => ({
  811. ...materialItem,
  812. categoryName: productItem.categoryName,
  813. categoryCode: productItem.categoryCode,
  814. supplierCode: productItem.supplierCode,
  815. supplierName: productItem.supplierName
  816. })
  817. )
  818. }))
  819. }));
  820. // 去重合并产品列表和新产品列表
  821. const uniqueProducts = [
  822. ...new Map(
  823. [...this.productList, ...newProducts].map((item) => [item.id, item])
  824. ).values()
  825. ];
  826. this.productList = uniqueProducts;
  827. // 排序
  828. this.productList.sort((a, b) => a.categoryCode - b.categoryCode);
  829. // 获取包装维度数据
  830. const arr = [];
  831. for (const key in this.productList) {
  832. for (const k in this.productList[key].outInDetailRecordRequestList) {
  833. arr.push({
  834. ...this.productList[key].outInDetailRecordRequestList[k]
  835. });
  836. }
  837. }
  838. this.packingList = arr;
  839. const newPacking = [];
  840. newProducts.forEach((item) => {
  841. newPacking.push(...item.outInDetailRecordRequestList);
  842. });
  843. //去重
  844. const newPackingList = [
  845. ...new Map(
  846. [...this.packingList, ...newPacking].map((item) => [item.id, item])
  847. ).values()
  848. ];
  849. this.packingList = newPackingList;
  850. this.packingList.sort((a, b) => a.categoryCode - b.categoryCode);
  851. // 获取物料维度数据
  852. let iArr = [];
  853. arr.forEach((item) => {
  854. item.materialDetailList.forEach((ele) => {
  855. iArr.push({ ...ele });
  856. });
  857. });
  858. this.materialList = iArr;
  859. const newMaterial = [];
  860. newPacking.forEach((item) => {
  861. newMaterial.push(...item.materialDetailList);
  862. });
  863. this.materialList = [...this.materialList, ...newMaterial];
  864. // 触发分页更新
  865. this.pickingPageNum = 1;
  866. this.materielPageNum = 1;
  867. this.pickingFetchData();
  868. this.materielFetchData();
  869. this.formData.outInDetailList = this.productList;
  870. console.log(this.productList, 'this.productList');
  871. console.log(this.packingList, 'this.packingList');
  872. },
  873. async getReturnStorage() {
  874. return new Promise((resolve) => {
  875. console.log(this.formData);
  876. this.$refs.formName.validate((valid) => {
  877. let isPass = true;
  878. if (!this.productList?.length) {
  879. isPass = false;
  880. this.$message.error('请添加出库明细!');
  881. }
  882. if (!valid) {
  883. isPass = false;
  884. }
  885. let obj = deepClone({ ...this.formData, type: 2 });
  886. obj.extInfo.sourceBizNo = obj.sourceBizNo;
  887. obj.fromType = obj.type;
  888. // 处理物品类型assetType
  889. obj.extInfo.assetType = obj.extInfo?.assetType.join(',');
  890. // 处理仓库id
  891. let warehouseId = [];
  892. let warehouseName = [];
  893. let warehouseIds = this.productList
  894. .map((item) => item.warehouseId)
  895. .flat();
  896. let warehouseNames = this.productList
  897. .map((item) => item.warehouseName)
  898. .flat();
  899. warehouseIds.forEach((item, index) => {
  900. if (!warehouseId.includes(item)) {
  901. warehouseId.push(item);
  902. warehouseName.push(warehouseNames[index]);
  903. }
  904. });
  905. obj.warehouseIds = warehouseId;
  906. obj.warehouseNames = warehouseName;
  907. console.log('2222', obj);
  908. // // 1按数量计费 2按重量计费
  909. // if (this.form.pricingWay == 2) {
  910. // if (this.materialList.length > 0) {
  911. // // 判断物料
  912. // isPass = this.materialCodeReqList.every(
  913. // (item) => item.weight > 0
  914. // );
  915. // } else {
  916. // // 判断包装重量是否全部大于0
  917. // isPass = this.packingList.every((item) => item.weight > 0);
  918. // }
  919. // } else {
  920. // isPass = true;
  921. // }
  922. console.log(isPass,'isPass')
  923. if (isPass) {
  924. resolve(obj);
  925. } else {
  926. resolve(false);
  927. }
  928. });
  929. });
  930. },
  931. onClear() {
  932. this.formData.sourceBizNo = '';
  933. this.warehousingMaterialList = [];
  934. this.$refs.trees.valueTitle = '';
  935. this.formData.clientName = '';
  936. this.formData.clientUser = '';
  937. this.formData.clientPhone = '';
  938. this.$forceUpdate();
  939. },
  940. rowClass({ row, column, rowIndex, columnIndex }) {
  941. if (rowIndex === 1) {
  942. return {
  943. display: 'none',
  944. background: '#EEEEEE'
  945. };
  946. }
  947. return { background: '#0000' };
  948. },
  949. // 部门点击事件
  950. async auditorDeptClick(data) {
  951. console.log(data);
  952. this.formData.extInfo.verifyDeptCode = data?.id;
  953. this.formData.extInfo.verifyDeptName = data?.name;
  954. this.formData.verifyId = '';
  955. this.formData.verifyName = '';
  956. this.$refs.formName.validateField('verifyDeptName');
  957. if (data) {
  958. this.getStaffList(data);
  959. }
  960. },
  961. getStaffList(data) {
  962. return new Promise(async (resolve) => {
  963. let res = await warehouseDefinition.getUserPage({
  964. groupId: data.id,
  965. size: 9999,
  966. page: 1
  967. });
  968. this.llrLsit = res.list;
  969. resolve();
  970. });
  971. },
  972. // 初始化用户信息
  973. async initFormData() {
  974. console.log(this.form, 'ddddddddddddddddddddddddddddd123form');
  975. // const res = await warehouseDefinition.tree();
  976. // let obj = res.find(
  977. // (item) =>
  978. // item.id ===
  979. // this.user.info.deptIds[this.user.info.deptIds.length - 1]
  980. // );
  981. // if (!obj) return;
  982. // this.formData.extInfo.deptCode = obj.id;
  983. // this.formData.extInfo.deptName = obj.name;
  984. // this.formData.extInfo.createUserName = this.user.info.name;
  985. // this.formData.createUserId = this.user.info.userId;
  986. this.formData.extInfo.assetType = Array.from(
  987. new Set(this.form.categoryLevelTopId?.split(','))
  988. );
  989. //委外出库
  990. if (this.bizType == 7 && this.form.productList) {
  991. const categoryids = this.form.productList.map(
  992. (p) => p.categoryLevelTopId
  993. );
  994. console.log(categoryids, '委外出库的物品id');
  995. this.formData.extInfo.assetType = categoryids;
  996. }
  997. // 出库类型
  998. this.formData.bizType = this.bizType;
  999. // 添加单据来源
  1000. this.formData.sourceBizNo = this.sourceBizNo || this.form?.code;
  1001. // 将出库状态改成出库状态 2出库 1入库
  1002. this.formData.type = 2;
  1003. // 入库登记人
  1004. this.formData.extInfo.createUserId = this.$store.state.user.info.userId;
  1005. this.formData.extInfo.createUserName = this.$store.state.user.info.name;
  1006. this.formData.createUserId = this.$store.state.user.info.userId;
  1007. await this.initDeptData(); // 确保部门树加载
  1008. if (this.form.makerId) {
  1009. warehouseDefinition.getGroupById(this.form.makerId).then((res) => {
  1010. console.log(res, 'makerId');
  1011. this.$set(this.formData.extInfo, 'verifyDeptCode', res.groupId);
  1012. this.$set(this.formData.extInfo, 'verifyDeptName', res.groupName);
  1013. });
  1014. }
  1015. // 生产相关逻辑
  1016. console.log(this.detailList, 'this.detailList');
  1017. console.log(this.saleProductList, 'this.saleProductList');
  1018. console.log(this.productList, 'this.productList');
  1019. if (this.detailList?.length > 0) {
  1020. // 获取领料人列表
  1021. if (this.form.executorDeptId) {
  1022. this.getStaffList({ id: this.form.executorDeptId }).then(() => {
  1023. // 获取领料人和领料部门
  1024. this.formData.fromId = this.form.executorId;
  1025. this.formData.fromUser = this.form.executorName;
  1026. this.formData.extInfo.verifyDeptCode = this.form.executorDeptId;
  1027. this.formData.extInfo.verifyDeptName = this.form.executorDeptName;
  1028. });
  1029. } else {
  1030. this.formData.fromId = this.form.createUserId;
  1031. warehouseDefinition
  1032. .getGroupById(this.form.createUserId)
  1033. .then((res) => {
  1034. console.log(res, 'form没有executorDeptId有createUserId');
  1035. this.$set(this.formData, 'fromUser', res.name);
  1036. this.$set(this.formData.extInfo, 'verifyDeptCode', res.groupId);
  1037. this.$set(
  1038. this.formData.extInfo,
  1039. 'verifyDeptName',
  1040. res.groupName
  1041. );
  1042. });
  1043. }
  1044. let pData = {
  1045. type: '1',
  1046. builders: this.detailList.map((item) => {
  1047. return {
  1048. categoryId:
  1049. item.instanceId || item.categoryId || item.productId,
  1050. num: item.demandQuantity || item.measurementCount,
  1051. warehouseId: this.bizType == 11 ? item.warehouseId : '',
  1052. batchNo: item.batchNo || '',
  1053. systemBatchNo: item.systemBatchNo || ''
  1054. };
  1055. })
  1056. };
  1057. let pData2 = {
  1058. type: this.wwType,
  1059. taskIds: this.extractedList.map((item) => item.taskId),
  1060. workOrderIds: this.extractedList.map((item) => item.workOrderId)
  1061. };
  1062. let pData3 = {
  1063. //销售退货处理 外协出库
  1064. type: 3,
  1065. outInIds: this.form?.returnInReceiptId?.split(','),
  1066. packageNos: this.detailList.map((item) => item.packageNo)
  1067. };
  1068. let pData4 = {
  1069. //受托退货
  1070. type: 3,
  1071. ids: this.detailList.map((item) => item.packageId)?.toString()
  1072. };
  1073. let api = this.bizType == 8 ? 'getHierarchyList' : 'getHierarchyFifo';
  1074. storageApi[api](
  1075. this.wwType == 3
  1076. ? pData2
  1077. : this.bizType == 6
  1078. ? pData3
  1079. : this.bizType == 8
  1080. ? pData4
  1081. : pData
  1082. )
  1083. .then((data) => {
  1084. this.detailData(data, this.dimension);
  1085. })
  1086. .catch((err) => {
  1087. console.log(err);
  1088. });
  1089. return;
  1090. }
  1091. // 销售相关逻辑
  1092. if (this.saleProductList?.length > 0) {
  1093. // 获取领料人列表
  1094. this.getStaffList({ id: this.form.deptId }).then(() => {
  1095. // 获取领料人和领料部门
  1096. this.formData.fromId = this.form.makerId;
  1097. this.formData.fromUser = this.form.makerName;
  1098. this.formData.extInfo.verifyDeptCode = this.form.deptId;
  1099. this.formData.extInfo.verifyDeptName = this.form.deptName;
  1100. });
  1101. let pData = {
  1102. type: '1',
  1103. builders: this.saleProductList.map((item) => {
  1104. return {
  1105. categoryId: item.productId || item.categoryId,
  1106. num: item.totalCount,
  1107. batchNo: item.batchNo || '',
  1108. systemBatchNo: item.systemBatchNo || ''
  1109. // warehouseId: this.bizType == 3 ? item.warehouseId : ''
  1110. // batchNo: item.batchNo || '',
  1111. };
  1112. })
  1113. };
  1114. let pData2 = {
  1115. type: this.wwType,
  1116. taskIds: this.extractedList.map((item) => item.taskId),
  1117. workOrderIds: this.extractedList.map((item) => item.workOrderId)
  1118. };
  1119. storageApi
  1120. .getHierarchyFifo(this.wwType == 3 ? pData2 : pData)
  1121. .then((data) => {
  1122. this.detailData(data, this.dimension);
  1123. })
  1124. .catch((err) => {
  1125. console.log(err);
  1126. });
  1127. return;
  1128. }
  1129. //采购委外
  1130. if (this.form.productList?.length > 0) {
  1131. this.getStaffList({ id: this.form.deptId }).then(() => {
  1132. this.formData.fromId = this.form.makerId;
  1133. this.formData.fromUser = this.form.makerName;
  1134. this.formData.extInfo.verifyDeptCode = this.form.deptId;
  1135. this.formData.extInfo.verifyDeptName = this.form.deptName;
  1136. });
  1137. let pData = {
  1138. type: '1',
  1139. builders: this.form.productList.map((item) => {
  1140. return {
  1141. categoryId: item.productId,
  1142. num: item.totalCount,
  1143. price: item.totalPrice,
  1144. unitPrice: item.singlePrice,
  1145. weight: item.singleWeight * item.totalCount || 0,
  1146. batchNo: item.batchNo || '',
  1147. systemBatchNo: item.systemBatchNo || '',
  1148. taskId: item.taskId || ''
  1149. };
  1150. })
  1151. };
  1152. let pData2 = {
  1153. type: 3,
  1154. taskIds: this.form.productList.map((item) => item.taskId),
  1155. workOrderIds: [this.form.sourceId]
  1156. };
  1157. storageApi
  1158. .getHierarchyFifo(this.form.sourceId ? pData2 : pData)
  1159. .then((data) => {
  1160. this.detailData(data, this.dimension);
  1161. })
  1162. .catch((err) => {
  1163. console.log(err);
  1164. });
  1165. }
  1166. // if (this.form.productList?.length > 0) {
  1167. // this.getStaffList({ id: this.form.deptId }).then(() => {
  1168. // this.formData.fromId = this.form.makerId;
  1169. // this.formData.fromUser = this.form.makerName;
  1170. // this.formData.extInfo.verifyDeptCode = this.form.deptId;
  1171. // this.formData.extInfo.verifyDeptName = this.form.deptName;
  1172. // });
  1173. // let pData = {
  1174. // type: '1',
  1175. // builders: this.form.productList.map((item) => {
  1176. // return {
  1177. // categoryId: item.productId,
  1178. // num: item.totalCount,
  1179. // price: item.totalPrice,
  1180. // unitPrice: item.singlePrice,
  1181. // weight: item.singleWeight * item.totalCount || 0,
  1182. // batchNo: item.batchNo || '',
  1183. // taskId: item.taskId || ''
  1184. // };
  1185. // })
  1186. // };
  1187. // let pData2 = {
  1188. // type: 3,
  1189. // taskIds: this.form.productList.map((item) => item.taskId),
  1190. // workOrderIds: [this.form.sourceId]
  1191. // };
  1192. // storageApi
  1193. // .getHierarchyFifo(this.form.sourceId ? pData2 : pData)
  1194. // .then((data) => {
  1195. // this.detailData(data, this.dimension);
  1196. // })
  1197. // .catch((err) => {
  1198. // console.log(err);
  1199. // });
  1200. // }
  1201. },
  1202. // 初始化部门数据
  1203. initDeptData() {
  1204. return new Promise(async (resolve) => {
  1205. const res = await warehouseDefinition.tree();
  1206. this.treeList = this.$util.toTreeData({
  1207. data: res,
  1208. idField: 'id',
  1209. parentIdField: 'parentId'
  1210. });
  1211. this.$nextTick(() => {
  1212. resolve();
  1213. });
  1214. });
  1215. },
  1216. addStock() {
  1217. console.log(this.formData.extInfo.assetType);
  1218. if (
  1219. !(
  1220. this.formData.extInfo.assetType &&
  1221. this.formData.extInfo.assetType.length > 0
  1222. )
  1223. )
  1224. return this.$message.error('请选择出库产品类型');
  1225. if (!this.formData.bizType && this.formData.bizType !== 0)
  1226. return this.$message.error('请选择出库场景');
  1227. this.$refs.assetsDialogRef.open(this.productList);
  1228. },
  1229. handleBizSceneChange() {
  1230. if (this.formData.extInfo.assetType == 7) {
  1231. this.formData.extInfo.sourceBizNo = '';
  1232. }
  1233. this.formData.sourceBizNo = '';
  1234. },
  1235. deleteProductList(row, index) {
  1236. // 1. 获取当前物料的所有包装列表
  1237. const targetPackages = row.outInDetailRecordRequestList || [];
  1238. const packageIds = new Set(targetPackages.map((p) => p.id));
  1239. console.log('targetPackages', targetPackages);
  1240. console.log('packageIds包装的id', packageIds);
  1241. // 从packingList中移除相关包装
  1242. this.packingList = this.packingList.filter(
  1243. (p) => !packageIds.has(p.id) && p.categoryCode !== row.categoryCode
  1244. );
  1245. console.log('包装列表', this.packingList);
  1246. // 从materialList中移除关联物料
  1247. const materialIds = new Set();
  1248. targetPackages.forEach((packageItem) => {
  1249. packageItem.materialDetailList.forEach((material) => {
  1250. materialIds.add(material.id);
  1251. });
  1252. });
  1253. this.materialList = this.materialList.filter(
  1254. (m) => !materialIds.has(m.id) && m.categoryCode !== row.categoryCode
  1255. );
  1256. this.productList.splice(index, 1);
  1257. // this.$nextTick(() => {
  1258. // this.$refs.productListTable?.doLayout()
  1259. // this.$refs.showPackingListTable?.doLayout()
  1260. // this.$refs.multipleTable?.doLayout()
  1261. // })
  1262. }
  1263. },
  1264. watch: {
  1265. packingList: {
  1266. handler(newVal) {
  1267. console.log('包装列表', newVal);
  1268. console.log('当前包装列表加载页数2', this.pickingPageNum);
  1269. this.showPackingList = newVal.slice(
  1270. 0,
  1271. this.pageSize * (this.pickingPageNum > 0 ? this.pickingPageNum : 1)
  1272. );
  1273. },
  1274. deep: true
  1275. },
  1276. materialList: {
  1277. handler(newVal) {
  1278. console.log('物料列表', newVal);
  1279. console.log('当前物料列表加载页数', this.materielPageNum);
  1280. this.showMaterialList = newVal.slice(
  1281. 0,
  1282. this.pageSize *
  1283. (this.materielPageNum > 0 ? this.materielPageNum : 1)
  1284. );
  1285. },
  1286. deep: true
  1287. }
  1288. // detailList: {
  1289. // handler(newVal) {
  1290. // if (newVal.length) {
  1291. // this.initFormData();
  1292. // }
  1293. // },
  1294. // deep: true
  1295. // }
  1296. }
  1297. };
  1298. </script>
  1299. <style lang="scss" scoped>
  1300. ::v-deep .el-row {
  1301. display: flex;
  1302. flex-wrap: wrap;
  1303. }
  1304. ::v-deep.form-table {
  1305. .el-form-item {
  1306. margin-bottom: 0;
  1307. }
  1308. .el-input__inner {
  1309. padding: 0 10px;
  1310. }
  1311. }
  1312. .p20 {
  1313. padding: 20px;
  1314. }
  1315. .el-select,
  1316. .el-date-editor {
  1317. width: 100%;
  1318. }
  1319. .el-form-item {
  1320. margin-bottom: 22px;
  1321. }
  1322. .material {
  1323. margin-top: 20px;
  1324. .flex {
  1325. display: flex;
  1326. justify-content: space-between;
  1327. font-size: 14px;
  1328. align-items: center;
  1329. .red {
  1330. color: #ff4949;
  1331. }
  1332. }
  1333. }
  1334. .mt10 {
  1335. margin-top: 10px;
  1336. }
  1337. .mt20 {
  1338. margin-top: 20px;
  1339. }
  1340. .center {
  1341. text-align: center;
  1342. }
  1343. </style>