index.vue 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061
  1. <template>
  2. <div class="app-container">
  3. <el-tabs v-model="queryParams.orderStatus" @tab-click="onOrderStatusChange">
  4. <el-tab-pane v-for="item in status" :key="item.name" :label="item.label" :name="item.name"/>
  5. </el-tabs>
  6. <el-form ref="queryForm" :model="queryParams" size="small" :inline="true" label-width="68px">
  7. <el-form-item prop="storageId">
  8. <el-select v-model="queryParams.storageId" placeholder="请选择前置仓" clearable>
  9. <el-option v-for="item in storages" :key="item.id" :label="item.name" :value="item.id"/>
  10. </el-select>
  11. </el-form-item>
  12. <el-form-item prop="orderId">
  13. <el-input v-model="queryParams.orderId" clearable placeholder="输入订单号" @keyup.enter.native="toQuery"/>
  14. </el-form-item>
  15. <el-form-item prop="createTime">
  16. <el-date-picker
  17. v-model="queryParams.createTime"
  18. type="datetimerange"
  19. value-format="yyyy-MM-dd HH:mm:ss"
  20. start-placeholder="创建开始时间"
  21. end-placeholder="创建结束时间"
  22. range-separator="至"
  23. unlink-panels
  24. />
  25. </el-form-item>
  26. <el-form-item>
  27. <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  28. </el-form-item>
  29. </el-form>
  30. <el-table v-loading="loading" :data="storeOrderList">
  31. <!-- <el-table-column type="selection" width="55" align="center" /> -->
  32. <el-table-column type="index" label="序号" align="center">
  33. <template slot-scope="{$index}">
  34. {{ (queryParams.pageNum - 1) * queryParams.pageSize + $index + 1 }}
  35. </template>
  36. </el-table-column>
  37. <el-table-column
  38. width="200"
  39. prop="orderId"
  40. align="center"
  41. label="订单号">
  42. <template slot-scope="scope">
  43. <el-tooltip content="点击复制订单号" placement="top">
  44. <span ref="orderId" @click="copyOrderId(scope.row.orderId)">
  45. {{ scope.row.orderId }}
  46. <span v-if="isToday(scope.row.createTime)" style="color: red">今</span>
  47. </span>+
  48. </el-tooltip>
  49. </template>
  50. </el-table-column>
  51. <el-table-column
  52. width="200"
  53. prop="storageId"
  54. align="center"
  55. label="仓库"
  56. >
  57. <template slot-scope="scope">
  58. {{ storageMap[scope.row.storeId] }}
  59. </template>
  60. </el-table-column>
  61. <el-table-column
  62. v-if="queryParams.orderStatus==='32'"
  63. prop="exceptionReason"
  64. align="center"
  65. label="异常原因"
  66. />
  67. <el-table-column
  68. v-if="queryParams.orderStatus==='80'"
  69. prop="exceptionReason"
  70. align="center"
  71. label="付款状态"
  72. />
  73. <el-table-column
  74. v-if="queryParams.orderStatus!=='14'&&queryParams.orderStatus!=='16'&&queryParams.orderStatus!=='10'"
  75. align="center"
  76. label="配送员"
  77. >
  78. <template slot-scope="{row}">
  79. <el-tag :type="row.riderName ? 'error' : 'success'">
  80. {{ row.riderName ? row.riderName : (row.deliveryType ? row.deliveryType : '商家自配') }}
  81. </el-tag>
  82. </template>
  83. </el-table-column>
  84. <el-table-column
  85. align="left"
  86. width="100"
  87. prop="realName"
  88. label="姓名"
  89. />
  90. <el-table-column
  91. align="left"
  92. width="110"
  93. prop="userPhone"
  94. label="电话"
  95. />
  96. <el-table-column
  97. :show-overflow-tooltip="true"
  98. align="left"
  99. width="80"
  100. prop="address"
  101. label="订单类型"
  102. >
  103. <template slot-scope="{row}">
  104. <el-tag :type="row.shippingType==1 ? 'error' : 'success'">{{
  105. row.shippingType == 1 ? '配送' : '自提'
  106. }}
  107. </el-tag>
  108. </template>
  109. </el-table-column>
  110. <el-table-column
  111. :show-overflow-tooltip="true"
  112. align="left"
  113. width="200"
  114. prop="userAddress"
  115. label="地址"
  116. />
  117. <el-table-column
  118. align="center"
  119. label="配送费"
  120. >
  121. <template slot-scope="scope">
  122. <span>{{ scope.row.freightPrice == 0 ? '免配送' : scope.row.freightPrice }}</span>
  123. </template>
  124. </el-table-column>
  125. <el-table-column
  126. align="center"
  127. label="订单金额"
  128. >
  129. <template slot-scope="scope">
  130. <span>{{ scope.row.originalTotalPrice }}</span>
  131. </template>
  132. </el-table-column>
  133. <el-table-column
  134. width="90"
  135. align="center"
  136. label="实付金额"
  137. >
  138. <template slot-scope="scope">
  139. <span>{{ scope.row.payIntegral ? '积分' + scope.row.payIntegral : '¥' + scope.row.payPrice }}</span>
  140. </template>
  141. </el-table-column>
  142. <el-table-column
  143. width="200"
  144. align="center"
  145. label="要求送达时间"
  146. >
  147. <template slot-scope="scope">
  148. <span>{{ scope.row.predictTime }}</span>
  149. </template>
  150. </el-table-column>
  151. <el-table-column
  152. prop="phone"
  153. width="160"
  154. align="center"
  155. label="下单时间"
  156. >
  157. <template slot-scope="scope">
  158. <span>{{ scope.row.createTime }}</span>
  159. </template>
  160. </el-table-column>
  161. <el-table-column
  162. align="center"
  163. width="160"
  164. label="支付时间"
  165. prop="payTime"
  166. >
  167. <template slot-scope="scope">
  168. <span>{{ scope.row.payTime }}</span>
  169. </template>
  170. </el-table-column>
  171. <el-table-column
  172. width="280"
  173. align="center"
  174. label="付款交易号"
  175. >
  176. <template slot-scope="scope">
  177. <span>{{ scope.row.payId }}</span>
  178. </template>
  179. </el-table-column>
  180. <el-table-column
  181. align="center"
  182. width="160"
  183. label="创建时间"
  184. >
  185. <template slot-scope="scope">
  186. <span>{{ scope.row.createTime }}</span>
  187. </template>
  188. </el-table-column>
  189. <el-table-column
  190. align="center"
  191. width="160"
  192. label="修改时间"
  193. >
  194. <template slot-scope="scope">
  195. <span>{{ scope.row.updateTime }}</span>
  196. </template>
  197. </el-table-column>
  198. <el-table-column
  199. fixed="right"
  200. align="center"
  201. label="操作"
  202. width="400"
  203. >
  204. <template slot-scope="{row}">
  205. <el-button
  206. type="primary"
  207. size="mini"
  208. @click="viewDetail(row.id)"
  209. >详情
  210. </el-button>
  211. <el-button
  212. v-if="row.status===14"
  213. type="primary"
  214. size="mini"
  215. @click="handleOperation(row.id,'startStocking')"
  216. >开始配货
  217. </el-button>
  218. <el-button
  219. v-if="row.status===16"
  220. type="primary"
  221. size="mini"
  222. @click="handleOperation(row.id,'completeAllocation')"
  223. >完成配货
  224. </el-button>
  225. <el-button
  226. v-if="row.status===30"
  227. type="primary"
  228. size="mini"
  229. @click="handleOperation(row.id,'completeDelivery')"
  230. >完成配送
  231. </el-button>
  232. <el-button
  233. v-if="(row.status===20||row.status===32||row.status===30) && row.shippingType===2"
  234. type="success"
  235. size="mini"
  236. @click="showVerifyDialog(row.id)"
  237. >完成取货
  238. </el-button>
  239. <!-- 合并后的配送下拉按钮 -->
  240. <el-dropdown
  241. v-if="(row.status===20||row.status===32||row.status===30) && row.shippingType===1"
  242. @command="handleDeliveryCommand(row, $event)"
  243. >
  244. <el-button type="primary" size="mini">
  245. 配送方式<i class="el-icon-arrow-down el-icon--right"></i>
  246. </el-button>
  247. <el-dropdown-menu slot="dropdown">
  248. <el-dropdown-item command="system">系统配送</el-dropdown-item>
  249. <el-dropdown-item command="thirdParty">第三方配送</el-dropdown-item>
  250. <el-dropdown-item command="merchant">商家自配</el-dropdown-item>
  251. </el-dropdown-menu>
  252. </el-dropdown>
  253. <el-button
  254. v-if="[16,20,30,32,34].includes(row.status)"
  255. type="danger"
  256. size="mini"
  257. style="margin-left: 10px;"
  258. @click="handleCancelOrder(row)"
  259. >取消订单
  260. </el-button>
  261. </template>
  262. </el-table-column>
  263. </el-table>
  264. <pagination
  265. v-show="total > 0"
  266. :total="total"
  267. :page.sync="queryParams.pageNum"
  268. :limit.sync="queryParams.pageSize"
  269. @pagination="getList"
  270. />
  271. <!-- 添加或修改订单对话框 -->
  272. <el-dialog title="订单详情" :visible.sync="open" width="1050px" append-to-body class="order-detail-dialog">
  273. <div class="detail-container">
  274. <!-- 基本信息部分 -->
  275. <div class="detail-section">
  276. <h3 class="section-title">基本信息</h3>
  277. <el-row :gutter="20">
  278. <el-col :span="8">
  279. <div class="detail-item">
  280. <span class="item-label">订单编号:</span>
  281. <span class="item-value">{{ form.orderId }}</span>
  282. </div>
  283. </el-col>
  284. <el-col :span="8">
  285. <div class="detail-item">
  286. <span class="item-label">订单状态:</span>
  287. <el-tag :type="getStatusTagType(form.status)">{{ getStatus(form.status) }}</el-tag>
  288. </div>
  289. </el-col>
  290. <el-col :span="8">
  291. <div class="detail-item">
  292. <span class="item-label">订单类型:</span>
  293. <el-tag :type="form.shippingType==1 ? 'primary' : 'success'">
  294. {{ form.shippingType == 1 ? '配送' : '自提' }}
  295. </el-tag>
  296. </div>
  297. </el-col>
  298. </el-row>
  299. <el-row :gutter="20">
  300. <el-col :span="8">
  301. <div class="detail-item">
  302. <span class="item-label">下单时间:</span>
  303. <span class="item-value">{{ form.createTime }}</span>
  304. </div>
  305. </el-col>
  306. <el-col :span="8">
  307. <div class="detail-item">
  308. <span class="item-label">送达时间:</span>
  309. <span class="item-value">{{ form.predictTime }}</span>
  310. </div>
  311. </el-col>
  312. <el-col :span="8">
  313. <div class="detail-item">
  314. <span class="item-label">订单类别:</span>
  315. <el-tag type="info">{{ getOrderType(form) }}</el-tag>
  316. </div>
  317. </el-col>
  318. </el-row>
  319. <div class="detail-item">
  320. <span class="item-label">备注:</span>
  321. <span class="item-value" :class="{'empty-remark': !form.remark}">
  322. {{ form.remark || '无备注' }}
  323. </span>
  324. </div>
  325. </div>
  326. <!-- 客户信息部分 -->
  327. <div class="detail-section">
  328. <h3 class="section-title">客户信息</h3>
  329. <el-row :gutter="20">
  330. <el-col :span="8">
  331. <div class="detail-item">
  332. <span class="item-label">客户姓名:</span>
  333. <span class="item-value">{{ form.realName }}</span>
  334. </div>
  335. </el-col>
  336. <el-col :span="8">
  337. <div class="detail-item">
  338. <span class="item-label">客户电话:</span>
  339. <span class="item-value">{{ form.userPhone }}</span>
  340. </div>
  341. </el-col>
  342. <el-col :span="8">
  343. <div class="detail-item">
  344. <span class="item-label">客户地址:</span>
  345. <span class="item-value">{{ form.userAddress }}</span>
  346. </div>
  347. </el-col>
  348. </el-row>
  349. </div>
  350. <!-- 骑手信息部分 -->
  351. <div v-if="form.riderOrder" class="detail-section">
  352. <h3 class="section-title">骑手信息</h3>
  353. <el-row :gutter="20">
  354. <el-col :span="8">
  355. <div class="detail-item">
  356. <span class="item-label">骑手姓名:</span>
  357. <span class="item-value">{{ form.riderName || '无' }}</span>
  358. </div>
  359. </el-col>
  360. <el-col :span="8">
  361. <div class="detail-item">
  362. <span class="item-label">配送状态:</span>
  363. <el-tag :type="getRiderStatusTagType(form.riderOrder.status)">
  364. {{ getRiderStatus(form.riderOrder.status) }}
  365. </el-tag>
  366. </div>
  367. </el-col>
  368. <el-col :span="8">
  369. <div class="detail-item">
  370. <span class="item-label">异常状态:</span>
  371. <el-tag v-if="form.riderOrder.abnormal" type="danger">
  372. 异常
  373. </el-tag>
  374. <span v-else class="item-value">正常</span>
  375. </div>
  376. </el-col>
  377. </el-row>
  378. <div v-if="form.riderOrder.reason" class="detail-item">
  379. <span class="item-label">异常原因:</span>
  380. <span class="item-value" style="color: #f56c6c">{{ form.riderOrder.reason }}</span>
  381. </div>
  382. <div class="detail-item">
  383. <span class="item-label">配送时间:</span>
  384. <span class="item-value">{{ form.riderOrder.finishTime ? form.riderOrder.finishTime : '未完成' }}</span>
  385. </div>
  386. </div>
  387. <!-- 支付信息部分 -->
  388. <div class="detail-section">
  389. <h3 class="section-title">支付信息</h3>
  390. <el-row :gutter="20">
  391. <el-col :span="8">
  392. <div class="detail-item">
  393. <span class="item-label">支付方式:</span>
  394. <span class="item-value">{{ form.payTypeName }}</span>
  395. </div>
  396. </el-col>
  397. <el-col :span="8">
  398. <div class="detail-item">
  399. <span class="item-label">支付金额:</span>
  400. <span class="item-value highlight">
  401. {{ form.payIntegral ? '积分' + form.payIntegral : '¥' + form.payPrice }}
  402. </span>
  403. </div>
  404. </el-col>
  405. <el-col :span="8">
  406. <div class="detail-item">
  407. <span class="item-label">支付时间:</span>
  408. <span class="item-value">{{ form.payTime || '未支付' }}</span>
  409. </div>
  410. </el-col>
  411. </el-row>
  412. <div class="detail-item">
  413. <span class="item-label">交易号:</span>
  414. <span class="item-value">{{ form.payId || '无' }}</span>
  415. </div>
  416. <div v-if="form.status === 70" class="detail-item refund-reason">
  417. <span class="item-label">退款原因:</span>
  418. <span class="item-value">{{ form.refundReason }}</span>
  419. </div>
  420. </div>
  421. <!-- 商品信息部分 -->
  422. <div class="detail-section">
  423. <h3 class="section-title">商品信息</h3>
  424. <el-table
  425. :data="form.productList"
  426. size="small"
  427. border
  428. fit
  429. highlight-current-row
  430. style="width: 100%"
  431. >
  432. <el-table-column
  433. align="center"
  434. label="序号"
  435. type="index"
  436. width="50"
  437. />
  438. <el-table-column
  439. align="center"
  440. label="商品条码"
  441. prop="barCode"
  442. width="120"
  443. />
  444. <el-table-column
  445. align="center"
  446. label="商品编码"
  447. prop="productId"
  448. width="120"
  449. />
  450. <el-table-column
  451. align="center"
  452. label="商品名称"
  453. prop="productTitle"
  454. min-width="150"
  455. />
  456. <el-table-column
  457. align="center"
  458. label="数量"
  459. prop="num"
  460. width="80"
  461. />
  462. <el-table-column
  463. align="center"
  464. label="单位"
  465. prop="unitName"
  466. width="80"
  467. />
  468. <el-table-column
  469. align="center"
  470. label="原价"
  471. width="100"
  472. >
  473. <template slot-scope="{row}">
  474. <span>¥{{ row.otPrice }}</span>
  475. </template>
  476. </el-table-column>
  477. <el-table-column
  478. align="center"
  479. label="售价"
  480. width="100"
  481. >
  482. <template slot-scope="{row}">
  483. <span>¥{{ row.price }}</span>
  484. </template>
  485. </el-table-column>
  486. <el-table-column
  487. align="center"
  488. label="总价"
  489. width="120"
  490. >
  491. <template slot-scope="{row}">
  492. <span class="highlight">¥{{ Number(row.price * row.num).toFixed(2) }}</span>
  493. </template>
  494. </el-table-column>
  495. </el-table>
  496. </div>
  497. <!-- 金额汇总部分 -->
  498. <div class="detail-section amount-summary">
  499. <h3 class="section-title">金额汇总</h3>
  500. <div class="summary-row">
  501. <span class="summary-label">商品金额:</span>
  502. <span class="summary-value">¥{{ form.originalTotalPrice }}</span>
  503. </div>
  504. <div class="summary-row">
  505. <span class="summary-label">运费:</span>
  506. <span class="summary-value">{{ form.freightPrice == 0 ? '免运费' : '¥' + form.freightPrice }}</span>
  507. </div>
  508. <div class="summary-row">
  509. <span class="summary-label">优惠:</span>
  510. <span class="summary-value highlight">
  511. ¥{{ Number(form.originalTotalPrice) - Number(form.payPrice) + Number(form.freightPrice) }}
  512. </span>
  513. </div>
  514. <div class="summary-row total-row">
  515. <span class="summary-label">实付金额:</span>
  516. <span class="summary-value highlight">
  517. {{ form.payIntegral ? '积分' + form.payIntegral : '¥' + form.payPrice }}
  518. </span>
  519. </div>
  520. </div>
  521. </div>
  522. </el-dialog>
  523. <el-dialog
  524. :visible.sync="allotShow"
  525. title="选择配送员"
  526. width="30%"
  527. >
  528. <el-table
  529. :data="courierList"
  530. border
  531. style="width: 100%; margin-top:20px"
  532. >
  533. <el-table-column
  534. prop="name"
  535. align="center"
  536. label="骑手名"
  537. />
  538. <el-table-column
  539. align="center"
  540. label="配送时间"
  541. >
  542. <template slot-scope="scope">
  543. <span>{{ scope.row.deliveryStart }}-{{ scope.row.deliveryEnd }}</span>
  544. </template>
  545. </el-table-column>
  546. <el-table-column
  547. align="center"
  548. label="操作"
  549. >
  550. <template slot-scope="scope">
  551. <el-button @click="check(scope.row.id)">选 择</el-button>
  552. </template>
  553. </el-table-column>
  554. </el-table>
  555. </el-dialog>
  556. <!-- Add this dialog after the allot dialog -->
  557. <el-dialog
  558. :visible.sync="verifyDialogVisible"
  559. title="核销码验证"
  560. width="30%"
  561. >
  562. <el-form>
  563. <el-form-item label="核销码">
  564. <el-input v-model="verifyCode" placeholder="请输入核销码"></el-input>
  565. </el-form-item>
  566. </el-form>
  567. <span slot="footer" class="dialog-footer">
  568. <el-button @click="verifyDialogVisible = false">取消</el-button>
  569. <el-button type="primary" @click="confirmCompletePickup">确认</el-button>
  570. </span>
  571. </el-dialog>
  572. </div>
  573. </template>
  574. <script>
  575. import Clipboard from 'clipboard';
  576. import {multiply} from '@/utils/math'
  577. import {
  578. listStoreOrder /** delStoreOrder, addStoreOrder, updateStoreOrder*/,
  579. getStoreOrder,
  580. startStocking,
  581. completeAllocation,
  582. merchantDistribution,
  583. completeDelivery,
  584. distributeOrder,
  585. completePickup,
  586. thirdPartyDistribution,
  587. cancelOrder
  588. } from '@/api/order/storeOrder'
  589. import {listAllStorage} from '@/api/storage/storage'
  590. import {getRiderByStorageId} from '@/api/rider/rider'
  591. export default {
  592. name: 'StoreOrder',
  593. components: {
  594. // PrintDialog
  595. },
  596. data() {
  597. return {
  598. verifyDialogVisible: false,
  599. verifyCode: '',
  600. currentPickupOrderId: null,
  601. // 按钮loading
  602. buttonLoading: false,
  603. // 遮罩层
  604. loading: false,
  605. // 选中数组
  606. // ids: [],
  607. // // 非单个禁用
  608. // single: true,
  609. // // 非多个禁用
  610. // multiple: true,
  611. // 总条数
  612. total: 0,
  613. // 仓库map
  614. storageMap: {},
  615. // 订单表格数据
  616. storeOrderList: [],
  617. courierList: [],
  618. // 是否显示弹出层
  619. open: false,
  620. allotShow: false,
  621. // 查询参数
  622. queryParams: {
  623. pageNum: 1,
  624. pageSize: 10,
  625. orderStatus: '14',
  626. storageId: '',
  627. orderId: '',
  628. // type: '',
  629. // orderType: '0',
  630. createTime: []
  631. },
  632. // 表单参数
  633. form: {},
  634. // 表单校验
  635. status: [
  636. {label: '待配货', name: '14'},
  637. {label: '配货中', name: '16'},
  638. {label: '待配送', name: '20'},
  639. {label: '配送中', name: '30'},
  640. {label: '已完成', name: '40,50'},
  641. {label: '配送异常', name: '32'},
  642. {label: '超时订单', name: '34'},
  643. {label: '待支付', name: '10'},
  644. {label: '已退款', name: '70'},
  645. {label: '已取消', name: '80'},
  646. {label: '全部订单', name: 'all'}
  647. ],
  648. storages: []
  649. }
  650. },
  651. computed: {
  652. // title() {
  653. // const { modes, currentMode } = this.dialog
  654. // return modes[currentMode]?.title || ''
  655. // }
  656. },
  657. created() {
  658. this.getList()
  659. this.listAllStorage()
  660. },
  661. methods: {
  662. multiply,
  663. listAllStorage() {
  664. listAllStorage().then(({data}) => {
  665. this.storages = data
  666. this.storages.forEach(storage => {
  667. this.storageMap[storage.id] = storage.name
  668. })
  669. })
  670. },
  671. isToday(dateString) {
  672. if (!dateString) return false;
  673. const orderDate = new Date(dateString);
  674. const today = new Date();
  675. return (
  676. orderDate.getFullYear() === today.getFullYear() &&
  677. orderDate.getMonth() === today.getMonth() &&
  678. orderDate.getDate() === today.getDate()
  679. );
  680. },
  681. getRiderStatusTagType(status) {
  682. const typeMap = {
  683. 0: 'warning', // 待取货 - 黄色
  684. 1: 'primary', // 配送中 - 蓝色
  685. 2: 'danger', // 超时 - 红色
  686. 3: 'danger', // 配送异常 - 红色
  687. 4: 'success', // 已完成 - 绿色
  688. 5: 'info' // 被更改分配 - 灰色
  689. }
  690. return typeMap[status] || ''
  691. },
  692. getRiderStatus(status) {
  693. const statusMap = {
  694. 0: '待取货',
  695. 1: '配送中',
  696. 2: '超时',
  697. 3: '配送异常',
  698. 4: '已完成',
  699. 5: '被更改分配'
  700. }
  701. return statusMap[status] || '未知状态'
  702. },
  703. showVerifyDialog(orderId) {
  704. this.currentPickupOrderId = orderId;
  705. this.verifyDialogVisible = true;
  706. this.verifyCode = '';
  707. },
  708. // In methods section
  709. handleThirdPartyDistribution(row) {
  710. this.$confirm('确定要使用第三方配送此订单吗?', '提示', {
  711. confirmButtonText: '确定',
  712. cancelButtonText: '取消',
  713. type: 'warning'
  714. }).then(() => {
  715. this.handleOperation(row.id, 'thirdPartyDistribution')
  716. }).catch(() => {
  717. this.$message({
  718. type: 'info',
  719. message: '已取消操作'
  720. })
  721. })
  722. },
  723. // In methods section
  724. handleCancelOrder(row) {
  725. this.$confirm('确定要取消此订单吗?', '提示', {
  726. confirmButtonText: '确定',
  727. cancelButtonText: '取消',
  728. type: 'warning'
  729. }).then(() => {
  730. this.handleOperation(row.id, 'cancelOrder')
  731. }).catch(() => {
  732. this.$message({
  733. type: 'info',
  734. message: '已取消操作'
  735. })
  736. })
  737. },
  738. // 添加这个新方法
  739. handleDeliveryCommand(row, command) {
  740. switch (command) {
  741. case 'system':
  742. this.allot(row.storeId, row.orderId, row.postId);
  743. break;
  744. case 'thirdParty':
  745. this.handleOperation(row.id, 'thirdPartyDistribution');
  746. break;
  747. case 'merchant':
  748. this.handleOperation(row.id, 'merchantDistribution');
  749. break;
  750. }
  751. },
  752. async confirmCompletePickup() {
  753. if (!this.verifyCode) {
  754. this.$message.warning('请输入核销码');
  755. return;
  756. }
  757. try {
  758. this.loading = true
  759. // Call the API with both orderId and verifyCode
  760. await completePickup({
  761. id: this.currentPickupOrderId,
  762. verifyCode: this.verifyCode
  763. });
  764. this.$message.success('核销成功');
  765. this.verifyDialogVisible = false;
  766. this.handleQuery();
  767. } finally {
  768. this.loading = false
  769. }
  770. },
  771. copyOrderId(orderId) {
  772. const clipboard = new Clipboard(this.$refs.orderId, {
  773. text: () => orderId
  774. });
  775. clipboard.on('success', () => {
  776. this.$message.success('订单号已复制');
  777. clipboard.destroy(); // 销毁 clipboard 实例
  778. });
  779. clipboard.on('error', () => {
  780. this.$message.error('复制失败');
  781. clipboard.destroy(); // 销毁 clipboard 实例
  782. });
  783. // 手动触发点击事件
  784. this.$refs.orderId.click();
  785. },
  786. /** 查询订单列表 */
  787. getList() {
  788. this.loading = true
  789. this.storeOrderList = []
  790. const params = {...this.queryParams}
  791. if (params.createTime) {
  792. params.startTime = params.createTime[0]
  793. params.endTime = params.createTime[1]
  794. }
  795. delete params.createTime
  796. listStoreOrder(params).then(response => {
  797. this.storeOrderList = response.rows
  798. this.total = response.total
  799. }).finally(() => {
  800. this.loading = false
  801. })
  802. },
  803. // // 取消按钮
  804. // cancel() {
  805. // this.open = false
  806. // this.reset()
  807. // },
  808. // // 表单重置
  809. // reset(row) {
  810. // this.form = JSON.parse(JSON.stringify(row)) || {}
  811. // this.resetForm('form')
  812. // },
  813. /** 搜索按钮操作 */
  814. handleQuery() {
  815. this.queryParams.pageNum = 1
  816. this.getList()
  817. },
  818. onOrderStatusChange() {
  819. this.handleQuery()
  820. },
  821. viewDetail(id) {
  822. getStoreOrder(id).then(({data}) => {
  823. this.form = data
  824. this.open = true
  825. })
  826. },
  827. allot(val, id, postId) {
  828. this.orderId = id
  829. if (postId) {
  830. this.reAllot(val, id)
  831. return
  832. }
  833. getRiderByStorageId({
  834. storageId: val
  835. }).then(res => {
  836. if (res.code !== 200) {
  837. this.$message.warning(res.message)
  838. return
  839. }
  840. this.courierList = res.data
  841. if (res.data[0].automatic === 1) {
  842. this.check(res.data[0].id)
  843. } else {
  844. this.allotShow = true
  845. this.allotValue = val
  846. }
  847. })
  848. },
  849. reAllot(val, id) {
  850. this.orderId = id
  851. this.allotShow = true
  852. this.allotValue = val
  853. getRiderByStorageId({
  854. storageId: val
  855. }).then(res => {
  856. this.courierList = res.data
  857. })
  858. },
  859. getStatusTagType(status) {
  860. const typeMap = {
  861. 14: 'warning', // 待配货 - 黄色
  862. 16: 'warning', // 配货中 - 黄色
  863. 20: 'primary', // 待配送 - 蓝色
  864. 30: 'primary', // 配送中 - 蓝色
  865. 40: 'success', // 已完成 - 绿色
  866. 50: 'success', // 已完成 - 绿色
  867. 32: 'danger', // 配送异常 - 红色
  868. 34: 'danger', // 超时订单 - 红色
  869. 10: 'info', // 待支付 - 灰色
  870. 70: 'danger', // 已退款 - 红色
  871. 80: 'info', // 已取消 - 灰色
  872. 90: 'info' // 已取消(系统) - 灰色
  873. }
  874. return typeMap[status] || ''
  875. },
  876. getStatus(s) {
  877. const status = {
  878. 14: '待配货',
  879. 16: '配货中',
  880. 20: '待配送',
  881. 30: '配送中',
  882. 50: '已完成',
  883. 40: '已完成',
  884. 32: '配送异常',
  885. 34: '超时订单',
  886. 10: '待支付',
  887. 70: '已退款',
  888. 80: '已取消',
  889. 90: '已取消(系统)'
  890. }
  891. return status[s]
  892. },
  893. getOrderType(s) {
  894. if (s.combinationId) {
  895. return '团购'
  896. }
  897. if (s.seckillId) {
  898. return '秒杀'
  899. }
  900. return '普通'
  901. },
  902. handleOperation(id, operation) {
  903. const operations = {
  904. startStocking,
  905. completeAllocation,
  906. merchantDistribution,
  907. completeDelivery,
  908. completePickup,
  909. thirdPartyDistribution,
  910. cancelOrder
  911. }
  912. operations[operation]({id}).then(() => {
  913. this.$message({
  914. message: '操作成功',
  915. type: 'success'
  916. })
  917. this.handleQuery()
  918. })
  919. },
  920. check(val) {
  921. const loadingInstance = this.$loading({text: '正在分配中...'})
  922. distributeOrder({
  923. orderNo: this.orderId,
  924. riderId: val
  925. }).then(res => {
  926. this.allotShow = false
  927. loadingInstance.close()
  928. this.$message({
  929. message: '操作成功',
  930. type: 'success'
  931. })
  932. this.handleQuery()
  933. }).finally(() => {
  934. loadingInstance.close()
  935. })
  936. }
  937. }
  938. }
  939. </script>
  940. <style lang="scss" scoped>
  941. .order-detail-dialog {
  942. .detail-container {
  943. padding: 0 10px;
  944. .detail-section {
  945. margin-bottom: 20px;
  946. padding: 15px;
  947. background-color: #f9f9f9;
  948. border-radius: 4px;
  949. .section-title {
  950. margin: 0 0 15px 0;
  951. padding-bottom: 8px;
  952. border-bottom: 1px solid #eee;
  953. color: #333;
  954. font-size: 16px;
  955. }
  956. }
  957. .detail-item {
  958. margin-bottom: 12px;
  959. font-size: 14px;
  960. .item-label {
  961. display: inline-block;
  962. width: 80px;
  963. color: #888;
  964. text-align: right;
  965. margin-right: 10px;
  966. }
  967. .item-value {
  968. color: #333;
  969. }
  970. .empty-remark {
  971. color: #999;
  972. font-style: italic;
  973. }
  974. }
  975. .refund-reason {
  976. .item-value {
  977. color: #f56c6c;
  978. }
  979. }
  980. .amount-summary {
  981. .summary-row {
  982. display: flex;
  983. justify-content: space-between;
  984. padding: 8px 0;
  985. border-bottom: 1px dashed #eee;
  986. .summary-label {
  987. color: #666;
  988. }
  989. .summary-value {
  990. font-weight: 500;
  991. }
  992. &.total-row {
  993. margin-top: 10px;
  994. border-top: 1px solid #ddd;
  995. border-bottom: none;
  996. .summary-value {
  997. font-size: 16px;
  998. color: #f56c6c;
  999. }
  1000. }
  1001. }
  1002. }
  1003. .highlight {
  1004. color: #f56c6c;
  1005. font-weight: bold;
  1006. }
  1007. }
  1008. ::v-deep .el-dialog__body {
  1009. padding: 20px;
  1010. }
  1011. }
  1012. .rider-info {
  1013. .status-tag {
  1014. margin-left: 5px;
  1015. }
  1016. .abnormal-reason {
  1017. color: #f56c6c;
  1018. font-weight: bold;
  1019. }
  1020. }
  1021. </style>