index.vue 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. <template>
  2. <view class="callRecord_wrap">
  3. <view v-if="dataList.length > 0" class="timeline-list">
  4. <view v-for="(data, index) in dataList" :key="index" class="timeline-item">
  5. <view class="timeline-icon">
  6. <uni-icons type="phone" size="20" color="#6cc040"></uni-icons>
  7. </view>
  8. <view class="timeline-content">
  9. <view class="timestamp">{{ titleText(data) }}</view>
  10. <view class="info_top">
  11. <view class="info_left">
  12. <text class="name_text">{{ data.caller }} 打给 {{ data.callee }}</text>
  13. </view>
  14. <view class="info_right">
  15. {{ data.type === 1 ? data.followState : '' }}
  16. </view>
  17. <view class="delete-btn" @tap="handleDelete({ id: data.id })">
  18. <uni-icons type="trash" size="20" color="#ff6666"></uni-icons>
  19. </view>
  20. </view>
  21. <view class="file_name" v-if="data.type === '3'">{{ data.fileName }}</view>
  22. <view class="call_file" v-if="data.fileUrl">
  23. <view class="audio-container" @tap="toggleAudio(data, index)">
  24. <text class="audio-btn">{{ playingIndex === index ? '暂停' : '播放' }}</text>
  25. <text class="audio-hint">{{ playingIndex === index ? '点击暂停' : '点击播放录音' }}</text>
  26. </view>
  27. </view>
  28. </view>
  29. </view>
  30. </view>
  31. <view v-else class="empty_wrap">
  32. <uni-icons type="empty" size="60" color="#cccccc"></uni-icons>
  33. <text class="empty-text">暂无通话记录</text>
  34. </view>
  35. </view>
  36. </template>
  37. <script>
  38. export default {
  39. props: {
  40. clueId: {
  41. type: [String, Number],
  42. required: true
  43. },
  44. clueDetail: {
  45. type: Object,
  46. default: () => ({})
  47. }
  48. },
  49. data() {
  50. return {
  51. dataList: [],
  52. playingIndex: -1,
  53. innerAudio: null
  54. }
  55. },
  56. methods: {
  57. toggleAudio(data, index) {
  58. if (this.playingIndex === index) {
  59. if (this.innerAudio) {
  60. this.innerAudio.pause();
  61. }
  62. this.playingIndex = -1;
  63. return;
  64. }
  65. if (this.innerAudio) {
  66. this.innerAudio.stop();
  67. this.innerAudio.destroy();
  68. }
  69. this.innerAudio = uni.createInnerAudioContext();
  70. this.innerAudio.src = data.fileUrl;
  71. this.playingIndex = index;
  72. this.innerAudio.onPlay(() => {});
  73. this.innerAudio.onEnded(() => {
  74. this.playingIndex = -1;
  75. });
  76. this.innerAudio.onError((err) => {
  77. uni.showToast({ title: '播放失败', icon: 'none' });
  78. this.playingIndex = -1;
  79. });
  80. this.innerAudio.play();
  81. },
  82. titleText(data) {
  83. return `${data.createTime} 号码(${data.caller}) ${(data.type === 1 ? data.hangupCauseName : '上传录音')}`
  84. },
  85. handleDelete({
  86. id
  87. }) {
  88. uni.showModal({
  89. title: '提示',
  90. content: '是否确定删除?',
  91. confirmColor: '#6cc040',
  92. success: async (res) => {
  93. if (res.confirm) {
  94. try {
  95. await uni.$u.api.deleteClueFile([id])
  96. uni.showToast({
  97. title: '删除成功',
  98. icon: 'success',
  99. duration: 2000
  100. })
  101. this.getData()
  102. } catch (error) {
  103. uni.showToast({
  104. title: '删除失败',
  105. icon: 'error',
  106. duration: 2000
  107. })
  108. }
  109. }
  110. }
  111. })
  112. },
  113. async getData() {
  114. const {
  115. data
  116. } = await uni.$u.api.getCallClueFileByClueId({
  117. clueId: this.clueId
  118. });
  119. this.dataList = data;
  120. },
  121. },
  122. mounted() {
  123. this.getData();
  124. },
  125. beforeUnmount() {
  126. uni.$off('uploadRecordSuccess');
  127. if (this.innerAudio) {
  128. this.innerAudio.stop();
  129. this.innerAudio.destroy();
  130. }
  131. },
  132. created() {
  133. uni.$on('uploadRecordSuccess', () => {
  134. this.getData();
  135. });
  136. }
  137. }
  138. </script>
  139. <style lang="scss" scoped>
  140. .callRecord_wrap {
  141. position: relative;
  142. padding: 20rpx;
  143. min-height: 400px;
  144. box-sizing: border-box;
  145. .loading-mask {
  146. position: absolute;
  147. top: 0;
  148. left: 0;
  149. right: 0;
  150. bottom: 0;
  151. background-color: rgba(255, 255, 255, 0.8);
  152. display: flex;
  153. justify-content: center;
  154. align-items: center;
  155. z-index: 999;
  156. }
  157. .timeline-list {
  158. .timeline-item {
  159. display: flex;
  160. margin-bottom: 30rpx;
  161. .timeline-icon {
  162. width: 60rpx;
  163. height: 60rpx;
  164. border-radius: 50%;
  165. background-color: #f1f3f4;
  166. display: flex;
  167. justify-content: center;
  168. align-items: center;
  169. margin-right: 20rpx;
  170. flex-shrink: 0;
  171. }
  172. .timeline-content {
  173. width: 690rpx;
  174. .timestamp {
  175. font-size: 24rpx;
  176. color: #999;
  177. margin-bottom: 10rpx;
  178. }
  179. .info_top {
  180. display: flex;
  181. justify-content: space-between;
  182. align-items: center;
  183. margin-bottom: 20rpx;
  184. .info_left {
  185. .name_text {
  186. font-size: 28rpx;
  187. font-weight: 500;
  188. }
  189. }
  190. .info_right {
  191. color: #6cc040;
  192. font-size: 26rpx;
  193. }
  194. }
  195. .file_name {
  196. color: #999;
  197. font-size: 26rpx;
  198. }
  199. .call_file {
  200. width: 100%;
  201. border-radius: 12rpx;
  202. display: flex;
  203. align-items: center;
  204. justify-content: space-between;
  205. box-sizing: border-box;
  206. .audio-container {
  207. width: 100%;
  208. padding: 16rpx 0;
  209. .audio-btn {
  210. color: #6cc040;
  211. font-size: 28rpx;
  212. margin-right: 16rpx;
  213. }
  214. .audio-hint {
  215. color: #999;
  216. font-size: 24rpx;
  217. }
  218. }
  219. }
  220. }
  221. }
  222. }
  223. .empty_wrap {
  224. text-align: center;
  225. padding: 100rpx 0;
  226. .empty-text {
  227. display: block;
  228. margin-top: 30rpx;
  229. color: #999;
  230. font-size: 28rpx;
  231. }
  232. }
  233. }
  234. </style>