design.vue 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094
  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 disabled 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 #orderSkuList>
  24. <div style="width: 100%; padding: 0 20px">
  25. <el-collapse v-model="activeNames">
  26. <div v-for="(item, index) in formData.data.orderSkuList" :key="index" style="margin-bottom: 20px">
  27. <div style="border: 1px solid #edf0f5">
  28. <el-table :data="[item]" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
  29. <el-table-column label="产品" width="300">
  30. <template #default="{ row }">
  31. <div style="width: 100%">
  32. <div style="line-height: 35px">
  33. <span style="color: black; font-weight: 700">库存数量: </span>
  34. <span>{{ item.inventoryQuantity }}</span>
  35. </div>
  36. <div style="line-height: 35px">
  37. <span style="color: black; font-weight: 700">商品名称: </span>
  38. <span>{{ item.wlnSkuName }}</span>
  39. </div>
  40. <div style="line-height: 35px">
  41. <span style="color: black; font-weight: 700">品号: </span>
  42. <span>{{ item.code }}</span>
  43. </div>
  44. <div style="line-height: 35px; word-break: break-all">
  45. <span style="color: black; font-weight: 700">品名: </span>
  46. <span>{{ item.name }}</span>
  47. </div>
  48. <div style="line-height: 35px; word-break: break-all">
  49. <span style="color: black; font-weight: 700">E10成品品号: </span>
  50. <span>{{ item.erpCode }}</span>
  51. </div>
  52. <div style="line-height: 35px; word-break: break-all">
  53. <span style="color: black; font-weight: 700">特征码: </span>
  54. <span>{{ item.featureCode }}</span>
  55. </div>
  56. <div style="line-height: 35px; display: flex">
  57. <span style="width: 37px; color: black; font-weight: 700">数量: </span>
  58. <el-form-item style="width: calc(100% - 37px)">
  59. {{ row.quantity }}
  60. </el-form-item>
  61. </div>
  62. <div style="line-height: 35px">
  63. <span style="color: black; font-weight: 700">加工费: </span>
  64. <span>{{ item.customProcessingFee }}</span>
  65. </div>
  66. <div style="line-height: 35px">
  67. <span style="color: black; font-weight: 700">代发费: </span>
  68. <span>{{ item.lssueFee }}</span>
  69. </div>
  70. <div style="line-height: 35px">
  71. <span style="color: black; font-weight: 700">快递包材费: </span>
  72. <span>{{ computeSingleDeliveryMaterialsFee(index) }}</span>
  73. </div>
  74. <div style="line-height: 35px">
  75. <span style="color: black; font-weight: 700">包装人工费: </span>
  76. <span>{{ item.packingLabor }}</span>
  77. </div>
  78. <div style="line-height: 35px">
  79. <span style="color: black; font-weight: 700">管理费: </span>
  80. <span>{{ item.managementFee }}</span>
  81. </div>
  82. <div style="line-height: 35px">
  83. <span style="color: black; font-weight: 700">单价: </span>
  84. <span>{{ item.unitPrice }}</span>
  85. </div>
  86. <div style="line-height: 35px">
  87. <span style="color: black; font-weight: 700">小计: </span>
  88. <span>{{ getSubtotal(item) }}</span>
  89. </div>
  90. <div style="line-height: 35px">
  91. <span style="color: black; font-weight: 700">打样费: </span>
  92. <span>{{ item.proofingFee }}</span>
  93. </div>
  94. <div style="line-height: 35px">
  95. <span style="width: 37px; color: black; font-weight: 700">打印: </span>
  96. <el-form-item
  97. :prop="'orderSkuList.' + index + '.printType'"
  98. :rules="rules.printType"
  99. :inline-message="true"
  100. style="width: calc(100% - 37px)">
  101. {{ dictKeyValue(item.printType, printType) }}
  102. </el-form-item>
  103. </div>
  104. </div>
  105. </template>
  106. </el-table-column>
  107. <el-table-column label="产品图稿" width="400">
  108. <template #default="{ row }">
  109. <div style="display: flex; width: 100%">
  110. <div style="width: 80px">设计图:</div>
  111. <div style="width: calc(100% - 80px)">
  112. <el-image
  113. fit="scale-down"
  114. style="width: 148px; height: 148px; margin-right: 10px; cursor: pointer"
  115. v-if="row.blueprint"
  116. :src="row.blueprint"
  117. @click="openFile(row.blueprint)" />
  118. <div style="display: flex">
  119. <el-button type="primary" @click="clickDrawingFile(index)" text>选择图稿</el-button>
  120. <el-upload
  121. :show-file-list="false"
  122. action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
  123. :data="uploadImgData"
  124. :before-upload="uploadImgFile"
  125. :on-success="
  126. (response, uploadFile) => {
  127. return handleImgSuccess(uploadFile, index);
  128. }
  129. "
  130. style="width: 100%"
  131. accept=".jpg,.jpeg,.png,.GIF,.JPG,.PNG">
  132. <el-button type="primary" style="margin-left: 12px" text>上传图片</el-button>
  133. </el-upload>
  134. </div>
  135. </div>
  136. </div>
  137. <div style="display: flex; margin-top: 20px; width: 100%">
  138. <div style="width: 80px">图稿文件:</div>
  139. <div style="width: calc(100% - 80px)">
  140. <a
  141. style="color: #16e5c1; cursor: pointer; word-break: break-all; margin-right: 10px"
  142. @click="openFile(row.productionDocument)"
  143. v-if="row.productionDocument">
  144. {{ row.productionDocument }}
  145. </a>
  146. <div style="display: flex">
  147. <el-button type="primary" @click="clickDrawingFile(index)" text>选择图稿</el-button>
  148. <el-upload
  149. :show-file-list="false"
  150. action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
  151. :data="uploadData"
  152. :before-upload="uploadFile"
  153. :on-success="
  154. (response, uploadFile) => {
  155. return handleSuccess(uploadFile, index);
  156. }
  157. "
  158. style="width: 100%">
  159. <el-button type="primary" style="margin-left: 12px" text>上传文件</el-button>
  160. </el-upload>
  161. </div>
  162. </div>
  163. </div>
  164. <div style="font-weight: 700; margin-top: 20px">产品不干胶图稿</div>
  165. <div style="display: flex; width: 100%">
  166. <div style="width: 80px">不干胶图片:</div>
  167. <div style="width: calc(100% - 80px)">
  168. <el-image
  169. fit="scale-down"
  170. style="width: 148px; height: 148px; margin-right: 10px; cursor: pointer"
  171. v-if="row.selfAdhesiveStickerFile && row.selfAdhesiveStickerFile.fileUrl"
  172. :src="row.selfAdhesiveStickerFile.fileUrl"
  173. @click="openFile(row.selfAdhesiveStickerFile.fileUrl)" />
  174. <div style="display: flex" v-if="!(route.query && route.query.detailId)">
  175. <el-upload
  176. :show-file-list="false"
  177. action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
  178. :data="uploadAdhesiveData"
  179. :before-upload="uploadAdhesiveFile"
  180. :on-success="
  181. (response, uploadFile) => {
  182. return handleAdhesiveSuccess(uploadFile, index);
  183. }
  184. "
  185. style="width: 100%"
  186. accept=".jpg,.jpeg,.png,.GIF,.JPG,.PNG">
  187. <el-button type="primary" text>上传文件</el-button>
  188. </el-upload>
  189. </div>
  190. </div>
  191. </div>
  192. </template>
  193. </el-table-column>
  194. <el-table-column label="包材配件/单品" min-width="400">
  195. <template #default="{ row }">
  196. <div style="width: 100%">
  197. <div style="margin-bottom: 10px">
  198. <el-button type="primary" @click="clickPackingFittings(index)">选择包材配件</el-button>
  199. </div>
  200. <el-table :data="row.orderSkuBomList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
  201. <el-table-column label="单价¥" width="120">
  202. <template #default="props">
  203. <div>
  204. <span>{{ moneyFormat(props.row.unitPrice, 2) }}</span>
  205. </div>
  206. </template>
  207. </el-table-column>
  208. <el-table-column label="数量" width="100">
  209. <template #default="props">
  210. <el-form-item
  211. :prop="'orderSkuList.' + index + '.orderSkuBomList.' + props.$index + '.quantity'"
  212. :rules="rules.quantity"
  213. :inline-message="true"
  214. style="width: 100%">
  215. <el-input-number
  216. onmousewheel="return false;"
  217. v-model="props.row.quantity"
  218. placeholder="数量"
  219. style="width: 100%"
  220. :controls="false"
  221. :min="0" />
  222. </el-form-item>
  223. </template>
  224. </el-table-column>
  225. <el-table-column label="名称" prop="bomSpecName" min-width="150" />
  226. <el-table-column label="总量" width="80">
  227. <template #default="props">
  228. {{ computeQuantity(index, props.$index) }}
  229. </template>
  230. </el-table-column>
  231. <el-table-column label="小计¥" width="100">
  232. <template #default="props">
  233. {{ moneyFormat(computeMoney(index, props.$index), 2) }}
  234. </template>
  235. </el-table-column>
  236. <el-table-column label="操作" align="center" fixed="right" width="60">
  237. <template #default="props">
  238. <el-button type="danger" @click="clickDeletePackingFittings(index, props.$index, props.row)" text>删除</el-button>
  239. </template>
  240. </el-table-column>
  241. </el-table>
  242. </div>
  243. </template>
  244. </el-table-column>
  245. </el-table>
  246. <el-collapse-item :name="index">
  247. <template #title>
  248. <span>包装</span>
  249. </template>
  250. <div style="display: flex; padding: 8px 10px 0px">
  251. <div style="flex: 1; padding: 0px 10px">
  252. <div>包装要求:</div>
  253. <div v-html="getStyle(item.packageRemark)"></div>
  254. </div>
  255. </div>
  256. </el-collapse-item>
  257. </div>
  258. </div>
  259. </el-collapse>
  260. </div>
  261. </template>
  262. <template #deliveryTime>
  263. <div style="width: 100%">
  264. {{ formData.data.deliveryTime }}
  265. </div>
  266. </template>
  267. <template #expressDeliveryId>
  268. <div style="width: 100%">
  269. {{ dictKeyValue(formData.data.sourcePlatform, expressDeliveryList.value) }}
  270. </div>
  271. </template>
  272. <template #sourcePlatform>
  273. <div style="width: 100%">
  274. {{ dictKeyValue(formData.data.sourcePlatform, useUserStore().allDict["source_platform"]) }}
  275. </div>
  276. </template>
  277. <template #shopName>
  278. <div style="width: 100%">
  279. {{ dictKeyValue(formData.data.shopName, useUserStore().allDict["shop_name"]) }}
  280. </div>
  281. </template>
  282. <template #totalMonet>
  283. <div style="width: 100%; margin-left: 30px">
  284. <div>
  285. <span style="font-weight: 700; color: #6c88f1">产品总金额: ¥{{ moneyFormat(calculatedAmount("unitPrice"), 2) }}</span>
  286. <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">
  287. 定制加工费: ¥{{ moneyFormat(calculatedAmount("customProcessingFee"), 2) }}
  288. </span>
  289. <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">代发费: ¥{{ moneyFormat(calculatedAmount("lssueFee"), 2) }}</span>
  290. <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">快递包材费: ¥{{ moneyFormat(computeDeliveryMaterialsFee(), 2) }} </span>
  291. <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">包装人工费: ¥{{ moneyFormat(calculatedAmount("packingLabor"), 2) }}</span>
  292. <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">包材费: ¥{{ moneyFormat(calculatedPackagingMaterialCost(), 2) }}</span>
  293. <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">管理费: ¥{{ moneyFormat(calculatedAmount("managementFee"), 2) }}</span>
  294. <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">打样费: ¥{{ moneyFormat(getProofingFee(), 2) }}</span>
  295. </div>
  296. <div style="padding: 8px 0 0 0">
  297. <span style="font-weight: 700; color: red">订单总金额(含税): ¥{{ moneyFormat(calculatedTotalAmount(), 2) }}</span>
  298. </div>
  299. </div>
  300. </template>
  301. <template #attachments>
  302. <div style="width: 100%">
  303. <el-upload
  304. v-model:fileList="fileList"
  305. action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
  306. :data="uploadFileData"
  307. multiple
  308. :before-upload="beforeUpload"
  309. :on-success="onSuccessFile"
  310. :on-preview="onPreviewFile">
  311. <el-button style="background: #20b2aa; color: #fff; border: 1px solid #20b2aa">上传</el-button>
  312. </el-upload>
  313. </div>
  314. </template>
  315. <template #remark>
  316. <div style="margin: 0 2vw">
  317. <div v-html="getStyle(formData.data.remark)"></div>
  318. </div>
  319. </template>
  320. </byForm>
  321. <div style="text-align: center; margin: 10px">
  322. <el-button @click="clickCancel()" size="large">取 消</el-button>
  323. <el-button type="primary" @click="submitForm('20')" size="large" v-preReClick>提 交</el-button>
  324. </div>
  325. </el-card>
  326. <el-dialog title="选择图稿文件" v-if="openDrawingFile" v-model="openDrawingFile" width="70%">
  327. <SelectPicture @selectPic="selectPic"></SelectPicture>
  328. <template #footer>
  329. <el-button @click="openDrawingFile = false" size="large">关 闭</el-button>
  330. </template>
  331. </el-dialog>
  332. <el-dialog title="选择包材配件" v-if="openPackingFittings" v-model="openPackingFittings" width="90%">
  333. <SelectBOM :selectStatus="true" :bomClassifyIdList="[2, 3]" @selectBOM="selectPackingFittings"></SelectBOM>
  334. <template #footer>
  335. <el-button @click="openPackingFittings = false" size="large">关 闭</el-button>
  336. </template>
  337. </el-dialog>
  338. <el-dialog title="产品包装配置" v-if="openShippingPackage" v-model="openShippingPackage" width="80%" :close-on-press-escape="false" :show-close="false">
  339. <div style="height: calc(100vh - 184px); overflow-y: auto; overflow-x: hidden">
  340. <el-form :model="formData.data" :rules="rulesShippingPackage" ref="shippingPackage">
  341. <div style="font-weight: 700; margin: 20px 0 10px 0">发货包装</div>
  342. <div style="margin-bottom: 10px">
  343. <el-button type="primary" size="small" @click="clickExpressPacking()">选择包材</el-button>
  344. </div>
  345. <el-table :data="formData.data.orderPackageBomList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
  346. <el-table-column label="品号" prop="code" width="160" />
  347. <el-table-column label="品名" prop="name" min-width="220" />
  348. <el-table-column label="销售单价" prop="internalSellingPrice" width="100" />
  349. <el-table-column label="数量" width="120">
  350. <template #default="{ row, $index }">
  351. <div class="shippingPackage">
  352. <el-form-item
  353. :prop="'orderPackageBomList.' + $index + '.quantity'"
  354. :rules="rulesShippingPackage.quantity"
  355. :inline-message="true"
  356. style="width: 100%">
  357. <el-input-number
  358. onmousewheel="return false;"
  359. v-model="row.quantity"
  360. placeholder="修正数量"
  361. style="width: 100%"
  362. :controls="false"
  363. :min="0"
  364. :precision="0" />
  365. </el-form-item>
  366. </div>
  367. </template>
  368. </el-table-column>
  369. <el-table-column label="销售小计" width="120">
  370. <template #default="{ row }">
  371. {{ moneyFormat(computePackagingMoney(row, "internalSellingPrice"), 2) }}
  372. </template>
  373. </el-table-column>
  374. <el-table-column label="操作" align="center" fixed="right" width="80">
  375. <template #default="{ $index }">
  376. <el-button type="danger" @click="clickPackagingDelete($index)" text>删除</el-button>
  377. </template>
  378. </el-table-column>
  379. </el-table>
  380. <div style="font-weight: 700; margin: 20px 0 10px 0">外箱不干胶图稿</div>
  381. <div style="display: flex; width: 100%">
  382. <div style="width: 80px; line-height: 32px">不干胶图片:</div>
  383. <div style="width: calc(100% - 80px)">
  384. <el-image
  385. fit="scale-down"
  386. style="width: 148px; height: 148px; margin-right: 10px; cursor: pointer"
  387. v-if="formData.data.outerBoxSelfAdhesiveStickerFile && formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
  388. :src="formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
  389. @click="openFile(formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl)" />
  390. <div style="display: flex">
  391. <el-upload
  392. :show-file-list="false"
  393. action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
  394. :data="uploadAdhesiveData"
  395. :before-upload="uploadAdhesiveFile"
  396. :on-success="
  397. (response, uploadFile) => {
  398. return handleAdhesivePackagingSuccess(uploadFile);
  399. }
  400. "
  401. style="width: 100%">
  402. <el-button type="primary" text>上传文件</el-button>
  403. </el-upload>
  404. </div>
  405. </div>
  406. </div>
  407. </el-form>
  408. </div>
  409. <template #footer>
  410. <el-button @click="openShippingPackage = false" v-preReClick>关 闭</el-button>
  411. <el-button type="primary" @click="clickSaveShippingPackage" v-preReClick>提交订单</el-button>
  412. </template>
  413. </el-dialog>
  414. <el-dialog title="选择快递包装" v-if="openExpressPacking" v-model="openExpressPacking" width="90%">
  415. <SelectBOM :selectStatus="true" :bomClassifyIdList="[2, 3]" @selectBOM="selectExpressPacking"></SelectBOM>
  416. <template #footer>
  417. <el-button @click="openExpressPacking = false">关 闭</el-button>
  418. </template>
  419. </el-dialog>
  420. </div>
  421. </template>
  422. <script setup>
  423. import byForm from "/src/components/byForm/index";
  424. import { ElMessage, ElMessageBox } from "element-plus";
  425. import { useRouter, useRoute } from "vue-router";
  426. import useTagsViewStore from "/src/store/modules/tagsView";
  427. import SelectPicture from "/src/components/select-picture/index.vue";
  428. import SelectBOM from "/src/views/group/BOM/management/index";
  429. import refreshStore from "/src/store/modules/refresh";
  430. const { proxy } = getCurrentInstance();
  431. const router = useRouter();
  432. const route = useRoute();
  433. const submit = ref(null);
  434. const departmentList = ref([]);
  435. const activeNames = ref([]);
  436. const expressDeliveryList = ref([]);
  437. const formOption = reactive({
  438. inline: true,
  439. labelWidth: "120px",
  440. itemWidth: 100,
  441. rules: [],
  442. labelPosition: "right",
  443. });
  444. const formData = reactive({
  445. data: {
  446. remark: "",
  447. type: 1,
  448. orderSkuList: [],
  449. fileList: [],
  450. orderPackageBomList: [],
  451. outerBoxSelfAdhesiveStickerFile: {},
  452. },
  453. });
  454. const formConfig = computed(() => {
  455. return [
  456. {
  457. type: "title",
  458. title: "产品",
  459. label: "",
  460. },
  461. {
  462. type: "slot",
  463. prop: "orderSkuList",
  464. slotName: "orderSkuList",
  465. },
  466. {
  467. type: "title",
  468. title: "类型",
  469. label: "",
  470. },
  471. {
  472. type: "slot",
  473. prop: "type",
  474. slotName: "type",
  475. label: "订单类型",
  476. },
  477. {
  478. type: "slot",
  479. prop: "departmentId",
  480. slotName: "departmentId",
  481. label: "事业部",
  482. itemWidth: 25,
  483. },
  484. {
  485. type: "input",
  486. prop: "wlnCode",
  487. label: "E10单号",
  488. itemType: "text",
  489. itemWidth: 25,
  490. },
  491. {
  492. type: "title",
  493. title: "贸易",
  494. label: "",
  495. },
  496. {
  497. type: "slot",
  498. slotName: "deliveryTime",
  499. label: "交货时间",
  500. itemWidth: 25,
  501. },
  502. {
  503. type: "slot",
  504. label: "选择快递",
  505. slotName: "expressDeliveryId",
  506. itemWidth: 25,
  507. },
  508. {
  509. type: "slot",
  510. label: "店铺来源",
  511. slotName: "sourcePlatform",
  512. itemWidth: 25,
  513. },
  514. {
  515. type: "slot",
  516. label: "店铺名称",
  517. slotName: "shopName",
  518. itemWidth: 25,
  519. },
  520. {
  521. type: "title",
  522. title: "总计",
  523. label: "",
  524. },
  525. {
  526. type: "slot",
  527. prop: "totalMonet",
  528. slotName: "totalMonet",
  529. },
  530. {
  531. type: "title",
  532. title: "附件",
  533. label: "",
  534. },
  535. {
  536. type: "slot",
  537. slotName: "attachments",
  538. label: "附件",
  539. },
  540. {
  541. type: "title",
  542. title: "订单备注",
  543. label: "",
  544. },
  545. {
  546. type: "slot",
  547. slotName: "remark",
  548. },
  549. ];
  550. });
  551. const rules = ref({
  552. province: [{ required: true, message: "请输入省", trigger: "blur" }],
  553. detailedAddress: [{ required: true, message: "请输入详细地址", trigger: "blur" }],
  554. consignee: [{ required: true, message: "请输入联系人", trigger: "blur" }],
  555. consigneeNumber: [{ required: true, message: "请输入联系电话", trigger: "blur" }],
  556. deliveryTime: [{ required: true, message: "请选择交货时间", trigger: "change" }],
  557. expressDeliveryId: [{ required: true, message: "请选择快递", trigger: "change" }],
  558. sourcePlatform: [{ required: true, message: "请选择店铺来源", trigger: "change" }],
  559. shopName: [{ required: true, message: "请选择店铺", trigger: "change" }],
  560. quantity: [{ required: true, message: "请输入数量", trigger: "blur" }],
  561. type: [{ required: true, message: "请选择订单类型", trigger: "change" }],
  562. departmentId: [{ required: true, message: "请选择事业部", trigger: "change" }],
  563. wlnCode: [{ required: true, message: "请输入E10单号", trigger: "blur" }],
  564. });
  565. const getDemandData = () => {
  566. proxy.post("/department/page", { pageNum: 1, pageSize: 999 }).then((res) => {
  567. if (res.rows && res.rows.length > 0) {
  568. departmentList.value = res.rows.map((item) => {
  569. return {
  570. dictKey: item.id,
  571. dictValue: item.name,
  572. };
  573. });
  574. }
  575. });
  576. proxy.post("/expressDelivery/page", { pageNum: 1, pageSize: 999 }).then((res) => {
  577. if (res.rows && res.rows.length > 0) {
  578. expressDeliveryList.value = res.rows.map((item) => {
  579. return {
  580. dictKey: item.id,
  581. dictValue: item.expressage,
  582. };
  583. });
  584. }
  585. });
  586. };
  587. getDemandData();
  588. const drawingFileIndex = ref(0);
  589. const openDrawingFile = ref(false);
  590. const clickDrawingFile = (index) => {
  591. drawingFileIndex.value = index;
  592. openDrawingFile.value = true;
  593. };
  594. const selectPic = (row) => {
  595. formData.data.orderSkuList[drawingFileIndex.value].blueprint = row.imgUrl;
  596. formData.data.orderSkuList[drawingFileIndex.value].productionDocument = row.fileUrl;
  597. formData.data.orderSkuList[drawingFileIndex.value].artworkLibraryId = row.id;
  598. ElMessage({ message: "选择完成", type: "success" });
  599. openDrawingFile.value = false;
  600. };
  601. const openFile = (path) => {
  602. window.open(path);
  603. };
  604. const openShippingPackage = ref(false);
  605. const submitForm = (status) => {
  606. submit.value.handleSubmit(() => {
  607. if (formData.data.orderSkuList && formData.data.orderSkuList.length > 0) {
  608. for (let i = 0; i < formData.data.orderSkuList.length; i++) {
  609. if (!formData.data.orderSkuList[i].blueprint) {
  610. return ElMessage("请选择设计图");
  611. }
  612. if (!formData.data.orderSkuList[i].productionDocument) {
  613. return ElMessage("请选择生产文件");
  614. }
  615. let packagingMaterialCost = 0;
  616. if (formData.data.orderSkuList[i].quantity) {
  617. if (formData.data.orderSkuList[i].orderSkuBomList && formData.data.orderSkuList[i].orderSkuBomList.length > 0) {
  618. for (let j = 0; j < formData.data.orderSkuList[i].orderSkuBomList.length; j++) {
  619. if (formData.data.orderSkuList[i].orderSkuBomList[j].quantity && formData.data.orderSkuList[i].orderSkuBomList[j].unitPrice) {
  620. packagingMaterialCost = Number(
  621. Math.round(
  622. (packagingMaterialCost +
  623. formData.data.orderSkuList[i].orderSkuBomList[j].quantity * formData.data.orderSkuList[i].orderSkuBomList[j].unitPrice) *
  624. 100
  625. ) / 100
  626. );
  627. }
  628. }
  629. }
  630. }
  631. formData.data.orderSkuList[i].packagingMaterialCost = packagingMaterialCost;
  632. }
  633. formData.data.productTotalAmount = calculatedAmount("unitPrice");
  634. formData.data.customProcessingFee = calculatedAmount("customProcessingFee");
  635. formData.data.lssueFee = calculatedAmount("lssueFee");
  636. formData.data.deliveryMaterialsFee = computeDeliveryMaterialsFee();
  637. formData.data.packingLabor = calculatedAmount("packingLabor");
  638. formData.data.managementFee = calculatedAmount("managementFee");
  639. formData.data.packagingMaterialCost = calculatedPackagingMaterialCost();
  640. formData.data.totalAmount = calculatedTotalAmount();
  641. formData.data.proofingFee = getProofingFee();
  642. if (fileList.value && fileList.value.length > 0) {
  643. formData.data.fileList = fileList.value.map((item) => {
  644. return {
  645. id: item.raw.id,
  646. fileName: item.raw.fileName,
  647. fileUrl: item.raw.fileUrl,
  648. };
  649. });
  650. } else {
  651. formData.data.fileList = [];
  652. }
  653. formData.data.status = status;
  654. openShippingPackage.value = true;
  655. } else {
  656. return ElMessage("请添加产品");
  657. }
  658. });
  659. };
  660. const clickCancel = () => {
  661. const useTagsStore = useTagsViewStore();
  662. useTagsStore.delVisitedView(router.currentRoute.value);
  663. router.replace({
  664. path: "/subsidiary/order/subsidiary-order-management",
  665. });
  666. };
  667. onMounted(() => {
  668. if (route.query && (route.query.id || route.query.detailId)) {
  669. getOrderDetail({ id: route.query.id || route.query.detailId });
  670. }
  671. });
  672. const getOrderDetail = (parameter) => {
  673. proxy.post("/orderInfo/detail", parameter).then((res) => {
  674. formData.data = res;
  675. if (!formData.data.type) {
  676. formData.data.type = 1;
  677. }
  678. if (route.query.detailId) {
  679. let allIndex = [];
  680. for (let i = 0; i < formData.data.orderSkuList.length; i++) {
  681. allIndex.push(i);
  682. }
  683. activeNames.value = allIndex;
  684. formOption.disabled = true;
  685. }
  686. let list = [formData.data.id];
  687. if (formData.data.orderSkuList && formData.data.orderSkuList.length > 0) {
  688. for (let i = 0; i < formData.data.orderSkuList.length; i++) {
  689. proxy.post("/skuSpec/getSkuInventoryQuantity", { id: formData.data.orderSkuList[i].skuSpecId }).then((resQuantity) => {
  690. formData.data.orderSkuList[i].inventoryQuantity = resQuantity;
  691. });
  692. }
  693. list = list.concat(formData.data.orderSkuList.map((item) => item.id));
  694. proxy.post("/fileInfo/getList", { businessIdList: list }).then((fileObj) => {
  695. if (fileObj[formData.data.id] && fileObj[formData.data.id].length > 0) {
  696. let file = fileObj[formData.data.id].filter((item) => item.businessType == "0");
  697. if (file && file.length > 0) {
  698. fileList.value = file.map((item) => {
  699. return {
  700. raw: item,
  701. name: item.fileName,
  702. url: item.fileUrl,
  703. };
  704. });
  705. } else {
  706. fileList.value = [];
  707. }
  708. let outerBoxSelfAdhesiveStickerFile = fileObj[formData.data.id].filter((item) => item.businessType == "1");
  709. if (outerBoxSelfAdhesiveStickerFile && outerBoxSelfAdhesiveStickerFile.length > 0) {
  710. formData.data.outerBoxSelfAdhesiveStickerFile = outerBoxSelfAdhesiveStickerFile[0];
  711. } else {
  712. formData.data.outerBoxSelfAdhesiveStickerFile = {};
  713. }
  714. }
  715. for (let i = 0; i < formData.data.orderSkuList.length; i++) {
  716. if (fileObj[formData.data.orderSkuList[i].id] && fileObj[formData.data.orderSkuList[i].id].length > 0) {
  717. formData.data.orderSkuList[i].selfAdhesiveStickerFile = {
  718. id: fileObj[formData.data.orderSkuList[i].id][0].id,
  719. fileName: fileObj[formData.data.orderSkuList[i].id][0].fileName,
  720. fileUrl: fileObj[formData.data.orderSkuList[i].id][0].fileUrl,
  721. };
  722. }
  723. }
  724. });
  725. }
  726. });
  727. };
  728. const getStyle = (text) => {
  729. if (text) {
  730. return text.replace(/\n|\r\n/g, "<br>");
  731. } else {
  732. return "";
  733. }
  734. };
  735. const printType = ref([
  736. {
  737. dictKey: 1,
  738. dictValue: "单面",
  739. },
  740. {
  741. dictKey: 2,
  742. dictValue: "双面",
  743. },
  744. ]);
  745. const typeList = ref([
  746. {
  747. dictKey: 1,
  748. dictValue: "自主订单",
  749. },
  750. {
  751. dictKey: 2,
  752. dictValue: "委外订单",
  753. },
  754. ]);
  755. const uploadData = ref({});
  756. const uploadFile = async (file) => {
  757. const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
  758. uploadData.value = res.uploadBody;
  759. file.id = res.id;
  760. file.fileName = res.fileName;
  761. file.fileUrl = res.fileUrl;
  762. return true;
  763. };
  764. const handleSuccess = (UploadFile, index) => {
  765. formData.data.orderSkuList[index].productionDocument = UploadFile.raw.fileUrl;
  766. formData.data.orderSkuList[index].artworkLibraryId = "0";
  767. };
  768. const uploadImgData = ref({});
  769. const uploadImgFile = async (file) => {
  770. const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
  771. uploadImgData.value = res.uploadBody;
  772. file.id = res.id;
  773. file.fileName = res.fileName;
  774. file.fileUrl = res.fileUrl;
  775. return true;
  776. };
  777. const handleImgSuccess = (UploadFile, index) => {
  778. formData.data.orderSkuList[index].blueprint = UploadFile.raw.fileUrl;
  779. formData.data.orderSkuList[index].artworkLibraryId = "0";
  780. };
  781. const computeQuantity = (index, indexSKU) => {
  782. let quantity = 0;
  783. if (formData.data.orderSkuList[index].quantity && formData.data.orderSkuList[index].orderSkuBomList[indexSKU].quantity) {
  784. quantity = Number(
  785. Math.round(formData.data.orderSkuList[index].orderSkuBomList[indexSKU].quantity * formData.data.orderSkuList[index].quantity * 100) / 100
  786. );
  787. }
  788. return quantity;
  789. };
  790. const computeMoney = (index, indexSKU) => {
  791. let money = 0;
  792. if (
  793. formData.data.orderSkuList[index].quantity &&
  794. formData.data.orderSkuList[index].orderSkuBomList[indexSKU].quantity &&
  795. formData.data.orderSkuList[index].orderSkuBomList[indexSKU].unitPrice
  796. ) {
  797. money = Number(
  798. Math.round(
  799. formData.data.orderSkuList[index].orderSkuBomList[indexSKU].quantity *
  800. formData.data.orderSkuList[index].orderSkuBomList[indexSKU].unitPrice *
  801. formData.data.orderSkuList[index].quantity *
  802. 100
  803. ) / 100
  804. );
  805. }
  806. return money;
  807. };
  808. const clickDeletePackingFittings = (index, indexTwo, row) => {
  809. if (["1682221201491058690", "1682221249268375554"].includes(row.bomClassifyId)) {
  810. ElMessage("彩纸类和OPP膜类不可删除");
  811. } else {
  812. formData.data.orderSkuList[index].orderSkuBomList.splice(indexTwo, 1);
  813. }
  814. };
  815. const rowIndex = ref(null);
  816. const openPackingFittings = ref(false);
  817. const clickPackingFittings = (index) => {
  818. rowIndex.value = index;
  819. openPackingFittings.value = true;
  820. };
  821. const selectPackingFittings = (data) => {
  822. if (formData.data.orderSkuList[rowIndex.value].orderSkuBomList && formData.data.orderSkuList[rowIndex.value].orderSkuBomList.length > 0) {
  823. let list = formData.data.orderSkuList[rowIndex.value].orderSkuBomList.filter((item) => item.bomSpecId === data.id);
  824. if (list && list.length > 0) {
  825. return ElMessage("包材配件已添加");
  826. }
  827. formData.data.orderSkuList[rowIndex.value].orderSkuBomList.push({
  828. bomSpecId: data.id,
  829. unitPrice: data.internalSellingPrice,
  830. quantity: undefined,
  831. bomSpecName: data.name,
  832. });
  833. } else {
  834. formData.data.orderSkuList[rowIndex.value].orderSkuBomList = [
  835. {
  836. bomSpecId: data.id,
  837. unitPrice: data.internalSellingPrice,
  838. quantity: undefined,
  839. bomSpecName: data.name,
  840. },
  841. ];
  842. }
  843. ElMessage({ message: "添加成功", type: "success" });
  844. };
  845. const getSubtotal = (item) => {
  846. let money = 0;
  847. if (item.quantity) {
  848. money = Number(
  849. Math.round(
  850. (item.customProcessingFee + item.deliveryMaterialsFee + item.lssueFee + item.packingLabor + item.managementFee + item.unitPrice) * item.quantity * 100
  851. ) / 100
  852. );
  853. }
  854. return money;
  855. };
  856. const calculatedAmount = (label) => {
  857. let money = 0;
  858. if (formData.data.orderSkuList && formData.data.orderSkuList.length > 0) {
  859. for (let i = 0; i < formData.data.orderSkuList.length; i++) {
  860. if (formData.data.orderSkuList[i].quantity && formData.data.orderSkuList[i][label]) {
  861. money = Number(Math.round((money + formData.data.orderSkuList[i][label] * formData.data.orderSkuList[i].quantity) * 100) / 100);
  862. }
  863. }
  864. }
  865. return money;
  866. };
  867. const getProofingFee = () => {
  868. let money = 0;
  869. if (formData.data.orderSkuList && formData.data.orderSkuList.length > 0) {
  870. for (let i = 0; i < formData.data.orderSkuList.length; i++) {
  871. if (formData.data.orderSkuList[i].proofingFee) {
  872. money = Number(Math.round((money + formData.data.orderSkuList[i].proofingFee) * 100) / 100);
  873. }
  874. }
  875. }
  876. return money;
  877. };
  878. const calculatedPackagingMaterialCost = () => {
  879. let money = 0;
  880. if (formData.data.orderSkuList && formData.data.orderSkuList.length > 0) {
  881. for (let i = 0; i < formData.data.orderSkuList.length; i++) {
  882. if (formData.data.orderSkuList[i].orderSkuBomList && formData.data.orderSkuList[i].orderSkuBomList.length > 0) {
  883. for (let j = 0; j < formData.data.orderSkuList[i].orderSkuBomList.length; j++) {
  884. if (formData.data.orderSkuList[i].orderSkuBomList[j].quantity && formData.data.orderSkuList[i].orderSkuBomList[j].unitPrice) {
  885. money = Number(
  886. Math.round(
  887. (money +
  888. formData.data.orderSkuList[i].orderSkuBomList[j].quantity *
  889. formData.data.orderSkuList[i].orderSkuBomList[j].unitPrice *
  890. formData.data.orderSkuList[i].quantity) *
  891. 100
  892. ) / 100
  893. );
  894. }
  895. }
  896. }
  897. }
  898. }
  899. return money;
  900. };
  901. const calculatedTotalAmount = () => {
  902. let money = 0;
  903. money = Number(
  904. Math.round(
  905. (calculatedAmount("unitPrice") +
  906. calculatedAmount("customProcessingFee") +
  907. calculatedAmount("lssueFee") +
  908. computeDeliveryMaterialsFee() +
  909. calculatedAmount("packingLabor") +
  910. calculatedAmount("managementFee") +
  911. getProofingFee() +
  912. calculatedPackagingMaterialCost()) *
  913. 100
  914. ) / 100
  915. );
  916. return money;
  917. };
  918. const fileList = ref([]);
  919. const uploadFileData = ref({});
  920. const beforeUpload = async (file) => {
  921. const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
  922. uploadFileData.value = res.uploadBody;
  923. file.id = res.id;
  924. file.fileName = res.fileName;
  925. file.fileUrl = res.fileUrl;
  926. file.uploadState = true;
  927. return true;
  928. };
  929. const onSuccessFile = (any, UploadFile) => {
  930. UploadFile.raw.uploadState = false;
  931. };
  932. const onPreviewFile = (file) => {
  933. window.open(file.raw.fileUrl, "_blank");
  934. };
  935. const uploadAdhesiveData = ref({});
  936. const uploadAdhesiveFile = async (file) => {
  937. const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
  938. uploadAdhesiveData.value = res.uploadBody;
  939. file.id = res.id;
  940. file.fileName = res.fileName;
  941. file.fileUrl = res.fileUrl;
  942. return true;
  943. };
  944. const handleAdhesiveSuccess = (UploadFile, index) => {
  945. formData.data.orderSkuList[index].selfAdhesiveStickerFile = {
  946. id: UploadFile.raw.id,
  947. fileName: UploadFile.raw.fileName,
  948. fileUrl: UploadFile.raw.fileUrl,
  949. };
  950. };
  951. const rulesShippingPackage = ref({
  952. quantity: [{ required: true, message: "请输入数量", trigger: "blur" }],
  953. });
  954. const computePackagingMoney = (item, label) => {
  955. let money = 0;
  956. if (item.quantity && item[label]) {
  957. money = Number(Math.round(item.quantity * item[label] * 100) / 100);
  958. }
  959. return money;
  960. };
  961. const clickPackagingDelete = (index) => {
  962. formData.data.orderPackageBomList.splice(index, 1);
  963. };
  964. const handleAdhesivePackagingSuccess = (UploadFile) => {
  965. formData.data.outerBoxSelfAdhesiveStickerFile = {
  966. id: UploadFile.raw.id,
  967. fileName: UploadFile.raw.fileName,
  968. fileUrl: UploadFile.raw.fileUrl,
  969. };
  970. };
  971. const clickSaveShippingPackage = () => {
  972. proxy.$refs.shippingPackage.validate((valid) => {
  973. if (valid) {
  974. if (formData.data.orderPackageBomList && formData.data.orderPackageBomList.length > 0) {
  975. formData.data.deliveryMaterialsFee = computeDeliveryMaterialsFee();
  976. formData.data.totalAmount = calculatedTotalAmount();
  977. formData.data.proofingFee = getProofingFee();
  978. proxy.post("/orderInfo/confirmation", formData.data).then(() => {
  979. ElMessage({ message: "提交成功", type: "success" });
  980. refreshStore().setRefresh("order");
  981. clickCancel();
  982. });
  983. } else {
  984. ElMessageBox.confirm("是否确认无产品发货包装", "提示", {
  985. confirmButtonText: "确定",
  986. cancelButtonText: "取消",
  987. type: "warning",
  988. })
  989. .then(() => {
  990. formData.data.deliveryMaterialsFee = computeDeliveryMaterialsFee();
  991. formData.data.totalAmount = calculatedTotalAmount();
  992. formData.data.proofingFee = getProofingFee();
  993. proxy.post("/orderInfo/confirmation", formData.data).then(() => {
  994. ElMessage({ message: "提交成功", type: "success" });
  995. refreshStore().setRefresh("order");
  996. clickCancel();
  997. });
  998. })
  999. .catch(() => {});
  1000. }
  1001. }
  1002. });
  1003. };
  1004. const openExpressPacking = ref(false);
  1005. const clickExpressPacking = () => {
  1006. openExpressPacking.value = true;
  1007. };
  1008. const selectExpressPacking = (data) => {
  1009. if (formData.data.orderPackageBomList && formData.data.orderPackageBomList.length > 0) {
  1010. let list = formData.data.orderPackageBomList.filter((item) => item.bomSpecId === data.id);
  1011. if (list && list.length > 0) {
  1012. return ElMessage("快递物流包材已添加");
  1013. }
  1014. formData.data.orderPackageBomList.push({
  1015. bomSpecId: data.id,
  1016. code: data.code,
  1017. name: data.name,
  1018. internalSellingPrice: data.internalSellingPrice,
  1019. quantity: undefined,
  1020. });
  1021. } else {
  1022. formData.data.orderPackageBomList = [
  1023. {
  1024. bomSpecId: data.id,
  1025. code: data.code,
  1026. name: data.name,
  1027. internalSellingPrice: data.internalSellingPrice,
  1028. quantity: undefined,
  1029. },
  1030. ];
  1031. }
  1032. ElMessage({ message: "添加成功", type: "success" });
  1033. };
  1034. const computeDeliveryMaterialsFee = () => {
  1035. let money = 0;
  1036. if (formData.data.orderPackageBomList && formData.data.orderPackageBomList.length > 0) {
  1037. for (let i = 0; i < formData.data.orderPackageBomList.length; i++) {
  1038. if (formData.data.orderPackageBomList[i].internalSellingPrice && formData.data.orderPackageBomList[i].quantity) {
  1039. money = Number(
  1040. Math.round((money + formData.data.orderPackageBomList[i].internalSellingPrice * formData.data.orderPackageBomList[i].quantity) * 100) / 100
  1041. );
  1042. }
  1043. }
  1044. }
  1045. return money;
  1046. };
  1047. const computeSingleDeliveryMaterialsFee = (index) => {
  1048. let money = computeDeliveryMaterialsFee();
  1049. let list = formData.data.orderSkuList.filter((item) => item.quantity > 0);
  1050. let num = 0;
  1051. let singlePrice = 0;
  1052. if (list && list.length > 0) {
  1053. for (let i = 0; i < list.length; i++) {
  1054. num = Number(Math.round(num + list[i].quantity));
  1055. }
  1056. singlePrice = Number(Math.ceil((money / num) * 1000) / 1000);
  1057. }
  1058. formData.data.orderSkuList[index].deliveryMaterialsFee = singlePrice;
  1059. return formData.data.orderSkuList[index].deliveryMaterialsFee;
  1060. };
  1061. </script>
  1062. <style lang="scss" scoped>
  1063. ::v-deep(.el-input-number .el-input__inner) {
  1064. text-align: left;
  1065. }
  1066. :deep(.el-dialog) {
  1067. margin-top: 10px !important;
  1068. margin-bottom: 10px !important;
  1069. }
  1070. :deep(.ql-editor) {
  1071. height: auto;
  1072. }
  1073. :deep(.el-collapse-item__header) {
  1074. justify-content: center;
  1075. }
  1076. :deep(.el-collapse-item__arrow) {
  1077. margin: 0;
  1078. }
  1079. :deep(.el-table__cell) {
  1080. vertical-align: top;
  1081. }
  1082. .shippingPackage {
  1083. .el-form-item {
  1084. margin-bottom: 0;
  1085. }
  1086. }
  1087. </style>