taskForm.vue 76 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005
  1. <template>
  2. <view class="">
  3. <u-sticky offset-top="50">
  4. <u-subsection fontSize='25' mode='subsection' :list="list" :current="curNow" @change="sectionChange"
  5. activeColor='#157A2C'></u-subsection>
  6. </u-sticky>
  7. <view v-show="curNow===0">
  8. <u--form style="margin: 0 20px;" labelPosition="left" :model="form" ref="uForm" labelWidth='140rpx'>
  9. <u-form-item label="收货单编码" prop="receiveNo" borderBottom>
  10. <u--input style="width: 100%;" disabled v-model="form.receiveNo"></u--input>
  11. </u-form-item>
  12. <u-form-item label="订单编码" prop="orderNo" borderBottom>
  13. <u--input style="width: 100%;" disabled v-model="form.orderNo"></u--input>
  14. </u-form-item>
  15. <u-form-item label="制单人" prop="makerName" borderBottom>
  16. <u--input style="width: 100%;" disabled v-model="form.makerName"></u--input>
  17. </u-form-item>
  18. <u-form-item label="供应商名称" prop="supplierName" borderBottom>
  19. <u--input style="width: 100%;" disabled v-model="form.supplierName"></u--input>
  20. </u-form-item>
  21. <u-form-item label="供应商联系人" prop="linkName" borderBottom>
  22. <u--input style="width: 100%;" disabled v-model="form.linkName"></u--input>
  23. </u-form-item>
  24. <u-form-item label="供应商电话" prop="linkPhone" borderBottom>
  25. <u--input style="width: 100%;" disabled v-model="form.linkPhone"></u--input>
  26. </u-form-item>
  27. <u-form-item label="车牌" prop="carNo" borderBottom>
  28. <u--input style="width: 100%;" disabled v-model="form.carNo"></u--input>
  29. </u-form-item>
  30. <u-form-item label="收货日期" prop="receiveDate" borderBottom>
  31. <u--input style="width: 100%;" disabled v-model="form.receiveDate"></u--input>
  32. </u-form-item>
  33. <u-form-item label="委外发货单编码" prop="outsourceSendCode" borderBottom>
  34. <u--input style="width: 100%;" disabled v-model="form.outsourceSendCode"></u--input>
  35. </u-form-item>
  36. <u-form-item label="附件" prop="receiveFiles" borderBottom>
  37. <fileMain v-model="form.receiveFiles" type="view"></fileMain>
  38. </u-form-item>
  39. </u--form>
  40. </view>
  41. <view v-show="curNow===1">
  42. <view v-for="(item,index) in form['productList']" :key="index">
  43. <u--form style="margin: 0 20px;" labelPosition="left" :model="form" ref="uForm" labelWidth='140rpx'>
  44. <u-row v-for="(key,index1) in tableField" :key="index1">
  45. <u-col :span="12">
  46. <u-form-item :label="key.label" prop="categoryName" borderBottom>
  47. <text>{{ key.formatter ? key.formatter(item) : (item[key.field] || '-') }}</text>
  48. </u-form-item>
  49. </u-col>
  50. </u-row>
  51. </u--form>
  52. <u-gap height="40" bgColor="#f0f0f0"></u-gap>
  53. </view>
  54. </view>
  55. <view v-show="curNow===2">
  56. <u--form style="margin: 0 20px;" labelPosition="left" :model="formData" ref="outForm" :rules="outRules" labelWidth='140rpx'>
  57. <u-form-item label="物品类型" prop="extInfo.assetType" borderBottom>
  58. <u--input style="width: 100%;" disabled v-model="formData.extInfo.assetTypeName"></u--input>
  59. </u-form-item>
  60. <u-form-item label="入库类型" prop="bizType" borderBottom>
  61. <u--input style="width: 100%;" disabled v-model="formData.bizTypeStr"></u--input>
  62. </u-form-item>
  63. <u-form-item label="单据来源" prop="sourceBizNo" borderBottom>
  64. <u--input style="width: 100%;" disabled v-model="formData.sourceBizNo"></u--input>
  65. </u-form-item>
  66. <u-form-item label="入库时间" prop="storageTime" borderBottom>
  67. <uni-datetime-picker type="datetime" v-model="formData.storageTime" />
  68. </u-form-item>
  69. <u-form-item label="入库登记人" prop="extInfo.createUserName" borderBottom>
  70. <u--input style="width: 100%;" disabled v-model="formData.extInfo.createUserName"></u--input>
  71. </u-form-item>
  72. <u-form-item label="审核人" prop="approvalUserName" borderBottom>
  73. <u--input disabled style="width: 100%;" v-model="formData.approvalUserName"></u--input>
  74. </u-form-item>
  75. <u-form-item label="备注" prop="remark" borderBottom>
  76. <u--input style="width: 100%;" v-model="formData.remark"></u--input>
  77. </u-form-item>
  78. </u--form>
  79. </view>
  80. <view class="tab-content" v-show="curNow===3">
  81. <!-- 批量操作按钮 -->
  82. <view class="batch-actions" v-if="productList.length > 0">
  83. <u-button type="success" plain size="small" text="批量保存" @click="listSaveArrs" :disabled="packingList.length > 0"></u-button>
  84. <picker v-if="packingList.length === 0" class="info-picker" :value="warehouseIndex" :range="warehouseListOption" range-key="name" @change="handleWareHouse">
  85. <u-button type="success" plain size="small" text="批量选择仓库" v-if="packingList.length === 0"></u-button>
  86. </picker>
  87. </view>
  88. <view v-if="productList.length === 0" class="empty-tip" style="text-align: center; color: #999; font-size: 28rpx; padding: 100rpx 0;">
  89. 暂无产品信息
  90. </view>
  91. <view v-else>
  92. <view class="product-card" v-for="(row, index) in productList" :key="index">
  93. <view class="card-header">
  94. <text class="product-name">{{ row.categoryName || '-' }}</text>
  95. <text class="product-code">{{ row.categoryCode || '-' }}</text>
  96. <!-- <text class="card-index">{{ index + 1 }}</text> -->
  97. </view>
  98. <view class="card-body">
  99. <!-- 批次号 - isSave为false时可编辑 -->
  100. <view class="info-row edit-row">
  101. <text class="info-label">批次号 <text class="required">*</text></text>
  102. <u--input v-if="!row.isSave" class="info-input" type="text" v-model="row.batchNo" placeholder="请输入批次号" />
  103. <text v-else class="info-value">{{ row.batchNo || '-' }}</text>
  104. </view>
  105. <!-- 数量 - isSave为false时可编辑 -->
  106. <view class="info-row edit-row">
  107. <text class="info-label">数量 <text class="required">*</text></text>
  108. <u--input v-if="!row.isSave" class="info-input" type="number" v-model="row.packingQuantity" placeholder="请输入数量" @input="computeNum(row, index, true)" />
  109. <text v-else class="info-value">{{ row.packingQuantity || '-' }}</text>
  110. </view>
  111. <!-- 单位选择 -->
  112. <view class="info-row edit-row">
  113. <text class="info-label">单位 <text class="required">*</text></text>
  114. <picker v-if="!row.isSave" class="info-picker" :value="row.packingUnitIndex" :range="row.packingSpecificationOption" range-key="conversionUnit" @change="(e) => onPackingUnitChange(e, row, index)">
  115. <view class="picker-value">{{ row.packingUnit || '请选择单位' }}</view>
  116. </picker>
  117. <text v-else class="info-value">{{ row.packingUnit || '-' }}</text>
  118. </view>
  119. <!-- 包装完好与否 -->
  120. <view class="info-row edit-row" v-if="isShowPackage">
  121. <text class="info-label">包装完好 <text class="required">*</text></text>
  122. <picker v-if="!row.isSave" class="info-picker" :value="row.ifPackageOkIndex" :range="packageOkOptions" range-key="label" @change="(e) => onPackageOkChange(e, index)">
  123. <view class="picker-value">{{ row.ifPackageOkLabel || '请选择' }}</view>
  124. </picker>
  125. <text v-else class="info-value">{{ row.ifPackageOk == 1 ? '是' : row.ifPackageOk == 0 ? '否' : '-' }}</text>
  126. </view>
  127. <!-- 拆包装责任人 -->
  128. <view class="info-row edit-row" v-if="isShowPackage">
  129. <text class="info-label">拆包责任人 <text class="required">*</text></text>
  130. <input v-if="!row.isSave" class="info-input" type="text" v-model="row.unpackUserName" placeholder="请选择" readonly @click="handHead(row, index)" />
  131. <text v-else class="info-value">{{ row.unpackUserName || '-' }}</text>
  132. </view>
  133. <!-- 只读字段 -->
  134. <view class="info-row">
  135. <text class="info-label">计量数量</text>
  136. <text class="info-value">{{ row.measureQuantity || '0' }}</text>
  137. </view>
  138. <view class="info-row">
  139. <text class="info-label">计量单位</text>
  140. <text class="info-value">{{ row.measureUnit || '-' }}</text>
  141. </view>
  142. <!-- 单重 -->
  143. <view class="info-row edit-row">
  144. <text class="info-label">单重</text>
  145. <u--input v-if="!row.isSave" class="info-input" type="digit" v-model="row.singleWeight" placeholder="请输入单重" :disabled="row.weightUnit == row.packingUnit" @input="inputsingleWeight(row, index)" />
  146. <text v-else class="info-value">{{ row.singleWeight || '0' }} {{ row.weightUnit || '' }}</text>
  147. </view>
  148. <!-- 总重 -->
  149. <view class="info-row edit-row">
  150. <text class="info-label">总重</text>
  151. <u--input v-if="!row.isSave" class="info-input" type="digit" v-model="row.weight" placeholder="请输入总重" :disabled="row.weightUnit == row.packingUnit" @input="inputWeight(row, index)" />
  152. <text v-else class="info-value">{{ row.weight || '0' }} {{ row.weightUnit || '' }}</text>
  153. </view>
  154. <view class="info-row">
  155. <text class="info-label">重量单位</text>
  156. <text class="info-value">{{ row.weightUnit || '-' }}</text>
  157. </view>
  158. <view class="info-row">
  159. <text class="info-label">生产要求</text>
  160. <text class="info-value">{{ row.productionRequirements || '-' }}</text>
  161. </view>
  162. <view class="info-row">
  163. <text class="info-label">包装规格</text>
  164. <text class="info-value">{{ row.packingSpecificationLabel ? row.packingSpecificationLabel.join(', ') : '-' }}</text>
  165. </view>
  166. <view class="info-row">
  167. <text class="info-label">允许拆包</text>
  168. <text class="info-value">{{ row.isUnpack == 1 ? '是' : '否' }}</text>
  169. </view>
  170. <!-- 仓库 - 必填 -->
  171. <view class="info-row edit-row">
  172. <text class="info-label">仓库 <text class="required">*</text></text>
  173. <picker v-if="!row.isSave" class="info-picker" :value="row.warehouseIndex" :range="warehouseListOption" range-key="name" @change="(e) => onWarehouseChange(e, index)">
  174. <view class="picker-value">{{ row.warehouseName || '请选择仓库' }}</view>
  175. </picker>
  176. <text v-else class="info-value" :class="{ 'red-text': !row.warehouseName }">{{ row.warehouseName || '请选择仓库' }}</text>
  177. </view>
  178. <!-- 供应商 -->
  179. <view class="info-row edit-row">
  180. <text class="info-label">供应商</text>
  181. <picker v-if="!row.isSave" class="info-picker" :value="row.supplierIndex" :range="row.supplierListOptions" range-key="name" @change="(e) => onSupplierChange(e, index)">
  182. <view class="picker-value">{{ row.supplierName || '请选择供应商' }}</view>
  183. </picker>
  184. <text v-else class="info-value">{{ row.supplierName || '-' }}</text>
  185. </view>
  186. <view class="info-row">
  187. <text class="info-label">供应商代号</text>
  188. <text class="info-value">{{ row.supplierCode || '-' }}</text>
  189. </view>
  190. <!-- 采购原因 -->
  191. <view class="info-row edit-row">
  192. <text class="info-label">采购原因</text>
  193. <u--input v-if="!row.isSave" class="info-input" type="text" v-model="row.purpose" placeholder="请输入采购原因" />
  194. <text v-else class="info-value">{{ row.purpose || '-' }}</text>
  195. </view>
  196. <view class="info-row">
  197. <text class="info-label">是否质检</text>
  198. <text class="info-value">{{ row.qualityControl == 1 ? '是' : '否' }}</text>
  199. </view>
  200. <!-- 生产日期 -->
  201. <view class="info-row edit-row">
  202. <text class="info-label">生产日期</text>
  203. <!-- <picker v-if="!row.isSave" class="info-picker" mode="date" :value="row.detailProductionDate" @change="(e) => onDateChange(e, row, 'detailProductionDate')">
  204. <view class="picker-value" :class="{ 'placeholder': !row.detailProductionDate }">{{ row.detailProductionDate || '请选择日期' }}</view>
  205. </picker> -->
  206. <uni-datetime-picker v-if="!row.isSave" type="datetime" v-model="row.detailProductionDate" />
  207. <text v-else class="info-value">{{ row.detailProductionDate || '-' }}</text>
  208. </view>
  209. <!-- 采购日期 -->
  210. <view class="info-row edit-row">
  211. <text class="info-label">采购日期</text>
  212. <!-- <picker v-if="!row.isSave" class="info-picker" mode="date" :value="row.detailPurchaseDate" @change="(e) => onDateChange(e, row, 'detailPurchaseDate')">
  213. <view class="picker-value" :class="{ 'placeholder': !row.detailPurchaseDate }">{{ row.detailPurchaseDate || '请选择日期' }}</view>
  214. </picker> -->
  215. <uni-datetime-picker v-if="!row.isSave" type="datetime" v-model="row.detailPurchaseDate" />
  216. <text v-else class="info-value">{{ row.detailPurchaseDate || '-' }}</text>
  217. </view>
  218. <!-- 失效日期 -->
  219. <view class="info-row edit-row">
  220. <text class="info-label">失效日期</text>
  221. <!-- <picker v-if="!row.isSave" class="info-picker" mode="date" :value="row.detailExpireDate" @change="(e) => onDateChange(e, row, 'detailExpireDate')">
  222. <view class="picker-value" :class="{ 'placeholder': !row.detailExpireDate }">{{ row.detailExpireDate || '请选择日期' }}</view>
  223. </picker> -->
  224. <uni-datetime-picker v-if="!row.isSave" type="datetime" v-model="row.detailExpireDate" />
  225. <text v-else class="info-value">{{ row.detailExpireDate || '-' }}</text>
  226. </view>
  227. <!-- 机型 - 单选 -->
  228. <view class="info-row edit-row">
  229. <text class="info-label">机型</text>
  230. <picker v-if="!row.isSave" class="info-picker" mode="selector" :value="row.modelIndex" :range="modelOptions" range-key="dictValue" @change="(e) => onModelChange(e, index)">
  231. <view class="picker-value">{{ row.modelKeyName || '请选择机型' }}</view>
  232. </picker>
  233. <text v-else class="info-value">{{ row.modelKeyName || '-' }}</text>
  234. </view>
  235. <!-- 颜色 - 单选 -->
  236. <view class="info-row edit-row">
  237. <text class="info-label">颜色</text>
  238. <picker v-if="!row.isSave" class="info-picker" mode="selector" :value="row.colorIndex" :range="colorOptions" range-key="dictValue" @change="(e) => onColorChange(e, index)">
  239. <view class="picker-value">{{ row.colorKeyName || '请选择颜色' }}</view>
  240. </picker>
  241. <text v-else class="info-value">{{ row.colorKeyName || '-' }}</text>
  242. </view>
  243. </view>
  244. <view class="card-footer">
  245. <view class="action-buttons">
  246. <u-button v-if="!row.isSave" type="primary" size="small" text="保存" @click="listSave(row, index)"></u-button>
  247. <u-button v-else type="primary" size="small" text="编辑" @click="editProductList(row, index)"></u-button>
  248. <u-button type="error" size="small" text="删除" @click="listDel(row, index)"></u-button>
  249. </view>
  250. </view>
  251. </view>
  252. </view>
  253. <view class="add" @click="addProduct">
  254. <u-icon name="plus" color="#fff"></u-icon>
  255. </view>
  256. </view>
  257. <view class="tab-content" v-show="curNow===4">
  258. <!-- 包装明细 -->
  259. <view v-if="showPackingList.length > 0" class="packing-section">
  260. <view class="packing-card" v-for="(item, idx) in showPackingList" :key="'pkg-' + idx">
  261. <!-- <view class="card_title">包装 {{ idx + 1 }}</view> -->
  262. <view class="info-row">
  263. <text class="info-label">编码</text>
  264. <text class="info-value">{{ item.categoryCode || '-' }}</text>
  265. </view>
  266. <view class="info-row">
  267. <text class="info-label">名称</text>
  268. <text class="info-value">{{ item.categoryName || '-' }}</text>
  269. </view>
  270. <view class="info-row">
  271. <text class="info-label">批次号</text>
  272. <text class="info-value">{{ item.batchNo || '-' }}</text>
  273. </view>
  274. <view class="info-row">
  275. <text class="info-label">包装编码</text>
  276. <text class="info-value">{{ item.packageNo || '-' }}</text>
  277. </view>
  278. <view class="info-row">
  279. <text class="info-label">包装数量</text>
  280. <text class="info-value">{{ formatPackingValue(item.packingQuantity, item.packingUnit) }}</text>
  281. </view>
  282. <view class="info-row edit-row">
  283. <text class="info-label">计量数量</text>
  284. <u--input class="info-input" type="digit" v-model="item.measureQuantity" placeholder="请输入计量数量" />
  285. </view>
  286. <view class="info-row">
  287. <text class="info-label">计量单位</text>
  288. <text class="info-value">{{ item.measureUnit || '-' }}</text>
  289. </view>
  290. <view class="info-row">
  291. <text class="info-label">仓库</text>
  292. <text class="info-value">{{ item.warehouseName || '-' }}</text>
  293. </view>
  294. <view class="info-row edit-row">
  295. <text class="info-label">物料代号</text>
  296. <u--input class="info-input" type="text" v-model="item.materielDesignation" placeholder="请输入物料代号" />
  297. </view>
  298. <view class="info-row edit-row">
  299. <text class="info-label">客户代号</text>
  300. <u--input class="info-input" type="text" v-model="item.clientCode" placeholder="请输入客户代号" />
  301. </view>
  302. <view class="info-row">
  303. <text class="info-label">牌号</text>
  304. <text class="info-value">{{ item.brandNum || '-' }}</text>
  305. </view>
  306. <!-- 机型 - 单选 -->
  307. <view class="info-row edit-row">
  308. <text class="info-label">机型</text>
  309. <picker class="info-picker" mode="selector" :value="item.modelIndex" :range="modelOptions" range-key="dictValue" @change="(e) => onPackingModelChange(e, item)">
  310. <view class="picker-value">{{ item.modelKeyName || '请选择机型' }}</view>
  311. </picker>
  312. </view>
  313. <!-- 颜色 - 单选 -->
  314. <view class="info-row edit-row">
  315. <text class="info-label">颜色</text>
  316. <picker class="info-picker" mode="selector" :value="item.colorIndex" :range="colorOptions" range-key="dictValue" @change="(e) => onPackingColorChange(e, item)">
  317. <view class="picker-value">{{ item.colorKeyName || '请选择颜色' }}</view>
  318. </picker>
  319. </view>
  320. <view class="info-row edit-row">
  321. <text class="info-label">发货条码</text>
  322. <text class="info-value">{{ item.barcodes || '-' }}</text>
  323. </view>
  324. <view class="info-row edit-row">
  325. <text class="info-label">刻码</text>
  326. <u--input class="info-input" type="text" v-model="item.engrave" placeholder="请输入刻码" />
  327. </view>
  328. <view class="info-row edit-row">
  329. <text class="info-label">重量</text>
  330. <u--input class="info-input" type="digit" v-model="item.weight" placeholder="请输入重量" />
  331. <text class="info-unit">{{ item.weightUnit || '' }}</text>
  332. </view>
  333. <view class="info-row">
  334. <text class="info-label">供应商</text>
  335. <text class="info-value">{{ item.supplierName || '-' }}</text>
  336. </view>
  337. <view class="info-row">
  338. <text class="info-label">供应商代号</text>
  339. <text class="info-value">{{ item.supplierCode || '-' }}</text>
  340. </view>
  341. <view class="info-row">
  342. <text class="info-label">序列号</text>
  343. <text class="info-value">{{ item.serialNo || '-' }}</text>
  344. </view>
  345. <view class="info-row">
  346. <text class="info-label">是否质检</text>
  347. <text class="info-value">{{ item.qualityControl == 1 ? '是' : '否' }}</text>
  348. </view>
  349. <view class="info-row">
  350. <text class="info-label">质检状态</text>
  351. <text class="info-value">{{ qualityStatus[item.status] || '-' }}</text>
  352. </view>
  353. <!-- 质检结果 - 单选 -->
  354. <view class="info-row edit-row">
  355. <text class="info-label">质检结果</text>
  356. <picker class="info-picker" mode="selector" :value="getResultIndex(item.result)" :range="qualityResultsOptions" range-key="label" @change="(e) => onPackingResultChange(e, item)">
  357. <view class="picker-value">{{ qualityResults[item.result] || '请选择' }}</view>
  358. </picker>
  359. </view>
  360. <!-- 生产日期 -->
  361. <view class="info-row edit-row">
  362. <text class="info-label">生产日期</text>
  363. <uni-datetime-picker type="date" v-model="item.productionDate" />
  364. </view>
  365. <!-- 采购日期 -->
  366. <view class="info-row edit-row">
  367. <text class="info-label">采购日期</text>
  368. <uni-datetime-picker type="date" v-model="item.purchaseDate" />
  369. </view>
  370. <!-- 失效日期 -->
  371. <view class="info-row edit-row">
  372. <text class="info-label">失效日期</text>
  373. <uni-datetime-picker type="date" v-model="item.expireDate" />
  374. </view>
  375. </view>
  376. </view>
  377. </view>
  378. </view>
  379. </template>
  380. <script>
  381. import {
  382. purchaseOrderReceiveGetByIdAPI
  383. } from '@/api/wt/index.js'
  384. import { sceneState } from '@/enum/dict.js'
  385. import fileMain from "@/pages/doc/index.vue"
  386. import { parameterGetByCode } from '@/api/mainData/index.js'
  387. import { getListByNameOrModeType, getCode, contactQueryByCategoryIdsAPI, getCategoryPackageDisposition, getProduceTreeByPid, warehouseDefinitionList, getAssetNum, getWarehouseList, isVerifyRepeatIsStock } from '@/api/warehouseManagement/index.js'
  388. import { mapGetters, mapActions } from 'vuex'
  389. import { unary } from 'lodash'
  390. // 质检结果映射
  391. const qualityResults = {
  392. 1: '合格',
  393. 2: '不合格',
  394. };
  395. // 质检状态映射
  396. const qualityStatus = {
  397. 0: '未质检',
  398. 1: '待检',
  399. 2: '已质检',
  400. };
  401. // 质检结果 picker 选项
  402. const qualityResultsOptions = [
  403. { value: 1, label: '合格' },
  404. { value: 2, label: '不合格' },
  405. ];
  406. export default {
  407. components: {
  408. fileMain
  409. },
  410. props: {
  411. businessId: {
  412. default: ''
  413. },
  414. taskDefinitionKey: {
  415. default: ''
  416. },
  417. },
  418. computed: {
  419. ...mapGetters(['dict', 'getDict', 'getDictValue']),
  420. // 颜色选项(数组)
  421. colorOptions() {
  422. return this.dict?.product_color_key || []
  423. },
  424. // 机型选项(数组)
  425. modelOptions() {
  426. return this.dict?.product_model_key || []
  427. },
  428. list() {
  429. return this.showPackingList.length > 0 ? ['收货信息', '物品清单', '入库信息', '产品信息', '包装明细'] : ['收货信息', '物品清单', '入库信息', '产品信息']
  430. },
  431. tableField() {
  432. const priceField = [
  433. { label: '单价', field: 'singlePrice' },
  434. { label: '不含税单价', field: 'notaxSinglePrice' },
  435. { label: '折后单价', field: 'discountSinglePrice' },
  436. { label: '合计', field: 'totalPrice' },
  437. { label: '折后合计', field: 'discountTotalPrice' },
  438. ]
  439. const baseField = [
  440. { label: '名称', field: 'productName' },
  441. { label: '编码', field: 'productCode' },
  442. { label: '类型', field: 'productCategoryName' },
  443. { label: '批次号', field: 'batchNo' },
  444. { label: '规格', field: 'specification' },
  445. { label: '型号', field: 'modelType' },
  446. { label: '包装规格', field: 'packingSpecification' },
  447. { label: '供应商代号', field: 'supplierMark' },
  448. { label: '仓库名称', field: 'warehouseName' },
  449. { label: '收货数量', field: 'purchaseCount', formatter: (row) => (row.purchaseCount || '-') + row.purchaseUnit },
  450. { label: '单重', field: 'singleWeight', formatter: (row) => row.singleWeight ? row.singleWeight + ' ' + row.weightUnit : '-' },
  451. { label: '发货总重', field: 'sendTotalWeight', formatter: (row) => row.sendTotalWeight ? row.sendTotalWeight + ' ' + row.weightUnit : '-' },
  452. { label: '收货总重', field: 'receiveTotalWeight', formatter: (row) => row.receiveTotalWeight ? row.receiveTotalWeight + ' ' + row.weightUnit : '-' },
  453. { label: '增重重量', field: 'increaseTotalWeight', formatter: (row) => row.increaseTotalWeight ? row.increaseTotalWeight + ' ' + row.weightUnit : '-' },
  454. { label: '计量数量', field: 'totalCount', formatter: (row) => (row.totalCount || '-') + row.measuringUnit },
  455. { label: '是否来料检验', field: 'isComeCheck', formatter: (row) => row.isComeCheck == 1 ? '是' : '否' },
  456. ]
  457. return this.taskDefinitionKey == 'storeManagerApprove' && this.isHidePrice == 0 ? baseField : [...baseField, ...priceField]
  458. },
  459. tableField2() {
  460. return [
  461. { label: '名称', field: 'categoryName' },
  462. { label: '编码', field: 'categoryCode' },
  463. { label: '型号', field: 'categoryModel' },
  464. { label: '规格', field: 'specification' },
  465. { label: '牌号', field: 'brandNum' },
  466. { label: '批次号', field: 'batchNo' },
  467. { label: '数量', field: 'packingQuantity' },
  468. { label: '单位', field: 'packingUnit' },
  469. { label: '单重', field: 'singleWeight' },
  470. { label: '总重', field: 'weight' },
  471. { label: '重量单位', field: 'weightUnit' },
  472. { label: '供应商', field: 'supplierId' },
  473. { label: '仓库', field: 'warehouseName' },
  474. { label: '颜色', field: 'colorKey' },
  475. { label: '机型', field: 'modelKey' },
  476. { label: '采购原因', field: 'purpose' },
  477. { label: '生产日期', field: 'detailProductionDate' },
  478. { label: '采购日期', field: 'detailPurchaseDate' },
  479. { label: '失效日期', field: 'detailExpireDate' },
  480. { label: '是否质检', field: 'qualityControl' },
  481. { label: '包装规格', field: 'packingSpecificationLabel' },
  482. { label: '允许拆包', field: 'isUnpack' },
  483. { label: '计量数量', field: 'measureQuantity' },
  484. { label: '计量单位', field: 'measureUnit' },
  485. { label: '生产要求', field: 'weightUnit' },
  486. { label: '供应商名称', field: 'supplierName' },
  487. { label: '供应商代号', field: 'supplierCode' },
  488. { label: '产地', field: 'supplierCode' },
  489. ]
  490. }
  491. },
  492. data() {
  493. return {
  494. form: {},
  495. userInfo: {},
  496. formData: {
  497. bizType: '',
  498. bizTypeStr: '',
  499. storageTime: '',
  500. qualityControl: '',
  501. extInfo: {
  502. assetType: [],
  503. assetTypeName: ''
  504. }
  505. },
  506. isHidePrice: 0,
  507. warehouseIndex: 0,
  508. curNow: 0,
  509. packingSpecificationOption: [],
  510. productList: [],
  511. packingList: [],
  512. showPackingList: [],
  513. goodsLists: [],
  514. outRules: {},
  515. sceneState,
  516. qualityResultsOptions,
  517. qualityStatus,
  518. qualityResults,
  519. isWrapTable: true,
  520. pageSize: 20,
  521. pickingPageNum: 1,
  522. visibleDialog: false,
  523. title: '选择产品',
  524. loadTree: true,
  525. isShowPackage: false,
  526. packageOkOptions: [
  527. { label: '是', value: 1 },
  528. { label: '否', value: 0 }
  529. ],
  530. }
  531. },
  532. beforeDestroy() {
  533. uni.$off('setSelectList')
  534. },
  535. created() {
  536. uni.$on('setSelectList', async data => {
  537. // uni.removeStorageSync('productList')
  538. console.log('setSelectList~~~', data)
  539. if (data?.length) {
  540. // 获取批次号
  541. const batchNo = await getCode('lot_number_code');
  542. // 获取供应商
  543. const supplierList = await contactQueryByCategoryIdsAPI({
  544. categoryIds: data.map((item) => item.id)
  545. });
  546. // 获取包装规格
  547. let packingSpecification = await getCategoryPackageDisposition({
  548. categoryIds: data.map((item) => item.id)
  549. });
  550. this.packingSpecificationOption = data.map((item) => {
  551. return packingSpecification
  552. .filter((ite) => item.id == ite.categoryId)
  553. .sort((a, b) => a.sort - b.sort);
  554. });
  555. const newSpecificationOption = this.packingSpecificationOption;
  556. let productList = data.map((item, index) => {
  557. // 显示规格
  558. let packingSpecificationLabel = this.packingSpecificationOption[index].map((item) => {
  559. if (item.sort > 0) {
  560. return `${item.packageCell}${item.packageUnit}/${item.conversionUnit}`;
  561. }
  562. }).filter((item) => !!item);
  563. return {
  564. index:
  565. this.productList.length - 1 > -1
  566. ? this.productList[this.productList.length - 1].index + index + 1 : this.productList.length + index,
  567. categoryId: item.id, // 物品id
  568. categoryName: item.name, // 物品名称
  569. categoryCode: item.code, // 物品编码
  570. categoryModel: item.modelType, // 物品型号
  571. specification: item.specification, // 规格
  572. modelKey: item.modelKey ? item.modelKey : '', // 机型
  573. modelKeyName: item.modelKey ? (this.modelOptions.find(o => o.dictCode === item.modelKey)?.dictValue || '') : '',
  574. modelIndex: item.modelKey ? this.modelOptions.findIndex(o => o.dictCode === item.modelKey) : -1,
  575. colorKey: item.colorKey ? item.colorKey : '', // 颜色
  576. colorKeyName: item.colorKey ? (this.colorOptions.find(o => o.dictCode === item.colorKey)?.dictValue || '') : '',
  577. colorIndex: item.colorKey ? this.colorOptions.findIndex(o => o.dictCode === item.colorKey) : -1,
  578. brandNum: item.brandNum, // 牌号
  579. batchNo: batchNo, // 批次号
  580. supplierListOptions: supplierList[item.id], // 供应商列表
  581. supplierId: '', // 供应商id
  582. supplierIndex: -1, // 供应商索引
  583. supplierCode: item.supplierCode, // 供应商代号
  584. supplierName: item.supplierName, // 供应商名称
  585. measureType: item.measureType, // 计量类型
  586. approvalNumber: item.approvalNumber, // 批准文号
  587. packingSpecification: item.packingSpecification, // 包装规格
  588. packingSpecificationOption: newSpecificationOption[index], // 包装规格选项
  589. packingSpecificationLabel: packingSpecificationLabel, // 包装规格显示
  590. minPackingQuantity: '', // 最小包装单元数量
  591. packingQuantity: '', // 包装数量
  592. packingUnit: item.measuringUnit, // 单位
  593. packingUnitId: newSpecificationOption[index].find(
  594. (v) => v.conversionUnit == item.measuringUnit
  595. )?.id, // 单位
  596. measureQuantity: 0, // 计量数量
  597. measureUnit: item.measuringUnit, // 计量单位
  598. netWeight: item.netWeight > -1 ? item.netWeight : 0, // 净重
  599. weight: 0, // 重量
  600. singleWeight: item.measuringUnit != 'KG' ? item.netWeight : 0, // 单重
  601. pricingWay: item.pricingWay,
  602. weightUnit: item.weightUnit, // 重量单位
  603. totalMoney: item.totalPrice, // 总价
  604. unitPrice: item.unitPrice, // 单价
  605. purpose: '', // 用途
  606. isUnpack: item.isUnpack, // 是否允许拆包
  607. warehouseIndex: -1, // 仓库索引
  608. packingUnitIndex: newSpecificationOption[index]?.findIndex(v => v.conversionUnit == item.measuringUnit) ?? -1, // 单位索引
  609. isSave: false, // 是否已保存
  610. ifPackageOk: '', // 包装完好
  611. ifPackageOkIndex: -1, // 包装完好索引
  612. ifPackageOkLabel: '' // 包装完好标签
  613. };
  614. });
  615. this.productList = this.productList.concat(productList);
  616. }
  617. })
  618. },
  619. async mounted() {
  620. this.userInfo = uni.getStorageSync('userInfo')
  621. await this.requestDict('产地')
  622. await this.requestDict('不拆物料层规格')
  623. await this.requestDict('物品颜色')
  624. await this.requestDict('物品机型')
  625. await this.getListItems()
  626. await this.getwarehouseList()
  627. await parameterGetByCode({ code: 'eom_purchase_invoice_approval_price' }).then((res) => {
  628. this.isHidePrice = res.value;
  629. });
  630. await this.getDetailData(this.businessId);
  631. await this.getNowFormatDate();
  632. },
  633. watch: {
  634. packingList: {
  635. handler(newVal) {
  636. console.log('packingList~~', newVal)
  637. this.showPackingList = newVal.slice(0, this.pageSize * (this.pickingPageNum > 0 ? this.pickingPageNum : 1));
  638. this.pickingPageNum = Math.ceil(this.showPackingList.length / this.pageSize);
  639. },
  640. deep: true
  641. }
  642. },
  643. methods: {
  644. ...mapActions('dict', ['requestDict']),
  645. // 获取当前时间 YYYY-MM-DD HH:mm:ss
  646. getCurrentTime() {
  647. const now = new Date();
  648. const year = now.getFullYear();
  649. const month = String(now.getMonth() + 1).padStart(2, '0');
  650. const day = String(now.getDate()).padStart(2, '0');
  651. const hours = String(now.getHours()).padStart(2, '0');
  652. const minutes = String(now.getMinutes()).padStart(2, '0');
  653. const seconds = String(now.getSeconds()).padStart(2, '0');
  654. return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  655. },
  656. //获取仓库
  657. async getwarehouseList() {
  658. let res = await getWarehouseList()
  659. this.warehouseListOption = res.data.map(item => {
  660. return {
  661. id: item.id,
  662. name: item.name
  663. }
  664. })
  665. },
  666. handleWareHouse(e) {
  667. const val = Number(e.detail.value);
  668. this.warehouseIndex = val;
  669. const warehouseItem = this.warehouseListOption[val];
  670. if (warehouseItem) {
  671. this.productList.forEach((item, index) => {
  672. this.$set(this.productList[index], 'warehouseId', warehouseItem.id);
  673. this.$set(this.productList[index], 'warehouseName', warehouseItem.name);
  674. this.$set(this.productList[index], 'warehouseIds', [warehouseItem.id]);
  675. this.$set(this.productList[index], 'warehouseNames', [warehouseItem.name]);
  676. this.$set(this.productList[index], 'warehouseIndex', val);
  677. });
  678. }
  679. },
  680. // 获取物品列表
  681. async getListItems() {
  682. const res = await getProduceTreeByPid({});
  683. this.goodsLists = res;
  684. },
  685. sectionChange(index) {
  686. this.curNow = index;
  687. },
  688. async getDetailData(id) {
  689. const data = await purchaseOrderReceiveGetByIdAPI(id);
  690. this.form = data;
  691. this.initFormData()
  692. },
  693. initFormData() {
  694. const defaultTime = '00:00:00';
  695. this.formData.type = 1;
  696. this.formData.bizType = this.form.outsourceSendCode ? 10 : 2;
  697. const currentTime = this.getCurrentTime();
  698. if (this.formData.bizType == 2 || this.formData.bizType == 6) {
  699. this.formData.storageTime = this.form.receiveDate
  700. ? `${this.form.receiveDate} ${defaultTime}`
  701. : currentTime;
  702. } else {
  703. this.formData.storageTime = currentTime;
  704. }
  705. this.formData.bizTypeStr = sceneState.find(item => item.code == this.formData.bizType)?.label || ''
  706. if (this.form.receiveNo != null && this.form.receiveNo != '') {
  707. this.$set(this.formData, 'sourceBizNo', this.form.receiveNo);
  708. } else {
  709. uni.showToast({ title: '未获取到单据来源!', icon: 'none' });
  710. }
  711. this.formData.extInfo.createUserId = this.form.createUserId || this.userInfo.userId || '';
  712. this.formData.extInfo.createUserName = this.form.createUserName || this.userInfo.name || '';
  713. this.formData.extInfo.deliveryPhone = this.userInfo.phone || '';
  714. this.formData.createUserId = this.form.createUserId || this.userInfo.userId || '';
  715. this.formData.createUserName = this.form.createUserName || this.userInfo.name || '';
  716. this.formData.extInfo.deptName = this.form.deptName || this.userInfo.deptName || '';
  717. this.formData.approvalUserName = this.form.approvalUserName || this.userInfo.name;
  718. this.formData.approvalUserId = this.form.approvalUserId || this.userInfo.userId;
  719. if (this.form.productList?.length > 0) {
  720. let detailPurchaseDate;
  721. if (this.formData.bizType == '2' || this.formData.bizType == '10') {
  722. detailPurchaseDate = this.form.purchaseDate || `${this.form.receiveDate} ${defaultTime}`;
  723. }
  724. let codeList = this.form.productList.map((item) => item.productCode || item.categoryCode);
  725. getListByNameOrModeType({ codeList }).then(async (res) => {
  726. if (res.length <= 0) {
  727. uni.showToast({ title: '未获取到物品信息!', icon: 'none' });
  728. return;
  729. }
  730. this.formData.extInfo.assetType = Array.from(new Set(res.map((item) => item.categoryLevelPathIdParent)));
  731. this.formData.extInfo.assetTypeName = this.formData.extInfo.assetType.map(id => {
  732. const item = this.goodsLists.find(g => g.id == id);
  733. return item?.name || id;
  734. }).join(',');
  735. const batchNo1 = await getCode('lot_number_code');
  736. const supplierList = await contactQueryByCategoryIdsAPI({ categoryIds: res.map((item) => item.id) });
  737. let packingSpecification = await getCategoryPackageDisposition({ categoryIds: res.map((item) => item.id) });
  738. // 构建包装规格数组(按 res 顺序)和查找表(按 categoryId)
  739. this.packingSpecificationOption = res.map((item) => {
  740. return packingSpecification.filter((ite) => item.id == ite.categoryId).sort((a, b) => a.sort - b.sort);
  741. });
  742. const packingSpecMap = {};
  743. res.forEach((item, idx) => {
  744. packingSpecMap[item.id] = this.packingSpecificationOption[idx];
  745. });
  746. // 以 form.productList 为主循环,通过 res 适配补充品类字段
  747. this.productList = this.form.productList.map((formItem, index) => {
  748. let categoryItem = res.find(
  749. (r) => r.code === (formItem.productCode || formItem.categoryCode)
  750. );
  751. if (!categoryItem) return null;
  752. let filtersItem = formItem;
  753. const categorySpecs = packingSpecMap[categoryItem.id] || [];
  754. let packingSpecificationLabel = categorySpecs.map((item) => {
  755. if (item.sort > 0) {
  756. return `${item.packageCell}${item.packageUnit}/${item.conversionUnit}`;
  757. }
  758. }).filter((item) => !!item);
  759. let warehouseId = filtersItem.warehouseId;
  760. let warehouseName = filtersItem.warehouseName;
  761. let measureQuantity = filtersItem.totalCountNew || filtersItem.totalCount || 0;
  762. if ((filtersItem.sendTotalWeight || filtersItem.receiveTotalWeight) && categoryItem.weightUnit == categoryItem.measuringUnit) {
  763. measureQuantity = filtersItem.sendTotalWeight || filtersItem.receiveTotalWeight;
  764. }
  765. let packingQuantity = filtersItem.totalCountNew || filtersItem.purchaseCount || filtersItem.totalCount || 0;
  766. let packingUnit = filtersItem.purchaseUnit || filtersItem.measuringUnit || '';
  767. let unitPrice = filtersItem.singlePrice || 0;
  768. let pricingWay = filtersItem.pricingWay || '';
  769. let singleWeight = filtersItem.singleWeight || 0;
  770. let weight = filtersItem.sendTotalWeight || filtersItem.receiveTotalWeight || singleWeight * measureQuantity;
  771. let warehouseIds = [];
  772. let warehouseNames = [];
  773. for (let i = 0; i < filtersItem.totalCount; i++) {
  774. warehouseIds.push(filtersItem.warehouseId);
  775. warehouseNames.push(filtersItem.warehouseName);
  776. }
  777. let totalMoney = filtersItem.totalPrice || 0;
  778. let batchNo = filtersItem.batchNo || batchNo1;
  779. return {
  780. index: this.productList.length + index,
  781. categoryId: categoryItem.id,
  782. categoryName: categoryItem.name,
  783. categoryCode: categoryItem.code,
  784. categoryModel: categoryItem.modelType,
  785. specification: categoryItem.specification,
  786. brandNum: categoryItem.brandNum,
  787. batchNo: batchNo,
  788. supplierListOptions: supplierList[categoryItem.id],
  789. supplierId: this.form.supplierId,
  790. supplierIndex: this.form.supplierId ? (supplierList[categoryItem.id]?.findIndex(s => s.id == this.form.supplierId) ?? -1) : -1,
  791. productionRequirements: filtersItem.productionRequirements,
  792. supplierCode: this.formData.bizType == 2 || this.formData.bizType == 7 ? filtersItem.supplierMark : categoryItem.supplierCode,
  793. supplierName: this.form.supplierName,
  794. approvalNumber: categoryItem.approvalNumber,
  795. packingSpecification: categoryItem.packingSpecification,
  796. packingSpecificationOption: categorySpecs,
  797. packingSpecificationLabel: packingSpecificationLabel,
  798. packingQuantity: filtersItem?.isAllPackageData == 1
  799. ? filtersItem.packingCount : packingQuantity,
  800. packingUnit: filtersItem?.isAllPackageData == 1
  801. ? filtersItem.packingUnit : packingUnit,
  802. measureQuantity: filtersItem?.isAllPackageData == 1
  803. ? filtersItem.quantity : measureQuantity,
  804. measureUnit: filtersItem?.isAllPackageData == 1
  805. ? filtersItem.measuringUnit : categoryItem.measuringUnit,
  806. packingUnitId: filtersItem.purchaseUnitId || filtersItem.saleUnitId,
  807. modelKey: filtersItem.modelKey ? filtersItem.modelKey : '',
  808. modelKeyName: filtersItem.modelKey ? (this.modelOptions.find(o => o.dictCode === filtersItem.modelKey)?.dictValue || '') : '',
  809. modelIndex: filtersItem.modelKey ? this.modelOptions.findIndex(o => o.dictCode === filtersItem.modelKey) : -1,
  810. colorKey: filtersItem.colorKey ? filtersItem.colorKey : '',
  811. colorKeyName: filtersItem.colorKey ? (this.colorOptions.find(o => o.dictCode === filtersItem.colorKey)?.dictValue || '') : '',
  812. colorIndex: filtersItem.colorKey ? this.colorOptions.findIndex(o => o.dictCode === filtersItem.colorKey) : -1,
  813. measureType: categoryItem.measureType,
  814. netWeight: categoryItem.netWeight > -1 ? categoryItem.netWeight : 0,
  815. singleWeight: singleWeight || 0,
  816. weight: weight || 0,
  817. weightUnit: categoryItem.weightUnit,
  818. totalMoney: totalMoney,
  819. unitPrice: categoryItem.unitPrice || unitPrice,
  820. pricingWay: pricingWay,
  821. purpose: '',
  822. detailPurchaseDate,
  823. detailExpireDate: filtersItem?.guaranteePeriodDeadline,
  824. detailProductionDate: filtersItem?.productionDate,
  825. provenance: filtersItem.provenance,
  826. isUnpack: categoryItem.isUnpack,
  827. warehouseId,
  828. warehouseName,
  829. warehouseIds,
  830. warehouseNames,
  831. warehouseIndex: this.warehouseListOption?.findIndex(w => w.id == warehouseId) ?? -1,
  832. packingUnitIndex: categorySpecs?.findIndex(v => v.id == (filtersItem.purchaseUnitId || filtersItem.saleUnitId)) ?? -1,
  833. isSave: false,
  834. ifPackageOk: '',
  835. ifPackageOkIndex: -1,
  836. ifPackageOkLabel: '',
  837. qualityControl: filtersItem?.isComeCheck
  838. };
  839. }).filter(Boolean);
  840. this.$nextTick(() => {
  841. this.batchSave();
  842. });
  843. });
  844. }
  845. },
  846. // 赋值入库时间
  847. getNowFormatDate() {
  848. const obj = this.getNowDate();
  849. const defaultTime = '00:00:00';
  850. const currentTime = `${obj.hour}:${obj.minute}:${obj.second}`;
  851. if (this.formData.bizType === 2 || this.formData.bizType === '2' || this.formData.bizType === 6 || this.formData.bizType === '6') {
  852. this.formData.storageTime = this.form.receiveDate
  853. ? `${this.form.receiveDate} ${defaultTime}`
  854. : `${obj.year}-${obj.month}-${obj.strDate} ${currentTime}`;
  855. } else {
  856. this.formData.storageTime = `${obj.year}-${obj.month}-${obj.strDate} ${currentTime}`;
  857. }
  858. },
  859. // 获取当前时间函数
  860. getNowDate() {
  861. let date = new Date(),
  862. obj = {
  863. year: date.getFullYear(),
  864. month: date.getMonth() + 1,
  865. strDate: date.getDate(),
  866. hour: date.getHours(),
  867. minute: date.getMinutes(),
  868. second: date.getSeconds()
  869. };
  870. Object.keys(obj).forEach((key) => {
  871. if (obj[key] < 10) obj[key] = `0${obj[key]}`;
  872. });
  873. return obj;
  874. },
  875. changeCount(number) {
  876. // 移动端兼容的数字转字符串方法,避免浮点数精度显示问题
  877. const num = Number(number || 0);
  878. return isNaN(num) ? '0' : String(num);
  879. },
  880. // 格式化包装数量/计量数量/重量(带单位)
  881. formatPackingValue(value, unit) {
  882. if (value === null || value === undefined || value === '') return '-';
  883. return this.changeCount(value) + ' ' + (unit || '');
  884. },
  885. selectSupplier(val, row) {
  886. row.supplierId = val;
  887. row.supplierName = row.supplierListOptions.filter((item) => item.id == val)[0]?.name;
  888. row.supplierCode = row.supplierListOptions.filter((item) => item.id == val)[0]?.serialNo;
  889. },
  890. inputsingleWeight(row, index) {
  891. if (row.measureUnit == row.weightUnit) {
  892. this.$set(this.productList[index], 'weight', row.singleWeight * row.packingQuantity);
  893. this.$set(this.productList[index], 'measureQuantity', row.weight);
  894. } else {
  895. this.$set(this.productList[index], 'weight', row.singleWeight * row.measureQuantity);
  896. }
  897. },
  898. inputWeight(row, index) {
  899. if (row.measureUnit == row.weightUnit) {
  900. this.$set(this.productList[index], 'measureQuantity', row.weight);
  901. this.$set(this.productList[index], 'singleWeight', Math.trunc((row.measureQuantity / row.packingQuantity) * 10000) / 10000);
  902. } else {
  903. this.$set(this.productList[index], 'singleWeight', row.measureQuantity ? row.weight / row.measureQuantity : 0);
  904. }
  905. },
  906. // 计算最小单元数量
  907. async computeNum(row, index, isClear) {
  908. let data = row.packingSpecificationOption.find((item) => item.id == row.packingUnitId);
  909. if (data) {
  910. this.$set(this.productList[index], 'packingUnit', data.conversionUnit);
  911. }
  912. if (isClear && row.packingQuantity < 0) {
  913. this.$set(this.productList[index], 'packingQuantity', 1);
  914. }
  915. if (row.packingQuantity && row.packingUnit) {
  916. const res = await warehouseDefinitionList({});
  917. if (res.length == 1) {
  918. let name = res[0]?.factoryName + '-' + res[0]?.name;
  919. this.$set(this.productList[index], 'warehouseId', res[0].id);
  920. this.$set(this.productList[index], 'warehouseName', name);
  921. this.$set(this.productList[index], 'warehouseIndex', this.warehouseListOption?.findIndex(w => w.id == res[0].id) ?? -1);
  922. } else {
  923. this.$set(this.productList[index], 'warehouseId', '');
  924. this.$set(this.productList[index], 'warehouseName', '');
  925. }
  926. let endIndex = row.packingSpecificationOption.findIndex((ite) => data.id == ite.id);
  927. let total = Number(row.packingQuantity);
  928. if (row.packingUnit == row.measureUnit && row.measureUnit == '立方' && row.netWeight) {
  929. total = Number(row.packingQuantity) * row.netWeight;
  930. } else {
  931. for (; 0 < endIndex; endIndex--) {
  932. total = row.packingSpecificationOption[endIndex].packageCell * total;
  933. }
  934. }
  935. this.$set(this.productList[index], 'measureQuantity', this.changeCount(total));
  936. let packingBoolen = !!this.getDict('不拆物料层规格', row.packingUnit)?.dictValue;
  937. let measureBoolen = !!this.getDict('不拆物料层规格', row.measureUnit)?.dictValue;
  938. if (packingBoolen && measureBoolen && row.packingUnit != 'L') {
  939. this.$set(this.productList[index], 'weight', total);
  940. }
  941. let weight = 0;
  942. if (row.measureUnit == row.weightUnit) {
  943. weight = row.measureQuantity;
  944. if (row.weightUnit == row.packageUnit) {
  945. this.$set(this.productList[index], 'singleWeight', 0);
  946. } else {
  947. this.$set(this.productList[index], 'singleWeight', Math.trunc((row.measureQuantity / row.packingQuantity) * 10000) / 10000);
  948. }
  949. } else if (row.singleWeight) {
  950. weight = row.measureQuantity * Number(row.singleWeight);
  951. }
  952. this.$set(this.productList[index], 'weight', weight);
  953. }
  954. },
  955. // 添加产品
  956. addProduct() {
  957. if (this.formData.extInfo.assetType.length <= 0) {
  958. return uni.showToast({ title: '请选择物品类型', icon: 'none' });
  959. }
  960. if (!this.formData.bizType) {
  961. return uni.showToast({ title: '请选择入库类型', icon: 'none' });
  962. }
  963. this.visibleDialog = true;
  964. uni.navigateTo({
  965. url: '/pages/warehouse/enterHouse/selectEnterType?assetType=' + this.formData.extInfo.assetType
  966. })
  967. },
  968. // 批量保存
  969. async batchSave() {
  970. try {
  971. for (let i = 0; i < this.productList.length; i++) {
  972. const row = this.productList[i];
  973. if (!row.isSave) {
  974. await this.listSave(row, i);
  975. }
  976. }
  977. } catch (error) {
  978. console.log('保存失败', error);
  979. }
  980. },
  981. // 单行校验
  982. validateSingleRow(row, rowNum) {
  983. if (!row.batchNo) {
  984. uni.showToast({ title: rowNum !== undefined ? `第${rowNum}行:请填写批次号` : '请填写批次号', icon: 'none' });
  985. return false;
  986. }
  987. if (!row.packingQuantity && row.packingQuantity !== 0) {
  988. uni.showToast({ title: rowNum !== undefined ? `第${rowNum}行:请填写数量` : '请填写数量', icon: 'none' });
  989. return false;
  990. }
  991. if (!row.packingUnit) {
  992. uni.showToast({ title: rowNum !== undefined ? `第${rowNum}行:请选择单位` : '请选择单位', icon: 'none' });
  993. return false;
  994. }
  995. if (!row.warehouseId) {
  996. uni.showToast({ title: rowNum !== undefined ? `第${rowNum}行:请选择仓库` : '请选择仓库', icon: 'none' });
  997. return false;
  998. }
  999. return true;
  1000. },
  1001. // 计算包装参数(提取重复的 packingBoolen/measureBoolen/num 逻辑)
  1002. computePackagingParams(row) {
  1003. const packingBoolen = !!this.getDict('不拆物料层规格', row.packingUnit)?.dictValue;
  1004. const measureBoolen = !!this.getDict('不拆物料层规格', row.measureUnit)?.dictValue;
  1005. let num = row.packingQuantity;
  1006. // 处理单位为KG类的情况
  1007. if (packingBoolen) {
  1008. const filterArr = row.packingSpecificationOption?.filter((item) => {
  1009. return item.packageUnit == row.packingUnit && item.packageUnit != item.conversionUnit;
  1010. });
  1011. if (filterArr?.length) {
  1012. num = Math.ceil(row.packingQuantity / filterArr[0].packageCell);
  1013. }
  1014. } else if (measureBoolen) {
  1015. // 处理单位不为KG类,计量单位为KG类的情况
  1016. let splitIndex = row.packingSpecificationOption?.findIndex((item) =>
  1017. item.conversionUnit == row.packingUnit && item.packageUnit != item.conversionUnit
  1018. );
  1019. for (; splitIndex > 1; splitIndex--) {
  1020. num = num * row.packingSpecificationOption[splitIndex].packageCell;
  1021. }
  1022. }
  1023. return { packingBoolen, measureBoolen, num };
  1024. },
  1025. // 物品批量保存前校验
  1026. validateForm() {
  1027. return new Promise((resolve, reject) => {
  1028. for (let i = 0; i < this.productList.length; i++) {
  1029. const row = this.productList[i];
  1030. if (row.isSave) continue;
  1031. if (!this.validateSingleRow(row, i + 1)) {
  1032. reject(new Error('校验不通过'));
  1033. return;
  1034. }
  1035. }
  1036. resolve();
  1037. });
  1038. },
  1039. listSave(row, index) {
  1040. // 必填项校验
  1041. if (!this.validateSingleRow(row)) {
  1042. return;
  1043. }
  1044. // 判断单位和计量单位是否为不拆物料层规格
  1045. let packingBoolen = !!this.getDict('不拆物料层规格', row.packingUnit)?.dictValue;
  1046. let measureBoolen = !!this.getDict('不拆物料层规格', row.measureUnit)?.dictValue;
  1047. let packingNum = 0;
  1048. if (packingBoolen) {
  1049. if (!row.isUnpack && row.packingUnit == '立方') {
  1050. packingNum = 1;
  1051. } else {
  1052. let filterArr = row.packingSpecificationOption.filter((item) => {
  1053. return item.packageUnit == row.packingUnit && item.packageUnit != item.conversionUnit;
  1054. });
  1055. if (filterArr?.length) {
  1056. packingNum = Math.ceil(row.packingQuantity / filterArr[0].packageCell);
  1057. }
  1058. }
  1059. }
  1060. let measureNum = row.packingQuantity;
  1061. let num = 0;
  1062. if (measureBoolen) {
  1063. let splitIndex = row.packingSpecificationOption.findIndex((item) =>
  1064. item.conversionUnit == row.packingUnit && item.packageUnit != item.conversionUnit
  1065. );
  1066. for (; splitIndex > 1; splitIndex--) {
  1067. measureNum = measureNum * row.packingSpecificationOption[splitIndex].packageCell;
  1068. }
  1069. } else {
  1070. if (row.packingSpecificationOption[1]?.packageCell) {
  1071. num = Math.ceil(row.measureQuantity / row.packingSpecificationOption[1]?.packageCell);
  1072. } else {
  1073. num = row.packingQuantity;
  1074. }
  1075. }
  1076. if (row.packingSpecificationLabel?.length < 1) {
  1077. uni.showToast({ title: '请到主数据维护包装组信息!', icon: 'none' });
  1078. return;
  1079. }
  1080. // 不拆包
  1081. if (!row.isUnpack) {
  1082. if (row.packingUnit != row.measureUnit) {
  1083. getAssetNum([{ assetCode: row.categoryCode + row.index, batchNum: row.batchNo, num: row.packingQuantity }]).then(() => {});
  1084. } else {
  1085. getAssetNum([{ assetCode: row.categoryCode + row.index, batchNum: row.batchNo, num: 0 }]).then(() => {});
  1086. }
  1087. } else {
  1088. if (!packingNum) {
  1089. if (row.packingUnitId) {
  1090. let splitIndex = row.packingSpecificationOption.findIndex((item) => item.id == row.packingUnitId);
  1091. if (splitIndex == 0) {
  1092. packingNum = Math.ceil(row.measureQuantity / row.packingSpecificationOption[1]?.packageCell);
  1093. }
  1094. if (splitIndex == 1) {
  1095. packingNum = row.packingQuantity;
  1096. }
  1097. for (; splitIndex > 1; splitIndex--) {
  1098. packingNum = Math.ceil(row.packingQuantity * row.packingSpecificationOption[splitIndex].packageCell);
  1099. }
  1100. } else {
  1101. packingNum = Math.ceil(row.measureQuantity / row.packingSpecificationOption[1]?.packageCell);
  1102. }
  1103. }
  1104. getAssetNum([{ assetCode: row.categoryCode + row.index, batchNum: row.batchNo, num: packingNum }]).then((res) => {
  1105. this.generateWrappers(row, index, res.data || []);
  1106. });
  1107. }
  1108. this.$set(this.productList[index], 'isSave', true);
  1109. this.$set(this.productList[index], 'warehouseId', row.warehouseId);
  1110. this.$set(this.productList[index], 'warehouseName', row.warehouseName);
  1111. this.$set(this.productList[index], 'warehouseIds', row.warehouseId);
  1112. this.$set(this.productList[index], 'warehouseNames', row.warehouseName);
  1113. },
  1114. editProductList(row, index) {
  1115. this.$set(this.productList[index], 'isSave', false);
  1116. },
  1117. deleteProductList(row, index) {
  1118. uni.showModal({
  1119. title: '提示',
  1120. content: '确定删除该产品吗?',
  1121. success: (res) => {
  1122. if (res.confirm) {
  1123. this.productList.splice(index, 1);
  1124. }
  1125. }
  1126. });
  1127. },
  1128. saveProductList(row, index) {
  1129. this.listSave(row, index);
  1130. },
  1131. addStock() {
  1132. this.addProduct();
  1133. },
  1134. // 入库
  1135. async getReturnStorage() {
  1136. if (this.productList.length <= 0) {
  1137. uni.showToast({ title: '请先添加产品信息', icon: 'none' });
  1138. return;
  1139. }
  1140. let boolen = this.productList.every((item) => item.isSave);
  1141. if (!boolen) {
  1142. uni.showToast({ title: '请先保存所有产品信息', icon: 'none' });
  1143. return;
  1144. }
  1145. if (this.isShowPackage) {
  1146. const userNameLength = this.productList.filter(
  1147. (item) => !item.unpackUserName
  1148. ).length;
  1149. const packgeLength = this.productList.filter(
  1150. (item) => !item.ifPackageOk
  1151. ).length;
  1152. if (userNameLength || packgeLength) {
  1153. uni.showToast({ title: '请先填写拆包装责任人和包装完好与否', icon: 'none' });
  1154. return;
  1155. }
  1156. }
  1157. // 处理包装数据
  1158. let _packingList = [];
  1159. _packingList = this.packingList.map((packingItem) => {
  1160. let _taskId = null;
  1161. let _workOrderId = null;
  1162. // if ([1].includes(this.formData.bizType)) {
  1163. // _workOrderId = this.detailList[0]?.workOrderId;
  1164. // _taskId = this.detailList[0]?.taskId;
  1165. // } else {
  1166. _workOrderId = this.form.productList[0]?.workOrderId;
  1167. _taskId = this.form.productList[0]?.taskId;
  1168. // }
  1169. // if (packingItem.modelKey) {
  1170. // packingItem.modelKey = packingItem.modelKey.toString();
  1171. // }
  1172. // if (packingItem.colorKey) {
  1173. // packingItem.colorKey = packingItem.colorKey.toString();
  1174. // }
  1175. return {
  1176. ...packingItem,
  1177. workOrderId: _workOrderId,
  1178. taskId: _taskId,
  1179. outsourceBatchNo: this.form.productList[0]?.batchNo,
  1180. outsourceCode: this.form.productList[0]?.sourceCode,
  1181. // materialDetailList: this.materialList.filter(
  1182. // (item) => item.parentIndex === packingItem.index
  1183. // )
  1184. };
  1185. });
  1186. // 处理产品数据
  1187. this.productList = this.productList.map((productItem) => {
  1188. // if (productItem.modelKey) {
  1189. // productItem.modelKey = productItem.modelKey.toString();
  1190. // }
  1191. // if (productItem.colorKey) {
  1192. // productItem.colorKey = productItem.colorKey.toString();
  1193. // }
  1194. return {
  1195. ...productItem,
  1196. outInDetailRecordRequestList: _packingList.filter(
  1197. (item) => item.parentIndex === productItem.index
  1198. )
  1199. };
  1200. });
  1201. this.formData.outInDetailList = this.productList;
  1202. let obj = uni.$u.deepClone(this.formData);
  1203. // 处理物品类型assetType
  1204. obj.extInfo.assetType = obj.extInfo.assetType.join(',');
  1205. obj.extInfo.documentSource = this.formData.sourceBizNo;
  1206. obj.extInfo.deptName = this.formData.extInfo.deptName;
  1207. obj.extInfo.supplierName = this.form.supplierName;
  1208. obj.extInfo.deliveryPhone = this.formData.extInfo.deliveryPhone;
  1209. // 处理仓库id
  1210. let warehouseId = [];
  1211. let warehouseName = [];
  1212. let warehouseIds = this.productList.map((item) => item.warehouseIds).flat();
  1213. let warehouseNames = this.productList.map((item) => item.warehouseNames).flat();
  1214. warehouseIds.forEach((item, index) => {
  1215. if (!warehouseId.includes(item)) {
  1216. warehouseId.push(item);
  1217. warehouseName.push(warehouseNames[index]);
  1218. }
  1219. });
  1220. obj.warehouseIds = warehouseId;
  1221. obj.warehouseNames = warehouseName;
  1222. obj._packingList = _packingList;
  1223. const isVerifyData = await isVerifyRepeatIsStock({
  1224. categoryCodes: this.productList.map((item) => item.categoryCode),
  1225. batchNos: this.productList.map((item) => item.batchNo)
  1226. });
  1227. return new Promise((resolve, reject) => {
  1228. if (isVerifyData?.length) {
  1229. uni.showModal({
  1230. title: '提示',
  1231. content: `当前批次:${isVerifyData[0].batchNo},物品${isVerifyData
  1232. .map((item) => item.categoryName)
  1233. .join(',')}已有入库记录,是否继续入库!`,
  1234. confirmText: '是',
  1235. cancelText: '否',
  1236. success: (res) => {
  1237. if (res.confirm) {
  1238. resolve(obj);
  1239. } else {
  1240. resolve(false);
  1241. }
  1242. }
  1243. });
  1244. } else {
  1245. resolve(obj);
  1246. }
  1247. });
  1248. },
  1249. // 获取表数据
  1250. getTableValue() {
  1251. return new Promise(async (resolve, reject) => {
  1252. try {
  1253. const returnStorageData = await this.getReturnStorage();
  1254. resolve({
  1255. form: this.form,
  1256. returnStorageData,
  1257. });
  1258. } catch(e) {
  1259. reject(e);
  1260. }
  1261. });
  1262. },
  1263. // 单位选择变化
  1264. onPackingUnitChange(e, row, index) {
  1265. const val = Number(e.detail.value);
  1266. const item = row.packingSpecificationOption[val];
  1267. if (item) {
  1268. this.$set(this.productList[index], 'packingUnitId', item.id);
  1269. this.$set(this.productList[index], 'packingUnit', item.conversionUnit);
  1270. this.$set(this.productList[index], 'packingUnitIndex', val);
  1271. this.computeNum(row, index);
  1272. }
  1273. },
  1274. // 包装完好选择变化
  1275. onPackageOkChange(e, index) {
  1276. const val = Number(e.detail.value);
  1277. const item = this.packageOkOptions[val];
  1278. if (item) {
  1279. this.$set(this.productList[index], 'ifPackageOkIndex', val);
  1280. this.$set(this.productList[index], 'ifPackageOk', item.value);
  1281. this.$set(this.productList[index], 'ifPackageOkLabel', item.label);
  1282. }
  1283. },
  1284. // 仓库选择变化
  1285. onWarehouseChange(e, index) {
  1286. const val = Number(e.detail.value);
  1287. const item = this.warehouseListOption[val];
  1288. if (item) {
  1289. this.$set(this.productList[index], 'warehouseId', item.id);
  1290. this.$set(this.productList[index], 'warehouseName', item.name);
  1291. this.$set(this.productList[index], 'warehouseIndex', val);
  1292. this.$set(this.productList[index], 'warehouseIds', [item.id]);
  1293. this.$set(this.productList[index], 'warehouseNames', [item.name]);
  1294. }
  1295. },
  1296. // 供应商选择变化
  1297. onSupplierChange(e, index) {
  1298. const val = Number(e.detail.value);
  1299. const item = this.productList[index].supplierListOptions[val];
  1300. if (item) {
  1301. this.$set(this.productList[index], 'supplierId', item.id);
  1302. this.$set(this.productList[index], 'supplierName', item.name);
  1303. this.$set(this.productList[index], 'supplierCode', item.serialNo);
  1304. this.$set(this.productList[index], 'supplierIndex', val);
  1305. }
  1306. },
  1307. // 颜色选择变化
  1308. onColorChange(e, index) {
  1309. const val = Number(e.detail.value);
  1310. const item = this.colorOptions[val];
  1311. if (item) {
  1312. this.$set(this.productList[index], 'colorKey', item.dictCode);
  1313. this.$set(this.productList[index], 'colorKeyName', item.dictValue);
  1314. this.$set(this.productList[index], 'colorIndex', val);
  1315. }
  1316. },
  1317. // 机型选择变化
  1318. onModelChange(e, index) {
  1319. const val = Number(e.detail.value);
  1320. const item = this.modelOptions[val];
  1321. if (item) {
  1322. this.$set(this.productList[index], 'modelKey', item.dictCode);
  1323. this.$set(this.productList[index], 'modelKeyName', item.dictValue);
  1324. this.$set(this.productList[index], 'modelIndex', val);
  1325. }
  1326. },
  1327. // 包装明细-颜色选择变化
  1328. onPackingColorChange(e, packingItem) {
  1329. const val = Number(e.detail.value);
  1330. const item = this.colorOptions[val];
  1331. if (item) {
  1332. this.$set(packingItem, 'colorKey', item.dictCode);
  1333. this.$set(packingItem, 'colorKeyName', item.dictValue);
  1334. this.$set(packingItem, 'colorIndex', val);
  1335. }
  1336. },
  1337. // 包装明细-机型选择变化
  1338. onPackingModelChange(e, packingItem) {
  1339. const val = Number(e.detail.value);
  1340. const item = this.modelOptions[val];
  1341. if (item) {
  1342. this.$set(packingItem, 'modelKey', item.dictCode);
  1343. this.$set(packingItem, 'modelKeyName', item.dictValue);
  1344. this.$set(packingItem, 'modelIndex', val);
  1345. }
  1346. },
  1347. // 包装明细-质检结果选择变化
  1348. onPackingResultChange(e, packingItem) {
  1349. const val = Number(e.detail.value);
  1350. const item = this.qualityResultsOptions[val];
  1351. if (item) {
  1352. this.$set(packingItem, 'result', item.value);
  1353. }
  1354. },
  1355. // 获取质检结果的 picker index
  1356. getResultIndex(result) {
  1357. return this.qualityResultsOptions.findIndex(o => o.value === result);
  1358. },
  1359. // 日期选择变化
  1360. onDateChange(e, row, field) {
  1361. row[field] = e.detail.value;
  1362. },
  1363. //入库明细删除
  1364. listDel(row, index) {
  1365. this.productList.splice(index, 1);
  1366. this.deletePackingAndMaterial(row);
  1367. },
  1368. // 根据产品信息删除包装和物料
  1369. deletePackingAndMaterial(row) {
  1370. // 删除包装(去掉不相同的包装)
  1371. this.packingList = this.packingList.filter(
  1372. (item) => item.parentIndex !== row.index
  1373. );
  1374. this.showPackingList = this.showPackingList.filter(
  1375. (item) => item.parentIndex !== row.index
  1376. );
  1377. this.pickingPageNum = Math.ceil(
  1378. this.showPackingList.length / this.pageSize
  1379. );
  1380. // 删除物料(获取相同物料)
  1381. // let packingIndexs = this.packingList.map((item) => item.index);
  1382. // this.materialList = this.materialList.filter((item) =>
  1383. // packingIndexs.includes(item.parentIndex)
  1384. // // );
  1385. // this.showMaterialList = this.showMaterialList.filter((item) =>
  1386. // packingIndexs.includes(item.parentIndex)
  1387. // );
  1388. // this.materielPageNum = Math.ceil(
  1389. // this.showMaterialList.length / this.pageSize
  1390. // );
  1391. },
  1392. // 产品批量保存
  1393. async listSaveArrs() {
  1394. this.validateForm()
  1395. .then(async () => {
  1396. // 批量获取包装编码并处理
  1397. let packingCodePrams = this.productList.map((row) => {
  1398. if (row.isSave) return {};
  1399. const { packingBoolen, measureBoolen, num: baseNum } = this.computePackagingParams(row);
  1400. let num = baseNum;
  1401. // 处理单位为KG类的情况
  1402. if (packingBoolen) {
  1403. return {
  1404. assetCode: row.categoryCode + row.index,
  1405. batchNum: row.batchNo,
  1406. num
  1407. };
  1408. } else {
  1409. if (row.isUnpack == 1) {
  1410. if (measureBoolen) {
  1411. // 处理单位不为KG类,计量单位为KG类的情况
  1412. return {
  1413. assetCode: row.categoryCode + row.index,
  1414. batchNum: row.batchNo,
  1415. num: baseNum
  1416. };
  1417. } else {
  1418. // 处理拆包到最小包装单元数量的情况
  1419. return {
  1420. assetCode: row.categoryCode + row.index,
  1421. batchNum: row.batchNo,
  1422. num: row.measureQuantity
  1423. };
  1424. }
  1425. } else {
  1426. return {
  1427. assetCode: row.categoryCode + row.index,
  1428. batchNum: row.batchNo,
  1429. num
  1430. };
  1431. }
  1432. }
  1433. });
  1434. console.log('packingCodePrams', packingCodePrams);
  1435. let filterPackingCodePrams = packingCodePrams.filter(
  1436. (item) => item.assetCode
  1437. );
  1438. console.log('filterPackingCodePrams', filterPackingCodePrams);
  1439. let { data } = await getAssetNum(filterPackingCodePrams);
  1440. let packingCodeList = [];
  1441. packingCodePrams.forEach((item, index) => {
  1442. packingCodeList[index] = data.filter(
  1443. (ite) => ite.assetCode == item.assetCode
  1444. );
  1445. });
  1446. // 批量生成包装
  1447. this.productList.map((row, index) => {
  1448. if (!row.isSave) {
  1449. this.generateWrappers(row, index, packingCodeList[index]);
  1450. this.$set(this.productList[index], 'isSave', true);
  1451. }
  1452. });
  1453. // 加载虚拟列表数据(分页)
  1454. // this.pickingFetchData();
  1455. // this.materielFetchData();
  1456. })
  1457. .catch((err) => {
  1458. console.log(err);
  1459. });
  1460. },
  1461. // 生成包装
  1462. generateWrappers(row, productIndex, packingCodeList) {
  1463. console.log(packingCodeList, 'packingCodeList', row.measureType);
  1464. if (!row.measureType)
  1465. return uni.showToast({
  1466. title: '请到主数据维计量类型!',
  1467. icon: 'none'
  1468. });
  1469. if (!packingCodeList?.length) return;
  1470. console.log('包装数据--------', row);
  1471. // console.log('包装规格----', row.packingSpecificationOption);
  1472. console.log('计量单位----', row.measureUnit);
  1473. let packingList = [];
  1474. // let obj = this.getNowDate();
  1475. let productionDate = row.detailProductionDate || '';
  1476. let purchaseDate = row.detailPurchaseDate || '';
  1477. let expireDate = row.detailExpireDate || '';
  1478. console.log(expireDate, 'expireDate');
  1479. console.log(
  1480. this.formData.bizType,
  1481. 'bizTypebizTypebizTypebizTypebizTypebizTypebizTypebizTypebizTypebizTypebizType'
  1482. );
  1483. if (this.formData.bizType == '1') {
  1484. // 生产入库
  1485. productionDate = this.getNowDate();
  1486. // this.curDateType = 'productionDate';
  1487. }
  1488. // 判断单位和计量单位是否为不拆物料层规格
  1489. let packingBoolen = !!this.getDict('不拆物料层规格', row.packingUnit).dictValue;
  1490. let measureBoolen = !!this.getDict('不拆物料层规格', row.measureUnit).dictValue;
  1491. console.log('packingBoolen', packingBoolen, measureBoolen);
  1492. let num = row.packingQuantity;
  1493. let filterArr = [];
  1494. // 处理单位为KG类的情况
  1495. if (packingBoolen) {
  1496. console.log(
  1497. packingBoolen,
  1498. 'packingBoolenpackingBoolenpackingBoolenpackingBoolenpackingBoolenpackingBoolen'
  1499. );
  1500. if (!row.isUnpack && row.packingUnit == '立方') {
  1501. num = 1;
  1502. } else {
  1503. filterArr = row.packingSpecificationOption.filter((item) => {
  1504. return (
  1505. item.packageUnit == row.packingUnit &&
  1506. item.packageUnit != item.conversionUnit
  1507. );
  1508. });
  1509. num = Math.ceil(row.packingQuantity / filterArr[0]?.packageCell);
  1510. }
  1511. } else {
  1512. // if (row.isUnpack == 1) {
  1513. if (measureBoolen) {
  1514. // 处理单位不为KG类,计量单位为KG类的情况
  1515. let splitIndex = row.packingSpecificationOption.findIndex(
  1516. (item) =>
  1517. item.conversionUnit == row.packingUnit &&
  1518. item.packageUnit != item.conversionUnit
  1519. );
  1520. for (; splitIndex > 1; splitIndex--) {
  1521. num = num * row.packingSpecificationOption[splitIndex].packageCell;
  1522. }
  1523. } else {
  1524. if (row.packingSpecificationOption[1]?.packageCell) {
  1525. num = Math.ceil(
  1526. row.measureQuantity /
  1527. row.packingSpecificationOption[1]?.packageCell
  1528. );
  1529. filterArr = row.packingSpecificationOption.filter((item) => {
  1530. return (
  1531. item.packageUnit == row.packingUnit &&
  1532. item.packageUnit != item.conversionUnit
  1533. );
  1534. });
  1535. }
  1536. }
  1537. }
  1538. console.log('num-----------', num);
  1539. for (let index = 0; index < packingCodeList.length; index++) {
  1540. let measureQuantity = 1;
  1541. let packingQuantity = 1;
  1542. let packingUnit = row.packingUnit;
  1543. // 处理单位为KG类,计算每桶KG值
  1544. if (packingBoolen) {
  1545. measureQuantity = Number(row.packingQuantity) > filterArr[0].packageCell * (index + 1) ? filterArr[0].packageCell : Number(row.packingQuantity) - filterArr[0].packageCell * index;
  1546. console.log(measureQuantity, 'measureQuantit1111y');
  1547. } else {
  1548. console.log('1 拆--------', measureBoolen);
  1549. //计量单位等于重量单位并且有总重 计量数量=总重/包装数
  1550. if (row.weightUnit == row.measureUnit && row.weight) {
  1551. measureQuantity = Math.trunc((row.weight / packingCodeList.length) * 10000) / 10000;
  1552. } else if (measureBoolen) {
  1553. let splitIndex = row.packingSpecificationOption.findIndex((item) =>
  1554. item.conversionUnit == row.packingUnit &&
  1555. item.packageUnit != item.conversionUnit
  1556. );
  1557. for (; splitIndex > 0; splitIndex--) {
  1558. measureQuantity = measureQuantity *
  1559. row.packingSpecificationOption[splitIndex].packageCell;
  1560. }
  1561. } else {
  1562. measureQuantity = row.packingSpecificationOption[1].packageCell;
  1563. }
  1564. console.log(measureQuantity, 'measureQuantity');
  1565. }
  1566. let clientCode = '';
  1567. if (this.bizType == 2) {
  1568. clientCode = row?.customerMark;
  1569. } else if (this.bizType != 2) {
  1570. clientCode = row.extInfo?.clientCode;
  1571. }
  1572. console.log(filterArr[0], 'filterArr[0]');
  1573. let status = null;
  1574. if (row.qualityControl == 1) {
  1575. status = 0;
  1576. } else {
  1577. status = 2;
  1578. }
  1579. let item = {
  1580. index: row.index + '-' + index, // 包装索引
  1581. warehouseId: row.warehouseId, // 仓库id
  1582. warehouseName: row.warehouseName, // 仓库名称
  1583. categoryName: row.categoryName, // 产品名称
  1584. categoryCode: row.categoryCode, // 产品编码
  1585. categoryModel: row.categoryModel, // 物品型号
  1586. specification: row.specification, // 规格
  1587. supplierCode: row.supplierCode, // 供应商编码
  1588. supplierName: row.supplierName, // 供应商名称
  1589. brandNum: row.brandNum, // 牌号
  1590. parentIndex: row.index, // 产品索引
  1591. batchNo: row.batchNo, // 批次号
  1592. packageNo: packingCodeList[index]?.onlyCode, // 包装编码
  1593. packingQuantity: packingQuantity, // 包装数量
  1594. packingUnit: row.packingUnit, // 包装单位(默认)
  1595. modelKey: row.modelKey, // 机型
  1596. modelKeyName: row.modelKey ? (this.modelOptions.find(o => o.dictCode === row.modelKey)?.dictValue || '') : '',
  1597. modelIndex: row.modelKey ? this.modelOptions.findIndex(o => o.dictCode === row.modelKey) : -1,
  1598. colorKey: row.colorKey, //颜色
  1599. colorKeyName: row.colorKey ? (this.colorOptions.find(o => o.dictCode === row.colorKey)?.dictValue || '') : '',
  1600. colorIndex: row.colorKey ? this.colorOptions.findIndex(o => o.dictCode === row.colorKey) : -1,
  1601. measureQuantity: measureQuantity, // 计量数量
  1602. measureUnit: row.isUnpack
  1603. ? measureBoolen
  1604. ? row.packingSpecificationOption[1]
  1605. ? row.packingSpecificationOption[1].packageUnit
  1606. : row.packingSpecificationOption[0].packageUnit
  1607. : row.measureUnit
  1608. : row.measureUnit, // 计量单位
  1609. weight: 0, // 重量
  1610. packingSpecificationOption: row.packingSpecificationOption, // 包装规格
  1611. weightUnit: row.weightUnit, // 重量单位
  1612. netWeight: row.netWeight, // 净重
  1613. barcodes: '', // 发货条码
  1614. clientCode: clientCode, // 客户代号
  1615. materielDesignation: row.extInfo ? row.extInfo.materielCode : '', // 物料代号
  1616. engrave: '', // 刻码
  1617. isUnpack: row.isUnpack, // 是否允许拆包
  1618. productionDate: productionDate, // 生产日期
  1619. purchaseDate: purchaseDate, // 采购时间
  1620. expireDate: expireDate, //失效日期
  1621. serialNo: '', // 序列号
  1622. result: 1, // 结果(1合格 2不合格)
  1623. qualityControl: row.qualityControl,
  1624. status: status // 状态(0=未质检 1待检 2已检)
  1625. };
  1626. if (row.isUnpack) {
  1627. // 第二层条件: packingBoolen
  1628. if (packingBoolen) {
  1629. // 空值保护: 确保 filterArr[0] 存在
  1630. item.packingUnit = row.packingSpecificationOption[1].conversionUnit;
  1631. } else {
  1632. // 第三层条件: measureBoolen
  1633. if (measureBoolen) {
  1634. // 处理 packingSpecificationOption 的索引
  1635. const option =
  1636. row.packingSpecificationOption?.[1] ||
  1637. row.packingSpecificationOption?.[0];
  1638. item.packingUnit = option?.conversionUnit;
  1639. } else {
  1640. item.packingUnit =
  1641. row.packingSpecificationOption[1].conversionUnit;
  1642. }
  1643. }
  1644. }
  1645. let outBoolen = !!this.getDict('不拆物料层规格', item.measureUnit).dictValue;
  1646. //计量单位等于重量单位
  1647. if (row.weightUnit == row.measureUnit) {
  1648. item.weight = item.measureQuantity
  1649. ? Number(item.measureQuantity)
  1650. : 0;
  1651. } else if (outBoolen) {
  1652. // 计量单位为KG类,直接替换
  1653. item.weight = item.measureQuantity
  1654. ? Number(item.measureQuantity)
  1655. : 0;
  1656. } else {
  1657. console.log('计量单位为不为KG类======================');
  1658. // 计量单位为不为KG类,重新统计计算
  1659. let inBoolen = !!this.getDict('不拆物料层规格', item.packingSpecificationOption[0].packageUnit).dictValue;
  1660. let startIndex = item.packingSpecificationOption.findIndex(
  1661. (ite) => {
  1662. return (
  1663. item.measureUnit == ite.packingUnit &&
  1664. ite.packingUnit != ite.conversionUnit
  1665. );
  1666. }
  1667. );
  1668. let endIndex = item.packingSpecificationOption.findIndex(
  1669. (ite) => item.packingUnit == ite.conversionUnit
  1670. );
  1671. if (measureBoolen) {
  1672. let total = item.packingQuantity ? Number(item.packingQuantity) : 0;
  1673. for (; startIndex < endIndex; endIndex--) {
  1674. total = item.packingSpecificationOption[endIndex].packageCell * total;
  1675. }
  1676. if (inBoolen) {
  1677. // 第二层为KG类
  1678. item.weight = total ? Number(total) : 0;
  1679. } else {
  1680. // 第二层不为KG类
  1681. item.weight = total * item.netWeight;
  1682. }
  1683. } else if (!measureBoolen) {
  1684. if (inBoolen) {
  1685. // 第二层为KG类
  1686. item.weight = item.measureQuantity ? Number(item.measureQuantity) : 0;
  1687. } else {
  1688. // 第二层不为KG类
  1689. if (row.singleWeight && item.measureQuantity) {
  1690. item.weight = Number(item.measureQuantity) * Number(row.singleWeight);
  1691. } else {
  1692. item.weight = 0;
  1693. }
  1694. }
  1695. }
  1696. }
  1697. packingList.push(item);
  1698. console.log(
  1699. packingList,
  1700. 'packingList!!!!!!!!!!!!!!!!!!拆'
  1701. );
  1702. }
  1703. // 单独点击保存并插入对应位置(包装)
  1704. if (productIndex == 0) {
  1705. this.packingList.splice(productIndex, 0, ...packingList);
  1706. } else {
  1707. let packingIndex = this.packingList.findLastIndex(
  1708. (item) =>
  1709. item.parentIndex == this.productList[productIndex - 1].index
  1710. );
  1711. this.packingList.splice(packingIndex + 1, 0, ...packingList);
  1712. }
  1713. let remainder = 0;
  1714. if (row.weightUnit != row.measureUnit) {
  1715. remainder =
  1716. row.measureQuantity %
  1717. row.packingSpecificationOption[1]?.packageCell;
  1718. }
  1719. if (remainder > 0 && packingCodeList?.length) {
  1720. let onlyCode = packingCodeList[packingCodeList.length - 1]?.onlyCode;
  1721. let idx = this.packingList.findIndex(
  1722. (packingItem) => packingItem.packageNo == onlyCode
  1723. );
  1724. if (idx !== -1) {
  1725. this.$set(this.packingList[idx], 'measureQuantity', remainder);
  1726. if (row.singleWeight) {
  1727. this.$set(
  1728. this.packingList[idx],
  1729. 'weight',
  1730. row.singleWeight * remainder
  1731. );
  1732. }
  1733. }
  1734. }
  1735. },
  1736. }
  1737. }
  1738. </script>
  1739. <style scoped>
  1740. .add {
  1741. width: 96rpx;
  1742. height: 96rpx;
  1743. border-radius: 48rpx;
  1744. background: #3c9cff;
  1745. position: fixed;
  1746. bottom: 100rpx;
  1747. right: 24rpx;
  1748. display: flex;
  1749. align-items: center;
  1750. justify-content: center;
  1751. z-index: 99;
  1752. }
  1753. /* 产品卡片样式 */
  1754. .product-card {
  1755. background: #fff;
  1756. margin: 20rpx;
  1757. border-radius: 12rpx;
  1758. padding: 24rpx;
  1759. box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
  1760. }
  1761. .card-header {
  1762. display: flex;
  1763. justify-content: space-between;
  1764. align-items: center;
  1765. padding-bottom: 20rpx;
  1766. border-bottom: 1rpx solid #eee;
  1767. margin-bottom: 20rpx;
  1768. }
  1769. .product-name {
  1770. font-size: 28rpx;
  1771. font-weight: bold;
  1772. color: #333;
  1773. }
  1774. .product-code {
  1775. font-size: 26rpx;
  1776. color: #333;
  1777. }
  1778. .card-body {
  1779. padding: 0;
  1780. }
  1781. .info-row {
  1782. display: flex;
  1783. justify-content: space-between;
  1784. align-items: center;
  1785. padding: 16rpx 0;
  1786. border-bottom: 1rpx solid #f5f5f5;
  1787. }
  1788. .info-row:last-child {
  1789. border-bottom: none;
  1790. }
  1791. .info-label {
  1792. font-size: 28rpx;
  1793. color: #666;
  1794. min-width: 160rpx;
  1795. }
  1796. .info-value {
  1797. font-size: 28rpx;
  1798. color: #333;
  1799. text-align: right;
  1800. flex: 1;
  1801. }
  1802. .red-text {
  1803. color: #ff0000 !important;
  1804. }
  1805. .card-footer {
  1806. margin-top: 20rpx;
  1807. padding-top: 20rpx;
  1808. border-top: 1rpx solid #eee;
  1809. }
  1810. .action-buttons {
  1811. display: flex;
  1812. gap: 20rpx;
  1813. }
  1814. /* 包装明细样式 */
  1815. .packing-section {
  1816. margin-top: 40rpx;
  1817. padding: 0 20rpx;
  1818. }
  1819. .section-title {
  1820. font-size: 32rpx;
  1821. font-weight: bold;
  1822. color: #333;
  1823. padding: 20rpx 0;
  1824. }
  1825. .packing-card {
  1826. background: #fff;
  1827. border-radius: 12rpx;
  1828. padding: 24rpx;
  1829. margin-bottom: 20rpx;
  1830. box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
  1831. }
  1832. /* 包装卡片标题 */
  1833. .card_title {
  1834. font-size: 30rpx;
  1835. font-weight: bold;
  1836. color: #1890FF;
  1837. padding-bottom: 16rpx;
  1838. border-bottom: 1rpx solid #eee;
  1839. margin-bottom: 16rpx;
  1840. }
  1841. /* 单位后缀 */
  1842. .info-unit {
  1843. font-size: 26rpx;
  1844. color: #999;
  1845. margin-left: 8rpx;
  1846. }
  1847. /* 批量操作按钮 */
  1848. .batch-actions {
  1849. display: flex;
  1850. gap: 20rpx;
  1851. padding: 20rpx;
  1852. background: #f8f8f8;
  1853. margin-bottom: 20rpx;
  1854. }
  1855. /* 卡片序号 */
  1856. .card-index {
  1857. font-size: 24rpx;
  1858. color: #999;
  1859. background: #f0f0f0;
  1860. padding: 4rpx 16rpx;
  1861. border-radius: 20rpx;
  1862. }
  1863. /* 编辑行样式 */
  1864. .edit-row {
  1865. background: #fafafa;
  1866. }
  1867. /* 必填标识 */
  1868. .required {
  1869. color: #ff0000;
  1870. }
  1871. /* 输入框样式 */
  1872. .info-input {
  1873. flex: 1;
  1874. text-align: right;
  1875. font-size: 28rpx;
  1876. color: #333;
  1877. padding: 8rpx 0;
  1878. }
  1879. /* picker选择器样式 */
  1880. .info-picker {
  1881. flex: 1;
  1882. /* text-align: right; */
  1883. }
  1884. .picker-value {
  1885. font-size: 28rpx;
  1886. color: #333;
  1887. padding: 16rpx 32rpx 16rpx 16rpx;
  1888. /* background: #f0f0f0; */
  1889. border-radius: 8rpx;
  1890. display: inline-block;
  1891. min-width: 160rpx;
  1892. /* text-align: center; */
  1893. position: relative;
  1894. width: 100%;
  1895. border: 1rpx solid #dadbde;
  1896. }
  1897. .picker-value::after {
  1898. content: '';
  1899. position: absolute;
  1900. right: 8rpx;
  1901. top: 50%;
  1902. transform: translateY(-50%);
  1903. border: 8rpx solid transparent;
  1904. border-top-color: #666;
  1905. }
  1906. .picker-value.placeholder {
  1907. color: #999;
  1908. /* background: #e8e8e8; */
  1909. }
  1910. /* 仓库选择样式 */
  1911. .warehouse-select {
  1912. flex: 1;
  1913. text-align: right;
  1914. padding: 8rpx 0;
  1915. }
  1916. /* 多选组件样式 */
  1917. .multi-select-container {
  1918. flex: 1;
  1919. display: flex;
  1920. flex-wrap: wrap;
  1921. gap: 16rpx;
  1922. padding: 8rpx 0;
  1923. }
  1924. .multi-select-item {
  1925. display: flex;
  1926. align-items: center;
  1927. gap: 8rpx;
  1928. background: #f0f0f0;
  1929. padding: 8rpx 16rpx;
  1930. border-radius: 8rpx;
  1931. font-size: 24rpx;
  1932. }
  1933. .multi-select-label {
  1934. color: #333;
  1935. }
  1936. /* 颜色选择器触发器样式 */
  1937. .color-picker-trigger {
  1938. flex: 1;
  1939. display: flex;
  1940. justify-content: flex-end;
  1941. }
  1942. </style>