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

335 lines
9.8 KiB

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