建材商城系统20241014
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.

286 lines
8.2 KiB

  1. <template>
  2. <view class="quick-order-container"
  3. :style="{bottom}"
  4. @click="handleClick"
  5. @longpress="handleLongPress">
  6. <view class="new-message" v-if="innerHasNewMessage" @click.stop="goToOrderList">
  7. 你有新的快捷下单信息
  8. </view>
  9. <view class="quick-order">
  10. <view class="number-order" v-if="innerMessageCount > 0">
  11. {{ innerMessageCount }}
  12. </view>
  13. <image :src="imageUrl" mode=""></image>
  14. <view class="long-press-hint">长按查看更多</view>
  15. </view>
  16. </view>
  17. </template>
  18. <script>
  19. export default {
  20. name: 'QuickOrderEntry',
  21. props: {
  22. // 图标路径
  23. imageUrl: {
  24. type: String,
  25. default: '/static/image/home/7.png'
  26. },
  27. // 点击跳转的页面
  28. targetUrl: {
  29. type: String,
  30. default: '/pages_order/order/fastCreateOrder'
  31. },
  32. // 是否自动获取快捷下单信息
  33. autoFetch: {
  34. type: Boolean,
  35. default: true
  36. },
  37. bottom : {
  38. default : '33vh',
  39. }
  40. },
  41. data() {
  42. return {
  43. orderInfo: null,
  44. innerHasNewMessage: false,
  45. innerMessageCount: 0,
  46. isInitialized: false,
  47. timer: null // 定时器ID
  48. }
  49. },
  50. mounted() {
  51. this.getQuickOrderInfo()
  52. // 开启定时器,每30秒更新一次数据
  53. this.startTimer()
  54. uni.$on('getQuickOrderInfo', this.getQuickOrderInfo)
  55. },
  56. beforeDestroy() {
  57. // 组件销毁前清除定时器
  58. this.clearTimer()
  59. uni.$off('getQuickOrderInfo', this.getQuickOrderInfo)
  60. },
  61. methods: {
  62. // 处理点击事件
  63. async handleClick() {
  64. // 发出点击事件,便于父组件监听
  65. this.$emit('click');
  66. await this.getQuickOrderInfo()
  67. // 如果有订单信息,提供订单列表
  68. if (Array.isArray(this.orderInfo) && this.orderInfo.length > 0) {
  69. this.$emit('order-info', this.orderInfo);
  70. this.navigateTo('/pages_order/order/firmOrder');
  71. return
  72. }
  73. // 如果有目标页面,则跳转
  74. if (this.targetUrl) {
  75. this.navigateTo(this.targetUrl);
  76. }
  77. },
  78. // 处理长按事件 - 跳转到快捷订单列表
  79. handleLongPress() {
  80. // 震动反馈
  81. uni.vibrateShort();
  82. // 显示操作菜单
  83. uni.showActionSheet({
  84. itemList: ['快捷下单', '我的快捷订单'],
  85. success: (res) => {
  86. if (res.tapIndex === 0) {
  87. // 跳转到快捷下单页面
  88. this.navigateTo(this.targetUrl);
  89. } else if (res.tapIndex === 1) {
  90. // 跳转到快捷订单列表
  91. this.navigateTo('/pages_order/order/fastOrderList');
  92. }
  93. }
  94. });
  95. },
  96. // 直接跳转到快捷订单列表
  97. goToOrderList() {
  98. this.navigateTo('/pages_order/order/fastOrderList');
  99. },
  100. // 获取快捷下单的信息
  101. getQuickOrderInfo() {
  102. if(!uni.getStorageSync('token')){
  103. return
  104. }
  105. // 调用接口获取快捷下单信息
  106. return this.$api('getOrderInfo', {}, res => {
  107. if (res.code === 200 && res.result) {
  108. // 处理返回的订单列表
  109. const orderList = Array.isArray(res.result) ? res.result : [res.result];
  110. if (orderList.length > 0) {
  111. // 保存订单列表
  112. this.orderInfo = orderList;
  113. // 设置消息数量为订单列表长度
  114. this.innerHasNewMessage = true;
  115. this.innerMessageCount = orderList.length;
  116. // 通知父组件获取到了数据
  117. this.$emit('order-loaded', this.orderInfo);
  118. } else {
  119. this.innerHasNewMessage = false;
  120. this.innerMessageCount = 0;
  121. this.orderInfo = [];
  122. }
  123. } else {
  124. this.innerHasNewMessage = false;
  125. this.innerMessageCount = 0;
  126. this.orderInfo = [];
  127. }
  128. this.isInitialized = true;
  129. }, err => {
  130. console.error('获取快捷下单信息失败', err);
  131. this.innerHasNewMessage = false;
  132. this.innerMessageCount = 0;
  133. this.orderInfo = [];
  134. this.isInitialized = true;
  135. });
  136. },
  137. // 导航到指定页面
  138. navigateTo(url) {
  139. // 如果有订单列表,则优先使用第一个订单的ID
  140. if (Array.isArray(this.orderInfo) && this.orderInfo.length > 0 && this.orderInfo[0].id && url.indexOf('?') === -1) {
  141. url += `?orderId=${this.orderInfo[0].id}`;
  142. }
  143. this.$utils.navigateTo(url);
  144. },
  145. // 刷新快捷下单信息
  146. refresh() {
  147. this.getQuickOrderInfo();
  148. return this; // 链式调用
  149. },
  150. // 清除消息提示
  151. clearMessage() {
  152. this.innerHasNewMessage = false;
  153. this.innerMessageCount = 0;
  154. return this; // 链式调用
  155. },
  156. // 检查是否有新消息
  157. hasNewMessage() {
  158. return this.innerHasNewMessage;
  159. },
  160. // 获取消息数量
  161. getMessageCount() {
  162. return this.innerMessageCount;
  163. },
  164. // 开启定时器
  165. startTimer() {
  166. // 清除之前的定时器(如果存在)
  167. this.clearTimer()
  168. // 设置新的定时器,每30秒执行一次
  169. this.timer = setInterval(() => {
  170. // 只有在有token的情况下才更新数据
  171. if (uni.getStorageSync('token')) {
  172. this.getQuickOrderInfo()
  173. }
  174. }, 30000)
  175. },
  176. // 清除定时器
  177. clearTimer() {
  178. if (this.timer) {
  179. clearInterval(this.timer)
  180. this.timer = null
  181. }
  182. },
  183. },
  184. }
  185. </script>
  186. <style scoped lang="scss">
  187. .quick-order-container {
  188. position: fixed;
  189. right: 30rpx;
  190. bottom: 30vh;
  191. z-index: 99;
  192. transition: transform 0.3s;
  193. &:active {
  194. transform: scale(0.95);
  195. }
  196. .new-message {
  197. position: absolute;
  198. top: 50rpx;
  199. right: 100%;
  200. white-space: nowrap;
  201. background-color: #DC2828;
  202. border-radius: 20rpx;
  203. font-size: 25rpx;
  204. color: #ffffff;
  205. padding: 5rpx 15rpx;
  206. margin-bottom: 10rpx;
  207. box-shadow: 0 5rpx 10rpx rgba(220, 40, 40, 0.3);
  208. animation: pulse 2s infinite;
  209. }
  210. .quick-order {
  211. position: relative;
  212. width: 230rpx;
  213. height: 160rpx;
  214. image {
  215. width: 100%;
  216. height: 100%;
  217. }
  218. .number-order {
  219. background-color: #DC2828;
  220. position: absolute;
  221. font-size: 30rpx;
  222. height: 40rpx;
  223. width: 40rpx;
  224. text-align: center;
  225. border-radius: 20rpx;
  226. color: #ffffff;
  227. top: 10rpx;
  228. left: 25rpx;
  229. }
  230. .long-press-hint {
  231. position: absolute;
  232. bottom: -30rpx;
  233. left: 50%;
  234. transform: translateX(-50%);
  235. background-color: rgba(0, 0, 0, 0.7);
  236. color: #fff;
  237. font-size: 20rpx;
  238. padding: 4rpx 12rpx;
  239. border-radius: 12rpx;
  240. white-space: nowrap;
  241. opacity: 0.8;
  242. }
  243. }
  244. }
  245. @keyframes pulse {
  246. 0% {
  247. transform: scale(1);
  248. }
  249. 50% {
  250. transform: scale(1.05);
  251. }
  252. 100% {
  253. transform: scale(1);
  254. }
  255. }
  256. </style>