create.vue 10 KB

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