details.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. <template>
  2. <Theme>
  3. <Navbar fixed>
  4. <template #center>
  5. <view class="nav_title">
  6. <trans _t="tabbar.订单详情" />
  7. </view>
  8. </template>
  9. </Navbar>
  10. <view class="content">
  11. <view class="overview">
  12. <view class="img_box">
  13. <image
  14. class="img"
  15. mode="aspectFit"
  16. :src="queryData?.goods[0]['pic_url']"
  17. ></image>
  18. </view>
  19. <view class="information">
  20. <text class="name">{{ queryData?.goods[0]["goodTitle"] }}</text>
  21. <view
  22. v-for="(title, index) in queryData?.goods[0]['sku_desc'].split(';')"
  23. :key="index"
  24. >
  25. <text>{{ title }}</text>
  26. </view>
  27. <view class="num">x{{ queryData?.goods[0]["total"] }}</view>
  28. </view>
  29. </view>
  30. <view class="price_box">
  31. <text class="currency">{{ symbol.symbol }}:</text>
  32. <rich-text
  33. class="texts"
  34. :nodes="Moneyhtml(queryData?.goods[0]['price'])"
  35. ></rich-text>
  36. </view>
  37. <view class="dashed"></view>
  38. <view class="text_box">
  39. <trans class="title" _t="实付"></trans>
  40. <view class="price_box">
  41. <text class="currency">{{ symbol.symbol }}</text>
  42. <rich-text
  43. class="texts"
  44. :nodes="Moneyhtml(queryData?.amount)"
  45. ></rich-text>
  46. </view>
  47. </view>
  48. <view class="text_box" v-if="queryData?.payType">
  49. <trans class="title" _t="支付方式"></trans>
  50. <text>{{ queryData?.payType }}</text>
  51. </view>
  52. <view class="text_box">
  53. <trans class="title" _t="订单状态"></trans>
  54. <text>{{ queryData?.status_txt }}</text>
  55. </view>
  56. <view class="text_box">
  57. <trans class="title" _t="平台订单号"></trans>
  58. <up-copy
  59. :content="queryData?.orderNo"
  60. :notice="t('复制成功')"
  61. class="right_value"
  62. >
  63. <up-icon name="file-text" size="16px"></up-icon>
  64. <text>{{ queryData?.orderNo }}</text>
  65. </up-copy>
  66. </view>
  67. <view class="text_box" v-if="queryData?.payDate">
  68. <trans class="title" _t="订单时间"></trans>
  69. <text>{{ useGlobal().$format(queryData?.payDate) }}</text>
  70. </view>
  71. <view class="dashed"></view>
  72. <view class="quality_inspection" v-if="queryData?.checkStatus > 0">
  73. <view class="head">
  74. <text class="state">{{ t("当前状态") }}:</text>
  75. <view class="progress">
  76. <text class="text_red">{{ currentStatus + 1 }}</text>
  77. <text class="icon">/</text>
  78. <text class="sum">{{
  79. !queryData?.bzList.length ? 0 : queryData?.bzList.length
  80. }}</text>
  81. </view>
  82. <text class="hint">{{ t("专业质检") }}</text>
  83. <!-- <up-icon class="icon" color="#FF0000" name="info-circle"></up-icon> -->
  84. </view>
  85. <view class="body">
  86. <text>{{ queryData?.checkRemark }}</text>
  87. </view>
  88. <view class="foot">
  89. <view class="button" @click="noLook">
  90. <trans _t="查看" />
  91. </view>
  92. </view>
  93. </view>
  94. <view v-if="checkstatus" class="popup_close" @click="toPay">
  95. <trans class="menu_text" _t="去支付" />
  96. </view>
  97. <view
  98. v-if="queryData?.status > 300"
  99. class="popup_cancle"
  100. @click="logisticsPop"
  101. >
  102. <trans class="menu_text" _t="查看物流" />
  103. </view>
  104. <view
  105. class="popup_cancle"
  106. @click="orderCancel"
  107. v-if="queryData?.status == 100"
  108. >
  109. <trans class="menu_text" _t="取消" />
  110. </view>
  111. <view
  112. class="popup_cancle"
  113. @click="orderFinish"
  114. v-if="queryData?.status == 500"
  115. >
  116. <trans class="menu_text" _t="完成" />
  117. </view>
  118. <view class="popup_cancle" @click="onClose">
  119. <trans class="menu_text" _t="返回" />
  120. </view>
  121. <Popup ref="popRef" mode="center" isClose>
  122. <template #content>
  123. <view class="popup_content">
  124. <view class="img_box">
  125. <Swiper
  126. :listArr="queryData?.checkImg"
  127. urlName=""
  128. autoplay
  129. indicatorDots
  130. circular
  131. />
  132. </view>
  133. <view class="hint" @click="openKf">
  134. <text class="text"
  135. >{{ t("kf_hint")
  136. }}<up-icon
  137. class="icon"
  138. color="#EB3A68"
  139. name="kefu-ermai"
  140. ></up-icon
  141. ></text>
  142. </view>
  143. <view class="checkbox" v-if="queryData?.checkStatus != 10">
  144. <Tip title="同意并已阅读免责说明" :show="tipShow">
  145. <view class="confirm_box" style="">
  146. <up-checkbox
  147. activeColor="var(--black)"
  148. labelSize="14"
  149. labelColor="#000000"
  150. iconSize="16"
  151. size="16"
  152. name="agree"
  153. usedAlone
  154. v-model:checked="aloneChecked"
  155. shape="circle"
  156. >
  157. <template #label>
  158. <trans class="text" _t="同意并已阅读免责说明" />
  159. </template>
  160. </up-checkbox>
  161. </view>
  162. </Tip>
  163. </view>
  164. </view>
  165. </template>
  166. <template #footer>
  167. <view class="footer_button">
  168. <template v-if="queryData?.checkStatus != 10">
  169. <view class="accept" @click="accept">{{ t("接受瑕疵") }}</view>
  170. <view class="refund" @click="refund">{{ t("退款") }}</view>
  171. </template>
  172. <view class="refund" @click="close" v-else>{{ t("关闭") }}</view>
  173. </view>
  174. </template>
  175. </Popup>
  176. <popup ref="popRefExpress" :title="t('物流详细')" isClose>
  177. <template #content>
  178. <up-steps direction="column" current="0">
  179. <up-steps-item v-for="(item, index) in detail" :key="index">
  180. <template #content>
  181. <view class="default" :class="index == 0 ? 'express' : ''">
  182. <view class="slot-title">{{ item.status }}</view>
  183. <view class="slot-time">{{ item.time }}</view>
  184. <view class="slot-desc">{{ item.context }}</view>
  185. </view>
  186. </template>
  187. </up-steps-item>
  188. </up-steps>
  189. </template>
  190. </popup>
  191. </view>
  192. <cancelModel ref="cancelModelRef" />
  193. </Theme>
  194. </template>
  195. <script setup>
  196. import { ref, watchEffect, computed, watch, onMounted, nextTick } from "vue";
  197. import { $post, useGlobal } from "@/utils";
  198. import { useSystemStore } from "@/store";
  199. import { Moneyhtml, Modal, Toast } from "@/utils";
  200. import { t } from "@/locale";
  201. import Navbar from "@/components/navbar";
  202. import Popup from "@/components/popup.vue";
  203. import { onLoad } from "@dcloudio/uni-app";
  204. import {
  205. SHOP_ORDER_GETPAY,
  206. SHOP_ACTION,
  207. SELLER_ORDER_DETAIL,
  208. SELLER_ORDER_FINISH,
  209. } from "@/api";
  210. import Swiper from "@/components/swiper";
  211. import Tip from "@/components/tooltip";
  212. import cancelModel from "@/pages/dashboard/components/cancelModel.vue";
  213. import { SHOP_ORDER_EXPRESS } from "@/api";
  214. const popRef = ref(null);
  215. const parmes = ref();
  216. const useSystem = useSystemStore();
  217. const queryData = ref();
  218. const currentStatus = ref(-1);
  219. const flexdw = ref(0);
  220. const symbol = computed(() => useSystem.getSymbol);
  221. const tipShow = ref(false);
  222. const aloneChecked = ref(false);
  223. const popRefExpress = ref(null);
  224. const detail = ref({});
  225. watch(aloneChecked, (newVal) => {
  226. if (newVal) tipShow.value = false;
  227. });
  228. const checkstatus = ref(false);
  229. watchEffect(async () => {
  230. try {
  231. const res = await SELLER_ORDER_DETAIL(parmes.value.orderid);
  232. queryData.value = res.data;
  233. res.data.payStatus == 100
  234. ? (checkstatus.value = true)
  235. : (checkstatus.value = false);
  236. res.data?.bzList?.forEach((item) => {
  237. if (item.checked == 1) {
  238. currentStatus.value += item.checked;
  239. return;
  240. }
  241. });
  242. nextTick(() => {
  243. if (currentStatus.value >= 3) {
  244. flexdw.value = currentStatus.value * 90;
  245. }
  246. });
  247. } catch (err) {}
  248. });
  249. const noLook = () => {
  250. popRef.value && popRef.value.open();
  251. };
  252. const close = () => {
  253. popRef.value && popRef.value.close();
  254. };
  255. const openKf = () => {
  256. uni.navigateTo({ url: "/pages/setting/system" });
  257. };
  258. const onClose = () => {
  259. uni.navigateBack();
  260. };
  261. const previewImage = (index) => {
  262. uni.previewImage({
  263. current: index,
  264. urls: queryData.value.checkImg,
  265. indicator: "number",
  266. loop: true,
  267. });
  268. };
  269. const oids = ref("");
  270. const buyCart = async (oid) => {
  271. const res = await SHOP_ORDER_GETPAY(oid);
  272. oids.value = res.data.oid;
  273. };
  274. const toPay = () => {
  275. uni.navigateTo({ url: `/pages/shop/payment?oid=${oids.value}&type=order` });
  276. };
  277. const accept = () => {
  278. if (aloneChecked.value == false) {
  279. tipShow.value = true;
  280. } else {
  281. acfun(30);
  282. }
  283. };
  284. const acfun = async (val) => {
  285. try {
  286. const res = await SHOP_ACTION({
  287. orderid: parmes.value.orderid,
  288. type: val,
  289. });
  290. Toast(res.msg, 1000).then(() => {
  291. let timer = setTimeout(() => {
  292. popRef.value && popRef.value.close();
  293. clearTimeout(timer);
  294. }, 1000);
  295. });
  296. } catch (error) {
  297. Toast(error.msg);
  298. }
  299. };
  300. const logisticsPop = async () => {
  301. try {
  302. const res = await SHOP_ORDER_EXPRESS(queryData.value.id);
  303. detail.value = res.data;
  304. nextTick(() => {
  305. popRefExpress.value && popRefExpress.value.open();
  306. });
  307. } catch (error) {
  308. Toast(error.msg);
  309. }
  310. };
  311. const orderFinish = async () => {
  312. try {
  313. const res = await SELLER_ORDER_FINISH(parmes.value.orderid);
  314. Toast(res.msg);
  315. } catch (error) {
  316. Toast(error.msg);
  317. }
  318. };
  319. const cancelModelRef = ref(null);
  320. const orderCancel = () => {
  321. cancelModelRef.value && cancelModelRef.value.open(queryData.value.id);
  322. };
  323. const refund = () => {
  324. acfun(40);
  325. };
  326. onLoad((options) => {
  327. parmes.value = options;
  328. // buyCart(options.orderid);
  329. });
  330. </script>
  331. <style lang="less" scoped>
  332. @import url("@/style.less");
  333. .scroll-Y {
  334. height: 300rpx;
  335. }
  336. .scroll-view_H {
  337. width: 280%;
  338. }
  339. .scroll-view-item_H {
  340. width: 35%;
  341. }
  342. .content {
  343. padding: 15rpx 5%;
  344. border-top: 1rpx solid #ccc;
  345. .popup_close {
  346. background-color: var(--black);
  347. color: var(--light);
  348. .flex_center();
  349. padding: 28rpx 0;
  350. border-radius: 20rpx;
  351. }
  352. .popup_cancle {
  353. background-color: var(--white);
  354. color: var(--black);
  355. .flex_center();
  356. border-radius: 20rpx;
  357. margin-top: 15rpx;
  358. padding: 28rpx 0;
  359. border: 1px solid var(--black);
  360. }
  361. .steps_box {
  362. width: 100%;
  363. overflow-x: scroll;
  364. margin: 20rpx 0;
  365. border: 1px solid #ccc;
  366. padding: 10rpx 0;
  367. }
  368. .overview {
  369. color: var(--text);
  370. .flex();
  371. gap: 24rpx;
  372. .img_box {
  373. flex: 4;
  374. border-radius: 20rpx;
  375. .img {
  376. width: 100%;
  377. height: 100%;
  378. }
  379. }
  380. .information {
  381. flex: 6;
  382. .size(24rpx);
  383. .name {
  384. // .ellipsis(2);
  385. margin-bottom: 26rpx;
  386. .size(28rpx);
  387. }
  388. .num {
  389. text-align: right;
  390. }
  391. }
  392. }
  393. .orginal_price {
  394. .hor(end);
  395. }
  396. .text_box {
  397. .flex_position(space-between, flex-end);
  398. margin: 8rpx 0;
  399. .size(24rpx);
  400. .title {
  401. color: var(--text-01);
  402. }
  403. .currency,
  404. .texts {
  405. color: var(--red);
  406. .size(28rpx);
  407. font-weight: 500;
  408. }
  409. .right_value {
  410. .flex();
  411. }
  412. }
  413. .price_box {
  414. .flex_position(end, flex-end);
  415. color: var(--black);
  416. .size(28rpx);
  417. .currency {
  418. margin-right: 10rpx;
  419. }
  420. }
  421. .texts /deep/ {
  422. .price {
  423. .size();
  424. }
  425. }
  426. .check_box {
  427. .image-scroll {
  428. width: 100%;
  429. margin: 20rpx 0;
  430. white-space: nowrap;
  431. .image-row {
  432. display: inline-flex;
  433. gap: 12rpx;
  434. .image-item {
  435. width: 140rpx;
  436. height: 140rpx;
  437. border-radius: 12rpx;
  438. overflow: hidden;
  439. box-shadow: 0 2rpx 5rpx rgba(0, 0, 0, 0.1);
  440. .img {
  441. width: 100%;
  442. height: 100%;
  443. object-fit: cover;
  444. }
  445. }
  446. }
  447. }
  448. // 图片行容器
  449. // 图片项
  450. }
  451. .title_box {
  452. .size(28rpx);
  453. font-weight: 500;
  454. color: var(--text);
  455. }
  456. .hint {
  457. .size(24rpx);
  458. color: var(--text-01);
  459. margin-top: 10rpx;
  460. .steps-scroll-view {
  461. flex: 1;
  462. width: 100%;
  463. white-space: nowrap;
  464. padding: 24rpx 0;
  465. scroll-behavior: smooth;
  466. .custom-steps {
  467. display: inline-flex;
  468. min-width: 100%;
  469. .step-item {
  470. min-width: 120px;
  471. max-width: 180px;
  472. padding: 0 12rpx;
  473. box-sizing: border-box;
  474. white-space: normal;
  475. word-break: break-word;
  476. cursor: pointer;
  477. transition: all 0.3s;
  478. &:deep(.up-steps-item-title) {
  479. .size(28rpx);
  480. color: #333;
  481. font-weight: 500;
  482. // text-align: center;
  483. }
  484. }
  485. }
  486. }
  487. }
  488. .quality_inspection {
  489. margin-top: 10rpx;
  490. background-color: var(--bor-color);
  491. padding: 0 20rpx;
  492. border-radius: 20rpx;
  493. .head {
  494. .ver(flex-end);
  495. .icon {
  496. margin-left: 5rpx;
  497. }
  498. .state {
  499. .size(20rpx);
  500. }
  501. .progress {
  502. .ver(baseline);
  503. .text_red {
  504. color: var(--red);
  505. .size(28rpx);
  506. margin-left: 10rpx;
  507. }
  508. .icon,
  509. .sum {
  510. .size(24rpx);
  511. color: var(--text);
  512. }
  513. }
  514. .hint {
  515. .size(24rpx);
  516. font-weight: 500;
  517. margin-left: 10rpx;
  518. }
  519. }
  520. .body {
  521. .size(24rpx);
  522. color: var(--text);
  523. margin-top: 16rpx;
  524. }
  525. .foot {
  526. margin-top: 26rpx;
  527. .hor(end);
  528. .button {
  529. .size(24rpx);
  530. color: var(--light);
  531. background-color: var(--black);
  532. padding: 14rpx 28rpx;
  533. border-radius: 20rpx;
  534. margin-bottom: 16rpx;
  535. }
  536. }
  537. }
  538. /deep/ .u-popup__content {
  539. width: 80vw !important;
  540. position: relative;
  541. }
  542. .popup_content {
  543. .img_box {
  544. height: 400rpx;
  545. border-radius: 20rpx;
  546. .img {
  547. max-width: 100%;
  548. max-height: 100%;
  549. }
  550. }
  551. .hint {
  552. .ver(flex-start);
  553. .text {
  554. flex: 1;
  555. word-break: break-word;
  556. padding-right: 40rpx;
  557. position: relative;
  558. }
  559. .icon {
  560. position: absolute;
  561. right: 40rpx;
  562. bottom: 0;
  563. margin-left: 8rpx;
  564. }
  565. }
  566. .checkbox {
  567. margin-top: 44rpx;
  568. /deep/ .u-checkbox {
  569. .ver(baseline);
  570. }
  571. }
  572. }
  573. .footer_button {
  574. .hor(space-between);
  575. .size(28rpx);
  576. gap: 50rpx;
  577. text-align: center;
  578. .accept {
  579. flex: 1;
  580. color: var(--text);
  581. padding: 24rpx 0;
  582. border: 2rpx solid var(--black);
  583. border-radius: 20rpx;
  584. }
  585. .refund {
  586. flex: 1;
  587. color: var(--light);
  588. padding: 24rpx 0rpx;
  589. background-color: var(--black);
  590. border-radius: 20rpx;
  591. }
  592. }
  593. // .popup_close {
  594. // position: absolute;
  595. // top: -50rpx;
  596. // right: 4rpx;
  597. // padding: 6rpx;
  598. // .flex_position(center, center);
  599. // background-color: var(--light);
  600. // border-radius: 50%;
  601. // }
  602. }
  603. .default {
  604. color: var(--text-02);
  605. &.express {
  606. color: var(--black);
  607. }
  608. .slot-title {
  609. .size(28rpx);
  610. font-weight: 600;
  611. }
  612. .slot-desc {
  613. .size(20rpx);
  614. }
  615. .slot-time {
  616. .size(22rpx);
  617. }
  618. }
  619. </style>