zhuantiInfo.vue 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. <template>
  2. <view class="ezy-biaoqing-page">
  3. <view class="ezy-nav-bar-icon" @click="goUpPage"></view>
  4. <view class="biaoqing-bj-box" :class="'biaoqing-bj'+ type">
  5. <view v-for="(item, index) in bubbles" :key="index" class="qipao-item-box"
  6. :class="{ 'qipao-item-disabled': item.disabled }" @click="qipaoBtn(index)">
  7. <view v-if="item.showFlag ==1">
  8. <view :class="item.iconType"></view>
  9. <view class="show-biaoqing-icon"></view>
  10. <view class="qipao-text-row">
  11. <text>可扎破</text>
  12. <icon class="shou-icon"></icon>
  13. </view>
  14. </view>
  15. </view>
  16. <view class="biaoqing-img"></view>
  17. </view>
  18. <view :class="maikeType">
  19. <view class="maike-box" @touchstart="handleTouchStart" @touchend="handleTouchEnd"
  20. @touchcancel="handleTouchCancel" @touchmove="handleTouchMove">
  21. <icon class="maike-icon"></icon>
  22. </view>
  23. <text class="maike-text" v-if="maikeType =='maike-anzhu'">{{ buttonText }}</text>
  24. <text class="maike-text" v-if="maikeType =='maike-songkai'">{{ buttonText }}</text>
  25. </view>
  26. <CustomTabBar :currentTabNumber="1"></CustomTabBar>
  27. </view>
  28. </template>
  29. <script setup>
  30. import {
  31. toast,
  32. getUserIdentity
  33. } from "@/utils/common";
  34. import cacheManager from '@/utils/cacheManager.js';
  35. import {
  36. moodAdd,
  37. moodLess,
  38. moodSize
  39. } from '@/api/zhuanti.js'
  40. import CustomTabBar from '@/components/custom-tabbar/custom-tabbar.vue';
  41. import {
  42. reactive,
  43. ref,
  44. computed,
  45. onBeforeUnmount
  46. } from "vue";
  47. import {
  48. onLoad
  49. } from '@dcloudio/uni-app';
  50. const maikeType = ref('maike-anzhu');
  51. // 定义气泡数据状态
  52. // const bubbles = reactive(
  53. // // Array.from({
  54. // // length: 5
  55. // // }, () => ({
  56. // // disabled: false, // 是否破裂
  57. // // iconType: "qipao-mask", //mask
  58. // // }))
  59. // );
  60. let bubbles = ref([])
  61. const type = ref(null);
  62. const audioContext = ref(null);
  63. const audioPath = '/static/mp3/zhuanti/qipao.mp3';
  64. const isPlaying = ref(false);
  65. const showIcon = ref(null);
  66. const isPressing = ref(false); // 是否正在按压
  67. const isCancelled = ref(false); // 是否已取消
  68. const touchPos = ref({
  69. x: 0,
  70. y: 0
  71. }); // 触摸位置
  72. onLoad((options) => {
  73. console.log('opt', options);
  74. type.value = options.type
  75. getSize()
  76. initAudio()
  77. })
  78. function initAudio() {
  79. audioContext.value = uni.createInnerAudioContext();
  80. audioContext.value.src = audioPath;
  81. // 设置事件监听
  82. audioContext.value.onPlay(() => {
  83. console.log('开始播放');
  84. isPlaying.value = true;
  85. });
  86. audioContext.value.onPause(() => {
  87. console.log('暂停播放');
  88. isPlaying.value = false;
  89. });
  90. audioContext.value.onStop(() => {
  91. console.log('停止播放');
  92. isPlaying.value = false;
  93. });
  94. audioContext.value.onError((err) => {
  95. console.error('播放错误:', err);
  96. isPlaying.value = false;
  97. uni.showToast({
  98. title: '播放失败',
  99. icon: 'none'
  100. });
  101. });
  102. }
  103. function getSize() {
  104. moodSize({
  105. type: type.value
  106. }).then(res => {
  107. console.log('res', res);
  108. if (res.code == 0) {
  109. bubbles.value = Array.from({
  110. length: Number(res.data)
  111. }, () => ({
  112. disabled: false,
  113. iconType: "qipao-mask",
  114. showFlag: "1",
  115. }));
  116. } else {
  117. toast("查询数量失败")
  118. return false
  119. }
  120. })
  121. }
  122. // 点击气泡
  123. function qipaoBtn(index) {
  124. moodLess({
  125. type: type.value
  126. }).then(res => {
  127. console.log('res', res);
  128. if (res.code == 0) {
  129. // if (isPlaying.value) {
  130. // console.log('1231231231241242314');
  131. // audioContext.value.stop();
  132. // } else {
  133. // console.log('bibo');
  134. // audioContext.value.play(); // 开始播放
  135. // }
  136. bubbles.value[index].disabled = true;
  137. bubbles.value[index].iconType = "polie-qipao-mask";
  138. setTimeout(() => {
  139. bubbles.value[index] = {};
  140. }, 1000)
  141. console.log('bubbles', bubbles.value);
  142. // setTimeout(() => {
  143. // bubbles.value.splice(index, 1)
  144. // }, 1000)
  145. } else {
  146. toast("戳破气泡失败!")
  147. return false
  148. }
  149. })
  150. // wgy看这↓ 在这里播放mp3,时间一秒及删除接口
  151. }
  152. // const buttonState = computed(() => {
  153. // if (isCancelled.value) return 'cancelled';
  154. // return isPressing.value ? 'recording' : 'idle';
  155. // });
  156. // const showCancel = computed(() => {
  157. // return isPressing.value && !isCancelled.value;
  158. // });
  159. const buttonText = computed(() => {
  160. if (isCancelled.value) return '松开取消';
  161. return isPressing.value ? '松开发送' : '按住说话';
  162. });
  163. const handleTouchStart = (e) => {
  164. isPressing.value = true;
  165. isCancelled.value = false;
  166. touchPos.value = {
  167. x: e.touches[0].clientX,
  168. y: e.touches[0].clientY
  169. };
  170. // 这里触发开始逻辑(如开始录音)
  171. console.log('操作开始');
  172. maikeType.value = 'maike-songkai';
  173. };
  174. const handleTouchEnd = () => {
  175. if (isPressing.value && !isCancelled.value) {
  176. console.log('操作完成');
  177. const newLength = bubbles.value.filter(item =>
  178. Object.keys(item).length > 0
  179. ).length;
  180. if (newLength == 5) {
  181. console.log('5555');
  182. maikeType.value = 'maike-anzhu';
  183. resetState();
  184. return false
  185. }
  186. moodAdd({
  187. type: type.value
  188. }).then(res => {
  189. console.log('moodAdd', res);
  190. const array = {
  191. disabled: false,
  192. iconType: "qipao-mask",
  193. showFlag: "1",
  194. }
  195. addItem(array)
  196. //bubbles.value.push(array)
  197. })
  198. }
  199. console.log('bubbles', bubbles.value);
  200. maikeType.value = 'maike-anzhu';
  201. resetState();
  202. };
  203. function addItem(item) {
  204. const emptyIndex = bubbles.value.findIndex(item =>
  205. Object.keys(item).length == 0
  206. );
  207. if (emptyIndex !== -1) {
  208. // 如果找到空对象,替换它
  209. bubbles.value[emptyIndex] = item;
  210. } else {
  211. // 如果没有空对象,推入新项
  212. bubbles.value.push(item);
  213. }
  214. return bubbles.value;
  215. }
  216. const handleTouchCancel = () => {
  217. isCancelled.value = true;
  218. maikeType.value = 'maike-songkai';
  219. resetState();
  220. console.log('操作取消');
  221. };
  222. const handleTouchMove = (e) => {
  223. if (!isPressing.value) return;
  224. // 计算二维平面上两点之间直线距离
  225. const currentX = e.touches[0].clientX;
  226. const currentY = e.touches[0].clientY;
  227. const moveDistance = Math.sqrt(
  228. Math.pow(currentX - touchPos.value.x, 2) +
  229. Math.pow(currentY - touchPos.value.y, 2)
  230. );
  231. if (moveDistance > 50) {
  232. isCancelled.value = true;
  233. } else if (isCancelled.value && moveDistance <= 50) {
  234. isCancelled.value = false;
  235. }
  236. };
  237. const resetState = () => {
  238. isPressing.value = false;
  239. setTimeout(() => {
  240. isCancelled.value = false;
  241. }, 500); // 短暂保持
  242. };
  243. function goUpPage() {
  244. uni.redirectTo({
  245. url: `/pages/zhuanti/index`
  246. })
  247. }
  248. </script>