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

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