design.vue 43 KB

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