add.vue 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523
  1. <template>
  2. <div>
  3. <el-card class="box-card">
  4. <div style="padding: 8px; text-align: center" v-if="formData.data.code || formData.data.wlnCode">
  5. <span style="font-size: 18px; font-weight: 700">{{ formData.data.code }} </span>
  6. <span style="font-size: 18px; font-weight: 700" v-if="formData.data.wlnCode"> ({{ formData.data.wlnCode }})</span>
  7. </div>
  8. <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="submit">
  9. <template #type>
  10. <div style="width: 100%">
  11. <el-radio-group v-model="formData.data.type">
  12. <el-radio v-for="(itemType, index) in typeList" :key="index" :label="itemType.dictKey">{{ itemType.dictValue }}</el-radio>
  13. </el-radio-group>
  14. </div>
  15. </template>
  16. <template #departmentId>
  17. <div style="width: 100%">
  18. <el-select v-model="formData.data.departmentId" placeholder="请选择事业部" clearable style="width: 100%">
  19. <el-option v-for="item in departmentList" :key="item.dictKey" :label="item.dictValue" :value="item.dictKey" />
  20. </el-select>
  21. </div>
  22. </template>
  23. <template #deliveryAddress>
  24. <div style="width: 100%">
  25. <el-row>
  26. <el-col :span="3">
  27. <el-form-item label-width="0" prop="province" style="width: 100%">
  28. <el-input v-model="formData.data.province" placeholder="请输入省" />
  29. </el-form-item>
  30. </el-col>
  31. <el-col :span="3">
  32. <el-form-item label-width="0" prop="city" style="width: 100%">
  33. <el-input v-model="formData.data.city" placeholder="请输入市" />
  34. </el-form-item>
  35. </el-col>
  36. <el-col :span="3">
  37. <el-form-item label-width="0" prop="county" style="width: 100%">
  38. <el-input v-model="formData.data.county" placeholder="请输入区/县" />
  39. </el-form-item>
  40. </el-col>
  41. <el-col :span="11">
  42. <el-form-item label-width="0" prop="detailedAddress" style="width: 100%">
  43. <el-input v-model="formData.data.detailedAddress" placeholder="请输入详细地址" />
  44. </el-form-item>
  45. </el-col>
  46. <el-col :span="4">
  47. <el-form-item label-width="0" prop="postcode" style="width: 100%">
  48. <el-input v-model="formData.data.postcode" placeholder="请输入邮编" />
  49. </el-form-item>
  50. </el-col>
  51. </el-row>
  52. </div>
  53. </template>
  54. <template #consignee>
  55. <div style="width: 100%">
  56. <el-row>
  57. <el-col :span="6">
  58. <el-form-item label-width="0" prop="consignee" style="width: 100%">
  59. <el-input v-model="formData.data.consignee" placeholder="请输入联系人" />
  60. </el-form-item>
  61. </el-col>
  62. <el-col :span="6">
  63. <el-form-item label-width="0" prop="consigneeNumber" style="width: 100%">
  64. <el-input v-model="formData.data.consigneeNumber" placeholder="请输入联系电话" />
  65. </el-form-item>
  66. </el-col>
  67. </el-row>
  68. </div>
  69. </template>
  70. <template #orderSkuList>
  71. <div style="width: 100%; padding: 0 20px">
  72. <div style="margin-bottom: 10px" v-if="!(route.query && route.query.detailId)">
  73. <el-button type="primary" size="small" @click="clickAddProduct()">选择产品</el-button>
  74. <el-button type="primary" size="small" @click="clickUploadProduct()">导入产品</el-button>
  75. </div>
  76. <el-collapse v-model="activeNames">
  77. <div v-for="(item, index) in formData.data.orderSkuList" :key="index" style="margin-bottom: 20px">
  78. <div style="border: 1px solid #edf0f5">
  79. <el-table :data="[item]" :row-style="{ height: '35px' }" header-row-class-name="tableHeader" :cell-class-name="cellStyleName">
  80. <el-table-column label="产品" width="300">
  81. <template #default="{ row }">
  82. <div style="width: 100%">
  83. <div style="line-height: 35px" v-if="!(route.query && route.query.detailId)">
  84. <span style="color: black; font-weight: 700">库存数量: </span>
  85. <span>{{ item.inventoryQuantity }}</span>
  86. </div>
  87. <div style="line-height: 35px">
  88. <span style="color: black; font-weight: 700">商品名称: </span>
  89. <span>{{ item.wlnSkuName }}</span>
  90. </div>
  91. <div style="line-height: 35px">
  92. <span style="color: black; font-weight: 700">品号: </span>
  93. <span>{{ item.code }}</span>
  94. </div>
  95. <div style="line-height: 35px; word-break: break-all">
  96. <span style="color: black; font-weight: 700">品名: </span>
  97. <span>{{ item.name }}</span>
  98. </div>
  99. <div style="line-height: 35px; display: flex">
  100. <span style="width: 90px; color: black; font-weight: 700">E10成品品号: </span>
  101. <el-form-item
  102. :prop="'orderSkuList.' + index + '.erpCode'"
  103. :rules="rules.erpCode"
  104. :inline-message="true"
  105. style="width: calc(100% - 90px)">
  106. <el-input v-model="row.erpCode" placeholder="请输入E10成品品号" style="width: 100%" />
  107. </el-form-item>
  108. </div>
  109. <div style="line-height: 35px; display: flex">
  110. <span style="width: 52px; color: black; font-weight: 700">特征码: </span>
  111. <el-form-item
  112. :prop="'orderSkuList.' + index + '.featureCode'"
  113. :rules="rules.featureCode"
  114. :inline-message="true"
  115. style="width: calc(100% - 52px)">
  116. <el-input v-model="row.featureCode" placeholder="请输入特征码" style="width: 100%" />
  117. </el-form-item>
  118. </div>
  119. <div style="line-height: 35px; display: flex">
  120. <span style="width: 37px; color: black; font-weight: 700">数量: </span>
  121. <el-form-item
  122. :prop="'orderSkuList.' + index + '.quantity'"
  123. :rules="rules.quantity"
  124. :inline-message="true"
  125. style="width: calc(100% - 37px)">
  126. <el-input-number
  127. onmousewheel="return false;"
  128. v-model="row.quantity"
  129. placeholder="数量"
  130. style="width: 100%"
  131. :controls="false"
  132. :min="0"
  133. :precision="0"
  134. @change="changeQuantity(index, true)" />
  135. </el-form-item>
  136. </div>
  137. <div style="line-height: 35px">
  138. <span style="color: black; font-weight: 700">加工费: </span>
  139. <span>{{ item.customProcessingFee }}</span>
  140. </div>
  141. <div style="line-height: 35px">
  142. <span style="color: black; font-weight: 700">代发费: </span>
  143. <span>{{ item.lssueFee }}</span>
  144. </div>
  145. <div style="line-height: 35px">
  146. <span style="color: black; font-weight: 700">快递包材费: </span>
  147. <span>{{ computeSingleDeliveryMaterialsFee(index) }}</span>
  148. </div>
  149. <div style="line-height: 35px">
  150. <span style="color: black; font-weight: 700">包装人工费: </span>
  151. <span>{{ item.packingLabor }}</span>
  152. </div>
  153. <div style="line-height: 35px">
  154. <span style="color: black; font-weight: 700">管理费: </span>
  155. <span>{{ item.managementFee }}</span>
  156. </div>
  157. <div style="line-height: 35px">
  158. <span style="color: black; font-weight: 700">单价: </span>
  159. <span>{{ item.unitPrice }}</span>
  160. </div>
  161. <div style="line-height: 35px">
  162. <span style="color: black; font-weight: 700">小计: </span>
  163. <span>{{ getSubtotal(item) }}</span>
  164. </div>
  165. <div style="line-height: 35px">
  166. <span style="width: 37px; color: black; font-weight: 700">打印: </span>
  167. <el-form-item
  168. :prop="'orderSkuList.' + index + '.printType'"
  169. :rules="rules.printType"
  170. :inline-message="true"
  171. style="width: calc(100% - 37px)">
  172. <el-radio-group v-model="item.printType" @change="changeQuantity(index)">
  173. <el-radio v-for="(itemType, index) in printType" :key="index" :label="itemType.dictKey">{{ itemType.dictValue }}</el-radio>
  174. </el-radio-group>
  175. </el-form-item>
  176. </div>
  177. </div>
  178. </template>
  179. </el-table-column>
  180. <el-table-column label="产品图稿" width="400">
  181. <template #default="{ row }">
  182. <div style="display: flex; width: 100%">
  183. <div style="width: 80px">设计图:</div>
  184. <div style="width: calc(100% - 80px)">
  185. <el-image
  186. fit="scale-down"
  187. style="width: 148px; height: 148px; margin-right: 10px; cursor: pointer"
  188. v-if="row.blueprint"
  189. :src="row.blueprint"
  190. @click="openFile(row.blueprint)" />
  191. <div style="display: flex" v-if="!(route.query && route.query.detailId)">
  192. <el-button type="primary" @click="clickDrawingFile(index)" text>选择图稿</el-button>
  193. <el-upload
  194. :show-file-list="false"
  195. action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
  196. :data="uploadImgData"
  197. :before-upload="uploadImgFile"
  198. :on-success="
  199. (response, uploadFile) => {
  200. return handleImgSuccess(uploadFile, index);
  201. }
  202. "
  203. style="width: 100%"
  204. accept=".jpg,.jpeg,.png,.GIF,.JPG,.PNG">
  205. <el-button type="primary" style="margin-left: 12px" text>上传图片</el-button>
  206. </el-upload>
  207. </div>
  208. </div>
  209. </div>
  210. <div style="display: flex; margin-top: 20px; width: 100%">
  211. <div style="width: 80px">图稿文件:</div>
  212. <div style="width: calc(100% - 80px)">
  213. <a
  214. style="color: #409eff; cursor: pointer; word-break: break-all; margin-right: 10px"
  215. @click="openFile(row.productionDocument)"
  216. v-if="row.productionDocument">
  217. {{ row.productionDocument }}
  218. </a>
  219. <div style="display: flex" v-if="!(route.query && route.query.detailId)">
  220. <el-button type="primary" @click="clickDrawingFile(index)" text>选择图稿</el-button>
  221. <el-upload
  222. :show-file-list="false"
  223. action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
  224. :data="uploadData"
  225. :before-upload="uploadFile"
  226. :on-success="
  227. (response, uploadFile) => {
  228. return handleSuccess(uploadFile, index);
  229. }
  230. "
  231. style="width: 100%">
  232. <el-button type="primary" style="margin-left: 12px" text>上传文件</el-button>
  233. </el-upload>
  234. </div>
  235. </div>
  236. </div>
  237. <div style="font-weight: 700; margin-top: 20px">产品不干胶图稿</div>
  238. <div style="display: flex; width: 100%">
  239. <div style="width: 80px">不干胶图片:</div>
  240. <div style="width: calc(100% - 80px)">
  241. <el-image
  242. fit="scale-down"
  243. style="width: 148px; height: 148px; margin-right: 10px; cursor: pointer"
  244. v-if="row.selfAdhesiveStickerFile && row.selfAdhesiveStickerFile.fileUrl"
  245. :src="row.selfAdhesiveStickerFile.fileUrl"
  246. @click="openFile(row.selfAdhesiveStickerFile.fileUrl)" />
  247. <div style="display: flex" v-if="!(route.query && route.query.detailId)">
  248. <el-upload
  249. :show-file-list="false"
  250. action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
  251. :data="uploadAdhesiveData"
  252. :before-upload="uploadAdhesiveFile"
  253. :on-success="
  254. (response, uploadFile) => {
  255. return handleAdhesiveSuccess(uploadFile, index);
  256. }
  257. "
  258. style="width: 100%"
  259. accept=".jpg,.jpeg,.png,.GIF,.JPG,.PNG">
  260. <el-button type="primary" text>上传文件</el-button>
  261. </el-upload>
  262. </div>
  263. </div>
  264. </div>
  265. </template>
  266. </el-table-column>
  267. <el-table-column label="包材配件/单品" min-width="400">
  268. <template #default="{ row }">
  269. <div style="width: 100%">
  270. <div style="margin-bottom: 10px" v-if="!(route.query && route.query.detailId)">
  271. <el-button type="primary" @click="clickPackingFittings(index)">选择包材配件</el-button>
  272. </div>
  273. <el-table :data="row.orderSkuBomList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
  274. <el-table-column label="单价¥" width="120">
  275. <template #default="props">
  276. <div>
  277. <span>{{ moneyFormat(props.row.unitPrice, 2) }}</span>
  278. </div>
  279. </template>
  280. </el-table-column>
  281. <el-table-column label="数量" width="100">
  282. <template #default="props">
  283. <el-form-item
  284. :prop="'orderSkuList.' + index + '.orderSkuBomList.' + props.$index + '.quantity'"
  285. :rules="rules.quantity"
  286. :inline-message="true"
  287. style="width: 100%">
  288. <el-input-number
  289. onmousewheel="return false;"
  290. v-model="props.row.quantity"
  291. placeholder="数量"
  292. style="width: 100%"
  293. :controls="false"
  294. :min="0" />
  295. </el-form-item>
  296. </template>
  297. </el-table-column>
  298. <el-table-column label="名称" prop="bomSpecName" min-width="150" />
  299. <el-table-column label="总量" width="80">
  300. <template #default="props">
  301. {{ computeQuantity(index, props.$index) }}
  302. </template>
  303. </el-table-column>
  304. <el-table-column label="小计¥" width="100">
  305. <template #default="props">
  306. {{ moneyFormat(computeMoney(index, props.$index), 2) }}
  307. </template>
  308. </el-table-column>
  309. <el-table-column label="操作" align="center" fixed="right" width="60" v-if="!(route.query && route.query.detailId)">
  310. <template #default="props">
  311. <el-button type="danger" @click="clickDeletePackingFittings(index, props.$index)" text>删除</el-button>
  312. </template>
  313. </el-table-column>
  314. </el-table>
  315. </div>
  316. </template>
  317. </el-table-column>
  318. <el-table-column label="操作" align="center" fixed="right" width="60" v-if="!(route.query && route.query.detailId)">
  319. <template #default="{}">
  320. <el-button type="danger" @click="clickDelete(index)" text>删除</el-button>
  321. </template>
  322. </el-table-column>
  323. </el-table>
  324. <el-collapse-item :name="index">
  325. <template #title>
  326. <span>包装</span>
  327. </template>
  328. <div style="display: flex; padding: 8px 10px 0px">
  329. <div style="flex: 1; padding: 0px 10px">
  330. <div>包装要求:</div>
  331. <div v-if="route.query && route.query.detailId">
  332. <div v-html="getStyle(item.packageRemark)"></div>
  333. </div>
  334. <Editor
  335. v-else
  336. :value="item.packageRemark"
  337. @updateValue="
  338. (val) => {
  339. return updatePackageRemark(val, index);
  340. }
  341. "
  342. :ref="'editor_' + index" />
  343. </div>
  344. </div>
  345. </el-collapse-item>
  346. </div>
  347. </div>
  348. </el-collapse>
  349. </div>
  350. </template>
  351. <template #package>
  352. <div style="width: 100%; padding: 0 20px">
  353. <el-form :model="formData.data">
  354. <el-form-item>
  355. <el-button type="primary" size="small" @click="clickViewPackaging()" v-preReClick>产品包装配置</el-button>
  356. </el-form-item>
  357. </el-form>
  358. </div>
  359. </template>
  360. <template #deliveryTime>
  361. <div style="width: 100%">
  362. <el-date-picker
  363. v-model="formData.data.deliveryTime"
  364. type="datetime"
  365. placeholder="请选择交货日期"
  366. value-format="YYYY-MM-DD HH:mm:ss"
  367. style="width: 100%" />
  368. </div>
  369. </template>
  370. <template #totalMonet>
  371. <div style="width: 100%; margin-left: 30px">
  372. <div>
  373. <span style="font-weight: 700; color: #6c88f1">产品总金额: ¥{{ moneyFormat(calculatedAmount("unitPrice"), 2) }}</span>
  374. <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">
  375. 定制加工费: ¥{{ moneyFormat(calculatedAmount("customProcessingFee"), 2) }}
  376. </span>
  377. <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">代发费: ¥{{ moneyFormat(calculatedAmount("lssueFee"), 2) }}</span>
  378. <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">快递包材费: ¥{{ moneyFormat(computeDeliveryMaterialsFee(), 2) }} </span>
  379. <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">包装人工费: ¥{{ moneyFormat(calculatedAmount("packingLabor"), 2) }}</span>
  380. <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">包材费: ¥{{ moneyFormat(calculatedPackagingMaterialCost(), 2) }}</span>
  381. <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">管理费: ¥{{ moneyFormat(calculatedAmount("managementFee"), 2) }}</span>
  382. </div>
  383. <div style="padding: 8px 0 0 0">
  384. <span style="font-weight: 700; color: red">订单总金额(含税): ¥{{ moneyFormat(calculatedTotalAmount(), 2) }}</span>
  385. </div>
  386. </div>
  387. </template>
  388. <template #attachments>
  389. <div style="width: 100%">
  390. <el-upload
  391. v-model:fileList="fileList"
  392. action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
  393. :data="uploadFileData"
  394. multiple
  395. :before-upload="beforeUpload"
  396. :on-success="onSuccessFile"
  397. :on-preview="onPreviewFile">
  398. <el-button style="background: #20b2aa; color: #fff; border: 1px solid #20b2aa">上传</el-button>
  399. </el-upload>
  400. </div>
  401. </template>
  402. <template #remark>
  403. <div style="width: 100%">
  404. <div style="margin: 0 2vw" v-if="route.query && route.query.detailId">
  405. <div v-html="getStyle(formData.data.remark)"></div>
  406. </div>
  407. <Editor v-else :value="formData.data.remark" @updateValue="updateValue" ref="editor" />
  408. </div>
  409. </template>
  410. </byForm>
  411. <div style="text-align: center; margin: 10px">
  412. <el-button @click="clickCancel()" v-if="route.query && route.query.detailId" size="large">关 闭</el-button>
  413. <el-button @click="clickCancel()" v-if="!(route.query && route.query.detailId)" size="large">取 消</el-button>
  414. <el-button @click="submitForm('0')" v-if="!(route.query && route.query.detailId)" size="large" v-preReClick>暂 存</el-button>
  415. <el-button type="primary" @click="submitForm('20')" v-if="!(route.query && route.query.detailId)" size="large" v-preReClick>确认包装配置</el-button>
  416. </div>
  417. </el-card>
  418. <el-dialog title="选择产品" v-if="openProduct" v-model="openProduct" width="90%">
  419. <SelectProduct :selectStatus="true" :type="'null'" @selectProduct="selectProduct"></SelectProduct>
  420. <template #footer>
  421. <el-button @click="openProduct = false" size="large">关 闭</el-button>
  422. </template>
  423. </el-dialog>
  424. <el-dialog title="选择包材配件" v-if="openPackingFittings" v-model="openPackingFittings" width="90%">
  425. <SelectBOM :selectStatus="true" :bomClassifyIdList="[2, 3]" @selectBOM="selectPackingFittings"></SelectBOM>
  426. <template #footer>
  427. <el-button @click="openPackingFittings = false" size="large">关 闭</el-button>
  428. </template>
  429. </el-dialog>
  430. <el-dialog title="选择图稿文件" v-if="openDrawingFile" v-model="openDrawingFile" width="70%">
  431. <SelectPicture @selectPic="selectPic"></SelectPicture>
  432. <template #footer>
  433. <el-button @click="openDrawingFile = false" size="large">关 闭</el-button>
  434. </template>
  435. </el-dialog>
  436. <el-dialog title="产品包装配置" v-if="openShippingPackage" v-model="openShippingPackage" width="80%" :close-on-press-escape="false" :show-close="false">
  437. <div style="height: calc(100vh - 184px); overflow-y: auto; overflow-x: hidden">
  438. <el-form :model="formData.data" :rules="rulesShippingPackage" ref="shippingPackage">
  439. <div style="font-weight: 700; margin: 20px 0 10px 0">发货包装</div>
  440. <div style="margin-bottom: 10px">
  441. <el-button type="primary" size="small" @click="clickExpressPacking()">选择包材</el-button>
  442. </div>
  443. <el-table :data="formData.data.orderPackageBomList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
  444. <el-table-column label="品号" prop="code" width="160" />
  445. <el-table-column label="品名" prop="name" min-width="220" />
  446. <el-table-column label="销售单价" prop="internalSellingPrice" width="100" />
  447. <el-table-column label="数量" width="120">
  448. <template #default="{ row, $index }">
  449. <div class="shippingPackage">
  450. <el-form-item
  451. :prop="'orderPackageBomList.' + $index + '.quantity'"
  452. :rules="rulesShippingPackage.quantity"
  453. :inline-message="true"
  454. style="width: 100%">
  455. <el-input-number
  456. onmousewheel="return false;"
  457. v-model="row.quantity"
  458. placeholder="修正数量"
  459. style="width: 100%"
  460. :controls="false"
  461. :min="0"
  462. :precision="0" />
  463. </el-form-item>
  464. </div>
  465. </template>
  466. </el-table-column>
  467. <el-table-column label="销售小计" width="120">
  468. <template #default="{ row }">
  469. {{ moneyFormat(computePackagingMoney(row, "internalSellingPrice"), 2) }}
  470. </template>
  471. </el-table-column>
  472. <el-table-column label="操作" align="center" fixed="right" width="80">
  473. <template #default="{ $index }">
  474. <el-button type="danger" @click="clickPackagingDelete($index)" text>删除</el-button>
  475. </template>
  476. </el-table-column>
  477. </el-table>
  478. <div style="font-weight: 700; margin: 20px 0 10px 0">外箱不干胶图稿</div>
  479. <div style="display: flex; width: 100%">
  480. <div style="width: 80px; line-height: 32px">不干胶图片:</div>
  481. <div style="width: calc(100% - 80px)">
  482. <el-image
  483. fit="scale-down"
  484. style="width: 148px; height: 148px; margin-right: 10px; cursor: pointer"
  485. v-if="formData.data.outerBoxSelfAdhesiveStickerFile && formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
  486. :src="formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
  487. @click="openFile(formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl)" />
  488. <div style="display: flex">
  489. <el-upload
  490. :show-file-list="false"
  491. action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
  492. :data="uploadAdhesiveData"
  493. :before-upload="uploadAdhesiveFile"
  494. :on-success="
  495. (response, uploadFile) => {
  496. return handleAdhesivePackagingSuccess(uploadFile);
  497. }
  498. "
  499. style="width: 100%">
  500. <el-button type="primary" text>上传文件</el-button>
  501. </el-upload>
  502. </div>
  503. </div>
  504. </div>
  505. </el-form>
  506. </div>
  507. <template #footer>
  508. <el-button @click="openShippingPackage = false" v-preReClick>关 闭</el-button>
  509. <el-button type="primary" @click="clickSaveShippingPackage" v-preReClick>提交订单</el-button>
  510. </template>
  511. </el-dialog>
  512. <el-dialog title="选择快递包装" v-if="openExpressPacking" v-model="openExpressPacking" width="90%">
  513. <SelectBOM :selectStatus="true" :bomClassifyIdList="[2, 3]" @selectBOM="selectExpressPacking"></SelectBOM>
  514. <template #footer>
  515. <el-button @click="openExpressPacking = false">关 闭</el-button>
  516. </template>
  517. </el-dialog>
  518. <el-dialog title="包装配置" v-if="openViewPackaging" v-model="openViewPackaging" width="80%">
  519. <div style="height: calc(100vh - 184px); overflow-y: auto; overflow-x: hidden">
  520. <div style="font-weight: 700; margin: 20px 0 10px 0">发货包装</div>
  521. <el-table :data="formData.data.orderPackageBomList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
  522. <el-table-column label="品号" prop="code" width="160" />
  523. <el-table-column label="品名" prop="name" min-width="220" />
  524. <el-table-column label="销售单价" prop="internalSellingPrice" width="100" />
  525. <el-table-column label="数量" prop="quantity" width="120" />
  526. <el-table-column label="销售小计" width="120">
  527. <template #default="{ row }">
  528. {{ moneyFormat(computePackagingMoney(row, "internalSellingPrice"), 2) }}
  529. </template>
  530. </el-table-column>
  531. </el-table>
  532. <div style="font-weight: 700; margin: 20px 0 10px 0">外箱不干胶图稿</div>
  533. <div style="display: flex; width: 100%">
  534. <div style="width: 80px; line-height: 32px">不干胶图片:</div>
  535. <div style="width: calc(100% - 80px)">
  536. <el-image
  537. fit="scale-down"
  538. style="width: 148px; height: 148px; margin-right: 10px; cursor: pointer"
  539. v-if="formData.data.outerBoxSelfAdhesiveStickerFile && formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
  540. :src="formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
  541. @click="openFile(formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl)" />
  542. </div>
  543. </div>
  544. </div>
  545. <template #footer>
  546. <el-button @click="openViewPackaging = false">关 闭</el-button>
  547. </template>
  548. </el-dialog>
  549. <el-dialog title="导入产品" v-if="openUpload" v-model="openUpload" width="60%">
  550. <el-upload class="upload-demo" :show-file-list="false" drag action="##" :http-request="giveawayServerLog" v-loading="loadingUpload">
  551. <el-icon class="el-icon--upload"><upload-filled /></el-icon>
  552. <div class="el-upload__text">拖拽文件进行上传</div>
  553. </el-upload>
  554. <template #footer>
  555. <el-button @click="openUpload = false">关 闭</el-button>
  556. </template>
  557. </el-dialog>
  558. </div>
  559. </template>
  560. <script setup>
  561. import byForm from "/src/components/byForm/index";
  562. import { ElMessage, ElMessageBox } from "element-plus";
  563. import Editor from "/src/components/Editor/index.vue";
  564. import { useRouter, useRoute } from "vue-router";
  565. import SelectProduct from "/src/views/group/product/management/index";
  566. import SelectBOM from "/src/views/group/BOM/management/index";
  567. import useTagsViewStore from "/src/store/modules/tagsView";
  568. import SelectPicture from "/src/components/select-picture/index.vue";
  569. import refreshStore from "/src/store/modules/refresh";
  570. const { proxy } = getCurrentInstance();
  571. const router = useRouter();
  572. const route = useRoute();
  573. const submit = ref(null);
  574. const departmentList = ref([]);
  575. const activeNames = ref([]);
  576. const expressDeliveryList = ref([]);
  577. const formOption = reactive({
  578. inline: true,
  579. labelWidth: "120px",
  580. itemWidth: 100,
  581. rules: [],
  582. labelPosition: "right",
  583. });
  584. const formData = reactive({
  585. data: {
  586. remark: "",
  587. type: 1,
  588. orderSkuList: [],
  589. fileList: [],
  590. orderPackageBomList: [],
  591. outerBoxSelfAdhesiveStickerFile: {},
  592. },
  593. });
  594. const formConfig = computed(() => {
  595. return [
  596. {
  597. type: "title",
  598. title: "产品",
  599. label: "",
  600. },
  601. {
  602. type: "slot",
  603. prop: "orderSkuList",
  604. slotName: "orderSkuList",
  605. },
  606. route.query && route.query.detailId
  607. ? {
  608. type: "title",
  609. title: "产品包装配置",
  610. label: "",
  611. }
  612. : {},
  613. route.query && route.query.detailId
  614. ? {
  615. type: "slot",
  616. slotName: "package",
  617. }
  618. : {},
  619. {
  620. type: "title",
  621. title: "类型",
  622. label: "",
  623. },
  624. {
  625. type: "slot",
  626. prop: "type",
  627. slotName: "type",
  628. label: "订单类型",
  629. },
  630. {
  631. type: "slot",
  632. prop: "departmentId",
  633. slotName: "departmentId",
  634. label: "事业部",
  635. itemWidth: 25,
  636. },
  637. {
  638. type: "input",
  639. prop: "wlnCode",
  640. label: "E10单号",
  641. itemType: "text",
  642. itemWidth: 25,
  643. },
  644. route.query && route.query.detailId
  645. ? {}
  646. : {
  647. type: "title",
  648. title: "地址",
  649. label: "",
  650. },
  651. route.query && route.query.detailId
  652. ? {}
  653. : {
  654. type: "slot",
  655. slotName: "deliveryAddress",
  656. label: "收货地址",
  657. },
  658. route.query && route.query.detailId
  659. ? {}
  660. : {
  661. type: "slot",
  662. slotName: "consignee",
  663. label: "收货人",
  664. },
  665. {
  666. type: "title",
  667. title: "贸易",
  668. label: "",
  669. },
  670. {
  671. type: "slot",
  672. prop: "deliveryTime",
  673. slotName: "deliveryTime",
  674. label: "交货时间",
  675. itemWidth: 25,
  676. },
  677. {
  678. type: "select",
  679. label: "选择快递",
  680. prop: "expressDeliveryId",
  681. data: expressDeliveryList.value,
  682. itemWidth: 25,
  683. clearable: true,
  684. },
  685. {
  686. type: "select",
  687. label: "店铺来源",
  688. prop: "sourcePlatform",
  689. data: proxy.useUserStore().allDict["source_platform"],
  690. itemWidth: 25,
  691. clearable: true,
  692. },
  693. {
  694. type: "select",
  695. label: "店铺名称",
  696. prop: "shopName",
  697. data: proxy.useUserStore().allDict["shop_name"],
  698. itemWidth: 25,
  699. clearable: true,
  700. },
  701. {
  702. type: "title",
  703. title: "总计",
  704. label: "",
  705. },
  706. {
  707. type: "slot",
  708. prop: "totalMonet",
  709. slotName: "totalMonet",
  710. },
  711. {
  712. type: "title",
  713. title: "附件",
  714. label: "",
  715. },
  716. {
  717. type: "slot",
  718. slotName: "attachments",
  719. label: "附件",
  720. },
  721. {
  722. type: "title",
  723. title: "订单备注",
  724. label: "",
  725. },
  726. {
  727. type: "slot",
  728. slotName: "remark",
  729. },
  730. ];
  731. });
  732. const rules = ref({
  733. province: [{ required: true, message: "请输入省", trigger: "blur" }],
  734. detailedAddress: [{ required: true, message: "请输入详细地址", trigger: "blur" }],
  735. consignee: [{ required: true, message: "请输入联系人", trigger: "blur" }],
  736. consigneeNumber: [{ required: true, message: "请输入联系电话", trigger: "blur" }],
  737. deliveryTime: [{ required: true, message: "请选择交货时间", trigger: "change" }],
  738. expressDeliveryId: [{ required: true, message: "请选择快递", trigger: "change" }],
  739. sourcePlatform: [{ required: true, message: "请选择店铺来源", trigger: "change" }],
  740. shopName: [{ required: true, message: "请选择店铺", trigger: "change" }],
  741. quantity: [{ required: true, message: "请输入数量", trigger: "blur" }],
  742. type: [{ required: true, message: "请选择订单类型", trigger: "change" }],
  743. departmentId: [{ required: true, message: "请选择事业部", trigger: "change" }],
  744. wlnCode: [{ required: true, message: "请输入E10单号", trigger: "blur" }],
  745. erpCode: [{ required: true, message: "请输入E10成品品号", trigger: "blur" }],
  746. });
  747. const getDemandData = () => {
  748. proxy.post("/department/page", { pageNum: 1, pageSize: 999 }).then((res) => {
  749. if (res.rows && res.rows.length > 0) {
  750. departmentList.value = res.rows.map((item) => {
  751. return {
  752. dictKey: item.id,
  753. dictValue: item.name,
  754. };
  755. });
  756. }
  757. });
  758. proxy.post("/expressDelivery/page", { pageNum: 1, pageSize: 999 }).then((res) => {
  759. if (res.rows && res.rows.length > 0) {
  760. expressDeliveryList.value = res.rows.map((item) => {
  761. return {
  762. dictKey: item.id,
  763. dictValue: item.expressage,
  764. };
  765. });
  766. }
  767. });
  768. };
  769. getDemandData();
  770. const drawingFileIndex = ref(0);
  771. const openDrawingFile = ref(false);
  772. const clickDrawingFile = (index) => {
  773. drawingFileIndex.value = index;
  774. openDrawingFile.value = true;
  775. };
  776. const selectPic = (row) => {
  777. formData.data.orderSkuList[drawingFileIndex.value].blueprint = row.imgUrl;
  778. formData.data.orderSkuList[drawingFileIndex.value].productionDocument = row.fileUrl;
  779. formData.data.orderSkuList[drawingFileIndex.value].artworkLibraryId = row.id;
  780. ElMessage({ message: "选择完成", type: "success" });
  781. openDrawingFile.value = false;
  782. };
  783. const openFile = (path) => {
  784. window.open(path);
  785. };
  786. const updatePackageRemark = (val, index) => {
  787. formData.data.orderSkuList[index].packageRemark = val;
  788. };
  789. const clickDelete = (index) => {
  790. formData.data.orderSkuList.splice(index, 1);
  791. getShippingPackage();
  792. };
  793. const updateValue = (val) => {
  794. formData.data.remark = val;
  795. };
  796. const openShippingPackage = ref(false);
  797. const submitForm = (status) => {
  798. submit.value.handleSubmit(() => {
  799. if (formData.data.orderSkuList && formData.data.orderSkuList.length > 0) {
  800. for (let i = 0; i < formData.data.orderSkuList.length; i++) {
  801. if (!formData.data.orderSkuList[i].blueprint) {
  802. return ElMessage("请选择设计图");
  803. }
  804. if (!formData.data.orderSkuList[i].productionDocument) {
  805. return ElMessage("请选择生产文件");
  806. }
  807. let packagingMaterialCost = 0;
  808. if (formData.data.orderSkuList[i].quantity) {
  809. if (formData.data.orderSkuList[i].orderSkuBomList && formData.data.orderSkuList[i].orderSkuBomList.length > 0) {
  810. for (let j = 0; j < formData.data.orderSkuList[i].orderSkuBomList.length; j++) {
  811. if (formData.data.orderSkuList[i].orderSkuBomList[j].quantity && formData.data.orderSkuList[i].orderSkuBomList[j].unitPrice) {
  812. packagingMaterialCost = Number(
  813. Math.round(
  814. (packagingMaterialCost +
  815. formData.data.orderSkuList[i].orderSkuBomList[j].quantity * formData.data.orderSkuList[i].orderSkuBomList[j].unitPrice) *
  816. 100
  817. ) / 100
  818. );
  819. }
  820. }
  821. }
  822. }
  823. formData.data.orderSkuList[i].packagingMaterialCost = packagingMaterialCost;
  824. }
  825. formData.data.productTotalAmount = calculatedAmount("unitPrice");
  826. formData.data.customProcessingFee = calculatedAmount("customProcessingFee");
  827. formData.data.lssueFee = calculatedAmount("lssueFee");
  828. formData.data.deliveryMaterialsFee = computeDeliveryMaterialsFee();
  829. formData.data.packingLabor = calculatedAmount("packingLabor");
  830. formData.data.managementFee = calculatedAmount("managementFee");
  831. formData.data.packagingMaterialCost = calculatedPackagingMaterialCost();
  832. formData.data.totalAmount = calculatedTotalAmount();
  833. formData.data.proofingFee = 0;
  834. if (fileList.value && fileList.value.length > 0) {
  835. for (let i = 0; i < fileList.value.length; i++) {
  836. if (fileList.value[i].raw.uploadState) {
  837. return ElMessage("文件上传中,请稍后提交");
  838. }
  839. }
  840. formData.data.fileList = fileList.value.map((item) => {
  841. return {
  842. id: item.raw.id,
  843. fileName: item.raw.fileName,
  844. fileUrl: item.raw.fileUrl,
  845. };
  846. });
  847. } else {
  848. formData.data.fileList = [];
  849. }
  850. formData.data.status = status;
  851. if (status == "20") {
  852. openShippingPackage.value = true;
  853. } else {
  854. let type = "add";
  855. if (formData.data.id) {
  856. type = "edit";
  857. }
  858. proxy.post("/orderInfo/" + type, formData.data).then(() => {
  859. ElMessage({
  860. message: type == "add" ? "添加成功" : "编辑成功",
  861. type: "success",
  862. });
  863. refreshStore().setRefresh("order");
  864. clickCancel();
  865. });
  866. }
  867. } else {
  868. return ElMessage("请添加产品");
  869. }
  870. });
  871. };
  872. const clickCancel = () => {
  873. const useTagsStore = useTagsViewStore();
  874. useTagsStore.delVisitedView(router.currentRoute.value);
  875. if (route.query && route.query.orderInquiry) {
  876. router.replace({
  877. path: "/production/schedule/order-inquiry",
  878. });
  879. } else {
  880. router.replace({
  881. path: "/subsidiary/order/subsidiary-order-management",
  882. });
  883. }
  884. };
  885. onMounted(() => {
  886. if (route.query && (route.query.id || route.query.detailId)) {
  887. useTagsViewStore().visitedViews = useTagsViewStore().visitedViews.map((item) => {
  888. if (item.query && item.query.random === route.query.random) {
  889. return {
  890. ...item,
  891. name: route.query.text,
  892. title: route.query.text,
  893. };
  894. } else {
  895. return {
  896. ...item,
  897. };
  898. }
  899. });
  900. getOrderDetail({ id: route.query.id || route.query.detailId });
  901. }
  902. });
  903. const getOrderDetail = (parameter) => {
  904. proxy.post("/orderInfo/detail", parameter).then((res) => {
  905. formData.data = res;
  906. if (!formData.data.type) {
  907. formData.data.type = 1;
  908. }
  909. if (route.query.id) {
  910. proxy.$refs.editor.changeHtml(formData.data.remark);
  911. }
  912. if (route.query.detailId) {
  913. let allIndex = [];
  914. for (let i = 0; i < formData.data.orderSkuList.length; i++) {
  915. allIndex.push(i);
  916. }
  917. activeNames.value = allIndex;
  918. formOption.disabled = true;
  919. }
  920. let list = [formData.data.id];
  921. if (formData.data.orderSkuList && formData.data.orderSkuList.length > 0) {
  922. list = list.concat(formData.data.orderSkuList.map((item) => item.id));
  923. proxy.post("/fileInfo/getList", { businessIdList: list }).then((fileObj) => {
  924. if (fileObj[formData.data.id] && fileObj[formData.data.id].length > 0) {
  925. let file = fileObj[formData.data.id].filter((item) => item.businessType == "0");
  926. if (file && file.length > 0) {
  927. fileList.value = file.map((item) => {
  928. return {
  929. raw: item,
  930. name: item.fileName,
  931. url: item.fileUrl,
  932. };
  933. });
  934. } else {
  935. fileList.value = [];
  936. }
  937. let outerBoxSelfAdhesiveStickerFile = fileObj[formData.data.id].filter((item) => item.businessType == "1");
  938. if (outerBoxSelfAdhesiveStickerFile && outerBoxSelfAdhesiveStickerFile.length > 0) {
  939. formData.data.outerBoxSelfAdhesiveStickerFile = outerBoxSelfAdhesiveStickerFile[0];
  940. } else {
  941. formData.data.outerBoxSelfAdhesiveStickerFile = {};
  942. }
  943. }
  944. for (let i = 0; i < formData.data.orderSkuList.length; i++) {
  945. if (fileObj[formData.data.orderSkuList[i].id] && fileObj[formData.data.orderSkuList[i].id].length > 0) {
  946. formData.data.orderSkuList[i].selfAdhesiveStickerFile = {
  947. id: fileObj[formData.data.orderSkuList[i].id][0].id,
  948. fileName: fileObj[formData.data.orderSkuList[i].id][0].fileName,
  949. fileUrl: fileObj[formData.data.orderSkuList[i].id][0].fileUrl,
  950. };
  951. }
  952. }
  953. });
  954. }
  955. });
  956. };
  957. const getStyle = (text) => {
  958. if (text) {
  959. return text.replace(/\n|\r\n/g, "<br>");
  960. } else {
  961. return "";
  962. }
  963. };
  964. const openProduct = ref(false);
  965. const clickAddProduct = () => {
  966. openProduct.value = true;
  967. };
  968. const openUpload = ref(false);
  969. const loadingUpload = ref(false);
  970. const clickUploadProduct = () => {
  971. loadingUpload.value = false;
  972. openUpload.value = true;
  973. };
  974. const giveawayServerLog = (params) => {
  975. let file = params.file;
  976. let formFile = new FormData();
  977. formFile.append("file", file);
  978. loadingUpload.value = true;
  979. proxy.postUploadFile("/skuSpec/getSkuSpecListFromImport", formFile).then(
  980. (res) => {
  981. ElMessage({ message: "导入成功", type: "success" });
  982. openUpload.value = false;
  983. if (res.data && res.data.length > 0) {
  984. for (let i = 0; i < res.data.length; i++) {
  985. let list = formData.data.orderSkuList.filter((item) => item.skuSpecId === res.data[i].id && item.bomSpecId === res.data[i].bomSpecId);
  986. if (!(list && list.length > 0)) {
  987. let orderSkuBomList = [];
  988. if (res.data[i].packagingMaterialList && res.data[i].packagingMaterialList.length > 0) {
  989. orderSkuBomList = res.data[i].packagingMaterialList.map((item) => {
  990. return {
  991. bomSpecId: item.bomSpecId,
  992. unitPrice: item.internalSellingPrice,
  993. quantity: item.quantity,
  994. bomSpecName: item.name,
  995. };
  996. });
  997. }
  998. formData.data.orderSkuList.push({
  999. wlnSkuName: res.data[i].wlnSkuName,
  1000. skuId: res.data[i].skuId,
  1001. code: res.data[i].code,
  1002. name: res.data[i].name,
  1003. skuSpecId: res.data[i].id,
  1004. bomSpecId: res.data[i].bomSpecId,
  1005. quantity: undefined,
  1006. erpCode: "",
  1007. featureCode: "",
  1008. customProcessingFee: "",
  1009. customProcessingType: "",
  1010. lssueFee: "",
  1011. deliveryMaterialsFee: "",
  1012. packingLabor: "",
  1013. managementFee: "",
  1014. unitPrice: "",
  1015. printType: 1,
  1016. packageRemark: "",
  1017. orderSkuBomList: orderSkuBomList,
  1018. blueprint: res.data[i].designImgUrl,
  1019. productionDocument: res.data[i].sharedFolder,
  1020. artworkLibraryId: "0",
  1021. inventoryQuantity: res.data[i].inventoryQuantity,
  1022. proofingFee: 0,
  1023. });
  1024. }
  1025. }
  1026. }
  1027. },
  1028. (err) => {
  1029. console.log(err);
  1030. loadingUpload.value = false;
  1031. }
  1032. );
  1033. };
  1034. const printType = ref([
  1035. {
  1036. dictKey: 1,
  1037. dictValue: "单面",
  1038. },
  1039. {
  1040. dictKey: 2,
  1041. dictValue: "双面",
  1042. },
  1043. ]);
  1044. const typeList = ref([
  1045. {
  1046. dictKey: 1,
  1047. dictValue: "自主订单",
  1048. },
  1049. {
  1050. dictKey: 2,
  1051. dictValue: "委外订单",
  1052. },
  1053. ]);
  1054. const selectProduct = (row, SKU) => {
  1055. if (row.id) {
  1056. let list = formData.data.orderSkuList.filter((item) => item.skuSpecId === row.id && item.bomSpecId === row.bomSpecId);
  1057. if (list && list.length > 0) {
  1058. return ElMessage("该产品已添加");
  1059. }
  1060. proxy.post("/sku/detail", { id: SKU.id }).then(async (res) => {
  1061. let orderSkuBomList = [];
  1062. if (res.skuSpecList && res.skuSpecList.length > 0) {
  1063. let listTwo = res.skuSpecList.filter((item) => item.id === row.id);
  1064. if (listTwo && listTwo.length > 0) {
  1065. if (listTwo[0].packagingMaterialList && listTwo[0].packagingMaterialList.length > 0) {
  1066. orderSkuBomList = listTwo[0].packagingMaterialList.map((item) => {
  1067. return {
  1068. bomSpecId: item.bomSpecId,
  1069. unitPrice: item.internalSellingPrice,
  1070. quantity: item.quantity,
  1071. bomSpecName: item.name,
  1072. };
  1073. });
  1074. }
  1075. }
  1076. }
  1077. let inventoryQuantity = 0;
  1078. let getSkuInventoryQuantity = await proxy.post("/skuSpec/getSkuInventoryQuantity", { id: row.id }).then((resQuantity) => {
  1079. inventoryQuantity = resQuantity;
  1080. });
  1081. formData.data.orderSkuList.push({
  1082. wlnSkuName: SKU.name,
  1083. skuId: row.skuId,
  1084. code: row.code,
  1085. name: row.name,
  1086. skuSpecId: row.id,
  1087. bomSpecId: row.bomSpecId,
  1088. quantity: undefined,
  1089. erpCode: "",
  1090. featureCode: "",
  1091. customProcessingFee: "",
  1092. customProcessingType: "",
  1093. lssueFee: "",
  1094. deliveryMaterialsFee: "",
  1095. packingLabor: "",
  1096. managementFee: "",
  1097. unitPrice: "",
  1098. printType: 1,
  1099. packageRemark: "",
  1100. orderSkuBomList: orderSkuBomList,
  1101. blueprint: row.designImgUrl,
  1102. productionDocument: row.sharedFolder,
  1103. artworkLibraryId: "0",
  1104. inventoryQuantity: inventoryQuantity,
  1105. proofingFee: 0,
  1106. });
  1107. ElMessage({ message: "添加成功", type: "success" });
  1108. });
  1109. } else {
  1110. ElMessage("添加失败");
  1111. }
  1112. };
  1113. const rowIndex = ref(null);
  1114. const openPackingFittings = ref(false);
  1115. const clickPackingFittings = (index) => {
  1116. rowIndex.value = index;
  1117. openPackingFittings.value = true;
  1118. };
  1119. const clickDeletePackingFittings = (index, indexTwo) => {
  1120. formData.data.orderSkuList[index].orderSkuBomList.splice(indexTwo, 1);
  1121. };
  1122. const selectPackingFittings = (data) => {
  1123. if (formData.data.orderSkuList[rowIndex.value].orderSkuBomList && formData.data.orderSkuList[rowIndex.value].orderSkuBomList.length > 0) {
  1124. let list = formData.data.orderSkuList[rowIndex.value].orderSkuBomList.filter((item) => item.bomSpecId === data.id);
  1125. if (list && list.length > 0) {
  1126. return ElMessage("包材配件已添加");
  1127. }
  1128. formData.data.orderSkuList[rowIndex.value].orderSkuBomList.push({
  1129. bomSpecId: data.id,
  1130. unitPrice: data.internalSellingPrice,
  1131. quantity: undefined,
  1132. bomSpecName: data.name,
  1133. });
  1134. } else {
  1135. formData.data.orderSkuList[rowIndex.value].orderSkuBomList = [
  1136. {
  1137. bomSpecId: data.id,
  1138. unitPrice: data.internalSellingPrice,
  1139. quantity: undefined,
  1140. bomSpecName: data.name,
  1141. },
  1142. ];
  1143. }
  1144. ElMessage({ message: "添加成功", type: "success" });
  1145. };
  1146. const changeQuantity = (index, status) => {
  1147. if (formData.data.orderSkuList[index].quantity) {
  1148. proxy
  1149. .post("/orderInfo/getSkuSpecPrice", { skuSpecId: formData.data.orderSkuList[index].skuSpecId, quantity: formData.data.orderSkuList[index].quantity })
  1150. .then((res) => {
  1151. if (formData.data.orderSkuList[index].printType == 2 && res.customProcessingFee) {
  1152. formData.data.orderSkuList[index].customProcessingFee = Number(Math.round(res.customProcessingFee * 2 * 100) / 100);
  1153. } else {
  1154. formData.data.orderSkuList[index].customProcessingFee = res.customProcessingFee;
  1155. }
  1156. formData.data.orderSkuList[index].customProcessingType = res.customProcessingType;
  1157. formData.data.orderSkuList[index].deliveryMaterialsFee = res.deliveryMaterialsFee;
  1158. formData.data.orderSkuList[index].lssueFee = res.lssueFee;
  1159. formData.data.orderSkuList[index].packingLabor = res.packingLabor;
  1160. formData.data.orderSkuList[index].managementFee = res.managementFee;
  1161. formData.data.orderSkuList[index].unitPrice = res.unitPrice;
  1162. });
  1163. if (status) {
  1164. getShippingPackage();
  1165. }
  1166. }
  1167. };
  1168. const cellStyleName = ({ column, columnIndex }) => {
  1169. if (column.label === "操作" && columnIndex === 3) {
  1170. return "vertical-align";
  1171. }
  1172. };
  1173. const uploadData = ref({});
  1174. const uploadFile = async (file) => {
  1175. const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
  1176. uploadData.value = res.uploadBody;
  1177. file.id = res.id;
  1178. file.fileName = res.fileName;
  1179. file.fileUrl = res.fileUrl;
  1180. return true;
  1181. };
  1182. const handleSuccess = (UploadFile, index) => {
  1183. formData.data.orderSkuList[index].productionDocument = UploadFile.raw.fileUrl;
  1184. formData.data.orderSkuList[index].artworkLibraryId = "0";
  1185. };
  1186. const uploadImgData = ref({});
  1187. const uploadImgFile = async (file) => {
  1188. const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
  1189. uploadImgData.value = res.uploadBody;
  1190. file.id = res.id;
  1191. file.fileName = res.fileName;
  1192. file.fileUrl = res.fileUrl;
  1193. return true;
  1194. };
  1195. const handleImgSuccess = (UploadFile, index) => {
  1196. formData.data.orderSkuList[index].blueprint = UploadFile.raw.fileUrl;
  1197. formData.data.orderSkuList[index].artworkLibraryId = "0";
  1198. };
  1199. const computeQuantity = (index, indexSKU) => {
  1200. let quantity = 0;
  1201. if (formData.data.orderSkuList[index].quantity && formData.data.orderSkuList[index].orderSkuBomList[indexSKU].quantity) {
  1202. quantity = Number(
  1203. Math.round(formData.data.orderSkuList[index].orderSkuBomList[indexSKU].quantity * formData.data.orderSkuList[index].quantity * 100) / 100
  1204. );
  1205. }
  1206. return quantity;
  1207. };
  1208. const computeMoney = (index, indexSKU) => {
  1209. let money = 0;
  1210. if (
  1211. formData.data.orderSkuList[index].quantity &&
  1212. formData.data.orderSkuList[index].orderSkuBomList[indexSKU].quantity &&
  1213. formData.data.orderSkuList[index].orderSkuBomList[indexSKU].unitPrice
  1214. ) {
  1215. money = Number(
  1216. Math.round(
  1217. formData.data.orderSkuList[index].orderSkuBomList[indexSKU].quantity *
  1218. formData.data.orderSkuList[index].orderSkuBomList[indexSKU].unitPrice *
  1219. formData.data.orderSkuList[index].quantity *
  1220. 100
  1221. ) / 100
  1222. );
  1223. }
  1224. return money;
  1225. };
  1226. const getSubtotal = (item) => {
  1227. let money = 0;
  1228. if (item.quantity) {
  1229. money = Number(
  1230. Math.round(
  1231. (item.customProcessingFee + item.deliveryMaterialsFee + item.lssueFee + item.packingLabor + item.managementFee + item.unitPrice) * item.quantity * 100
  1232. ) / 100
  1233. );
  1234. }
  1235. return money;
  1236. };
  1237. const calculatedAmount = (label) => {
  1238. let money = 0;
  1239. if (formData.data.orderSkuList && formData.data.orderSkuList.length > 0) {
  1240. for (let i = 0; i < formData.data.orderSkuList.length; i++) {
  1241. if (formData.data.orderSkuList[i].quantity && formData.data.orderSkuList[i][label]) {
  1242. money = Number(Math.round((money + formData.data.orderSkuList[i][label] * formData.data.orderSkuList[i].quantity) * 100) / 100);
  1243. }
  1244. }
  1245. }
  1246. return money;
  1247. };
  1248. const calculatedPackagingMaterialCost = () => {
  1249. let money = 0;
  1250. if (formData.data.orderSkuList && formData.data.orderSkuList.length > 0) {
  1251. for (let i = 0; i < formData.data.orderSkuList.length; i++) {
  1252. if (formData.data.orderSkuList[i].orderSkuBomList && formData.data.orderSkuList[i].orderSkuBomList.length > 0) {
  1253. for (let j = 0; j < formData.data.orderSkuList[i].orderSkuBomList.length; j++) {
  1254. if (formData.data.orderSkuList[i].orderSkuBomList[j].quantity && formData.data.orderSkuList[i].orderSkuBomList[j].unitPrice) {
  1255. money = Number(
  1256. Math.round(
  1257. (money +
  1258. formData.data.orderSkuList[i].orderSkuBomList[j].quantity *
  1259. formData.data.orderSkuList[i].orderSkuBomList[j].unitPrice *
  1260. formData.data.orderSkuList[i].quantity) *
  1261. 100
  1262. ) / 100
  1263. );
  1264. }
  1265. }
  1266. }
  1267. }
  1268. }
  1269. return money;
  1270. };
  1271. const calculatedTotalAmount = () => {
  1272. let money = 0;
  1273. money = Number(
  1274. Math.round(
  1275. (calculatedAmount("unitPrice") +
  1276. calculatedAmount("customProcessingFee") +
  1277. calculatedAmount("lssueFee") +
  1278. computeDeliveryMaterialsFee() +
  1279. calculatedAmount("packingLabor") +
  1280. calculatedAmount("managementFee") +
  1281. calculatedPackagingMaterialCost()) *
  1282. 100
  1283. ) / 100
  1284. );
  1285. return money;
  1286. };
  1287. const fileList = ref([]);
  1288. const uploadFileData = ref({});
  1289. const beforeUpload = async (file) => {
  1290. const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
  1291. uploadFileData.value = res.uploadBody;
  1292. file.id = res.id;
  1293. file.fileName = res.fileName;
  1294. file.fileUrl = res.fileUrl;
  1295. file.uploadState = true;
  1296. return true;
  1297. };
  1298. const onSuccessFile = (any, UploadFile) => {
  1299. UploadFile.raw.uploadState = false;
  1300. };
  1301. const onPreviewFile = (file) => {
  1302. window.open(file.raw.fileUrl, "_blank");
  1303. };
  1304. const uploadAdhesiveData = ref({});
  1305. const uploadAdhesiveFile = async (file) => {
  1306. const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
  1307. uploadAdhesiveData.value = res.uploadBody;
  1308. file.id = res.id;
  1309. file.fileName = res.fileName;
  1310. file.fileUrl = res.fileUrl;
  1311. return true;
  1312. };
  1313. const handleAdhesiveSuccess = (UploadFile, index) => {
  1314. formData.data.orderSkuList[index].selfAdhesiveStickerFile = {
  1315. id: UploadFile.raw.id,
  1316. fileName: UploadFile.raw.fileName,
  1317. fileUrl: UploadFile.raw.fileUrl,
  1318. };
  1319. };
  1320. const rulesShippingPackage = ref({
  1321. quantity: [{ required: true, message: "请输入数量", trigger: "blur" }],
  1322. });
  1323. const computePackagingMoney = (item, label) => {
  1324. let money = 0;
  1325. if (item.quantity && item[label]) {
  1326. money = Number(Math.round(item.quantity * item[label] * 100) / 100);
  1327. }
  1328. return money;
  1329. };
  1330. const clickPackagingDelete = (index) => {
  1331. formData.data.orderPackageBomList.splice(index, 1);
  1332. };
  1333. const handleAdhesivePackagingSuccess = (UploadFile) => {
  1334. formData.data.outerBoxSelfAdhesiveStickerFile = {
  1335. id: UploadFile.raw.id,
  1336. fileName: UploadFile.raw.fileName,
  1337. fileUrl: UploadFile.raw.fileUrl,
  1338. };
  1339. };
  1340. const clickSaveShippingPackage = () => {
  1341. proxy.$refs.shippingPackage.validate((valid) => {
  1342. if (valid) {
  1343. if (formData.data.orderPackageBomList && formData.data.orderPackageBomList.length > 0) {
  1344. formData.data.deliveryMaterialsFee = computeDeliveryMaterialsFee();
  1345. formData.data.totalAmount = calculatedTotalAmount();
  1346. formData.data.proofingFee = 0;
  1347. let type = "add";
  1348. if (formData.data.id) {
  1349. type = "edit";
  1350. }
  1351. let bodyData = proxy.deepClone(formData.data);
  1352. if (bodyData.departmentId == "0") {
  1353. delete bodyData.orderPackageBomList;
  1354. }
  1355. proxy.post("/orderInfo/" + type, bodyData).then(() => {
  1356. ElMessage({
  1357. message: type == "add" ? "添加成功" : "编辑成功",
  1358. type: "success",
  1359. });
  1360. refreshStore().setRefresh("order");
  1361. clickCancel();
  1362. });
  1363. } else {
  1364. ElMessageBox.confirm("是否确认无产品发货包装", "提示", {
  1365. confirmButtonText: "确定",
  1366. cancelButtonText: "取消",
  1367. type: "warning",
  1368. })
  1369. .then(() => {
  1370. formData.data.deliveryMaterialsFee = computeDeliveryMaterialsFee();
  1371. formData.data.totalAmount = calculatedTotalAmount();
  1372. formData.data.proofingFee = 0;
  1373. let type = "add";
  1374. if (formData.data.id) {
  1375. type = "edit";
  1376. }
  1377. let bodyData = proxy.deepClone(formData.data);
  1378. if (bodyData.departmentId == "0") {
  1379. delete bodyData.orderPackageBomList;
  1380. }
  1381. proxy.post("/orderInfo/" + type, bodyData).then(() => {
  1382. ElMessage({
  1383. message: type == "add" ? "添加成功" : "编辑成功",
  1384. type: "success",
  1385. });
  1386. refreshStore().setRefresh("order");
  1387. clickCancel();
  1388. });
  1389. })
  1390. .catch(() => {});
  1391. }
  1392. }
  1393. });
  1394. };
  1395. const openExpressPacking = ref(false);
  1396. const clickExpressPacking = () => {
  1397. openExpressPacking.value = true;
  1398. };
  1399. const selectExpressPacking = (data) => {
  1400. if (formData.data.orderPackageBomList && formData.data.orderPackageBomList.length > 0) {
  1401. let list = formData.data.orderPackageBomList.filter((item) => item.bomSpecId === data.id);
  1402. if (list && list.length > 0) {
  1403. return ElMessage("快递物流包材已添加");
  1404. }
  1405. formData.data.orderPackageBomList.push({
  1406. bomSpecId: data.id,
  1407. code: data.code,
  1408. name: data.name,
  1409. internalSellingPrice: data.internalSellingPrice,
  1410. quantity: undefined,
  1411. });
  1412. } else {
  1413. formData.data.orderPackageBomList = [
  1414. {
  1415. bomSpecId: data.id,
  1416. code: data.code,
  1417. name: data.name,
  1418. internalSellingPrice: data.internalSellingPrice,
  1419. quantity: undefined,
  1420. },
  1421. ];
  1422. }
  1423. ElMessage({ message: "添加成功", type: "success" });
  1424. };
  1425. const getShippingPackage = () => {
  1426. let skuSpecList = formData.data.orderSkuList.filter((item) => item.quantity && item.quantity > 0);
  1427. if (skuSpecList && skuSpecList.length > 0) {
  1428. skuSpecList = skuSpecList.map((item) => {
  1429. return {
  1430. skuSpecId: item.skuSpecId,
  1431. quantity: item.quantity,
  1432. };
  1433. });
  1434. proxy.post("/orderInfo/getSkuSpecPackageBomList", { skuSpecList: skuSpecList }).then((res) => {
  1435. if (res && res.length > 0) {
  1436. formData.data.orderPackageBomList = res.map((item) => {
  1437. return {
  1438. bomSpecId: item.bomSpecId,
  1439. code: item.bomSpecCode,
  1440. name: item.bomSpecName,
  1441. internalSellingPrice: item.internalSellingPrice,
  1442. quantity: item.quantity,
  1443. };
  1444. });
  1445. } else {
  1446. formData.data.orderPackageBomList = [];
  1447. }
  1448. });
  1449. } else {
  1450. formData.data.orderPackageBomList = [];
  1451. }
  1452. };
  1453. const computeDeliveryMaterialsFee = () => {
  1454. let money = 0;
  1455. if (formData.data.orderPackageBomList && formData.data.orderPackageBomList.length > 0) {
  1456. for (let i = 0; i < formData.data.orderPackageBomList.length; i++) {
  1457. if (formData.data.orderPackageBomList[i].internalSellingPrice && formData.data.orderPackageBomList[i].quantity) {
  1458. money = Number(
  1459. Math.round((money + formData.data.orderPackageBomList[i].internalSellingPrice * formData.data.orderPackageBomList[i].quantity) * 100) / 100
  1460. );
  1461. }
  1462. }
  1463. }
  1464. return money;
  1465. };
  1466. const openViewPackaging = ref(false);
  1467. const clickViewPackaging = () => {
  1468. openViewPackaging.value = true;
  1469. };
  1470. const computeSingleDeliveryMaterialsFee = (index) => {
  1471. let money = computeDeliveryMaterialsFee();
  1472. let list = formData.data.orderSkuList.filter((item) => item.quantity > 0);
  1473. let num = 0;
  1474. let singlePrice = 0;
  1475. if (list && list.length > 0) {
  1476. for (let i = 0; i < list.length; i++) {
  1477. num = Number(Math.round(num + list[i].quantity));
  1478. }
  1479. singlePrice = Number(Math.ceil((money / num) * 1000) / 1000);
  1480. }
  1481. formData.data.orderSkuList[index].deliveryMaterialsFee = singlePrice;
  1482. return formData.data.orderSkuList[index].deliveryMaterialsFee;
  1483. };
  1484. </script>
  1485. <style lang="scss" scoped>
  1486. ::v-deep(.el-input-number .el-input__inner) {
  1487. text-align: left;
  1488. }
  1489. :deep(.el-dialog) {
  1490. margin-top: 10px !important;
  1491. margin-bottom: 10px !important;
  1492. }
  1493. :deep(.ql-editor) {
  1494. height: auto;
  1495. }
  1496. :deep(.el-collapse-item__header) {
  1497. justify-content: center;
  1498. }
  1499. :deep(.el-collapse-item__arrow) {
  1500. margin: 0;
  1501. }
  1502. :deep(.el-table__cell) {
  1503. vertical-align: top;
  1504. }
  1505. :deep(.vertical-align) {
  1506. vertical-align: middle;
  1507. }
  1508. .shippingPackage {
  1509. .el-form-item {
  1510. margin-bottom: 0;
  1511. }
  1512. }
  1513. </style>