rtc.ts 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. import { defineStore } from 'pinia';
  2. import consola from 'consola';
  3. import { genTestUserSig } from '/@/utils/generateTestUserSig';
  4. import type { RemoteStream } from 'trtc-js-sdk';
  5. import sortBy from 'lodash-es/sortBy';
  6. interface RtcState {
  7. socket: Nullable<SocketIOClient.Socket>;
  8. socketId: string;
  9. showDaoGou: boolean;
  10. sdkAppId: string;
  11. userId: string;
  12. roomId: string;
  13. role: 'leader' | 'customer';
  14. secretKey: string;
  15. userSig: string;
  16. audioDeviceId: string;
  17. videoDeviceId: string;
  18. cameraList: MediaDeviceInfo[];
  19. microphoneList: MediaDeviceInfo[];
  20. logs: any[];
  21. isJoined: boolean;
  22. isPublished: boolean;
  23. isShared: boolean;
  24. remoteStreams: RemoteStream[];
  25. // invitedRemoteStreams: any[],
  26. avatar: Nullable<string>;
  27. nickname: string;
  28. mode: string;
  29. chatList: ChatContentType[];
  30. memberList: UserInfoType[];
  31. audioMuted: boolean;
  32. inputStatus: boolean;
  33. currentSession: Nullable<UserInfoType>;
  34. baseDialog: BaseDialog;
  35. ifBaseDialog: boolean;
  36. baseDiaLogCallback?: () => void;
  37. }
  38. interface DeviceListParams {
  39. cameraItems: MediaDeviceInfo[];
  40. microphoneItems: MediaDeviceInfo[];
  41. }
  42. export interface ChatContentType {
  43. role: RoleType;
  44. mode: string;
  45. Nickname: Nullable<string>;
  46. UserId: string;
  47. text: string;
  48. }
  49. export interface UserInfoType {
  50. Avatar: string;
  51. Id: string;
  52. InTime: string;
  53. IsClient: boolean;
  54. IsMuted: boolean;
  55. IsWords: boolean;
  56. JoinTime: string;
  57. Nickname: string;
  58. Role: RoleType;
  59. RoomId: string;
  60. UserId: string;
  61. text?: string;
  62. order: number;
  63. }
  64. export type RoleType = 'leader' | 'customer';
  65. export interface SocketParams {
  66. userId: string;
  67. roomId: string;
  68. role: RoleType;
  69. avatar: string;
  70. nickname: string;
  71. mode: string;
  72. }
  73. interface BaseDialog {
  74. title: string;
  75. desc: string;
  76. okTxt: string;
  77. closeTxt: string;
  78. isSingle?: boolean;
  79. }
  80. const defaultBaseDialog: BaseDialog = {
  81. title: '温馨提示',
  82. desc: '',
  83. okTxt: '确定',
  84. closeTxt: '取消',
  85. };
  86. export const useRtcStore = defineStore({
  87. id: 'rtc',
  88. state: (): RtcState => ({
  89. socket: null,
  90. socketId: '',
  91. showDaoGou: false,
  92. sdkAppId: '1400685498',
  93. nickname: '',
  94. userId: '',
  95. roomId: '',
  96. role: 'customer',
  97. secretKey: '7500f8938c46c5d3c64621ae7826905eec9723bf218fbcf121242e056a4ee14f',
  98. userSig:
  99. 'eJwtzcsOgjAQBdB-6RaDU2jLI3EhsrHRBdGNK2Po0IyvNAWJxvjvEmA5597c*bLj7hD26FnOohDYYrzJ4LOjhkZ*tejPd7wY9EJwnsV8brXmdnGODMu5AEggExBNSUcPHFQpnkopIJkU34784ApECjBvkB1e8MLJfWyLOAis06Wut4b0tVdL77RVTb35dGXby6o6rVfs9wdhLDRy',
  100. audioDeviceId: '',
  101. videoDeviceId: '',
  102. cameraList: [],
  103. microphoneList: [],
  104. logs: [],
  105. isJoined: false,
  106. isPublished: false,
  107. isShared: false,
  108. remoteStreams: [],
  109. // invitedRemoteStreams: [],
  110. avatar: null,
  111. mode: '',
  112. chatList: [],
  113. memberList: [],
  114. audioMuted: true,
  115. inputStatus: true,
  116. currentSession: null,
  117. baseDialog: defaultBaseDialog,
  118. ifBaseDialog: false,
  119. }),
  120. persist: [
  121. {
  122. storage: localStorage,
  123. paths: ['memberList'],
  124. },
  125. {
  126. storage: sessionStorage,
  127. paths: ['userId'],
  128. },
  129. ],
  130. getters: {
  131. checkUserInMemberList() {
  132. return (userId: string) => this.memberList.find((item) => item.UserId === userId);
  133. },
  134. isLeader(): boolean {
  135. return this.role === 'leader';
  136. },
  137. isMe() {
  138. return (userId: string) => this.userId === userId;
  139. },
  140. genUserSig() {
  141. const { userSig } = genTestUserSig({
  142. sdkAppId: parseInt(this.sdkAppId, 10),
  143. userId: this.userId,
  144. secretKey: this.secretKey,
  145. });
  146. return userSig;
  147. },
  148. isUserInRemoteStream() {
  149. return (userId: string) => {
  150. return this.remoteStreams.some((item) => item.getUserId() === userId);
  151. };
  152. },
  153. },
  154. actions: {
  155. showBaseDialog(dialog: BaseDialog, callback?: () => void): void {
  156. this.ifBaseDialog = true;
  157. this.baseDialog = dialog;
  158. this.baseDiaLogCallback = callback;
  159. },
  160. hideBaseDialog() {
  161. this.ifBaseDialog = false;
  162. this.baseDialog = defaultBaseDialog;
  163. },
  164. setSocketParams(params: SocketParams): void {
  165. this.avatar = params.avatar;
  166. this.roomId = params.roomId;
  167. this.userId = params.userId;
  168. this.nickname = params.nickname;
  169. this.role = params.role;
  170. if (!['leader', 'customer'].includes(params.role)) {
  171. consola.info({
  172. message: '角色参数有误',
  173. level: 0,
  174. tag: 'role',
  175. });
  176. this.role = 'customer';
  177. }
  178. },
  179. setNickName(nickname: string) {
  180. this.nickname = nickname;
  181. },
  182. setAvatar(payload: string) {
  183. this.avatar = payload;
  184. localStorage.setItem('leaderAvatar', payload || '');
  185. },
  186. setSocket(payload: SocketIOClient.Socket) {
  187. this.socket = payload;
  188. },
  189. setShowDaoGou(payload: boolean) {
  190. this.showDaoGou = payload;
  191. },
  192. setUserId(payload: string) {
  193. this.userId = payload;
  194. },
  195. setRoomId(payload: string) {
  196. this.roomId = payload;
  197. },
  198. setRole(payload: RoleType) {
  199. this.role = payload;
  200. },
  201. setDeviceList(payload: DeviceListParams) {
  202. this.cameraList = payload.cameraItems;
  203. this.microphoneList = payload.microphoneItems;
  204. },
  205. setVideoDeviceId(payload: string) {
  206. this.videoDeviceId = payload;
  207. },
  208. setAudioDeviceId(payload: string) {
  209. this.audioDeviceId = payload;
  210. },
  211. setIsJoined(payload: boolean) {
  212. this.isJoined = payload;
  213. },
  214. setIsPublished(payload: boolean) {
  215. this.isPublished = payload;
  216. },
  217. addToChatList(content: ChatContentType) {
  218. this.chatList.push(content);
  219. },
  220. setMemberList(members: UserInfoType[]) {
  221. const memberList = members.reduce((prev: UserInfoType[], current: UserInfoType, index) => {
  222. if (prev.findIndex((ele: UserInfoType) => ele.UserId === current.UserId) === -1) {
  223. // console.log(current);
  224. current.order = index > 1 ? index : 2;
  225. if (current.Role === 'leader') {
  226. current.order = 0;
  227. }
  228. if (current.UserId === this.userId) {
  229. current.order = 1;
  230. this.currentSession = current;
  231. }
  232. prev.push(current);
  233. }
  234. return prev;
  235. }, []);
  236. const sortList = sortBy(memberList, ['order', 'UserId'], ['asc', 'asc']);
  237. console.log('sortList', sortList);
  238. this.memberList = sortList;
  239. },
  240. clearMemberList(): void {
  241. this.memberList = [];
  242. this.userId = '';
  243. },
  244. updateMemberDatabyId(UserId: string, data: Partial<UserInfoType>) {
  245. const updateIndex = this.memberList.findIndex((member) => member.UserId === UserId);
  246. if (updateIndex > -1) {
  247. this.memberList[updateIndex] = Object.assign({}, this.memberList[updateIndex], data);
  248. //单点更新并是当事人也更一份数据
  249. if (UserId === this.userId) {
  250. this.currentSession = this.memberList[updateIndex];
  251. }
  252. }
  253. },
  254. mute() {
  255. this.setMute(false);
  256. },
  257. unmute() {
  258. this.setMute(true);
  259. },
  260. setMute(mute: boolean) {
  261. this.audioMuted = mute;
  262. this.updateMemberDatabyId(this.userId, {
  263. IsMuted: mute,
  264. });
  265. },
  266. setinputStatus(status: boolean) {
  267. this.inputStatus = status;
  268. },
  269. pushRemoteStreams(stream: RemoteStream) {
  270. this.remoteStreams.push(stream);
  271. },
  272. removeRemoteStreams(id: string) {
  273. const existStreamIndex = this.remoteStreams.findIndex((stream) => stream.getId() === id);
  274. if (existStreamIndex > -1) {
  275. this.remoteStreams.splice(existStreamIndex, 1);
  276. }
  277. },
  278. },
  279. });