ChatHeader.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. <template>
  2. <view class="chat_header" :class="$companyUserIsLogin()?'ybc':'ybc'">
  3. <view class="self_info">
  4. <block v-if="$companyUserIsLogin()">
  5. <my-avatar :src="storeSelfInfo.faceURL" :desc="storeSelfInfo.nickname" size="46" />
  6. <view class="msgIcon">
  7. <view class="msgTitle">{{ storeSelfInfo.nickname }}</view>
  8. <view class="msgSubTitle">管家</view>
  9. </view>
  10. <view v-if="false" style="position: absolute; left: 51%; transform: translateX(-50%); display: flex; align-items: center;">
  11. <text class="nickname">消息{{getUnReadCount()}}</text>
  12. <view class="self_info_desc" v-if="false" style="margin-left: 10rpx;">
  13. <view class="user_state">
  14. <!-- <text class="nickname">{{ storeSelfInfo.nickname }}</text> -->
  15. <view v-if="!storeReinstall && false">
  16. <view class="tag" v-if="storeIsSyncing">
  17. <image class="loading" style="height: 24rpx; width: 24rpx" src="../../../../static/images/loading.png" alt="" />
  18. <text class="status">同步中</text>
  19. </view>
  20. <view class="tag" v-if="connectStart == 0">
  21. <image class="loading" style="height: 24rpx; width: 24rpx" src="../../../../static/images/loading.png" alt="" />
  22. <text class="status">连接中</text>
  23. </view>
  24. <view class="err-tag" v-if="connectStart == -1">
  25. <image style="height: 24rpx; width: 24rpx" src="../../../../static/images/sync_error.png" alt="" />
  26. <text class="status">连接失败</text>
  27. </view>
  28. </view>
  29. </view>
  30. </view>
  31. </view>
  32. </block>
  33. <block v-else>
  34. <my-avatar :src="storeSelfInfo.faceURL" :desc="storeSelfInfo.nickname" size="40" />
  35. <view class="msgIcon">
  36. <view class="msgTitle">{{ truncatedName }}</view>
  37. <view class="msgSubTitle">{{$getUserInfo().userId}}</view>
  38. </view>
  39. <view style="position: absolute; left: 51%; transform: translateX(-50%); display: flex; align-items: center;">
  40. <text class="nickname">消息{{getUnReadCount()}}</text>
  41. <view class="self_info_desc" v-if="false" style="margin-left: 10rpx;">
  42. <view class="user_state">
  43. <!-- <text class="nickname">{{ storeSelfInfo.nickname }}</text> -->
  44. <view v-if="!storeReinstall && false">
  45. <view class="tag" v-if="storeIsSyncing">
  46. <image class="loading" style="height: 24rpx; width: 24rpx" src="../../../../static/images/loading.png" alt="" />
  47. <text class="status">同步中</text>
  48. </view>
  49. <view class="tag" v-if="connectStart == 0">
  50. <image class="loading" style="height: 24rpx; width: 24rpx" src="../../../../static/images/loading.png" alt="" />
  51. <text class="status">连接中</text>
  52. </view>
  53. <view class="err-tag" v-if="connectStart == -1">
  54. <image style="height: 24rpx; width: 24rpx" src="../../../../static/images/sync_error.png" alt="" />
  55. <text class="status">连接失败</text>
  56. </view>
  57. </view>
  58. </view>
  59. </view>
  60. </view>
  61. </block>
  62. </view>
  63. <view class="right_action">
  64. <view @click="toSearchIM()" class="search_icon">
  65. <image src="/pages_im/static/images/common_search.png" ></image>
  66. </view>
  67. <view @click="showMore" v-if="showMoreMenu" class="more_icon">
  68. <image src="/pages_im/static/images/new/add_icon24.svg"></image>
  69. </view>
  70. <u-overlay :show="moreMenuVisible" @click="moreMenuVisible = false" opacity="0">
  71. <view :style="{ top: popMenuPosition.top, right: popMenuPosition.right }" class="more_menu">
  72. <view @click="clickMenu(item)" v-for="item in moreMenus" :key="item.idx" class="menu_item">
  73. <image :src="item.icon" mode=""></image>
  74. <text>{{ item.title }}</text>
  75. </view>
  76. </view>
  77. </u-overlay>
  78. </view>
  79. </view>
  80. </template>
  81. <script>
  82. import { mapGetters } from 'vuex';
  83. import MyAvatar from '../../../../components/MyAvatar/index.vue';
  84. import { scanQrCodeResult,IMSDK } from '../../../../util/imCommon';
  85. import { callingModule } from '../../../../util/imCommon';
  86. export default {
  87. name: 'ChatHeader',
  88. components: {
  89. MyAvatar
  90. },
  91. props: {},
  92. data() {
  93. return {
  94. connectStart: -2,
  95. moreMenuVisible: false,
  96. popMenuPosition: {
  97. top: 0,
  98. right: 0
  99. },
  100. showMoreMenu:false,
  101. moreMenus: [
  102. // {
  103. // idx: 0,
  104. // title: '扫一扫',
  105. // icon: require('../../../../static/images/new/scan_icon24.svg')
  106. // },
  107. // {
  108. // idx: 1,
  109. // title: '添加好友',
  110. // icon: require('../../../../static/images/new/add_friend_icon24.svg')
  111. // },
  112. // {
  113. // idx: 2,
  114. // title: '添加群聊',
  115. // icon: require('../../../../static/images/new/add_group_chat_icon24.svg')
  116. // }
  117. // ,{
  118. // idx: 3,
  119. // title: '创建群聊',
  120. // icon: require('../../../../static/images/new/create_group_chat_icon24.svg')
  121. // }
  122. // ,{
  123. // idx: 4,
  124. // title: '视频会议',
  125. // icon: require('../../../../static/images/new/video_conference_icon24.svg')
  126. // }
  127. ]
  128. };
  129. },
  130. computed: {
  131. ...mapGetters(['storeSelfInfo', 'storeIsSyncing', 'storeReinstall','storeUnReadCount']),
  132. truncatedName(){
  133. let name = (this.storeSelfInfo && this.storeSelfInfo.nickname) || '用户';
  134. if (name.length > 6) {
  135. return name.substring(0, 6) + '...';
  136. }
  137. return name;
  138. },
  139. },
  140. mounted() {
  141. this.subscribeAll();
  142. this.initMenu();
  143. uni.$on('refreshIMMenu', () => {
  144. this.initMenu();
  145. });
  146. },
  147. beforeDestroy() {
  148. this.unsubscribeAll();
  149. },
  150. methods: {
  151. initMenu(){
  152. this.moreMenus=[];
  153. if (this.$companyUserIsLogin()) {
  154. this.showMoreMenu=true;
  155. this.addCompanyMenu();
  156. } else {
  157. this.showMoreMenu=true;
  158. this.addUserMenu();
  159. }
  160. },
  161. addCompanyMenu() {
  162. //this.moreMenus.push({idx: 0,title: '扫一扫',icon: require('../../../../static/images/new/scan_icon24.svg')});
  163. //this.moreMenus.push({idx: 1,title: '添加好友',icon: require('../../../../static/images/new/add_friend_icon24.svg')});
  164. this.moreMenus.push({idx: 2,title: '添加群聊',icon: '/pages_im/static/images/new/add_group_chat_icon24.svg'});
  165. this.moreMenus.push({idx: 3, title: '通讯录', icon: '/pages_im/static/images/new/add_friend_icon24.svg' });
  166. },
  167. addUserMenu() {
  168. // this.moreMenus.push({idx: 1,title: '添加好友',icon: require('../../../../static/images/new/add_friend_icon24.svg')});
  169. // this.moreMenus.push({idx: 2,title: '添加群聊',icon: require('../../../../static/images/new/add_group_chat_icon24.svg')});
  170. this.moreMenus.push({idx: 3, title: '通讯录', icon: '/pages_im/static/images/new/add_friend_icon24.svg' });
  171. },
  172. toNativeCallHistory() {
  173. uni.navigateTo({
  174. url: '/pages/moments/index/index'
  175. });
  176. },
  177. toSearchIM() {
  178. uni.navigateTo({
  179. url: '/pages_im/pages/common/globalSearch/index'
  180. });
  181. },
  182. setStateStart() {
  183. this.connectStart = 0;
  184. },
  185. setStateSuccess() {
  186. const _IMSDK = IMSDK;
  187. _IMSDK.asyncApi('getSignalingInvitationInfoStartApp', _IMSDK.uuid()).then(({ data }) => {
  188. callingModule.launchLiveChat(data);
  189. });
  190. this.connectStart = 1;
  191. },
  192. setStateError() {
  193. this.connectStart = -1;
  194. },
  195. subscribeAll() {
  196. // const _IMSDK = IMSDK;
  197. IMSDK.subscribe(IMSDK.IMEvents.OnConnecting, this.setStateStart);
  198. IMSDK.subscribe(IMSDK.IMEvents.OnConnectSuccess, this.setStateSuccess);
  199. IMSDK.subscribe(IMSDK.IMEvents.OnConnectFailed, this.setStateError);
  200. },
  201. unsubscribeAll() {
  202. // const _IMSDK = IMSDK;
  203. IMSDK.unsubscribe(IMSDK.IMEvents.OnConnecting, this.setStateStart);
  204. IMSDK.unsubscribe(IMSDK.IMEvents.OnConnectSuccess, this.setStateSuccess);
  205. IMSDK.unsubscribe(IMSDK.IMEvents.OnConnectFailed, this.setStateError);
  206. },
  207. clickMenu({ idx }) {
  208. switch (idx) {
  209. case 0:
  210. // uni.scanCode({
  211. // scanType: ['qrCode'],
  212. // success: ({ result }) => scanQrCodeResult(result)
  213. // });
  214. uni.navigateTo({
  215. url: '/pages_watch/healthMonitoring/scanCode?typeFun=getIndexScanCode'
  216. });
  217. break;
  218. case 1:
  219. case 2:
  220. {
  221. uni.navigateTo({
  222. url: `/pages_im/pages/common/searchUserOrGroup/index?isSearchGroup=${idx === 2}`
  223. });
  224. }
  225. break;
  226. case 3:
  227. uni.navigateTo({
  228. // url: `/pages_im/pages/contact/index/index`,
  229. url: `/pages_im/pages/contact/friendList/index`
  230. });
  231. break;
  232. case 5:
  233. uni.navigateTo({
  234. url: `/pages_im/pages/common/createGroup/index`
  235. });
  236. break;
  237. // case 4:
  238. // uni.$u.route('/pages_im/pages/common/meetingCenter/index');
  239. // break;
  240. default:
  241. break;
  242. }
  243. },
  244. async showMore() {
  245. const { right, bottom } = await this.getEl('.more_icon');
  246. this.popMenuPosition.right = uni.getWindowInfo().windowWidth - right + 'px';
  247. this.popMenuPosition.top = bottom + 'px';
  248. this.moreMenuVisible = true;
  249. },
  250. getEl(el) {
  251. return new Promise((resolve) => {
  252. const query = uni.createSelectorQuery().in(this);
  253. query.select(el).boundingClientRect((data) => {
  254. // 存在data,且存在宽和高,视为渲染完毕
  255. resolve(data);
  256. }).exec();
  257. });
  258. },
  259. getUnReadCount(){
  260. if(this.storeUnReadCount>0){
  261. return "("+this.storeUnReadCount+")";
  262. }else{
  263. return "";
  264. }
  265. }
  266. }
  267. };
  268. </script>
  269. <style lang="scss" scoped>
  270. @keyframes loading {
  271. 0% {
  272. transform: rotate(0deg);
  273. }
  274. 100% {
  275. transform: rotate(360deg);
  276. }
  277. }
  278. .chat_header {
  279. display: flex;
  280. justify-content: center;
  281. align-items: center;
  282. position: relative;
  283. padding: 20rpx 20rpx;
  284. padding-right:0rpx;
  285. padding-top: var(--status-bar-height);
  286. background: #fff;
  287. .self_info {
  288. display: flex;
  289. justify-content: space-between;
  290. align-items: center;
  291. &_desc {
  292. @include colBox(true);
  293. // margin-left: 24rpx;
  294. color: $uni-text-color;
  295. .company {
  296. @include nomalEllipsis();
  297. font-size: 24rpx;
  298. margin-bottom: 10rpx;
  299. max-width: 300rpx;
  300. }
  301. .user_state {
  302. @include vCenterBox();
  303. .nickname {
  304. @include nomalEllipsis();
  305. font-size: 26rpx;
  306. max-width: 240rpx;
  307. }
  308. .err-tag {
  309. display: flex;
  310. justify-content: center;
  311. align-items: center;
  312. width: 152rpx;
  313. height: 44rpx;
  314. background: #ffe1dd;
  315. border-radius: 12rpx 12rpx 12rpx 12rpx;
  316. margin-left: 8rpx;
  317. .status {
  318. font-size: 24rpx;
  319. margin-left: 8rpx;
  320. font-weight: 400;
  321. color: #ff381f;
  322. }
  323. }
  324. .tag {
  325. display: flex;
  326. justify-content: center;
  327. align-items: center;
  328. width: 152rpx;
  329. height: 44rpx;
  330. background: #f2f8ff;
  331. border-radius: 12rpx 12rpx 12rpx 12rpx;
  332. margin-left: 8rpx;
  333. .loading {
  334. animation: loading 1.5s infinite;
  335. }
  336. .status {
  337. font-size: 24rpx;
  338. margin-left: 8rpx;
  339. font-weight: 400;
  340. color: #0089ff;
  341. }
  342. }
  343. .online_state {
  344. @include vCenterBox();
  345. margin-left: 24rpx;
  346. font-size: 24rpx;
  347. .dot {
  348. background-color: #10cc64;
  349. width: 12rpx;
  350. height: 12rpx;
  351. border-radius: 50%;
  352. margin-right: 12rpx;
  353. }
  354. }
  355. }
  356. }
  357. }
  358. .right_action {
  359. position: absolute;
  360. right: 20rpx;
  361. display: flex;
  362. .search_icon {
  363. margin-right: 24rpx;
  364. image {
  365. width: 62rpx;
  366. height: 62rpx;
  367. }
  368. }
  369. .call_icon {
  370. margin-right: 24rpx;
  371. image {
  372. width: 56rpx;
  373. height: 56rpx;
  374. }
  375. }
  376. .more_icon {
  377. image {
  378. width: 56rpx;
  379. height: 56rpx;
  380. }
  381. }
  382. .more_menu {
  383. position: absolute;
  384. // bottom: 0;
  385. // left: 100%;
  386. z-index: 999;
  387. // transform: translate(-100%, 100%);
  388. box-shadow: 0px 0px 6px 2px rgba(0, 0, 0, 0.16);
  389. width: max-content;
  390. border-radius: 12rpx;
  391. background-color: #fff;
  392. .menu_item {
  393. display: flex;
  394. justify-content: flex-start;
  395. align-items: center;
  396. padding: 20rpx 24rpx;
  397. font-size: 32rpx;
  398. color: $uni-text-color;
  399. border-bottom: 1px solid #f0f0f0;
  400. image {
  401. width: 24px;
  402. height: 24px;
  403. margin-right: 24rpx;
  404. }
  405. &:last-child {
  406. border: none;
  407. }
  408. }
  409. }
  410. }
  411. .nickname {
  412. font-size: 34rpx;
  413. color: #222;
  414. font-weight: 600;
  415. margin-left: 0rpx;
  416. margin-bottom:20rpx;
  417. }
  418. .msgTitle {
  419. font-size: 30rpx;
  420. color: #333;
  421. font-weight: 600;
  422. margin-left: 14rpx;
  423. margin-bottom:2rpx;
  424. }
  425. .msgSubTitle {
  426. font-size: 26rpx;
  427. color: #757575;
  428. font-weight: normal;
  429. margin-left: 14rpx;
  430. }
  431. .msgIcon {
  432. display: flex;
  433. flex-direction: column;
  434. justify-content: space-between;
  435. }
  436. }
  437. .ybc {
  438. justify-content: space-between;
  439. }
  440. .yc{
  441. justify-content: center;
  442. }
  443. </style>