add.vue 59 KB

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