recyle_order.vue 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. <template>
  2. <view class="list-page">
  3. <view class="tabs-box">
  4. <up-tabs :list="list" @click="tabsChange" lineColor="#f8c20f"></up-tabs>
  5. </view>
  6. <view v-if="orderList.length === 0" class="empty">
  7. <image
  8. style="width: 60%"
  9. src="https://mp-ad17e5cd-05c1-4df9-b060-556e25dac130.cdn.bspapp.com/mini/common/empty.png"
  10. mode="widthFix"
  11. ></image>
  12. <text>暂无订单~</text>
  13. </view>
  14. <view v-else class="inner">
  15. <view
  16. v-for="(item, index) in orderList"
  17. :key="index"
  18. class="block"
  19. @click="nativeTo(item)"
  20. >
  21. <view class="header">
  22. <view class="title">订单号:{{ item.orderNo }}</view>
  23. <view class="tag" :class="['status' + item.status]">
  24. {{ getOrderType(item.status) }}
  25. </view>
  26. </view>
  27. <view class="detail">
  28. <image
  29. @click="previewImage(item.imageList)"
  30. style="width: 50px; height: 50px; border-radius: 6px"
  31. :src="item.imageList[0] || emptyImg"
  32. mode="scaleToFill"
  33. ></image>
  34. <view class="info">
  35. <view>{{ item.metalTypeDesc }}</view>
  36. <view class="right">
  37. <view>
  38. 金价:
  39. <span class="weight">{{ item.goldPricePerGram }}/g</span>
  40. </view>
  41. <view>
  42. 自估重量:
  43. <span class="weight">{{ item.estimatedWeight }}克</span>
  44. </view>
  45. </view>
  46. </view>
  47. </view>
  48. <view class="end">
  49. <view class="desc">
  50. <view class="">下单时间:{{ item.createTime }}</view>
  51. <uni-countdown
  52. v-if="item.status == 1"
  53. :minute="item.countdown || 0"
  54. color="#ff0000"
  55. @timeup="timeupHandle(item)"
  56. ></uni-countdown>
  57. </view>
  58. </view>
  59. <view v-if="item.status == 1" class="footer"
  60. >*请尽快邮寄,倒计时结束后未寄出系统将自动取消订单。</view
  61. >
  62. </view>
  63. </view>
  64. <!-- 下拉加载必须代码块 -->
  65. <!-- <tm-loadding v-if="loading" style="padding-bottom: 15px"></tm-loadding>
  66. <tm-loadding
  67. v-if="!loading && !hasMore"
  68. success
  69. icon="icon-times-circle-fill"
  70. label="没有更多啦"
  71. color="mymain"
  72. style="padding-bottom: 15px"
  73. ></tm-loadding> -->
  74. </view>
  75. </template>
  76. <script setup>
  77. import { ref, computed, onMounted } from "vue";
  78. import { recycleListAPI } from "@/api/functions";
  79. import { useAppStore } from "@/stores/app";
  80. import {
  81. onLoad,
  82. onPullDownRefresh,
  83. onShow,
  84. onReachBottom,
  85. } from "@dcloudio/uni-app";
  86. const appStore = useAppStore();
  87. // 定义数据
  88. const list = ref([
  89. { name: "全部", status: "" },
  90. { name: "待寄出", status: 1 },
  91. { name: "待检测", status: 3 },
  92. { name: "待确认", status: 4 },
  93. { name: "已完成", status: 7 },
  94. ]);
  95. const orderList = ref([]);
  96. const orderAll = ref([]);
  97. const emptyImg = ref(
  98. "https://mp-ad17e5cd-05c1-4df9-b060-556e25dac130.cdn.bspapp.com/mini/recycle/example/example1.png"
  99. );
  100. // 计算属性
  101. const pageTop = computed(() => {
  102. // return vk.getVuex("$app.totalBarHeight");
  103. return 0; // 占位,实际项目中替换为正确的顶部高度计算
  104. });
  105. const total = ref(0);
  106. const hasMore = ref(true);
  107. const loading = ref(false);
  108. const params = ref({
  109. limit: 10,
  110. page: 1,
  111. status: "",
  112. userId: appStore.userInfo.userId,
  113. });
  114. // 初始化
  115. const init = async (isRefresh = false) => {
  116. if (loading.value) return;
  117. loading.value = true;
  118. uni.showLoading({
  119. title: "加载中",
  120. });
  121. try {
  122. // 模拟接口调用
  123. const res = await recycleListAPI(params.value);
  124. console.log(res);
  125. const newList = res.data.list?.map((item) => {
  126. return {
  127. ...item,
  128. countdown: getTimeDiff(item.expirationTime),
  129. imageList: item.images ? JSON.parse(item.images) : [],
  130. };
  131. });
  132. if (isRefresh) {
  133. orderList.value = newList;
  134. } else {
  135. if (params.value.page === 1) {
  136. orderList.value = newList;
  137. } else {
  138. orderList.value = [...orderList.value, ...newList];
  139. }
  140. }
  141. total.value = res.data.total;
  142. hasMore.value = orderList.value.length > total.value;
  143. uni.hideLoading();
  144. } catch (error) {
  145. console.error("获取订单列表失败:", error);
  146. uni.showToast({
  147. title: "加载失败",
  148. icon: "none",
  149. });
  150. } finally {
  151. loading.value = false;
  152. // 停止下拉刷新动画
  153. if (isRefresh) {
  154. uni.stopPullDownRefresh();
  155. }
  156. }
  157. };
  158. // 计算目标时间与当前时间的差值(返回分钟数)
  159. const getTimeDiff = (targetTimeStr) => {
  160. const targetTime = new Date(targetTimeStr).getTime();
  161. const currentTime = Date.now();
  162. const diffMs = targetTime - currentTime;
  163. const diffMinutes = diffMs / 60000;
  164. return diffMinutes > 0 ? diffMinutes : 0;
  165. };
  166. // 时间到结束
  167. const timeupHandle = (item) => {
  168. item.status = 0;
  169. };
  170. // 标签页切换
  171. const tabsChange = (item) => {
  172. params.value.status = item.status;
  173. params.value.page = 1;
  174. init();
  175. };
  176. // 跳转到详情页
  177. const nativeTo = (item) => {
  178. console.log(item);
  179. if (item.status == 1) {
  180. uni.navigateTo({
  181. url: `/pages/users/vault/recycle/order_fill?order=${JSON.stringify(
  182. item
  183. )}`,
  184. // url: "/pages/users/vault/recycle/report",
  185. });
  186. } else if (item.status == 4 || item.status == 7) {
  187. uni.navigateTo({
  188. url: `/pages/users/vault/recycle/report?orderInfo=${encodeURIComponent(
  189. JSON.stringify(item)
  190. )}`,
  191. });
  192. }
  193. };
  194. // 计算总重量
  195. const totalWeight = (order) => {
  196. let totalWeight = 0;
  197. for (const key in order.cart) {
  198. if (Object.hasOwnProperty.call(order.cart, key)) {
  199. const item = order.cart[key];
  200. totalWeight += Number(item.weight) || 0;
  201. }
  202. }
  203. return totalWeight.toFixed(2);
  204. };
  205. // 获取商品类别
  206. const getCate = (cate) => {
  207. switch (cate) {
  208. case "au":
  209. return "黄金";
  210. case "ag":
  211. return "白银";
  212. case "pt":
  213. return "铂金";
  214. case "kau":
  215. return "K金";
  216. default:
  217. return "其他";
  218. }
  219. };
  220. // 获取订单状态文本
  221. const getOrderType = (status) => {
  222. switch (status) {
  223. case 0:
  224. return "已取消";
  225. case 1:
  226. return "待寄出";
  227. case 2:
  228. return "等待签收";
  229. case 3:
  230. return "等待检测";
  231. case 4:
  232. return "确认报告";
  233. case 5:
  234. return "确认总价";
  235. case 6:
  236. return "正在打款";
  237. case 7:
  238. return "交易完成";
  239. default:
  240. return "未知状态";
  241. }
  242. };
  243. // 生命周期钩子
  244. onShow(() => {
  245. params.value.page = 1;
  246. init();
  247. });
  248. // 下拉刷新
  249. onPullDownRefresh(() => {});
  250. // 上拉加载更多
  251. onReachBottom(() => {
  252. // 如果没有更多数据或正在加载中,则不执行
  253. if (!hasMore.value || loading.value) return;
  254. // 增加页码
  255. params.value.page++;
  256. // 加载下一页数据
  257. init();
  258. });
  259. const previewImage = (urls) => {
  260. console.log(urls[0]);
  261. uni.previewImage({
  262. current: urls[0], // 当前显示图片的URL
  263. urls: urls, // 需要预览的图片URL列表
  264. success: () => {},
  265. fail: (err) => {
  266. console.error("预览图片失败:", err);
  267. },
  268. });
  269. };
  270. </script>
  271. <style>
  272. .empty {
  273. display: flex;
  274. flex-direction: column;
  275. justify-content: center;
  276. align-items: center;
  277. color: #ffffff;
  278. }
  279. page {
  280. height: 100%;
  281. background-color: #f8f8f8;
  282. }
  283. </style>
  284. <style scoped lang="scss">
  285. .list-page {
  286. background: $uni-bg-primary !important;
  287. min-height: 100vh;
  288. }
  289. .tabs-box {
  290. width: 100%;
  291. height: 75rpx;
  292. // background: #ffffff;
  293. box-sizing: border-box;
  294. ::v-deep .u-tabs__wrapper__nav__item {
  295. padding: 0 37rpx;
  296. }
  297. }
  298. .tabs {
  299. z-index: 100;
  300. position: sticky;
  301. }
  302. .inner {
  303. padding: 10px;
  304. .footer {
  305. border-radius: 5px;
  306. border: 0 0 10px 20px;
  307. color: #707070;
  308. font-size: 12px;
  309. padding: 10px;
  310. background-color: rgb(252, 247, 230);
  311. }
  312. }
  313. .block {
  314. margin-bottom: 10px;
  315. padding-top: 10px;
  316. border-radius: 5px;
  317. background-color: #fff;
  318. border: 1px solid #cecece;
  319. .header {
  320. padding: 0 10px;
  321. position: relative;
  322. display: flex;
  323. align-items: center;
  324. justify-content: space-between;
  325. padding-bottom: 10px;
  326. border-bottom: 1px solid #eee;
  327. .tag {
  328. font-size: 12px;
  329. padding: 2px 5px;
  330. border-radius: 4px;
  331. color: #ff0800;
  332. background-color: #ffcece;
  333. &.status-1 {
  334. color: #555;
  335. background-color: #eeeeee;
  336. }
  337. &.status1 {
  338. color: #ff9900;
  339. background-color: #ffeccf;
  340. }
  341. &.status2 {
  342. color: #d6006b;
  343. background-color: #fdd3e9;
  344. }
  345. &.status3 {
  346. color: #9900ff;
  347. background-color: #e2b7ff;
  348. }
  349. &.status4,
  350. &.status5 {
  351. color: rgb(48, 24, 136);
  352. background-color: #bbb0fa;
  353. }
  354. &.status6 {
  355. color: #3dac27;
  356. background-color: #c8ffb7;
  357. }
  358. }
  359. .title {
  360. font-size: 14px;
  361. }
  362. }
  363. .detail {
  364. display: flex;
  365. padding: 10px 13px;
  366. .info {
  367. flex: 1;
  368. width: 100%;
  369. font-size: 14px;
  370. margin-left: 10px;
  371. color: #999;
  372. .right {
  373. min-width: 120px;
  374. // display: flex;
  375. // justify-content: space-between;
  376. .weight {
  377. // width: 100%;
  378. color: #daa520;
  379. }
  380. }
  381. }
  382. }
  383. .end {
  384. padding: 10px 10px;
  385. color: #999;
  386. font-size: 14px;
  387. .desc {
  388. margin-bottom: 6px;
  389. display: flex;
  390. align-items: center;
  391. justify-content: space-between;
  392. }
  393. }
  394. }
  395. </style>