detail.vue 45 KB

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