create.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. <template>
  2. <view class="TUI-Create-conversation-container">
  3. <view class="tui-search-area">
  4. <view class="tui-search-bar">
  5. <!-- <image class="tui-searchcion" src="/static/static/assets/serach-icon.svg"></image> -->
  6. <input
  7. class="tui-search-bar-input"
  8. :value="inputUserID"
  9. placeholder="请输入用户ID"
  10. @input="handleUserIdInput"
  11. @confirm="handleGetUserProfileInfo"
  12. @blur="handleGetUserProfileInfo"
  13. />
  14. </view>
  15. <view class="tui-showID"></view>
  16. </view>
  17. <!-- 用户列表 -->
  18. <view class="tui-person-list-container">
  19. <view
  20. class="tui-person-to-invite"
  21. v-for="(item, index) in chooseUserList"
  22. :key="index"
  23. @click="handleChoose(item)">
  24. <view class="tui-person-choose-container">
  25. <image
  26. class="tui-normal-choose"
  27. v-if="item.isChoose"
  28. src="../../assets/icon/selected.svg"
  29. ></image>
  30. <view class="tui-normal-unchoose" v-else></view>
  31. </view>
  32. <view class="tui-person-profile">
  33. <image
  34. class="tui-person-profile-avatar"
  35. :src="
  36. item.avatar ||
  37. 'https://sdk-web-1252463788.cos.ap-hongkong.myqcloud.com/component/TUIKit/assets/avatar_21.png'
  38. "
  39. >
  40. </image>
  41. <view>
  42. <view class="tui-person-profile-nick">{{ item.nick }}</view>
  43. <view class="tui-person-profile-userID"
  44. >用户ID:{{ item.userID }}</view
  45. >
  46. </view>
  47. </view>
  48. </view>
  49. </view>
  50. <view class="tui-confirm-btn-container">
  51. <view class="tui-confirm-btn" @tap="handleCreateGroup">确认创建</view>
  52. </view>
  53. </view>
  54. </template>
  55. <script>
  56. import { defineComponent, watchEffect, reactive, toRefs } from "vue";
  57. import store from "@/store";
  58. import { onLoad } from "@dcloudio/uni-app";
  59. export default defineComponent({
  60. name: "Create",
  61. props: {},
  62. setup(props, context) {
  63. const TUIConversationServer = uni.$TUIKit.TUIConversationServer;
  64. const { userInfo } = store.state.timStore;
  65. const data = reactive({
  66. userID: userInfo?.userID || "",
  67. inputUserID: "",
  68. chooseUserList: [],
  69. title: "发起会话",
  70. myProfile: {},
  71. type: uni.$TIM.TYPES.CONV_C2C,
  72. });
  73. // 获取页面参数
  74. onLoad((options) => {
  75. data.title = (options && options.title) || "发起会话";
  76. data.type = (options && options.type) || uni.$TIM.TYPES.CONV_C2C;
  77. });
  78. // 输入查询 inputUserID 变动
  79. const handleUserIdInput = (e) => {
  80. data.inputUserID = e.detail.value;
  81. uni.$TUIKit.getMyProfile().then((imResponse) => {
  82. data.myProfile = imResponse.data;
  83. })
  84. .catch((imError) => {
  85. console.warn("getMyProfile error:", imError); // 获取个人资料失败的相关信息
  86. });
  87. };
  88. // 获取用户信息
  89. const handleGetUserProfileInfo = () => {
  90. if (!data.inputUserID) return;
  91. const userIDList = [data.inputUserID];
  92. //uni.showLoading({ title: "加载中" });
  93. uni.$TUIKit.getUserProfile({ userIDList }).then((imRes) => {
  94. uni.hideLoading();
  95. if (imRes.data.length > 0) {
  96. const userInfo = {
  97. ...imRes.data[0],
  98. isChoose: false,
  99. };
  100. if (data.chooseUserList.filter(
  101. (obj) => userInfo.userID === obj.userID
  102. ).length === 0
  103. ) {
  104. data.chooseUserList.push(userInfo);
  105. }
  106. } else {
  107. uni.showToast({
  108. title: "搜索用户不存在",
  109. icon: "error",
  110. });
  111. data.inputUserID = "";
  112. }
  113. })
  114. .catch((err) => {
  115. uni.hideLoading();
  116. });
  117. };
  118. // 用户选择切换
  119. const handleChoose = (item) => {
  120. const list = data.chooseUserList.map((obj) => {
  121. if (item.userID == obj.userID) {
  122. return {
  123. ...obj,
  124. isChoose: !obj.isChoose,
  125. };
  126. } else {
  127. return obj;
  128. }
  129. });
  130. data.chooseUserList = list;
  131. };
  132. // 确认邀请
  133. const handleCreateGroup = () => {
  134. const chooseList = data.chooseUserList.filter((obj) => obj.isChoose);
  135. if (chooseList.length > 0) {
  136. switch (data.type) {
  137. case uni.$TIM.TYPES.CONV_C2C: {
  138. if (chooseList.length > 1) {
  139. uni.showToast({
  140. title: `“发起会话”仅能选择一个用户`,
  141. icon: "none",
  142. });
  143. return;
  144. } else {
  145. const conversationId = `C2C${chooseList[0].userID}`;
  146. console.log(conversationId)
  147. handleJumpToChat(conversationId);
  148. }
  149. break;
  150. }
  151. // 群操作
  152. case uni.$TIM.TYPES.GRP_WORK:
  153. case uni.$TIM.TYPES.GRP_PUBLIC:
  154. case uni.$TIM.TYPES.GRP_MEETING: {
  155. let name = "";
  156. if (chooseList.length > 2) {
  157. name =
  158. chooseList
  159. .slice(0, 3)
  160. .map((obj) => obj.nick || obj.userID)
  161. .join(",") || "";
  162. } else {
  163. name =
  164. chooseList.map((obj) => obj.nick || obj.userID).join(",") +
  165. "、" +
  166. (data.myProfile?.nick || data.myProfile?.userID);
  167. }
  168. const groupOptions = {
  169. avatar:
  170. "https://web.sdk.qcloud.com/component/TUIKit/assets/group_avatar.png",
  171. type: data.type,
  172. name: name,
  173. memberList: chooseList.map((obj) => ({
  174. userID: obj.userID,
  175. role: obj.role,
  176. memberCustomField: obj.memberCustomField,
  177. })),
  178. };
  179. uni.showLoading({ title: "群组创建中…" });
  180. uni.$TUIKit
  181. .createGroup(groupOptions)
  182. .then((imResponse) => {
  183. uni.hideLoading();
  184. const { groupID } = imResponse.data && imResponse.data.group;
  185. if (groupID) {
  186. const conversationId = `GROUP${groupID}`;
  187. handleJumpToChat(conversationId);
  188. }
  189. })
  190. .catch((err) => {
  191. uni.showToast({ title: "群组创建失败!" });
  192. uni.hideLoading();
  193. });
  194. break;
  195. }
  196. }
  197. } else {
  198. uni.showToast({
  199. title: "请选择相关用户",
  200. icon: "none",
  201. });
  202. }
  203. };
  204. // 跳转到会话聊天
  205. const handleJumpToChat = (conversationId) => {
  206. store.commit("timStore/setConversationID", conversationId);
  207. //uni.$TUIKit.TUIChatServer.updateStore(conversationId)
  208. TUIConversationServer.setMessageRead(conversationId);
  209. TUIConversationServer.getConversationProfile(conversationId)
  210. .then((res) => {
  211. // 通知 TUIChat 关闭当前会话
  212. const { conversation } = res.data;
  213. console.log("create conversation response = ", res);
  214. store.commit("timStore/setConversation", conversation);
  215. let url = "../TUIChat/index";
  216. if (conversationId.slice(0, 5) === "GROUP") {
  217. const { name } = conversation.groupProfile;
  218. url = `${url}?conversationName=${name}`;
  219. } else if (conversationId.slice(0, 3) === "C2C") {
  220. const { nick: name } = conversation.userProfile;
  221. url = `${url}?conversationName=${
  222. conversation.userProfile.nick?.nick ||
  223. conversation.userProfile.userID
  224. }`;
  225. }
  226. uni.redirectTo({ url });
  227. })
  228. .catch((err) => {
  229. console.warn("获取 group profile 异常 = ", err);
  230. });
  231. };
  232. return {
  233. ...toRefs(data),
  234. handleUserIdInput,
  235. handleGetUserProfileInfo,
  236. handleChoose,
  237. handleCreateGroup,
  238. };
  239. },
  240. });
  241. </script>
  242. <style lang="scss" scoped>
  243. .TUI-Create-conversation-container {
  244. width: 100%;
  245. height: 100%;
  246. background-color: #f4f5f9;
  247. overflow: hidden;
  248. }
  249. .tui-search-area {
  250. position: fixed;
  251. width: 750rpx;
  252. background-color: #ebf0f6;
  253. z-index: 100;
  254. }
  255. .tui-showID {
  256. padding-left: 80rpx;
  257. line-height: 40rpx;
  258. font-size: 28rpx;
  259. color: black;
  260. height: 50rpx;
  261. padding-top: 8rpx;
  262. }
  263. .tui-search-bar {
  264. display: flex;
  265. flex-wrap: nowrap;
  266. align-items: center;
  267. margin-left: 40rpx;
  268. margin-top: 32rpx;
  269. width: 670rpx;
  270. height: 80rpx;
  271. background: #ffffff;
  272. border-radius: 40rpx;
  273. border-radius: 40rpx;
  274. }
  275. .tui-searchcion {
  276. display: inline-block;
  277. margin-left: 24rpx;
  278. width: 48rpx;
  279. height: 48rpx;
  280. }
  281. .tui-search-bar-input {
  282. line-height: 40rpx;
  283. font-size: 28rpx;
  284. padding: 0 36rpx;
  285. width: 100%;
  286. display: inline-block;
  287. }
  288. .tui-person-list-container {
  289. position: absolute;
  290. top: 100px;
  291. display: flex;
  292. flex-direction: column;
  293. width: 100%;
  294. /* height: 150rpx; */
  295. background-color: #ffffff;
  296. padding-left: 16px;
  297. align-items: center;
  298. overflow: auto;
  299. padding-bottom: 100rpx;
  300. }
  301. .tui-person-to-invite {
  302. display: flex;
  303. flex-wrap: nowrap;
  304. width: 750rpx;
  305. height: 150rpx;
  306. background-color: #ffffff;
  307. padding-left: 16px;
  308. align-items: center;
  309. border-bottom: 1rpx solid #dbdbdb;
  310. }
  311. .tui-person-to-invite:last-child {
  312. border-bottom: 0rpx solid #dbdbdb;
  313. }
  314. .tui-person-choose-container {
  315. width: 22px;
  316. height: 22px;
  317. display: flex;
  318. align-items: center;
  319. margin-right: 17px;
  320. }
  321. .tui-normal-unchoose {
  322. width: 100%;
  323. height: 100%;
  324. border-radius: 50%;
  325. border: 1px solid #dddddd;
  326. }
  327. .tui-normal-choose {
  328. width: 100%;
  329. height: 100%;
  330. }
  331. .tui-person-profile {
  332. width: 622rpx;
  333. display: flex;
  334. align-items: center;
  335. }
  336. .tui-person-profile-avatar {
  337. width: 96rpx;
  338. height: 96rpx;
  339. margin-right: 24rpx;
  340. border-radius: 10rpx;
  341. }
  342. .tui-person-profile-nick {
  343. color: #333333;
  344. line-height: 50rpx;
  345. font-size: 36rpx;
  346. margin-bottom: 4rpx;
  347. }
  348. .tui-person-profile-userID {
  349. color: #999999;
  350. line-height: 40rpx;
  351. font-size: 28rpx;
  352. }
  353. .tui-confirm-btn-container {
  354. position: fixed;
  355. display: flex;
  356. justify-content: center;
  357. align-items: center;
  358. bottom: 0rpx;
  359. width: 100%;
  360. height: 96rpx;
  361. background-color: #ffffff;
  362. line-height: 44rpx;
  363. font-size: 32rpx;
  364. .tui-confirm-btn {
  365. width: 670rpx;
  366. height: 42px;
  367. background: #006eff;
  368. color: #ffffff;
  369. border-radius: 42rpx;
  370. line-height: 44rpx;
  371. display: flex;
  372. justify-content: center;
  373. align-items: center;
  374. }
  375. }
  376. </style>