-
-
-
-
-
-
- {{ item.content }}
-
-
-
-
-
-
-
+
+
+ {{ item.sendTime }}
+
@@ -83,7 +98,7 @@
-
+
+
-
-
- {{ _getFileName(item.content) }}
+
+
+
+ {{ item.content }}
+
+
+
+
+
+
+
+
+
+
+
+
-
+ {{ _getFileName(item.content) }}
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
-
+
+
@@ -151,8 +151,6 @@ export default { this.$message.success("注销成功,即将跳转到登录界面"); setTimeout(() => { this.$router.push(`/login?redirect=${this.$route.fullPath}`); - const { ipcRenderer } = window.require('electron'); - ipcRenderer.send('resize-window', { width: 400, height: 320 }); }, 1000); }); }, @@ -177,9 +175,16 @@ export default { }, toUpdateInfo() { let formData = new FormData(); + if (!this.userInfo['name'].trim()) { + return this.$message.warning("昵称不能为空") + } + if (this.userInfo['phone'] && this.userInfo['phone'].length != 11) { + return this.$message.warning("手机号必须11位") + } formData.append("username", this.userInfo['username']); + formData.append("name", this.userInfo['name'].trim()); formData.append("phone", this.userInfo['phone']); - formData.append("signature", this.userInfo['signature']); + formData.append("signature", this.userInfo['signature'].trim()); if (this.avatar) { formData.append("avatar", this.avatar); } @@ -208,7 +213,7 @@ export default { inputType: "password", center: true }).then(({ value }) => { - if (!value) { + if (!value.trim()) { return this.$message.warning('请填写新密码') } let data = { diff --git a/ui/src/views/Index/index.vue b/ui/src/views/Index/index.vue index 15c751e..7348c7a 100644 --- a/ui/src/views/Index/index.vue +++ b/ui/src/views/Index/index.vue @@ -1,9 +1,18 @@
-
-
+
+
+
+
+
+
@@ -11,19 +20,27 @@
// 在渲染进程中发送消息通知主进程修改窗口大小
-import SideBar from './components/sidebar.vue'
-import List from './components/list.vue'
-import chatRoom from './components/chatRoom.vue'
-import AIRoom from './components/AIRoom.vue'
+import SideBar from './components/SideBar/sidebar.vue'
+import List from './components/List/list.vue'
+import chatRoom from './components/Room/chatRoom.vue'
+import AIRoom from './components/Room/AIRoom.vue'
+import groupRoom from './components/Room/groupRoom.vue'
+import Info from './components/Room/Info.vue'
+import Group from './components/Room/group.vue'
import { getConversationInfo } from '@/api/bing';
const remote = window.require('electron').remote;
const win = remote.getCurrentWindow();
+import { mapActions } from "vuex";
+const { ipcRenderer } = window.require('electron');
export default {
components: {
SideBar,
List,
chatRoom,
- AIRoom
+ AIRoom,
+ groupRoom,
+ Info,
+ Group
},
data() {
@@ -39,18 +56,26 @@ export default {
/**
* 聊天框相关参数
*/
+ currentRoom: "chat",
options: "",
+ /**
+ * 群聊相关
+ */
+ groupOptions: "",
/**
* bing相关参数
*/
- AI: false,
AIoptions: {
room: ""
- }
+ },
+ /**
+ * 好友信息或群聊相关参数
+ */
+ friendoptions: "",
+ groupInfooptions: ""
};
},
created() {
- const { ipcRenderer } = window.require('electron');
ipcRenderer.send('resize-window', { width: 1000, height: 600 });
this.getBingData()
//检测窗口关闭,自动挂断电话
@@ -62,12 +87,14 @@ export default {
this.initSocket()
},
methods: {
+ ...mapActions(["Logout"]),
/**
* 通信相关
*/
initSocket() {
this.socket = new WebSocket(`${this.wssaddress}/api/chat/v1/auth/user_channel?username=${this.$store.getters.userInfo.username}`)
this.socket.onmessage = (message) => {
+ let options
let data = JSON.parse(message.data)
switch (data.name) {
case "friend":
@@ -75,30 +102,184 @@ export default {
//重新加载消息列表
this.updateList()
break
+ //音视频
+ case "audio":
+ options = {
+ method: data.name,
+ room: data.room,
+ sender: data.sender_name,
+ receiver: data.receiver_username,
+ beInviter: 1
+ }
+ ipcRenderer.send('open-window', options);
+ break
+ //音视频
+ case "video":
+ options = {
+ method: data.name,
+ room: data.room,
+ sender: data.sender_name,
+ receiver: data.receiver_username,
+ beInviter: 1
+ }
+ ipcRenderer.send('open-window', options);
+ break
+ //群聊音视频
+ case "group_audio":
+ options = {
+ method: data.name,
+ room: data.room,
+ sender: data.sender_name,
+ group_id: data.group_id,
+ beInviter: 1
+ }
+ ipcRenderer.send('open-window', options);
+ break;
+ //群聊音视频
+ case "group_video":
+ options = {
+ method: data.name,
+ room: data.room,
+ sender: data.sender_name,
+ group_id: data.group_id,
+ beInviter: 1
+ }
+ ipcRenderer.send('open-window', options);
+ break;
+ case "group_peer":
+ options = {
+ method: data.method,
+ room: data.room,
+ sender: data.sender_name,
+ group_id: data.group_id,
+ beInviter: 0
+ }
+ ipcRenderer.send('open-window', options);
+ break
+ //音视频相应
+ case "peer":
+ options = {
+ method: data.method,
+ room: data.room,
+ sender: data.sender_name,
+ receiver: data.receiver_username,
+ beInviter: 0
+ }
+ ipcRenderer.send('open-window', options);
+ break
+ //拒绝
+ case "reject":
+ if (data.message) {
+ this.$message.error(data.message)
+ } else {
+ this.socket.send(JSON.stringify({ name: "reject" }))
+ }
+ break;
+ case "logout":
+ this.$message.error("你已在其他地方被登录!!!")
+ this.Logout()
+ break;
+
}
}
},
+ //音视频邀请
+ sendInvitation(options) {
+ this.socket.send(JSON.stringify({ name: options.method, sender_name: options.sender, receiver_username: options.receiver, room: options.room, beInviter: options.beInviter }))
+ },
+ //群聊音视频邀请
+ sendGroupInvitation(options) {
+ this.socket.send(JSON.stringify({
+ name: options.method,
+ userList: this.userList,
+ sender_name: options.sender,
+ group_id: options.group_id,
+ userList: options.userList,
+ room: options.room,
+ beInviter: options.beInviter
+ }))
+
+ },
//改变侧边栏选项
changeStatus(tag) {
this.current = tag
},
- ListCHangeStatus(tag) {
+ ListChangeStatus(tag) {
this.$refs.SideBar.changeStatus(tag)
+ this.updateList()
+
},
chooseRoom(item) {
if (item.AI) {
if (!this.AIoptions.room) {
return this.$message.warning("你无法进行AI对话,请前往设置中生成")
}
- this.AI = true
- } else {
- this.AI = false
+ this.$nextTick(() => {
+ this.$refs.List.updatecurrentRoom(0)
+ });
+ this.currentRoom = 'ai'
+ } else if (!item.group_id) {
+ this.currentRoom = 'chat'
this.options = item
+ } else if (item.group_id) {
+ this.currentRoom = 'group'
+ this.groupOptions = item
+ } else if (item.info) {
+ this.currentRoom = 'info'
}
},
updateList() {
- this.$refs.List.loadListData()
+ this.$nextTick(() => {
+ this.$refs.List.loadListData()
+ });
+ },
+ /***
+ * 好友详情相关信息
+ */
+ showFriendInfo(item) {
+ this.currentRoom = 'info'
+ this.friendoptions = item
+ },
+ sendFriendMessage(item) {
+ this.currentRoom = 'chat'
+ this.ListChangeStatus("chat")
+ this.options = item
+ this.$nextTick(() => {
+ this.$refs.List.updatecurrentRoom(item.user_id)
+ });
+ },
+ update_friend() {
+ if (this.current != 'chat') {
+ this.$refs.List.refreshList()
+ }
+ },
+ /**
+ * 群聊相关
+ */
+ //显示群聊信息
+ showGroupInfo(item) {
+ this.currentRoom = 'group_info'
+ this.groupInfooptions = item
+ },
+ //去群聊
+ sendGroupMessage(item) {
+ this.currentRoom = 'group'
+ this.ListChangeStatus("chat")
+ this.groupOptions = item
+ this.$nextTick(() => {
+ this.$refs.List.updatecurrentRoom(undefined, item.group_id)
+ });
+ },
+ //邀请好友
+ ShowinvitationFriend(group_id) {
+ this.$refs.List.ShowinvitationFriend(group_id)
+ },
+ //更新群聊信息
+ update_group_info(){
+ if( this.currentRoom =='group_info'){
+ this.$refs.group_info.loadData()
+ }
},
/**
* bing相关方法
diff --git a/ui/src/views/Login/Login.vue b/ui/src/views/Login/Login.vue
index d0bcc90..1c6052c 100644
--- a/ui/src/views/Login/Login.vue
+++ b/ui/src/views/Login/Login.vue
@@ -7,11 +7,11 @@
-
+
-
+
{{ item }}
@@ -106,7 +121,8 @@
const remote = window.require('electron').remote;
const win = remote.getCurrentWindow();
import { EmojiList } from '@/utils/emoji';
-import { getFileSuffix2, getFileSuffix, getFileIcons, getFileName } from '@/utils/file'
+import { toggleTime } from '@/utils/timeFormat';
+import { getFileSuffix2, getFileIcons, getFileName } from '@/utils/file'
export default {
@@ -122,12 +138,15 @@ export default {
sender_id: 1,
receiver_id: 2,
username: "",
+ receiver_username: "",
room: "",
name: "",
sendType: 'enter',
avatar: "",
content: "",
chatList: [],
+ //计入所有的时间
+ messageTimeList: [],
/**
* 表情包
* */
@@ -144,7 +163,24 @@ export default {
};
},
created() {
- this.sendType = localStorage.getItem('sendType') ? localStorage.getItem('sendType') : 'enter'
+ if (this.options) {
+ this.sendType = localStorage.getItem('sendType') ? localStorage.getItem('sendType') : 'enter'
+ this.containerAni = 'opacity:0'
+ this.empty = false
+ this.sender_id = this.$store.getters.userInfo.id
+ this.username = this.$store.getters.userInfo.username
+ this.avatar = this.$store.getters.userInfo.avatar
+ this.room = this.options.room
+ this.receiver_id = this.options.user_id
+ this.name = this.options.name
+ this.receiver_username = this.options.receiver_username
+ this.initSocket()
+ this.chatList = []
+ setTimeout(() => {
+ this.containerAni = 'opacity:1'
+ this.empty = false
+ }, 100);
+ }
},
watch: {
@@ -161,8 +197,8 @@ export default {
this.room = this.options.room
this.receiver_id = this.options.user_id
this.name = this.options.name
+ this.receiver_username = this.options.receiver_username
this.initSocket()
- this.initRTCSocket()
this.chatList = []
setTimeout(() => {
this.containerAni = 'opacity:1'
@@ -172,6 +208,19 @@ export default {
},
deep: true
},
+ computed: {
+ List() {
+ return this.chatList.map(item => {
+ let sendTime = toggleTime(item.created_at)
+ if (this.messageTimeList.indexOf(sendTime) == -1) {
+ item.sendTime = sendTime
+ this.messageTimeList.push(sendTime)
+ }
+ // 处理数据
+ return item;
+ });
+ }
+ },
updated() {
this.$nextTick(() => {
this.$refs.record.scrollTop = this.$refs.record.scrollHeight;
@@ -200,7 +249,7 @@ export default {
this.socket.close()
this.socket = null
}
- this.socket = new WebSocket(`${this.wssaddress}/api/chat/v1/message/single?room=${this.room}&id=${this.sender_id}`)
+ this.socket = new WebSocket(`${this.wssaddress}/api/chat/v1/message/chat?room=${this.room}&id=${this.sender_id}&type=private`)
this.socket.onopen = () => {
console.log('连接成功');
};
@@ -292,6 +341,26 @@ export default {
//发送文件
async SendFile(e) {
if (e.target.files.length > 0) {
+ var file = e.target.files[0];
+ if (getFileSuffix2(file.name) != 'file') {
+ const reader = new FileReader();
+ reader.onload = (event) => {
+ const fileContent = event.target.result;
+ const content = new Uint8Array(fileContent);
+ let filename = file.name
+ this.socket.send(JSON.stringify({
+ "filename": filename,
+ "sender_id": this.sender_id,
+ "receiver_id": this.receiver_id,
+ "content": Array.from(content),
+ "avatar": this.avatar,
+ "room": this.room,
+ "type": getFileSuffix2(filename)
+ }))
+ };
+ reader.readAsArrayBuffer(file);
+ return
+ }
const loading = this.$loading({
target: document.getElementById("message"),
lock: true,
@@ -299,7 +368,7 @@ export default {
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
- var file = e.target.files[0];
+
// 发送文件信息
const fileInfo = {
fileName: file.name,
@@ -369,52 +438,12 @@ export default {
*/
//发送语音邀请
SendAudioInvitation() {
- if (this.callActive) {
- return this.$message.error("正在通话中....")
- }
- const { ipcRenderer } = window.require('electron');
- ipcRenderer.send('open-window', { room: this.room, receiver: this.name, beInviter: 0, method: 'audio' });
+ this.$emit("sendInvitation", { room: this.room, sender: this.username, receiver: this.receiver_username, beInviter: 0, method: 'audio' })
},
//发送视频邀请
SendVideoInvitation() {
- if (this.callActive) {
- return this.$message.error("正在通话中....")
- }
- const { ipcRenderer } = window.require('electron');
- ipcRenderer.send('open-window', { room: this.room, receiver: this.name, beInviter: 0, method: 'video' });
+ this.$emit("sendInvitation", { room: this.room, sender: this.username, receiver: this.receiver_username, beInviter: 0, method: 'video' })
},
- //监听别人打语音视频电话
- initRTCSocket() {
- if (this.rtcsocket) {
- this.rtcsocket.close()
- this.rtcsocket = null
- }
- this.rtcsocket = new WebSocket(`${this.wssaddress}/api/chat/v1/rtc/single?room=${this.room}&username=${this.username}_listen`)
- const { ipcRenderer } = window.require('electron');
- this.rtcsocket.onmessage = (message) => {
- let data = JSON.parse(message.data)
- switch (data.name) {
- case 'status':
- this.callActive = data.flag
- break
- case 'reject':
- this.callActive = false
- break
- case "audio_invitation":
- if (this.callActive) {
- return
- }
- ipcRenderer.send('open-window', { room: this.room, receiver: this.name, beInviter: 1, method: 'audio' });
- break;
- case "video_invitation":
- if (this.callActive) {
- return
- }
- ipcRenderer.send('open-window', { room: this.room, receiver: this.name, beInviter: 1, method: 'video' });
- break;
- }
- }
- }
},
destroyed() {
if (this.rtcsocket) {
@@ -434,7 +463,7 @@ export default {
height: 100vh;
overflow: hidden;
background-color: #eee;
- transition: opacity 1s linear;
+ transition: opacity 0.5s linear;
opacity: 0;
.header {
@@ -497,6 +526,20 @@ export default {
box-shadow: 0 0 1px rgba(0, 0, 0, 0.5);
overflow: auto;
position: relative;
+ text-align: center;
+
+ .chat-item {
+ margin: 10px 0;
+ }
+
+ .message-create-time {
+ font-size: 10px;
+ padding: 2px 0;
+ color: #606266;
+ display: inline-block;
+ padding: 5px;
+ margin: 0 auto;
+ }
.other {
display: flex;
diff --git a/ui/src/views/Index/components/Room/group.vue b/ui/src/views/Index/components/Room/group.vue
new file mode 100644
index 0000000..0c8442d
--- /dev/null
+++ b/ui/src/views/Index/components/Room/group.vue
@@ -0,0 +1,260 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/src/views/Index/components/Room/groupRoom.vue b/ui/src/views/Index/components/Room/groupRoom.vue
new file mode 100644
index 0000000..ddb41bc
--- /dev/null
+++ b/ui/src/views/Index/components/Room/groupRoom.vue
@@ -0,0 +1,888 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ info.name }}
+ {{ info.announcement ? info.announcement : + '未设置群简介' + }} +
+
+
+
+
+
+
+
+
+
+
+
+ {{ new Date(scope.row.created_at).toLocaleString() }}
+
+
+
+
+
+ {{ scope.row.lastMessageTime ? new Date(scope.row.lastMessageTime).toLocaleString() : ""
+ }}
+
+
+
+
+
+
+
+
+
+ 群介绍
+本群创建于{{ describe }}
+
+
+ 群主
+{{ creator_name }}
+
+
+
+ 群成员
+
+
+
+
+
+
+
+
+
+ 邀请好友
+ 发送消息
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/src/views/Index/components/sidebar.vue b/ui/src/views/Index/components/SideBar/sidebar.vue
similarity index 95%
rename from ui/src/views/Index/components/sidebar.vue
rename to ui/src/views/Index/components/SideBar/sidebar.vue
index 4b38ccc..3392013 100644
--- a/ui/src/views/Index/components/sidebar.vue
+++ b/ui/src/views/Index/components/SideBar/sidebar.vue
@@ -37,9 +37,9 @@
accept="image/jpeg,image/jpg,image/png" @change="changeImage">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ name }}
+
+
+
+
+
+ 何当有翅翎,飞去堕尔前!
+ 主动一点,世界会更大! +
+
+
+
+
+ {{ item.sendTime }}
+
+
+
+
+
+
+
+ {{ item.nickname }}
+
+
+
+ {{ item.content }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ _getFileName(item.content) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 发送(S)
+
+ 按Enter键发送消息
+ 按Ctrl+Enter键发送消息
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
-
+
+ v-model="userInfo.signature" placeholder="暂无个性签名" oninput="value=value.trim()">
@@ -151,8 +151,6 @@ export default { this.$message.success("注销成功,即将跳转到登录界面"); setTimeout(() => { this.$router.push(`/login?redirect=${this.$route.fullPath}`); - const { ipcRenderer } = window.require('electron'); - ipcRenderer.send('resize-window', { width: 400, height: 320 }); }, 1000); }); }, @@ -177,9 +175,16 @@ export default { }, toUpdateInfo() { let formData = new FormData(); + if (!this.userInfo['name'].trim()) { + return this.$message.warning("昵称不能为空") + } + if (this.userInfo['phone'] && this.userInfo['phone'].length != 11) { + return this.$message.warning("手机号必须11位") + } formData.append("username", this.userInfo['username']); + formData.append("name", this.userInfo['name'].trim()); formData.append("phone", this.userInfo['phone']); - formData.append("signature", this.userInfo['signature']); + formData.append("signature", this.userInfo['signature'].trim()); if (this.avatar) { formData.append("avatar", this.avatar); } @@ -208,7 +213,7 @@ export default { inputType: "password", center: true }).then(({ value }) => { - if (!value) { + if (!value.trim()) { return this.$message.warning('请填写新密码') } let data = { diff --git a/ui/src/views/Index/index.vue b/ui/src/views/Index/index.vue index 15c751e..7348c7a 100644 --- a/ui/src/views/Index/index.vue +++ b/ui/src/views/Index/index.vue @@ -1,9 +1,18 @@
-
+
-
+
diff --git a/ui/src/views/Login/Register.vue b/ui/src/views/Login/Register.vue
index 86288d3..b8d3892 100644
--- a/ui/src/views/Login/Register.vue
+++ b/ui/src/views/Login/Register.vue
@@ -4,11 +4,11 @@
-
+
-
+
-
+
-
+
diff --git a/ui/src/views/Login/forgetPassword.vue b/ui/src/views/Login/forgetPassword.vue
index dbaad2e..1028781 100644
--- a/ui/src/views/Login/forgetPassword.vue
+++ b/ui/src/views/Login/forgetPassword.vue
@@ -4,7 +4,7 @@
-
+
@@ -13,7 +13,7 @@
-
+
-
-
-
+
+
+
@@ -27,7 +27,8 @@ import S_Login from './Login.vue';
import S_Register from './Register.vue';
import S_forgetPassword from './forgetPassword.vue';
import S_settings from './settings.vue';
-
+const { ipcRenderer } = window.require('electron');
+ipcRenderer.send('resize-window', { width: 400, height: 320 });
export default {
name: "Login",
components: {
@@ -56,10 +57,10 @@ export default {
this.status = path
},
//跳转到设置
- toSettings(){
+ toSettings() {
this.status = "settings"
}
-
+
},
}
@@ -98,7 +99,6 @@ export default {
}
}
- .content {
- }
+ .content {}
}
\ No newline at end of file
diff --git a/ui/src/views/audioVideo/audio.vue b/ui/src/views/audioVideo/audio.vue
index 193757a..32c2403 100644
--- a/ui/src/views/audioVideo/audio.vue
+++ b/ui/src/views/audioVideo/audio.vue
@@ -7,14 +7,14 @@
style="width: 100px;height: 100px;object-fit: cover;object-position: center;">
-
+
@@ -13,7 +13,7 @@
-
+
-
{{ receiver }}发起语音通话
+ {{ username }}对你发起语音通话
-
对{{ receiver }}发起语音通话
+ 你对{{ username }}发起语音通话
@@ -64,16 +64,21 @@ export default {
beInviter: false,
room: "",
socket: "",
- receiver: "",
+ username: "",
localStream: "",
pc: "",
broadcastTime: 0,
- timer: ""
+ timer: "",
+ receiver: ""
};
},
created() {
this.beInviter = this.$route.query.beInviter == 1
- this.receiver = this.$route.query.receiver
+ if (this.beInviter) {
+ this.username = this.$route.query.sender
+ } else {
+ this.username = this.$route.query.receiver
+ }
this.room = this.$route.query.room
},
@@ -95,7 +100,7 @@ export default {
}))
this.socket.close()
}
- }, 6000);
+ }, 60 * 1000);
},
methods: {
//初始化websocket
@@ -129,16 +134,39 @@ export default {
};
this.socket.onmessage = (message) => {
let data = JSON.parse(message.data)
+
switch (data.name) {
/**
- * 1.邀请人接受到对方同意的指令后,将对方的音视频流通过setRemoteDescription函数进行存储
- * 2.存储完后邀请人创建answer来获取自己的音视频流,通过setLocalDescription函数存储自己的音视频流,并发送answer指令(携带自己的音视频)告诉对方要存储邀请人的音视频
+ * 1.邀请人接收到有新人进入房间,则发送视频流和offer指令给新人
*/
- case "offer":
+ case "new_peer":
if (this.timer) {
clearTimeout(this.timer)
this.timer = null
}
+ this.flag = true
+ this.pc.createOffer((session_desc) => {
+ this.pc.setLocalDescription(session_desc);
+ this.socket.send(
+ JSON.stringify({
+ name: "offer",
+ data: {
+ sdp: session_desc,
+ },
+ receiver: this.username,
+ })
+ );
+ }, (err) => {
+ console.log(err);
+ });
+
+ break
+ /**
+ * 1.新人接受到对方同意的指令后,将对方的音视频流通过setRemoteDescription函数进行存储
+ * 2.存储完后新人创建answer来获取自己的音视频流,通过setLocalDescription函数存储自己的音视频流,并发送answer指令(携带自己的音视频)告诉对方要存储邀请人的音视频
+ */
+ case "offer":
+
try {
this.flag = true
//当收到对方接收请求后,设置音频源,并发送answer给对方
@@ -151,7 +179,7 @@ export default {
data: {
sdp: session_desc,
},
- receiver: this.receiver,
+ receiver: this.username,
})
)
}, (err) => {
@@ -171,8 +199,8 @@ export default {
this.pc.addIceCandidate(candidate);
break
case 'reject':
- this.flag = false
this.$message.warning("对方已挂断,即将退出")
+ this.socket.send(JSON.stringify({ name: "reject" }))
this.socket.close()
this.socket = null
setTimeout(() => {
@@ -183,6 +211,11 @@ export default {
break;
}
}
+ this.socket.onclose = () => {
+ setTimeout(() => {
+ win.close()
+ }, 1000);
+ }
},
//接收情况
async acceptAudio() {
@@ -191,8 +224,7 @@ export default {
* 2.获取自己的视频流
* 3.初始化PC源
* 4.PC添加音视频流
- * 5.创建offer,获取自己的音视频流,并通过setLocalDescription函数存储自己的音视频流
- * 6.并发送peer指令(携带自己的音视频)告诉邀请人要存储自己的音视频
+ * 5.并发送new_peer指令(携带自己的音视频)告诉房间的人,我要进入房间
*/
try {
if (this.timer) {
@@ -206,9 +238,15 @@ export default {
this.$nextTick(() => {
this.initPC()
this.pc.addStream(this.localStream)
- this.pc.createOffer(this.pcCreateCbGen("peer"), (err) => {
- console.log(err);
- });
+ this.socket.send(
+ JSON.stringify({
+ name: "new_peer",
+ data: {
+ username: this.username,
+ },
+ receiver: this.username,
+ })
+ );
});
} catch (error) {
alert("检测到当前设备不支持麦克风,请设置权限后在重试")
@@ -233,20 +271,6 @@ export default {
}, 1000);
}
},
- pcCreateCbGen(sendEventName) {
- return (session_desc) => {
- this.pc.setLocalDescription(session_desc);
- this.socket.send(
- JSON.stringify({
- name: sendEventName,
- data: {
- sdp: session_desc,
- },
- receiver: this.receiver,
- })
- );
- };
- },
//初始化PC
initPC() {
let pc = new PeerConnection(iceServer);
@@ -261,7 +285,7 @@ export default {
sdpMLineIndex: evt.candidate.sdpMLineIndex,
candidate: evt.candidate.candidate,
},
- receiver: this.receiver,
+ receiver: this.username,
})
);
}
@@ -353,7 +377,7 @@ export default {
.audio-Inviter {
margin-top: 30px;
- width: 200px;
+ min-width: 200px;
display: flex;
align-items: center;
justify-content: center;
diff --git a/ui/src/views/audioVideo/group_audio.vue b/ui/src/views/audioVideo/group_audio.vue
new file mode 100644
index 0000000..8d4dda0
--- /dev/null
+++ b/ui/src/views/audioVideo/group_audio.vue
@@ -0,0 +1,454 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/src/views/audioVideo/group_video.vue b/ui/src/views/audioVideo/group_video.vue
new file mode 100644
index 0000000..f8b7402
--- /dev/null
+++ b/ui/src/views/audioVideo/group_video.vue
@@ -0,0 +1,505 @@
+
+
+
+
+
+
+
+
+ 你接收到群通话!!!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ broadcastTime }}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/src/views/audioVideo/video.vue b/ui/src/views/audioVideo/video.vue
index 381b7ae..308c999 100644
--- a/ui/src/views/audioVideo/video.vue
+++ b/ui/src/views/audioVideo/video.vue
@@ -2,29 +2,30 @@
+
+
+
+
+
+
+ 你接收到群通话!!!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ broadcastTime }}
+
+
-
+
-
{{ receiver }}发起视频通话
+ {{ username }}发起视频通话
-
对{{ receiver }}发起视频通话
+ 对{{ username }}发起视频通话
+ @timeupdate="updateTime" poster="@/assets/black.png">
-
+
{{ broadcastTime }}
@@ -70,6 +71,7 @@ export default {
room: "",
socket: "",
receiver: "",
+ username: "",
localStream: "",
pc: "",
broadcastTime: 0,
@@ -79,7 +81,11 @@ export default {
},
created() {
this.beInviter = this.$route.query.beInviter == 1
- this.receiver = this.$route.query.receiver
+ if (this.beInviter) {
+ this.username = this.$route.query.sender
+ } else {
+ this.username = this.$route.query.receiver
+ }
this.room = this.$route.query.room
},
mounted() {
@@ -99,7 +105,7 @@ export default {
}))
this.socket.close()
}
- }, 6000);
+ }, 60 * 1000);
},
methods: {
//初始化websocket
@@ -111,7 +117,6 @@ export default {
try {
//最新的标准API
stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true })
-
} catch (error) {
try {
//最新的标准API
@@ -127,9 +132,7 @@ export default {
}
}
this.localStream = stream
- //初始化PC源
this.initPC()
- //添加音频流
this.pc.addStream(this.localStream)
//发起邀请
this.socket.send(JSON.stringify({ "name": "createRoom", mode: "video_invitation" }))
@@ -138,11 +141,40 @@ export default {
this.socket.onmessage = (message) => {
let data = JSON.parse(message.data)
switch (data.name) {
- case "offer":
+ /**
+ * 1.邀请人接收到有新人进入房间,则发送视频流和offer指令给新人
+ */
+ case "new_peer":
if (this.timer) {
clearTimeout(this.timer)
this.timer = null
}
+ this.flag = true
+ this.$nextTick(() => {
+ let selfvideo = document.getElementById("selfvideo")
+ selfvideo.srcObject = this.localStream
+ this.pc.createOffer((session_desc) => {
+ this.pc.setLocalDescription(session_desc);
+ this.socket.send(
+ JSON.stringify({
+ name: "offer",
+ data: {
+ sdp: session_desc,
+ },
+ receiver: this.username,
+ })
+ );
+ }, (err) => {
+ console.log(err);
+ });
+ });
+
+ break
+ /**
+ * 1.新人接受到对方同意的指令后,将对方的音视频流通过setRemoteDescription函数进行存储
+ * 2.存储完后新人创建answer来获取自己的音视频流,通过setLocalDescription函数存储自己的音视频流,并发送answer指令(携带自己的音视频)告诉对方要存储邀请人的音视频
+ */
+ case "offer":
try {
this.flag = true
//当收到对方接收请求后,设置音频源,并发送answer给对方
@@ -155,7 +187,7 @@ export default {
data: {
sdp: session_desc,
},
- receiver: this.receiver,
+ receiver: this.username,
})
)
}, (err) => {
@@ -177,6 +209,7 @@ export default {
case 'reject':
this.flag = false
this.$message.warning("对方已挂断,即将退出")
+ this.socket.send(JSON.stringify({ name: "reject" }))
this.socket.close()
this.socket = null
setTimeout(() => {
@@ -187,6 +220,11 @@ export default {
break;
}
}
+ this.socket.onclose = () => {
+ setTimeout(() => {
+ win.close()
+ }, 1000);
+ }
},
//接收情况
async acceptVideo() {
@@ -194,6 +232,13 @@ export default {
clearTimeout(this.timer)
this.timer = null
}
+ /**
+ * 1.点击同意后
+ * 2.获取自己的视频流
+ * 3.初始化PC源
+ * 4.PC添加音视频流
+ * 5.并发送new_peer指令(携带自己的音视频)告诉房间的人,我要进入房间
+ */
let stream
try {
//最新的标准API
@@ -212,15 +257,23 @@ export default {
}
}
this.localStream = stream
+ this.initPC()
+ this.pc.addStream(this.localStream)
this.flag = true
this.$nextTick(() => {
- this.initPC()
- this.pc.addStream(this.localStream)
- this.pc.createOffer(this.pcCreateCbGen("peer"), (err) => {
- console.log(err);
- });
- // this.$refs.selfvideo.srcObject = this.localStream;
- });
+ let selfvideo = document.getElementById("selfvideo")
+ selfvideo.srcObject = stream
+ this.socket.send(
+ JSON.stringify({
+ name: "new_peer",
+ data: {
+ username: this.username,
+ },
+ receiver: this.username,
+ })
+ );
+ })
+
},
//拒绝或挂断
@@ -238,20 +291,6 @@ export default {
}, 1000);
}
},
- pcCreateCbGen(sendEventName) {
- return (session_desc) => {
- this.pc.setLocalDescription(session_desc);
- this.socket.send(
- JSON.stringify({
- name: sendEventName,
- data: {
- sdp: session_desc,
- },
- receiver: this.receiver,
- })
- );
- };
- },
//初始化PC
initPC() {
let pc = new PeerConnection(iceServer);
@@ -266,7 +305,7 @@ export default {
sdpMLineIndex: evt.candidate.sdpMLineIndex,
candidate: evt.candidate.candidate,
},
- receiver: this.receiver,
+ receiver: this.username,
})
);
}
@@ -274,10 +313,15 @@ export default {
pc.onaddstream = (evt) => {
let stream = evt.stream
this.$nextTick(() => {
- this.$refs.video.srcObject = stream;
- if (this.localStream) {
- this.$refs.selfvideo.srcObject = this.localStream;
+ try {
+ this.$refs.video.srcObject = stream;
+ // if (this.localStream) {
+ // this.$refs.selfvideo.srcObject = this.localStream;
+ // }
+ } catch (error) {
+ console.log(error);
}
+
});
};
this.pc = pc
@@ -293,15 +337,6 @@ export default {
var second = parseInt(duration % 60) < 10 ? '0' + parseInt(duration % 60) : parseInt(duration % 60);
this.broadcastTime = hour + ":" + minute + ":" + second
},
- // updateTime2() {
- // if (this.localStream) {
- // let duration = this.$refs.selfvideo.currentTime;
- // var hour = parseInt((duration) / 3600) < 10 ? '0' + parseInt((duration) / 3600) : parseInt((duration) / 3600);
- // var minute = parseInt((duration % 3600) / 60) < 10 ? '0' + parseInt((duration % 3600) / 60) : parseInt((duration % 3600) / 60);
- // var second = parseInt(duration % 60) < 10 ? '0' + parseInt(duration % 60) : parseInt(duration % 60);
- // this.broadcastTime = hour + ":" + minute + ":" + second
- // }
- // },
/**
* 监听移动
*/
@@ -380,7 +415,7 @@ export default {
.audio-Inviter {
margin-top: 30px;
- width: 200px;
+ min-width: 200px;
display: flex;
align-items: center;
justify-content: center;
@@ -411,7 +446,7 @@ export default {
.self-video {
position: absolute;
- bottom: 0;
+ top: 0;
right: 0;
}
-
+
+
-
-
+