猫妈狗爸伴宠师小程序前端代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

360 lines
8.9 KiB

2 weeks ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
  1. <template>
  2. <view>
  3. <view class="header-buts flex flex-center">
  4. <view class="flex buts-box">
  5. <view class="buts" :class="{'buts-active':activeIndex===1}" @click="handleClickTab(1)">总订单</view>
  6. <view class="buts" :class="{'buts-active':activeIndex===2}" @click="handleClickTab(2)">日订单</view>
  7. </view>
  8. </view>
  9. <up-sticky bgColor="#fff" v-if="activeIndex == 1">
  10. <view class="container-tabs">
  11. <up-tabs @click="handleClassifyClickTab" :list="tabList1" lineWidth="68rpx" :activeStyle="{
  12. color: '#FFFFFF',
  13. fontWeight: 'bold',
  14. transform: 'scale(1.05)'
  15. }" :inactiveStyle="{
  16. color: '#FFFFFF',
  17. transform: 'scale(1)'
  18. }" :itemStyle="{height:'88rpx',width : '33%'}"
  19. lineColor="#FFFFFF"></up-tabs>
  20. </view>
  21. </up-sticky>
  22. <up-sticky bgColor="#fff" v-else>
  23. <view class="container-tabs">
  24. <up-tabs :list="tabList2" lineWidth="68rpx" :activeStyle="{
  25. color: '#FFFFFF',
  26. fontWeight: 'bold',
  27. transform: 'scale(1.05)'
  28. }" :inactiveStyle="{
  29. color: '#FFFFFF',
  30. transform: 'scale(1)'
  31. }" :itemStyle="{height:'88rpx',padding:'0 52rpx', width : '400rpx'}"
  32. @click="handleClassifyClickTab"
  33. lineColor="#FFFFFF"></up-tabs>
  34. </view>
  35. </up-sticky>
  36. <view class="container">
  37. <!-- 未登录提示 -->
  38. <view v-if="!isLogin" class="login-tip-container">
  39. <view class="login-tip-content">
  40. <up-image class="login-image" width="120rpx" height="120rpx"
  41. src="https://image.hhlm1688.com/img/work/log/headImage.png" shape="circle"></up-image>
  42. <view class="login-tip">请先登录查看订单数据</view>
  43. <up-button @click="goToLogin" type="primary" text="立即登录"
  44. shape="circle" color="#FFBF60" class="login-btn"></up-button>
  45. </view>
  46. </view>
  47. <!-- 已登录但加载中状态 -->
  48. <view v-else-if="loading" class="loading-container">
  49. <up-loading-icon size="36" mode="circle" color="#FFAA48"></up-loading-icon>
  50. <text class="loading-text">加载中...</text>
  51. </view>
  52. <!-- 总订单内容 -->
  53. <systemOrder :list="list" :current="current" v-else-if="activeIndex == 1" />
  54. <!-- 日订单内容 -->
  55. <view v-else>
  56. <view v-if="dateOrderList && dateOrderList.length > 0">
  57. <timelineService
  58. v-for="(item,index) in dateOrderList"
  59. :key="index"
  60. :date="item.date"
  61. :status="current == 0"
  62. :list="item.list"
  63. :current="current"
  64. />
  65. </view>
  66. <view v-else class="empty-state">
  67. <image src="/static/images/ydd/empty.png" mode="aspectFit" class="empty-image"></image>
  68. <text class="empty-text">暂无订单数据</text>
  69. </view>
  70. </view>
  71. </view>
  72. <!-- 客服组件 -->
  73. <CustomerService />
  74. </view>
  75. </template>
  76. <script setup>
  77. import {
  78. computed,
  79. reactive,
  80. ref
  81. } from "vue";
  82. import systemOrder from "./components/systemOrder.vue";
  83. import orderListByData from "./components/orderListByData.vue";
  84. import timelineService from "./components/timelineService.vue";
  85. import {
  86. onShow,
  87. onLoad,
  88. } from "@dcloudio/uni-app"
  89. import {
  90. getLoginStatus
  91. } from "@/utils/useMixin.js"
  92. import {
  93. getIsLogin,
  94. getToken
  95. } from "@/utils/auth";
  96. import {
  97. myList
  98. } from "@/api/receivingHall/index.js"
  99. import {
  100. getOrderDateList,
  101. } from "@/api/order/order.js"
  102. import {
  103. appletOrderDateFrequencyList,
  104. } from "@/api/order/frequency.js"
  105. import {
  106. useStore
  107. } from "vuex"
  108. import { getOrderServiceText, getProductNameText } from '@/utils/serviceTime.js'
  109. onLoad(() => {
  110. requestId.value = 0;
  111. activeIndex.value = 1;
  112. })
  113. onShow(() => {
  114. checkLoginStatus();
  115. if (isLogin.value) {
  116. getList();
  117. }
  118. })
  119. const current = ref(0)
  120. const activeIndex = ref(1)
  121. const list = ref([])
  122. const dateOrderList = ref([])
  123. const loading = ref(false) // 添加loading状态
  124. const requestId = ref(0) // 添加请求序列号
  125. const isLogin = ref(false) // 添加登录状态
  126. const store = useStore();
  127. const userInfo = computed(() => {
  128. return store.getters.userInfo;
  129. })
  130. const tabList1 = reactive([{
  131. name: '待服务',
  132. badge: {
  133. value: 0,
  134. }
  135. },
  136. {
  137. name: '进行中',
  138. badge: {
  139. value: 0,
  140. }
  141. },
  142. {
  143. name: '已完成',
  144. badge: {
  145. value: 0,
  146. }
  147. },
  148. ])
  149. const tabList2 = reactive([{
  150. name: '待上门',
  151. badge: {
  152. value: 0,
  153. }
  154. },
  155. {
  156. name: '已完成',
  157. badge: {
  158. value: 0,
  159. }
  160. },
  161. ])
  162. // 检查登录状态
  163. const checkLoginStatus = () => {
  164. if (getIsLogin() && getToken()) {
  165. isLogin.value = true
  166. } else {
  167. isLogin.value = false
  168. }
  169. }
  170. // 跳转登录页面
  171. const goToLogin = () => {
  172. uni.navigateTo({
  173. url: "/pages/login/index"
  174. })
  175. }
  176. // 检查登录状态,未登录则跳转登录
  177. const checkLoginAndRedirect = () => {
  178. if (!isLogin.value) {
  179. goToLogin()
  180. return false
  181. }
  182. return true
  183. }
  184. function getList() {
  185. if (!isLogin.value) return;
  186. loading.value = true; // 开始加载
  187. requestId.value++; // 递增请求序列号
  188. const currentRequestId = requestId.value; // 保存当前请求的ID
  189. let index = current.value;
  190. if (activeIndex.value == 1) {
  191. myList({
  192. orderStatus: index,
  193. userId: userInfo.value.userId
  194. })
  195. .then(res => {
  196. // 检查请求是否是最新的
  197. if (currentRequestId !== requestId.value) {
  198. return; // 如果不是最新请求,忽略响应
  199. }
  200. if (res.code == 200) {
  201. list.value = res.data.rows
  202. tabList1[index].badge.value = res.data.total
  203. list.value.forEach(item => {
  204. item.h5OrderVO.petVOList.forEach(pet => {
  205. pet.orderServiceText = getOrderServiceText(pet.id, item.h5OrderVO.orderServiceList)
  206. pet.productNameText = getProductNameText(pet.id, item.h5OrderVO.orderItemList, item.h5OrderVO.orderServiceList)
  207. })
  208. })
  209. }
  210. })
  211. .finally(() => {
  212. // 只有最新请求才能关闭loading
  213. if(activeIndex.value == 1 && currentRequestId === requestId.value){
  214. loading.value = false; // 结束加载
  215. }
  216. })
  217. }else{
  218. dateOrderList.value = []
  219. appletOrderDateFrequencyList({
  220. status: index == 0 ? '0,1' : '2',
  221. masterId: userInfo.value.userId
  222. })
  223. .then(res => {
  224. // 检查请求是否是最新的
  225. if (currentRequestId !== requestId.value) {
  226. return; // 如果不是最新请求,忽略响应
  227. }
  228. if (res.code == 200) {
  229. dateOrderList.value = res.data
  230. // 更新标签数量显示
  231. let totalOrders = 0;
  232. dateOrderList.value.forEach(item => {
  233. totalOrders += item.list.length || 0;
  234. item.list.forEach(n => {
  235. n.pets.forEach(pet => {
  236. pet.orderItemList.reverse()
  237. })
  238. })
  239. });
  240. tabList2[index].badge.value = totalOrders;
  241. }
  242. })
  243. .finally(() => {
  244. // 只有最新请求才能关闭loading
  245. if(activeIndex.value == 2 && currentRequestId === requestId.value){
  246. loading.value = false; // 结束加载
  247. }
  248. })
  249. }
  250. }
  251. function handleClickTab(index) {
  252. current.value = 0;
  253. activeIndex.value = index;
  254. if (checkLoginAndRedirect()) {
  255. getList();
  256. }
  257. }
  258. const handleClassifyClickTab = (item) => {
  259. current.value = item.index;
  260. if (checkLoginAndRedirect()) {
  261. getList();
  262. }
  263. }
  264. </script>
  265. <style scoped lang="scss">
  266. @import "index.scss";
  267. .loading-container {
  268. display: flex;
  269. flex-direction: column;
  270. align-items: center;
  271. justify-content: center;
  272. padding: 40rpx;
  273. .loading-text {
  274. margin-top: 20rpx;
  275. color: #999;
  276. font-size: 28rpx;
  277. }
  278. }
  279. .empty-state {
  280. display: flex;
  281. flex-direction: column;
  282. align-items: center;
  283. justify-content: center;
  284. padding: 80rpx 40rpx;
  285. .empty-image {
  286. width: 200rpx;
  287. height: 200rpx;
  288. margin-bottom: 20rpx;
  289. }
  290. .empty-text {
  291. color: #999;
  292. font-size: 28rpx;
  293. }
  294. }
  295. .login-tip-container {
  296. display: flex;
  297. align-items: center;
  298. justify-content: center;
  299. padding: 80rpx 40rpx;
  300. .login-tip-content {
  301. display: flex;
  302. flex-direction: column;
  303. align-items: center;
  304. padding: 60rpx;
  305. border-radius: 20rpx;
  306. .login-image {
  307. margin-bottom: 30rpx;
  308. }
  309. .login-tip {
  310. font-size: 28rpx;
  311. color: #666;
  312. margin-bottom: 30rpx;
  313. }
  314. .login-btn {
  315. width: 240rpx;
  316. }
  317. }
  318. }
  319. </style>