profile.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. <template>
  2. <div :class="['TUI-profile', !isPC && 'TUI-profile-h5']">
  3. <div
  4. v-if="displayType !== 'setting'"
  5. :class="['TUI-profile-basic', !isPC && 'TUI-profile-h5-basic']"
  6. >
  7. <img
  8. :class="[
  9. 'TUI-profile-basic-avatar',
  10. !isPC && 'TUI-profile-h5-basic-avatar',
  11. ]"
  12. :src="
  13. userProfile.avatar ||
  14. 'https://web.sdk.qcloud.com/component/TUIKit/assets/avatar_21.png'
  15. "
  16. >
  17. <div
  18. :class="[
  19. 'TUI-profile-basic-info',
  20. !isPC && 'TUI-profile-h5-basic-info',
  21. ]"
  22. >
  23. <div
  24. :class="[
  25. 'TUI-profile-basic-info-nick',
  26. !isPC && 'TUI-profile-h5-basic-info-nick',
  27. ]"
  28. >
  29. {{ userProfile.nick || "-" }}
  30. </div>
  31. <div
  32. :class="[
  33. 'TUI-profile-basic-info-id',
  34. !isPC && 'TUI-profile-h5-basic-info-id',
  35. ]"
  36. >
  37. <label
  38. :class="[
  39. 'TUI-profile-basic-info-id-label',
  40. !isPC && 'TUI-profile-h5-basic-info-id-label',
  41. ]"
  42. >{{ "用户ID" }}:</label>
  43. <div
  44. :class="[
  45. 'TUI-profile-basic-info-id-value',
  46. !isPC && 'TUI-profile-h5-basic-info-id-value',
  47. ]"
  48. >
  49. {{ userProfile.userID }}
  50. </div>
  51. </div>
  52. </div>
  53. </div>
  54. <div
  55. v-if="displayType !== 'profile' && (!isPC || showSetting)"
  56. ref="settingDomRef"
  57. :class="['TUI-profile-setting', !isPC && 'TUI-profile-h5-setting']"
  58. >
  59. <div
  60. v-for="(item, key) in settingList"
  61. :key="key"
  62. :class="[
  63. 'TUI-profile-setting-item',
  64. !isPC && 'TUI-profile-h5-setting-item',
  65. item.value === 'exit' && 'TUI-profile-h5-setting-item-exit',
  66. ]"
  67. >
  68. <div
  69. :class="[
  70. 'TUI-profile-setting-item-label',
  71. !isPC && 'TUI-profile-h5-setting-item-label',
  72. ]"
  73. @click="handleSettingListItemOnClick(item)"
  74. >
  75. <div :class="['label-left']">
  76. <div :class="['label-title']">
  77. {{ item.label }}
  78. </div>
  79. <div
  80. v-if="
  81. item.children && !isPC && item.childrenShowType === 'switch'
  82. "
  83. :class="['label-desc']"
  84. >
  85. {{ item.value }}
  86. </div>
  87. </div>
  88. <div :class="['label-right']">
  89. <div
  90. v-if="
  91. !isPC &&
  92. item.children &&
  93. item.selectedChild &&
  94. item.childrenShowType === 'bottomPopup'
  95. "
  96. :class="[
  97. 'TUI-profile-setting-item-label-value',
  98. !isPC && 'TUI-profile-h5-setting-item-label-value',
  99. ]"
  100. >
  101. {{ generateLabel(item) }}
  102. </div>
  103. <Icon
  104. v-if="item.children"
  105. :file="rightArrowIcon"
  106. width="14px"
  107. height="14px"
  108. style="width: 14px; height: 14px; display: flex"
  109. />
  110. </div>
  111. </div>
  112. <!-- 移动端 children显示,分多个类型 -->
  113. <BottomPopup
  114. v-if="
  115. item.children && !isPC && item.childrenShowType === 'bottomPopup'
  116. "
  117. :show="item.showChildren"
  118. @onClose="bottomPopupOnClose(item)"
  119. >
  120. <div
  121. v-for="child in item.children"
  122. :class="[
  123. 'TUI-profile-setting-item-bottom-popup',
  124. !isPC && 'TUI-profile-h5-setting-item-bottom-popup',
  125. ]"
  126. @click="handleSettingListItemOnClick(child)"
  127. >
  128. {{ child.label }}
  129. </div>
  130. </BottomPopup>
  131. </div>
  132. </div>
  133. </div>
  134. </template>
  135. <script lang="ts" setup>
  136. import TUIChatEngine, {
  137. TUIUserService,
  138. TUIStore,
  139. StoreName,
  140. TUIChatService,
  141. } from '@tencentcloud/chat-uikit-engine';
  142. import { TUILogin } from '@tencentcloud/tui-core';
  143. import { TUIGlobal } from '@tencentcloud/universal-api';
  144. import { ref, defineProps, onMounted } from '../../TUIKit/adapter-vue';
  145. import { isPC } from '../../TUIKit/utils/env';
  146. import { Toast, TOAST_TYPE } from '../../TUIKit/components/common/Toast/index';
  147. import BottomPopup from '../../TUIKit/components/common/BottomPopup/index.vue';
  148. import Icon from '../../TUIKit/components/common/Icon.vue';
  149. import rightArrowIcon from '../../TUIKit/assets/icon/right-icon.svg';
  150. import { IUserProfile } from '../../TUIKit/interface';
  151. import { onHide } from '@dcloudio/uni-app';
  152. import { translator } from '../../TUIKit/components/TUIChat/utils/translation';
  153. import { removeTokenStorage } from '../../utils/token';
  154. const props = defineProps({
  155. displayType: {
  156. type: String,
  157. default: 'all', // "profile"/"setting"/"all"
  158. },
  159. showSetting: {
  160. type: Boolean,
  161. default: false,
  162. },
  163. });
  164. const settingDomRef = ref();
  165. const userProfile = ref<IUserProfile>({});
  166. const settingList = ref<{
  167. [propsName: string]: {
  168. value: string;
  169. label: string;
  170. onClick?: any;
  171. // children相关
  172. selectedChild?: string;
  173. childrenShowType?: string; // "bottomPopup"/"switch"
  174. showChildren?: boolean;
  175. children?: {
  176. [propsName: string]: {
  177. value: string;
  178. label: string;
  179. onClick?: any;
  180. };
  181. };
  182. };
  183. }>({
  184. editProfile: {
  185. value: 'editProfile',
  186. label: '编辑资料(暂未开放)',
  187. onClick: (item: any) => {
  188. console.warn('编辑资料功能努力开发中,敬请期待');
  189. },
  190. },
  191. allowType: {
  192. value: 'allowType',
  193. label: '加我为好友时',
  194. selectedChild: '',
  195. childrenShowType: 'bottomPopup',
  196. showChildren: false,
  197. onClick: (item: any) => {
  198. if (!isPC) {
  199. item.showChildren = true;
  200. }
  201. },
  202. children: {
  203. [TUIChatEngine.TYPES.ALLOW_TYPE_ALLOW_ANY]: {
  204. value: TUIChatEngine.TYPES.ALLOW_TYPE_ALLOW_ANY,
  205. label: '同意任何用户加好友',
  206. onClick: (item: any) => {
  207. updateMyProfile({ allowType: item.value });
  208. },
  209. },
  210. [TUIChatEngine.TYPES.ALLOW_TYPE_NEED_CONFIRM]: {
  211. value: TUIChatEngine.TYPES.ALLOW_TYPE_NEED_CONFIRM,
  212. label: '需要验证',
  213. onClick: (item: any) => {
  214. updateMyProfile({ allowType: item.value });
  215. },
  216. },
  217. [TUIChatEngine.TYPES.ALLOW_TYPE_DENY_ANY]: {
  218. value: TUIChatEngine.TYPES.ALLOW_TYPE_DENY_ANY,
  219. label: '拒绝任何人加好友',
  220. onClick: (item: any) => {
  221. updateMyProfile({ allowType: item.value });
  222. },
  223. },
  224. },
  225. },
  226. displayMessageReadReceipt: {
  227. value: 'displayMessageReadReceipt',
  228. label: '消息阅读状态',
  229. selectedChild: 'userLevelReadReceiptOpen',
  230. childrenShowType: 'bottomPopup',
  231. showChildren: false,
  232. onClick(item: any) {
  233. if (!isPC) {
  234. item.showChildren = true;
  235. }
  236. },
  237. children: {
  238. userLevelReadReceiptOpen: {
  239. value: 'userLevelReadReceiptOpen',
  240. label: '开启',
  241. onClick() {
  242. switchEnabelUserLevelReadRecript(true);
  243. },
  244. },
  245. userLevelReadReceiptClose: {
  246. value: 'userLevelReadReceiptClose',
  247. label: '关闭',
  248. onClick() {
  249. switchEnabelUserLevelReadRecript(false);
  250. },
  251. },
  252. },
  253. },
  254. displayOnlineStatus: {
  255. value: 'displayOnlineStatus',
  256. label: '显示在线状态',
  257. selectedChild: 'userLevelOnlineStatusOpen',
  258. childrenShowType: 'bottomPopup',
  259. showChildren: false,
  260. onClick(item: any) {
  261. if (!isPC) {
  262. item.showChildren = true;
  263. }
  264. },
  265. children: {
  266. userLevelOnlineStatusOpen: {
  267. value: 'userLevelOnlineStatusOpen',
  268. label: '开启',
  269. onClick() {
  270. switchUserLevelOnlineStatus(true);
  271. },
  272. },
  273. userLevelOnlineStatusClose: {
  274. value: 'userLevelOnlineStatusClose',
  275. label: '关闭',
  276. onClick() {
  277. switchUserLevelOnlineStatus(false);
  278. },
  279. },
  280. },
  281. },
  282. translateLanguage: {
  283. value: 'translateLanguage',
  284. label: '翻译语言',
  285. selectedChild: 'zh',
  286. childrenShowType: 'bottomPopup',
  287. showChildren: false,
  288. onClick(item: any) {
  289. if (!isPC) {
  290. item.showChildren = true;
  291. }
  292. },
  293. children: {
  294. zh: {
  295. value: 'zh',
  296. label: '中文',
  297. onClick() {
  298. switchTranslationTargetLanguage('zh');
  299. },
  300. },
  301. en: {
  302. value: 'en',
  303. label: 'English',
  304. onClick() {
  305. switchTranslationTargetLanguage('en');
  306. },
  307. },
  308. jp: {
  309. value: 'jp',
  310. label: '日本語',
  311. onClick() {
  312. switchTranslationTargetLanguage('jp');
  313. },
  314. },
  315. kr: {
  316. value: 'kr',
  317. label: '한국인',
  318. onClick() {
  319. switchTranslationTargetLanguage('kr');
  320. },
  321. },
  322. },
  323. },
  324. exit: {
  325. value: 'exit',
  326. label: '退出登录',
  327. onClick: (item: any) => {
  328. TUILogin.logout().then(() => {
  329. uni.removeStorage({
  330. key: 'userInfo',
  331. });
  332. removeTokenStorage();
  333. TUIGlobal?.reLaunch({
  334. url: '/pages/views/login',
  335. });
  336. });
  337. },
  338. },
  339. });
  340. const handleSettingListItemOnClick = (item: any) => {
  341. if (item?.onClick && typeof item?.onClick === 'function') {
  342. item.onClick(item);
  343. }
  344. };
  345. const bottomPopupOnClose = (item: any) => {
  346. item.showChildren = false;
  347. };
  348. const generateLabel = (item: any) => {
  349. return item?.children[item?.selectedChild]?.label;
  350. };
  351. const updateMyProfile = (props: object) => {
  352. TUIUserService.updateMyProfile(props)
  353. .then((res: any) => {
  354. Toast({
  355. message: '更新用户资料成功',
  356. type: TOAST_TYPE.SUCCESS,
  357. duration: 0,
  358. });
  359. if ('allowType' in props) {
  360. settingList.value['allowType'].showChildren = false;
  361. }
  362. })
  363. .catch((err: any) => {
  364. console.warn('更新用户资料失败', err);
  365. Toast({
  366. message: '更新用户资料失败',
  367. type: TOAST_TYPE.ERROR,
  368. duration: 0,
  369. });
  370. });
  371. };
  372. TUIStore.watch(StoreName.USER, {
  373. userProfile: (userProfileData: IUserProfile) => {
  374. userProfile.value = userProfileData;
  375. if (userProfile?.value?.allowType) {
  376. settingList.value.allowType.selectedChild = userProfile?.value?.allowType;
  377. }
  378. },
  379. displayMessageReadReceipt(isDisplay: boolean) {
  380. settingList.value.displayMessageReadReceipt.selectedChild
  381. = isDisplay ? 'userLevelReadReceiptOpen' : 'userLevelReadReceiptClose';
  382. },
  383. displayOnlineStatus(isOnlineStatusDisplay: boolean) {
  384. settingList.value.displayOnlineStatus.selectedChild = isOnlineStatusDisplay
  385. ? 'userLevelOnlineStatusOpen'
  386. : 'userLevelOnlineStatusClose';
  387. },
  388. });
  389. // 规避TUIStore.watch userProfile 登录后暂时不能及时触发更新
  390. onMounted(() => {
  391. // 查询自己的资料
  392. TUIUserService.getUserProfile().then((res: any) => {
  393. userProfile.value = res.data;
  394. });
  395. });
  396. // tabbar 切换其他tab,关闭profile已经打开的设置弹窗
  397. onHide(() => {
  398. for (const settingItemKey in settingList.value) {
  399. if (settingList?.value[settingItemKey]?.hasOwnProperty('showChildren')) {
  400. settingList.value[settingItemKey].showChildren = false;
  401. }
  402. }
  403. });
  404. function switchEnabelUserLevelReadRecript(status: boolean) {
  405. TUIStore.update(StoreName.USER, 'displayMessageReadReceipt', status);
  406. settingList.value['displayMessageReadReceipt'].showChildren = false;
  407. }
  408. function switchUserLevelOnlineStatus(status: boolean) {
  409. TUIUserService.switchUserStatus({ displayOnlineStatus: status });
  410. settingList.value['displayOnlineStatus'].showChildren = false;
  411. }
  412. function switchTranslationTargetLanguage(lang: string) {
  413. translator.clear();
  414. TUIChatService.setTranslationLanguage(lang);
  415. settingList.value.translateLanguage.selectedChild = lang;
  416. settingList.value.translateLanguage.showChildren = false;
  417. }
  418. </script>
  419. <style lang="scss" scoped src="../../styles/profile/index.scss"></style>