This commit is contained in:
2020-11-25 10:00:46 +08:00
parent acab6b35e1
commit 80eec979f6
155 changed files with 13664 additions and 1 deletions

2
dist/js/app.069d4ac9.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/js/app.069d4ac9.js.map vendored Normal file

File diff suppressed because one or more lines are too long

6939
dist/js/bootstrap-material-design.js vendored Normal file

File diff suppressed because it is too large Load Diff

2
dist/js/chunk-04e3a2fa.9e6a7256.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-05d3c41a.91415477.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-06828374.d411ceff.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-07015098.22f8b33a.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-073b023e.481ac075.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-10d1cf7a.05afa329.js vendored Normal file
View File

@@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-10d1cf7a"],{"77fb":function(e,t,c){"use strict";c.r(t);var n=c("7a23"),r=Object(n["withScopeId"])("data-v-7b21720b"),o=r((function(e,t,c,r,o,i){return Object(n["openBlock"])(),Object(n["createBlock"])("iframe",{style:{width:"100%",height:"100%"},src:e.url,frameborder:"0"},null,8,["src"])})),i=(c("99af"),c("79f6")),a=c("6c02"),b=Object(n["defineComponent"])({setup:function(){var e=Object(a["d"])().query.id,t=Object(n["ref"])();return e&&"string"==typeof e&&Object(i["u"])(parseInt(e)).then((function(e){t.value="/zhibo.html?roomid=".concat(e.roomid,"&memberid=").concat(e.memberid)})),{url:t}}});c("9b27");b.render=o,b.__scopeId="data-v-7b21720b";t["default"]=b},"8da0":function(e,t,c){},"9b27":function(e,t,c){"use strict";c("8da0")}}]);
//# sourceMappingURL=chunk-10d1cf7a.05afa329.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["webpack:///./src/views/regime/Liveing.vue","webpack:///./src/views/regime/Liveing.vue?771a","webpack:///./src/views/regime/Liveing.vue?9755","webpack:///./src/views/regime/Liveing.vue?c154"],"names":["style","src","url","frameborder","setup","id","query","parseInt","then","res","value","roomid","memberid","render","__scopeId"],"mappings":"kPACI,yBAA4E,UAApEA,MAAA,6BAAiCC,IAAK,EAAAC,IAAKC,YAAY,K,uDCKpD,+BAAgB,CAC3BC,MAD2B,WAEvB,IAAMC,EAAK,iBAAWC,MAAMD,GACtBH,EAAM,mBAQZ,OAPGG,GAAmB,iBAANA,GACZ,eAAYE,SAASF,IAAKG,MAAK,SAACC,GAC5BP,EAAIQ,MAAJ,6BAAkCD,EAAIE,OAAtC,qBAAyDF,EAAIG,aAK9D,CACHV,U,UCbZ,EAAOW,OAAS,EAChB,EAAOC,UAAY,kBAEJ,gB,6DCRf","file":"js/chunk-10d1cf7a.05afa329.js","sourcesContent":["<template>\n <iframe style=\"width:100%;height: 100%\" :src=\"url\" frameborder=\"0\"></iframe>\n</template>\n<style lang=\"scss\" scoped>\n\n</style>\n<script lang=\"ts\">\nimport { getliveinfo } from '@/api';\nimport { defineComponent, ref } from 'vue';\nimport { useRoute } from 'vue-router';\n\n\nexport default defineComponent({\n setup(){\n const id = useRoute().query.id;\n const url = ref<string>()\n if(id && typeof id == 'string'){\n getliveinfo(parseInt(id)).then((res: any)=>{\n url.value = `/zhibo.html?roomid=${res.roomid}&memberid=${res.memberid}`\n })\n\n }\n\n return {\n url\n }\n }\n})\n\n</script>","\nimport { getliveinfo } from '@/api';\nimport { defineComponent, ref } from 'vue';\nimport { useRoute } from 'vue-router';\n\n\nexport default defineComponent({\n setup(){\n const id = useRoute().query.id;\n const url = ref<string>()\n if(id && typeof id == 'string'){\n getliveinfo(parseInt(id)).then((res: any)=>{\n url.value = `/zhibo.html?roomid=${res.roomid}&memberid=${res.memberid}`\n })\n\n }\n\n return {\n url\n }\n }\n})\n\n","import { render } from \"./Liveing.vue?vue&type=template&id=7b21720b&scoped=true&bindings={}\"\nimport script from \"./Liveing.vue?vue&type=script&lang=ts\"\nexport * from \"./Liveing.vue?vue&type=script&lang=ts\"\n\nimport \"./Liveing.vue?vue&type=style&index=0&id=7b21720b&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-7b21720b\"\n\nexport default script","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./Liveing.vue?vue&type=style&index=0&id=7b21720b&lang=scss&scoped=true\""],"sourceRoot":""}

2
dist/js/chunk-21d6a1b9.ecc97c3b.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-27236dd2.6a20330a.js vendored Normal file
View File

@@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-27236dd2"],{"85e6":function(e,t,c){},b6ff:function(e,t,c){"use strict";c("85e6")},f9ca:function(e,t,c){"use strict";c.r(t);var n=c("7a23"),o=Object(n["withScopeId"])("data-v-408c2078");Object(n["pushScopeId"])("data-v-408c2078");var d={class:"body",id:"rbody"};Object(n["popScopeId"])();var i=o((function(e,t,c,o,i,a){var r=Object(n["resolveComponent"])("NavTop"),u=Object(n["resolveComponent"])("router-view");return Object(n["openBlock"])(),Object(n["createBlock"])("div",{class:"mine",style:{height:e.height+"px"}},[Object(n["createVNode"])(r,{type:1,style:{"flex-shrink":"0"}}),Object(n["createVNode"])("div",d,[Object(n["createVNode"])(u)])],4)})),a=c("c022"),r=Object(n["defineComponent"])({components:{NavTop:a["a"]},setup:function(){var e=Object(n["ref"])(0);return Object(n["onMounted"])((function(){e.value=document.documentElement.clientHeight})),window.onresize=function(){e.value=document.documentElement.clientHeight},{height:e}}});c("b6ff");r.render=i,r.__scopeId="data-v-408c2078";t["default"]=r}}]);
//# sourceMappingURL=chunk-27236dd2.6a20330a.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["webpack:///./src/layout/Regime.vue?ec2d","webpack:///./src/layout/Regime.vue","webpack:///./src/layout/Regime.vue?982c","webpack:///./src/layout/Regime.vue?cb68"],"names":["class","id","style","height","type","components","NavTop","setup","value","document","documentElement","clientHeight","window","onresize","render","__scopeId"],"mappings":"yIAAA,W,0JCGaA,MAAM,OAAOC,GAAG,S,sLAFzB,yBAKM,OALDD,MAAM,OAAQE,MAAK,QAAU,EAAAC,OAAM,O,CACpC,yBAAiD,GAAxCC,KAAM,EAAGF,MAAA,sBAClB,yBAEM,MAFN,EAEM,CADF,yBAAc,M,kBCAX,+BAAgB,CAC3BG,WAAW,CACPC,SAAA,MAEJC,MAJ2B,WAMvB,IAAMJ,EAAS,iBAAI,GAOnB,OANA,wBAAU,WACNA,EAAOK,MAAQC,SAASC,gBAAgBC,gBAE5CC,OAAOC,SAAS,WACZV,EAAOK,MAAQC,SAASC,gBAAgBC,cAErC,CACHR,a,UCbZ,EAAOW,OAAS,EAChB,EAAOC,UAAY,kBAEJ","file":"js/chunk-27236dd2.6a20330a.js","sourcesContent":["export * from \"-!../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./Regime.vue?vue&type=style&index=0&id=408c2078&lang=scss&scoped=true\"","<template>\n <div class=\"mine\" :style=\"{height:height + 'px'}\">\n <NavTop :type=\"1\" style=\"flex-shrink:0\"></NavTop>\n <div class=\"body\" id=\"rbody\">\n <router-view/>\n </div>\n </div>\n</template>\n<style lang=\"scss\" scoped>\n.mine{\n display: flex;\n flex-direction: column;\n .body{\n // display: flex;\n width: 100%;\n height: calc(100% - 57px);\n overflow: auto;\n background-color: #F5F5F5;\n padding: 23px;\n }\n}\n</style>\n<script lang=\"ts\">\nimport { defineComponent, onMounted, ref } from 'vue';\nimport NavTop from \"@/components/NavTop.vue\"\n\nexport default defineComponent({\n components:{\n NavTop\n },\n setup(){\n console.log(1)\n const height = ref(0);\n onMounted(() => {\n height.value = document.documentElement.clientHeight;\n })\n window.onresize=function(){ \n height.value = document.documentElement.clientHeight;\n }\n return {\n height\n }\n }\n})\n</script>","\nimport { defineComponent, onMounted, ref } from 'vue';\nimport NavTop from \"@/components/NavTop.vue\"\n\nexport default defineComponent({\n components:{\n NavTop\n },\n setup(){\n console.log(1)\n const height = ref(0);\n onMounted(() => {\n height.value = document.documentElement.clientHeight;\n })\n window.onresize=function(){ \n height.value = document.documentElement.clientHeight;\n }\n return {\n height\n }\n }\n})\n","import { render } from \"./Regime.vue?vue&type=template&id=408c2078&scoped=true&bindings={}\"\nimport script from \"./Regime.vue?vue&type=script&lang=ts\"\nexport * from \"./Regime.vue?vue&type=script&lang=ts\"\n\nimport \"./Regime.vue?vue&type=style&index=0&id=408c2078&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-408c2078\"\n\nexport default script"],"sourceRoot":""}

2
dist/js/chunk-2a197f09.31e80702.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-34d93bb8.99541265.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-371ee143.db48ebbc.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-3c7641ed.47b122a8.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-43a87df0.464f9357.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-46e3b07d.d6873afe.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-4cbe0c82.4f446d66.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-4e0b884c.9c3a81c9.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

17
dist/js/chunk-520d8a08.2b87a45a.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-623eb100.0d77f748.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-650d0cb1.7cc3b70b.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-68091c98.6bc9c5f0.js vendored Normal file
View File

@@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-68091c98"],{"04fd":function(a,d,t){"use strict";t("665d")},1009:function(a,d,t){"use strict";t("b0c0");var c=t("7a23"),e=Object(c["withScopeId"])("data-v-6dd528d6");Object(c["pushScopeId"])("data-v-6dd528d6");var i={class:"nav-bottom"};Object(c["popScopeId"])();var v=e((function(a,d,t,e,v,s){return Object(c["openBlock"])(),Object(c["createBlock"])("div",i,[Object(c["createVNode"])("div",{class:"nav-container",style:a.color},[(Object(c["openBlock"])(!0),Object(c["createBlock"])(c["Fragment"],null,Object(c["renderList"])(a.navArray,(function(d,t){return Object(c["openBlock"])(),Object(c["createBlock"])("div",{key:t,class:"nav-item",onClick:function(t){return a.navto(d.route)}},[Object(c["createVNode"])("div",{class:d.route==a.nowroute?"active":""},Object(c["toDisplayString"])(a.lan.$t(d.name)),3)],8,["onClick"])})),128))],4),Object(c["createVNode"])("div",{class:"copyright",style:a.color},Object(c["toDisplayString"])(a.lan.$t("banquan")),5)])})),s=t("afbc"),n=t("5699"),o=t("6c02"),l=Object(c["defineComponent"])({props:{color:Object},setup:function(){var a=Object(n["c"])(),d=Object(o["d"])(),t=Object(c["ref"])(d.path),e=[{name:"zhiboguanli",route:"/regime/live"},{name:"shipinguanli",route:"/regime/video"},{name:"dingyuezheguanli",route:"/regime/subscriber"},{name:"gerenzhongxin",route:"/mine/archives"}];function i(a){t.value=a,s["a"].push(a)}return{navArray:e,navto:i,nowroute:t,lan:a}}});t("9af0");l.render=v,l.__scopeId="data-v-6dd528d6";d["a"]=l},"3c6d":function(a,d,t){"use strict";t.r(d);var c=t("7a23"),e=Object(c["withScopeId"])("data-v-d91c5628");Object(c["pushScopeId"])("data-v-d91c5628");var i={class:"transaction"},v={class:"mingxilist"},s=Object(c["createStaticVNode"])('<div class="tabs" data-v-d91c5628><div class="beforetab" data-v-d91c5628>提现记录详情</div></div><div class="detail" data-v-d91c5628><div class="infoitem" data-v-d91c5628><div class="left" data-v-d91c5628>提现金额</div><div class="right" data-v-d91c5628>¥30.00</div></div><div class="infoitem" data-v-d91c5628><div class="left" data-v-d91c5628>到账金额</div><div class="right" data-v-d91c5628>¥30.00</div></div><div class="infoitem" data-v-d91c5628><div class="left" data-v-d91c5628>手续费</div><div class="right" data-v-d91c5628>¥30.00</div></div><div class="infoitem" data-v-d91c5628><div class="left" data-v-d91c5628>提现状态</div><div class="right" data-v-d91c5628>失败</div></div><div class="infoitem" data-v-d91c5628><div class="left" data-v-d91c5628>原因描述</div><div class="right" data-v-d91c5628>提交账户出错</div></div><div class="infoitem" data-v-d91c5628><div class="left" data-v-d91c5628>流水号</div><div class="right" data-v-d91c5628>126545654561656515616256565646556</div></div><div class="infoitem" data-v-d91c5628><div class="left" data-v-d91c5628>名称</div><div class="right" data-v-d91c5628>余额提现</div></div><div class="infoitem" data-v-d91c5628><div class="left" data-v-d91c5628>日期</div><div class="right" data-v-d91c5628>2020-08-17 14:23:20</div></div><div class="infoitem" data-v-d91c5628><div class="left" data-v-d91c5628>收款账户</div><div class="right" data-v-d91c5628>储蓄卡 6217 **** 264</div></div><div class="btns" data-v-d91c5628><div class="back" data-v-d91c5628>返回</div><div class="back shensu" data-v-d91c5628>申诉</div></div></div>',2);Object(c["popScopeId"])();var n=e((function(a,d,t,e,n,o){var l=Object(c["resolveComponent"])("NavBottom");return Object(c["openBlock"])(),Object(c["createBlock"])("div",i,[Object(c["createVNode"])("div",v,[s,Object(c["createVNode"])(l,{class:"navbottom"})])])})),o=t("1009"),l=t("5699"),r=Object(c["defineComponent"])({name:"Cashoutdetail",components:{NavBottom:o["a"]},setup:function(){var a=Object(l["c"])();return{lan:a}}});t("04fd");r.render=n,r.__scopeId="data-v-d91c5628";d["default"]=r},"665d":function(a,d,t){},"9af0":function(a,d,t){"use strict";t("ac9a")},ac9a:function(a,d,t){}}]);
//# sourceMappingURL=chunk-68091c98.6bc9c5f0.js.map

File diff suppressed because one or more lines are too long

2
dist/js/chunk-737c53fe.f61ff849.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-74d7e8d4.02cdd824.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-94cd6d3c.97ee0e5b.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-977f0f52.4ec7ef7e.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-cc7ac8b2.279475fe.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-d0ed1ba4.02a0fef7.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/chunk-da7e1532.4b71bb2c.js vendored Normal file
View File

@@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-da7e1532"],{"083f":function(e,c,t){"use strict";t("0988")},"0988":function(e,c,t){},"16fb":function(e,c,t){"use strict";t.r(c);var a=t("7a23"),s=t("cfbd"),o=t.n(s),d=t("a7fd"),l=t.n(d),i=t("c7ed"),r=t.n(i),n=t("e1f4"),b=t.n(n),j=Object(a["withScopeId"])("data-v-2961cc68");Object(a["pushScopeId"])("data-v-2961cc68");var O={class:"share"},N=Object(a["createVNode"])("div",{class:"box"},[Object(a["createVNode"])("div",{class:"top"},[Object(a["createTextVNode"])(" 您好,欢迎来到 "),Object(a["createVNode"])("span",{class:"org_name"},"Beelink")]),Object(a["createVNode"])("div",{class:"mid"},[Object(a["createVNode"])("div",{class:"left active"},[Object(a["createVNode"])("div",{class:"title"},"如果您是老师"),Object(a["createVNode"])("img",{src:o.a,alt:"",class:"pic"}),Object(a["createVNode"])("div",{class:"ale"},"想要赚取直播收益,请使用电脑端访问一下域名"),Object(a["createVNode"])("div",{class:"link"},"https://www.beelinkXXXX.com")]),Object(a["createVNode"])("div",{class:"left right"},[Object(a["createVNode"])("div",null,[Object(a["createVNode"])("div",{class:"title"},"如果您是老师"),Object(a["createVNode"])("img",{src:o.a,alt:"",class:"pic"}),Object(a["createVNode"])("div",{class:"ale"},"想要赚取直播收益,请使用电脑端访问一下域名"),Object(a["createVNode"])("div",{class:"link"},"https://www.beelinkXXXX.com")]),Object(a["createVNode"])("div",{class:"line"}),Object(a["createVNode"])("div",{class:"ewms"},[Object(a["createVNode"])("div",null,[Object(a["createVNode"])("span",null,"Google play "),Object(a["createVNode"])("img",{src:l.a,alt:"",class:"ewm"})]),Object(a["createVNode"])("div",null,[Object(a["createVNode"])("span",null," App store "),Object(a["createVNode"])("img",{src:l.a,alt:"",class:"ewm ewm1"})])])])])],-1),p=Object(a["createVNode"])("div",{class:"bottom"},[Object(a["createVNode"])("div",{class:"content"},[Object(a["createVNode"])("div",{class:"title"},"关于 Beelink"),Object(a["createVNode"])("div",{class:"rowline"}),Object(a["createVNode"])("div",{class:"texts"}," Beelink平台拥有数千名优秀老师丰富的教育经验和有趣的课堂环境一对一辅导 平台的教务管理、线上课堂、线下课堂、助学互动,课程回放等多项教学功能,让 您利用碎片时间,轻轻松松学会各种语言。 "),Object(a["createVNode"])("div",{class:"relation"},[Object(a["createVNode"])("div",{class:"more"},"了解更多"),Object(a["createVNode"])("img",{src:r.a,alt:"",class:"icon"}),Object(a["createVNode"])("div",null,"136-0111-1111"),Object(a["createVNode"])("img",{src:b.a,alt:"",class:"icon email"}),Object(a["createVNode"])("div",null,"136-0111-1111")])])],-1);Object(a["popScopeId"])();var v=j((function(e,c,t,s,o,d){var l=Object(a["resolveComponent"])("NavTop");return Object(a["openBlock"])(),Object(a["createBlock"])("div",O,[Object(a["createVNode"])(l,{type:0,style:{"flex-shrink":"0"}}),N,p])})),V=t("c022"),m=Object(a["defineComponent"])({name:"Share",components:{NavTop:V["a"]},setup:function(){return{}}});t("083f");m.render=v,m.__scopeId="data-v-2961cc68";c["default"]=m},a7fd:function(e,c,t){e.exports=t.p+"img/ewm1.6726120a.png"},cfbd:function(e,c,t){e.exports=t.p+"img/teacher.4bac0ea8.png"}}]);
//# sourceMappingURL=chunk-da7e1532.4b71bb2c.js.map

File diff suppressed because one or more lines are too long

2
dist/js/chunk-ef207110.3414d58c.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

294
dist/js/chunk-vendors.5e652f88.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/js/chunk-vendors.5e652f88.js.map vendored Normal file

File diff suppressed because one or more lines are too long

656
dist/js/common.js vendored Normal file
View File

@@ -0,0 +1,656 @@
/* eslint-disable no-cond-assign */
/* global $ TRTC presetting RtcClient ShareClient */
/* eslint-disable require-jsdoc */
let isCamOn = true;
let isMicOn = true;
let isScreenOn = false;
let isJoined = true;
let rtc = null;
let share = null;
let shareUserId = '';
let cameraId = '';
let micId = '';
function login() {
presetting.login(false, options => {
rtc = new RtcClient(options);
join();
});
presetting.login(true, options => {
shareUserId = options.userId;
share = new ShareClient(options);
});
}
$(function (){
login();
})
function join() {
rtc.join();
$('#login-root').hide();
$('#room-root').show();
$('#header-roomId').html('房间号: ' + $('#roomId').val());
$('#member-me')
.find('.member-id')
.html($('#userId').val() + '(我)');
}
function leave() {
$('#mask_main').appendTo($('#main-video'));
rtc.leave();
share.leave();
}
function publish() {
rtc.publish();
}
function unpublish() {
rtc.unpublish();
}
function muteAudio() {
rtc.muteLocalAudio();
}
function unmuteAudio() {
rtc.unmuteLocalAudio();
}
function muteVideo() {
$('#mask_main').show();
rtc.muteLocalVideo();
}
function unmuteVideo() {
rtc.unmuteLocalVideo();
$('#mask_main').hide();
}
function startSharing() {
share.join();
}
function stopSharing() {
share.leave();
}
function setBtnClickFuc() {
//userid roomid规格
//$('#userId').on('input', function(e) {
// e.preventDefault();
// console.log('userId input ' + e.target.value);
// let val = $('#userId').val().slice(5);
// $('#userId').val('user_'+val.replace(/[^\d]/g,''));
//});
$('#roomId').on('input', function(e) {
e.preventDefault();
console.log('roomId input ' + e.target.value);
let val = $('#roomId').val();
$('#roomId').val(val.replace(/[^\d]/g, ''));
});
//login
$('#login-btn').click(() => {
login();
});
//open or close camera
$('#video-btn').on('click', () => {
if (isCamOn) {
$('#video-btn').attr('src', './img/big-camera-off.png');
$('#video-btn').attr('title', '打开摄像头');
$('#member-me')
.find('.member-video-btn')
.attr('src', 'img/camera-off.png');
isCamOn = false;
muteVideo();
} else {
$('#video-btn').attr('src', './img/big-camera-on.png');
$('#video-btn').attr('title', '关闭摄像头');
$('#member-me')
.find('.member-video-btn')
.attr('src', 'img/camera-on.png');
isCamOn = true;
unmuteVideo();
}
});
//open or close microphone
$('#mic-btn').on('click', () => {
if (isMicOn) {
$('#mic-btn').attr('src', './img/big-mic-off.png');
$('#mic-btn').attr('title', '打开麦克风');
$('#member-me')
.find('.member-audio-btn')
.attr('src', 'img/mic-off.png');
isMicOn = false;
muteAudio();
} else {
$('#mic-btn').attr('src', './img/big-mic-on.png');
$('#mic-btn').attr('title', '关闭麦克风');
$('#member-me')
.find('.member-audio-btn')
.attr('src', 'img/mic-on.png');
isMicOn = true;
unmuteAudio();
}
});
//share screen or not
$('#screen-btn').on(
'click',
throttle(() => {
if (!TRTC.isScreenShareSupported()) {
alert('当前浏览器不支持屏幕分享!');
return;
}
if ($('#screen-btn').attr('src') == './img/screen-on.png') {
$('#screen-btn').attr('src', './img/screen-off.png');
stopSharing();
isScreenOn = false;
} else {
$('#screen-btn').attr('src', './img/screen-on.png');
startSharing();
isScreenOn = true;
}
}, 2000)
);
//logout
$('#logout-btn').on('click', () => {
leave();
$('#room-root').hide();
$('#login-root').show();
});
//switch main video
$('#main-video').on('click', () => {
let mainVideo = $('.video-box').first();
if ($('#main-video').is(mainVideo)) {
return;
}
//释放main-video grid-area
mainVideo.css('grid-area', 'auto/auto/auto/auto');
exchangeView($('#main-video'), mainVideo);
//将video-grid中第一个div设为main-video
$('.video-box')
.first()
.css('grid-area', '1/1/3/4');
//chromeM71以下会自动暂停手动唤醒
if (getBroswer().broswer == 'Chrome' && getBroswer().version < '72') {
rtc.resumeStreams();
}
});
//chrome60以下不支持popover防止error
if (getBroswer().broswer == 'Chrome' && getBroswer().version < '60') return;
//开启popover
$(function() {
$('[data-toggle="popover"]').popover();
});
$('#camera').popover({
html: true,
content: () => {
return $('#camera-option').html();
}
});
$('#microphone').popover({
html: true,
content: () => {
return $('#mic-option').html();
}
});
$('#camera').on('click', () => {
$('#microphone').popover('hide');
$('.popover-body')
.find('div')
.attr('onclick', 'setCameraId(this)');
});
$('#microphone').on('click', () => {
$('#camera').popover('hide');
$('.popover-body')
.find('div')
.attr('onclick', 'setMicId(this)');
});
//点击body关闭popover
$('body').click(() => {
$('#camera').popover('hide');
$('#microphone').popover('hide');
});
//popover事件
$('#camera').on('show.bs.popover', () => {
$('#camera').attr('src', './img/camera-on.png');
});
$('#camera').on('hide.bs.popover', () => {
$('#camera').attr('src', './img/camera.png');
});
$('#microphone').on('show.bs.popover', () => {
$('#microphone').attr('src', './img/mic-on.png');
});
$('#microphone').on('hide.bs.popover', () => {
$('#microphone').attr('src', './img/mic.png');
});
}
function setCameraId(thisDiv) {
cameraId = $(thisDiv).attr('id');
console.log('setCameraId: ' + cameraId);
}
function setMicId(thisDiv) {
micId = $(thisDiv).attr('id');
console.log('setMicId: ' + micId);
}
function addVideoView(id, isLocal = false) {
let div = $('<div/>', {
id: id,
class: 'video-box',
style: 'justify-content: center'
});
div.appendTo('#video-grid');
//设置监听
div.click(() => {
let mainVideo = $('.video-box').first();
if (div.is(mainVideo)) {
return;
}
//释放main-video grid-area
mainVideo.css('grid-area', 'auto/auto/auto/auto');
exchangeView(div, mainVideo);
//将video-grid中第一个div设为main-video
$('.video-box')
.first()
.css('grid-area', '1/1/3/4');
//chromeM71以下会自动暂停手动唤醒
if (getBroswer().broswer == 'Chrome' && getBroswer().version < '72') {
rtc.resumeStreams();
}
});
}
function addMemberView(id) {
let memberElm = $('#member-me').clone();
memberElm.attr('id', id);
memberElm.find('div.member-id').html(id);
memberElm.css('display', 'flex');
memberElm.appendTo($('#member-list'));
}
function removeView(id) {
if ($('#' + id)[0]) {
$('#' + id).remove();
//将video-grid中第一个div设为main-video
$('.video-box')
.first()
.css('grid-area', '1/1/3/4');
}
}
function exchangeView(a, b) {
var $div1 = $(a);
var $div3 = $(b);
var $temobj1 = $('<div></div>');
var $temobj2 = $('<div></div>');
$temobj1.insertBefore($div1);
$temobj2.insertBefore($div3);
$div1.insertAfter($temobj2);
$div3.insertAfter($temobj1);
$temobj1.remove();
$temobj2.remove();
}
function isPC() {
var userAgentInfo = navigator.userAgent;
var Agents = new Array('Android', 'iPhone', 'SymbianOS', 'Windows Phone', 'iPad', 'iPod');
var flag = true;
for (var v = 0; v < Agents.length; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
flag = false;
break;
}
}
return flag;
}
function getCameraId() {
console.log('selected cameraId: ' + cameraId);
return cameraId;
}
function getMicrophoneId() {
console.log('selected microphoneId: ' + micId);
return micId;
}
function throttle(func, delay) {
var timer = null;
var startTime = Date.now();
return function() {
var curTime = Date.now();
var remaining = delay - (curTime - startTime);
var context = this;
var args = arguments;
clearTimeout(timer);
if (remaining <= 0) {
func.apply(context, args);
startTime = Date.now();
} else {
timer = setTimeout(() => {
console.log('duplicate click');
}, remaining);
}
};
}
function resetView() {
isCamOn = true;
isMicOn = true;
isScreenOn = false;
isJoined = true;
$('#main-video-btns').hide();
$('#video-btn').attr('src', './img/big-camera-on.png');
$('#mic-btn').attr('src', './img/big-mic-on.png');
$('#screen-btn').attr('src', './img/screen-off.png');
$('#member-me')
.find('.member-video-btn')
.attr('src', 'img/camera-on.png');
$('#member-me')
.find('.member-audio-btn')
.attr('src', 'img/mic-on.png');
$('.mask').hide();
//清空member-list
if ($('#member-list')) {
$('#member-list')
.find('.member')
.each((index, element) => {
if (
$(element)
.parent()
.attr('id') != 'member-me'
) {
$(element)
.parent()
.remove();
}
});
}
}
function getBroswer() {
var sys = {};
var ua = navigator.userAgent.toLowerCase();
var s;
(s = ua.match(/edge\/([\d.]+)/))
? (sys.edge = s[1])
: (s = ua.match(/rv:([\d.]+)\) like gecko/))
? (sys.ie = s[1])
: (s = ua.match(/msie ([\d.]+)/))
? (sys.ie = s[1])
: (s = ua.match(/firefox\/([\d.]+)/))
? (sys.firefox = s[1])
: (s = ua.match(/chrome\/([\d.]+)/))
? (sys.chrome = s[1])
: (s = ua.match(/opera.([\d.]+)/))
? (sys.opera = s[1])
: (s = ua.match(/version\/([\d.]+).*safari/))
? (sys.safari = s[1])
: 0;
if (sys.edge) return { broswer: 'Edge', version: sys.edge };
if (sys.ie) return { broswer: 'IE', version: sys.ie };
if (sys.firefox) return { broswer: 'Firefox', version: sys.firefox };
if (sys.chrome) return { broswer: 'Chrome', version: sys.chrome };
if (sys.opera) return { broswer: 'Opera', version: sys.opera };
if (sys.safari) return { broswer: 'Safari', version: sys.safari };
return { broswer: '', version: '0' };
}
function isHidden() {
var hidden, visibilityChange;
if (typeof document.hidden !== 'undefined') {
hidden = 'hidden';
visibilityChange = 'visibilitychange';
} else if (typeof document.msHidden !== 'undefined') {
hidden = 'msHidden';
visibilityChange = 'msvisibilitychange';
} else if (typeof document.webkitHidden !== 'undefined') {
hidden = 'webkitHidden';
visibilityChange = 'webkitvisibilitychange';
}
return document[hidden];
}
function getIPAddress() {
return new Promise(resolve => {
window.RTCPeerConnection =
window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; //compatibility for firefox and chrome
let pc = new RTCPeerConnection({ iceServers: [] });
let noop = function() {};
let IPAddress = '';
let ipRegex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/;
pc.createDataChannel(''); //create a bogus data channel
pc.createOffer(pc.setLocalDescription.bind(pc), noop); // create offer and set local description
//listen for candidate events
pc.onicecandidate = function(ice) {
if (
!ice ||
!ice.candidate ||
!ice.candidate.candidate ||
!ipRegex.exec(ice.candidate.candidate)
) {
return;
}
IPAddress = ipRegex.exec(ice.candidate.candidate)[1];
pc.onicecandidate = noop;
resolve(IPAddress);
};
});
}
let isMobile = {
Android: function() {
return navigator.userAgent.match(/Android/i);
},
BlackBerry: function() {
return navigator.userAgent.match(/BlackBerry|BB10/i);
},
iOS: function() {
return navigator.userAgent.match(/iPhone|iPad|iPod/i);
},
Opera: function() {
return navigator.userAgent.match(/Opera Mini/i);
},
Windows: function() {
return navigator.userAgent.match(/IEMobile/i);
},
any: function() {
return (
isMobile.Android() ||
isMobile.BlackBerry() ||
isMobile.iOS() ||
isMobile.Opera() ||
isMobile.Windows()
);
},
getOsName: function() {
var osName = 'Unknown OS';
if (isMobile.Android()) {
osName = 'Android';
}
if (isMobile.BlackBerry()) {
osName = 'BlackBerry';
}
if (isMobile.iOS()) {
osName = 'iOS';
}
if (isMobile.Opera()) {
osName = 'Opera Mini';
}
if (isMobile.Windows()) {
osName = 'Windows';
}
return osName;
}
};
function detectDesktopOS() {
var unknown = '-';
var nVer = navigator.appVersion;
var nAgt = navigator.userAgent;
var os = unknown;
var clientStrings = [
{
s: 'Chrome OS',
r: /CrOS/
},
{
s: 'Windows 10',
r: /(Windows 10.0|Windows NT 10.0)/
},
{
s: 'Windows 8.1',
r: /(Windows 8.1|Windows NT 6.3)/
},
{
s: 'Windows 8',
r: /(Windows 8|Windows NT 6.2)/
},
{
s: 'Windows 7',
r: /(Windows 7|Windows NT 6.1)/
},
{
s: 'Windows Vista',
r: /Windows NT 6.0/
},
{
s: 'Windows Server 2003',
r: /Windows NT 5.2/
},
{
s: 'Windows XP',
r: /(Windows NT 5.1|Windows XP)/
},
{
s: 'Windows 2000',
r: /(Windows NT 5.0|Windows 2000)/
},
{
s: 'Windows ME',
r: /(Win 9x 4.90|Windows ME)/
},
{
s: 'Windows 98',
r: /(Windows 98|Win98)/
},
{
s: 'Windows 95',
r: /(Windows 95|Win95|Windows_95)/
},
{
s: 'Windows NT 4.0',
r: /(Windows NT 4.0|WinNT4.0|WinNT|Windows NT)/
},
{
s: 'Windows CE',
r: /Windows CE/
},
{
s: 'Windows 3.11',
r: /Win16/
},
{
s: 'Android',
r: /Android/
},
{
s: 'Open BSD',
r: /OpenBSD/
},
{
s: 'Sun OS',
r: /SunOS/
},
{
s: 'Linux',
r: /(Linux|X11)/
},
{
s: 'iOS',
r: /(iPhone|iPad|iPod)/
},
{
s: 'Mac OS X',
r: /Mac OS X/
},
{
s: 'Mac OS',
r: /(MacPPC|MacIntel|Mac_PowerPC|Macintosh)/
},
{
s: 'QNX',
r: /QNX/
},
{
s: 'UNIX',
r: /UNIX/
},
{
s: 'BeOS',
r: /BeOS/
},
{
s: 'OS/2',
r: /OS\/2/
},
{
s: 'Search Bot',
r: /(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/
}
];
for (var i = 0, cs; (cs = clientStrings[i]); i++) {
if (cs.r.test(nAgt)) {
os = cs.s;
break;
}
}
var osVersion = unknown;
if (/Windows/.test(os)) {
if (/Windows (.*)/.test(os)) {
osVersion = /Windows (.*)/.exec(os)[1];
}
os = 'Windows';
}
switch (os) {
case 'Mac OS X':
if (/Mac OS X (10[/._\d]+)/.test(nAgt)) {
// eslint-disable-next-line no-useless-escape
osVersion = /Mac OS X (10[\.\_\d]+)/.exec(nAgt)[1];
}
break;
case 'Android':
// eslint-disable-next-line no-useless-escape
if (/Android ([\.\_\d]+)/.test(nAgt)) {
// eslint-disable-next-line no-useless-escape
osVersion = /Android ([\.\_\d]+)/.exec(nAgt)[1];
}
break;
case 'iOS':
if (/OS (\d+)_(\d+)_?(\d+)?/.test(nAgt)) {
osVersion = /OS (\d+)_(\d+)_?(\d+)?/.exec(nVer);
osVersion = osVersion[1] + '.' + osVersion[2] + '.' + (osVersion[3] | 0);
}
break;
}
return {
osName: os + osVersion
};
}
function getOS() {
if (isMobile.any()) {
return isMobile.getOsName();
} else {
return detectDesktopOS();
}
}

10
dist/js/cropper.min.js vendored Normal file

File diff suppressed because one or more lines are too long

73
dist/js/debug/GenerateTestUserSig.js vendored Normal file
View File

@@ -0,0 +1,73 @@
/* eslint-disable require-jsdoc */
/*
* Module: GenerateTestUserSig
*
* Function: 用于生成测试用的 UserSigUserSig 是腾讯云为其云服务设计的一种安全保护签名。
* 其计算方法是对 SDKAppID、UserID 和 EXPIRETIME 进行加密,加密算法为 HMAC-SHA256。
*
* Attention: 请不要将如下代码发布到您的线上正式版本的 App 中,原因如下:
*
* 本文件中的代码虽然能够正确计算出 UserSig但仅适合快速调通 SDK 的基本功能,不适合线上产品,
* 这是因为客户端代码中的 SECRETKEY 很容易被反编译逆向破解,尤其是 Web 端的代码被破解的难度几乎为零。
* 一旦您的密钥泄露,攻击者就可以计算出正确的 UserSig 来盗用您的腾讯云流量。
*
* 正确的做法是将 UserSig 的计算代码和加密密钥放在您的业务服务器上,然后由 App 按需向您的服务器获取实时算出的 UserSig。
* 由于破解服务器的成本要高于破解客户端 App所以服务器计算的方案能够更好地保护您的加密密钥。
*
* Referencehttps://cloud.tencent.com/document/product/647/17275#Server
*/
function genTestUserSig(userID) {
/**
* 腾讯云 SDKAppId需要替换为您自己账号下的 SDKAppId。
*
* 进入腾讯云实时音视频[控制台](https://console.cloud.tencent.com/rav ) 创建应用,即可看到 SDKAppId
* 它是腾讯云用于区分客户的唯一标识。
*/
// const SDKAPPID = 1400435767;
// /**
// * 签名过期时间,建议不要设置的过短
// * <p>
// * 时间单位:秒
// * 默认时间7 x 24 x 60 x 60 = 604800 = 7 天
// */
// const EXPIRETIME = 604800;
// /**
// * 计算签名用的加密密钥,获取步骤如下:
// *
// * step1. 进入腾讯云实时音视频[控制台](https://console.cloud.tencent.com/rav ),如果还没有应用就创建一个,
// * step2. 单击“应用配置”进入基础配置页面,并进一步找到“帐号体系集成”部分。
// * step3. 点击“查看密钥”按钮,就可以看到计算 UserSig 使用的加密的密钥了,请将其拷贝并复制到如下的变量中
// *
// * 注意该方案仅适用于调试Demo正式上线前请将 UserSig 计算代码和密钥迁移到您的后台服务器上,以避免加密密钥泄露导致的流量盗用。
// * 文档https://cloud.tencent.com/document/product/647/17275#Server
// */
// const SECRETKEY = 'dzrUpsgeMo0ygiSmqeDVqxnLbdT3Lbbh';
// // a soft reminder to guide developer to configure sdkAppId/secretKey
// if (SDKAPPID === '' || SECRETKEY === '') {
// alert(
// '请先配置好您的账号信息: SDKAPPID 及 SECRETKEY ' +
// '\r\n\r\nPlease configure your SDKAPPID/SECRETKEY in js/debug/GenerateTestUserSig.js'
// );
// }
// const generator = new LibGenerateTestUserSig(SDKAPPID, SECRETKEY, EXPIRETIME);
// const userSig = window.istow ? "eJwtzdEKgjAUBuB32XXYdJubQhcV2IWBkGYEgohOO1SypoYQvXtLvTzff85-Pig5xtZbauQjx8JoNc1QybaHGibuboWW*dBJnRNMMcYeX9a66l4oBRXybeOUMO7yOZGjAi2NM8YcczJrD8*-uZhhYRPBlhZozJfW4*f9y7EPafmgTXjdnYQagjIRY7Ye4qim20sNaRsGEWk26PsDMPg1Xg__" : "eJwtzE8LgkAQBfDvstdCJt3RTeigl6gMw-7oLUK3GCNZ1Foj*u5t6vH93sz7sEO0t16yZj6zLWDTPlMhq5au1POzkfXZAQ4Ac288aIr7RSkqmD8zzh30XG9oZKeolsYR0TYvg7b0*JsLCAIcjuMK3cx*LmyV5GFXBWGZ6m4VVaejzjax3K3fehsTpk2QJKVeTsSCfX94djN6";
// console.log(userSig)
// window.istow = true
// return {
// sdkAppId: SDKAPPID,
// userSig:userSig
// };
return new Promise((res)=>{
$.ajax({
url: window.url + 'userSig?userid=' + userID,
headers: "Bearer " + localStorage.getItem("token"),
success(data){
res({data: data.data, id: 1400435767})
}
})
})
}

838
dist/js/device-testing.js vendored Normal file
View File

@@ -0,0 +1,838 @@
/**
* 设备检测demo
*/
/* global $ TRTC presetting getOS getBroswer cameraId micId */
// 用于记录检测结果,生成检测报告
let hasCameraDevice = false,
hasMicAndVoiceDevice = false,
hasCameraConnect,
hasVoiceConnect,
hasMicConnect,
hasNetworkConnect;
let cameraTestingResult = {};
let voiceTestingResult = {};
let micTestingResult = {};
let networkTestingResult = {};
// 记录检测步骤,用于关闭时清空弹窗
let completedTestingPageIdList = [];
let curTestingPageId = '';
let localStream = null;
let client = null;
let timeout = null;
// 监听到network-quality事件的次数
let networkQualityNum = 0;
const deviceFailAttention =
'1. 若浏览器弹出提示,请选择“允许”<br>' +
'2. 若杀毒软件弹出提示,请选择“允许”<br>' +
'3. 检查浏览器设置,允许网页访问摄像头及麦克风<br>' +
'4. 检查摄像头/麦克风是否正确连接并开启<br>' +
'5. 尝试重新连接摄像头/麦克风<br>' +
'6. 尝试重启电脑后重新检测';
const networkFailAttention =
'1. 请检查设备是否联网<br>' + '2. 请刷新网页后再次检测<br>' + '3. 请尝试更换网络后再次检测';
// 网络参数对照表
const NETWORK_QUALITY = {
'0': '未知',
'1': '极佳',
'2': '较好',
'3': '一般',
'4': '差',
'5': '极差',
'6': '断开'
};
// 设备检测tab页签对应的执行方法
const pageCallbackConfig = {
'camera-testing-body': 'startCameraTesting',
'voice-testing-body': 'startVoiceTesting',
'mic-testing-body': 'startMicTesting',
'network-testing-body': 'startNetworkTesting'
};
// 判断是否为safari浏览器
let isSafari = /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent);
hideVoiceForSafari();
/**
* safari浏览器中隐藏扬声器相关检测
*/
function hideVoiceForSafari() {
if (!isSafari) return;
$('#connect-voice').hide();
$('#device-voice').hide();
$('#voice-testing').hide();
$('#voice-report').hide();
$('#device-mic').addClass('safari');
$('#device-network').addClass('safari');
$('#mic-testing').addClass('safari');
$('#network-testing').addClass('safari');
}
// 是否是本地路径打开
let isFilePath = location.href.indexOf('file://') > -1;
/**
* 设备检测初始化
*/
async function deviceTestingInit() {
// 点击【设备检测】文字, 点击 【重新连接】按钮
$('#device-testing-btn, #connect-again-btn').on('click', () => {
startDeviceConnect();
});
// 连接设备错误icon
$('#connect-attention-icon').on('mouseover', () => {
$('#connect-attention-info').show();
});
// 连接设备错误icon
$('#connect-attention-icon').on('mouseout', () => {
$('#connect-attention-info').hide();
});
// 【开始检测】开始设备检测按钮
$('#start-test-btn').on('click', function() {
if ($(this).hasClass('start-gray')) return;
$('#device-testing-prepare').hide();
$('#device-testing').show();
startCameraTesting();
});
// 摄像头检测失败/成功
$('#camera-fail, #camera-success').on('click', function() {
cameraTestingResult.statusResult = $(this).attr('id') === 'camera-success';
$('#camera-testing-body').hide();
localStream.close();
// safari浏览器跳过扬声器检测
isSafari ? startMicTesting() : startVoiceTesting();
});
// 播放器检测失败/成功
$('#voice-fail, #voice-success').on('click', function() {
voiceTestingResult.statusResult = $(this).attr('id') === 'voice-success';
$('#voice-testing-body').hide();
let audioPlayer = document.querySelector('#audio-player');
if (!audioPlayer.paused) {
audioPlayer.pause();
}
startMicTesting();
});
// 麦克风测试失败/成功
$('#mic-fail, #mic-success').on('click', function() {
micTestingResult.statusResult = $(this).attr('id') === 'mic-success';
$('#mic-testing-body').hide();
localStream.close();
startNetworkTesting();
});
// 点击【查看检测报告】按钮
$('#testing-report-btn').on('click', () => {
showTestingReport();
localStream.close();
client && client.leave();
client && client.off('network-quality');
});
// 点击【重新测试】按钮
$('#testing-again').on('click', () => {
$('#device-testing-report').hide();
startDeviceConnect();
completedTestingPageIdList = [];
});
// 点击【测试完成】按钮 / 点击关闭图标
$('#testing-finish, #device-testing-close-btn').on('click', () => {
finishDeviceTesting();
});
// 测试tab页切换
$('#camera-testing, #voice-testing, #mic-testing, #network-testing').on('click', function() {
let targetPageId = $(this).attr('id') + '-body';
if (
targetPageId !== curTestingPageId &&
completedTestingPageIdList.indexOf(targetPageId) > -1
) {
$(`#${curTestingPageId}`).hide();
localStream && localStream.close();
client && client.leave();
client && client.off('network-quality');
// 停止播放器的音乐
let audioPlayer = document.querySelector('#audio-player');
if (!audioPlayer.paused) {
audioPlayer.pause();
}
// 展示要切换的设备检测tab页面
$(`#${targetPageId}`).show();
window[pageCallbackConfig[targetPageId]] && window[pageCallbackConfig[targetPageId]]();
}
});
// 摄像头设备切换
$('#camera-select').change(async function() {
let newCameraId = $(this)
.children('option:selected')
.val();
localStorage.setItem('txy_webRTC_cameraId', newCameraId);
cameraTestingResult.device = {
label: $(this)
.children('option:selected')
.text(),
deviceId: $(this)
.children('option:selected')
.val(),
kind: 'videoinput'
};
await localStream.switchDevice('video', newCameraId);
});
// 扬声器设备切换
$('#voice-select').change(async function() {
let newVoiceId = $(this)
.children('option:selected')
.val();
localStorage.setItem('txy_webRTC_voiceId', newVoiceId);
voiceTestingResult.device = {
label: $(this)
.children('option:selected')
.text(),
deviceId: $(this)
.children('option:selected')
.val(),
kind: 'audiooutput'
};
let audioPlayer = document.querySelector('#audio-player');
await audioPlayer.setSinkId(newVoiceId);
});
// 麦克风设备切换
$('#mic-select').change(async function() {
let newMicID = $(this)
.children('option:selected')
.val();
localStorage.setItem('txy_webRTC_micId', newMicID);
micTestingResult.device = {
label: $(this)
.children('option:selected')
.text(),
deviceId: $(this)
.children('option:selected')
.val(),
kind: 'audioinput'
};
await localStream.switchDevice('audio', newMicID);
});
$('body').on('click', function() {
$('#device-connect-list').hide();
});
// 获取设备信息
await getDevicesInfo();
// 初始化设备弹窗信息
deviceDialogInit();
}
/**
* 获取设备信息及网络连接信息
*/
async function getDevicesInfo() {
let micList = await TRTC.getMicrophones();
let voiceList = await TRTC.getSpeakers();
let cameraList = await TRTC.getCameras();
let index = isFilePath ? 'label' : 'deviceId';
if (cameraList.length > 0) {
hasCameraDevice = true;
}
if (micList.length > 0) {
hasMicAndVoiceDevice = true;
}
cameraList.forEach(camera => {
if (camera[index].length > 0) {
hasCameraConnect = true;
}
});
micList.forEach(mic => {
if (mic[index].length > 0) {
hasMicConnect = true;
}
});
if (isSafari) {
hasVoiceConnect = true;
} else {
voiceList.forEach(voice => {
if (voice[index].length > 0) {
hasVoiceConnect = true;
}
});
}
hasNetworkConnect = !!navigator.onLine;
}
/**
* 判断是否展示弹窗
*/
function deviceDialogInit() {
if (!localStorage.getItem('txy_device_testing')) {
localStorage.setItem('txy_device_testing', Date.now());
startDeviceConnect();
} else {
// 在首页展示设备连接结果
let showDeviceStatus = function() {
$('#device-connect-list').show();
timeout = setTimeout(() => {
$('#device-connect-list').hide();
}, 3000);
$('#connect-camera').css('color', `${hasCameraConnect ? 'green' : 'red'}`);
$('#connect-voice').css('color', `${hasVoiceConnect ? 'green' : 'red'}`);
$('#connect-mic').css('color', `${hasMicConnect ? 'green' : 'red'}`);
$('#connect-network').css('color', `${hasNetworkConnect ? 'green' : 'red'}`);
if (!(hasCameraConnect && hasVoiceConnect && hasMicConnect && hasNetworkConnect)) {
$('#device-testing-btn').css('color', 'red');
} else {
$('#device-testing-btn').css('color', 'green');
}
};
showDeviceStatus();
if (!(hasCameraConnect && hasVoiceConnect && hasMicConnect)) {
navigator.mediaDevices
.getUserMedia({ video: hasCameraDevice, audio: hasMicAndVoiceDevice })
.then(async () => {
// 重新获取设备信息
await getDevicesInfo();
// 更新首页popover的option list
getDevicesList();
// 展示连接结果
showDeviceStatus();
})
.catch(err => {});
}
}
}
/**
* 弹窗-设备连接检查
*/
function startDeviceConnect() {
// 显示设备检测弹窗
$('#device-testing-root').show();
// 设备检测弹窗-设备连接页
$('#device-testing-prepare').show();
curTestingPageId = 'device-testing-prepare';
initTestingTabTitle();
// 在设备检测弹窗显示设备连接信息
let showDeviceConnectInfo = function() {
if (!(hasCameraConnect && hasVoiceConnect && hasMicConnect && hasNetworkConnect)) {
$('#device-testing-btn').css('color', 'red');
} else {
$('#device-testing-btn').css('color', 'green');
}
// 隐藏设备连接失败提示
$('#connect-attention-container').hide();
// 设备连接中
$('#device-loading').show();
$('#connect-info')
.text('设备正在连接中,请稍等')
.css('color', '#cccccc');
$('#device-camera, #device-voice, #device-mic, #device-network').removeClass(
'connect-success connect-fail'
);
$('#connect-again-btn').hide();
$('#start-test-btn')
.addClass('start-gray')
.show();
// 设备连接结束,展示连接结果
setTimeout(() => {
$('#device-loading').hide();
$('#device-camera')
.removeClass('connect-success connect-fail')
.addClass(`${hasCameraConnect ? 'connect-success' : 'connect-fail'}`);
$('#device-voice')
.removeClass('connect-success connect-fail')
.addClass(`${hasVoiceConnect ? 'connect-success' : 'connect-fail'}`);
$('#device-mic')
.removeClass('connect-success connect-fail')
.addClass(`${hasMicConnect ? 'connect-success' : 'connect-fail'}`);
$('#device-network')
.removeClass('connect-success connect-fail')
.addClass(`${hasNetworkConnect ? 'connect-success' : 'connect-fail'}`);
if (!(hasCameraConnect && hasVoiceConnect && hasMicConnect)) {
let connectInfo = hasNetworkConnect
? '设备连接失败,请允许网页访问摄像头及麦克风'
: '设备及网络连接失败,请允许网页访问摄像头及麦克风并检查网络连接';
$('#connect-info')
.text(connectInfo)
.css('color', 'red');
// 显示设备连接失败引导
$('#connect-attention-container').show();
$('#connect-attention-info').html(deviceFailAttention);
// 切换按钮状态
$('#start-test-btn').hide();
$('#connect-again-btn').show();
}
if (hasCameraConnect && hasVoiceConnect && hasMicConnect && !hasNetworkConnect) {
$('#connect-info')
.text('网络连接失败,请检查网络连接')
.css('color', 'red');
// 显示网络连接失败引导
$('#connect-attention-container').show();
$('#connect-attention-info').html(networkFailAttention);
// 切换按钮状态
$('#start-test-btn').hide();
$('#connect-again-btn').show();
}
if (hasCameraConnect && hasVoiceConnect && hasMicConnect && hasNetworkConnect) {
$('#connect-info')
.text('设备及网络连接成功,请开始设备检测')
.css('color', '#32CD32');
$('#connect-again-btn').hide();
$('#start-test-btn')
.removeClass('start-gray')
.show();
}
}, 2000);
};
showDeviceConnectInfo();
// 如果有设备未连接,唤起请求弹窗
if (!(hasCameraConnect && hasVoiceConnect && hasMicConnect)) {
navigator.mediaDevices
.getUserMedia({ video: hasCameraDevice, audio: hasMicAndVoiceDevice })
.then(async () => {
// 重新获取设备信息
await getDevicesInfo();
// 更新首页popover的option list
getDevicesList();
// 显示设备连接信息
showDeviceConnectInfo();
})
.catch(err => {
console.log('err', err.name);
});
}
}
/**
* 更新首页popover的option list
*/
function getDevicesList() {
// populate camera options
TRTC.getCameras().then(devices => {
$('#camera-option').empty();
devices.forEach(device => {
if (!cameraId) {
// eslint-disable-next-line no-global-assign
cameraId = device.deviceId;
}
let div = $('<div></div>');
div.attr('id', device.deviceId);
div.html(device.label);
div.appendTo('#camera-option');
});
});
// populate microphone options
TRTC.getMicrophones().then(devices => {
$('#mic-option').empty();
devices.forEach(device => {
if (!micId) {
// eslint-disable-next-line no-global-assign
micId = device.deviceId;
}
let div = $('<div></div>');
div.attr('id', device.deviceId);
div.html(device.label);
div.appendTo('#mic-option');
});
});
}
/**
* 摄像头检测页-检测展示摄像头设备选择列表
*/
async function updateCameraDeviceList() {
let cameraDevices = await TRTC.getCameras();
cameraDevices.filter(camera => camera.deviceId !== 'default');
$('#camera-select').empty();
cameraDevices.forEach(camera => {
let option = $('<option></option>');
option.attr('value', camera.deviceId);
option.html(camera.label);
option.appendTo('#camera-select');
});
// 如果有用户设备选择缓存优先使用缓存的deviceId
let cacheCameraDevice = cameraDevices.filter(
camera => camera.deviceId === localStorage.getItem('txy_webRTC_cameraId')
);
if (cacheCameraDevice.length > 0) {
$('#camera-select').val(localStorage.getItem('txy_webRTC_cameraId'));
cameraTestingResult.device = cacheCameraDevice[0];
} else {
$('#camera-select').val(cameraDevices[0].deviceId);
cameraTestingResult.device = cameraDevices[0];
}
}
/**
* 摄像头设备测试
*/
async function startCameraTesting() {
$('#camera-testing-body').show();
curTestingPageId = 'camera-testing-body';
$('#camera-testing')
.removeClass('icon-normal')
.addClass('icon-blue complete');
completedTestingPageIdList.push('camera-testing-body');
completedTestingPageIdList = [...new Set(completedTestingPageIdList)];
await updateCameraDeviceList();
// 创建本地视频流
await createLocalStream(
{
audio: false,
video: true,
cameraId: cameraTestingResult.device.deviceId
},
'camera-video'
);
}
/**
* 初始化/更新扬声器设备数组
*/
async function updateVoiceDeviceList() {
// 获取扬声器设备并展示在界面中
let voiceDevices = await TRTC.getSpeakers();
voiceDevices = voiceDevices.filter(voice => voice.deviceId !== 'default');
$('#voice-select').empty();
voiceDevices.forEach(voice => {
let option = $('<option></option>');
option.attr('value', voice.deviceId);
option.html(voice.label);
option.appendTo('#voice-select');
});
// 如果有用户设备选择缓存优先使用缓存的deviceId
let cacheVoiceDevice = voiceDevices.filter(
mic => mic.deviceId === localStorage.getItem('txy_webRTC_voiceId')
);
if (cacheVoiceDevice.length > 0) {
$('#voice-select').val(localStorage.getItem('txy_webRTC_voiceId'));
voiceTestingResult.device = cacheVoiceDevice[0];
} else {
$('#voice-select').val(voiceDevices[0].deviceId);
voiceTestingResult.device = voiceDevices[0];
}
}
/**
* 播放器设备测试
*/
async function startVoiceTesting() {
$('#voice-testing-body').show();
curTestingPageId = 'voice-testing-body';
$('#voice-testing')
.removeClass('icon-gray')
.addClass('icon-blue complete');
completedTestingPageIdList.push('voice-testing-body');
completedTestingPageIdList = [...new Set(completedTestingPageIdList)];
await updateVoiceDeviceList();
}
/**
* 更新/初始化麦克风设备
*/
async function updateMicDeviceList() {
// 展示麦克风设备选择
let micDevices = await TRTC.getMicrophones();
micDevices = micDevices.filter(mic => mic.deviceId !== 'default');
$('#mic-select').empty();
micDevices.forEach(mic => {
let option = $('<option></option>');
option.attr('value', mic.deviceId);
option.html(mic.label);
option.appendTo('#mic-select');
});
// 如果有用户设备选择缓存优先使用缓存的deviceId
let cacheMicDevice = micDevices.filter(
mic => mic.deviceId === localStorage.getItem('txy_webRTC_micId')
);
if (cacheMicDevice.length > 0) {
$('#mic-select').val(localStorage.getItem('txy_webRTC_micId'));
micTestingResult.device = cacheMicDevice[0];
} else {
$('#mic-select').val(micDevices[0].deviceId);
micTestingResult.device = micDevices[0];
}
}
/**
* 麦克风设备测试
*/
async function startMicTesting() {
$('#mic-testing-body').show();
curTestingPageId = 'mic-testing-body';
$('#mic-testing')
.removeClass('icon-gray')
.addClass('icon-blue complete');
completedTestingPageIdList.push('mic-testing-body');
completedTestingPageIdList = [...new Set(completedTestingPageIdList)];
await updateMicDeviceList();
// 展示麦克风的声音大小显示
if ($('#mic-bar-container').children().length === 0) {
for (let index = 0; index < 28; index++) {
$('<div></div>')
.addClass('mic-bar')
.appendTo('#mic-bar-container');
}
}
// 创建本地音频流
await createLocalStream(
{
audio: true,
microphoneId: micTestingResult.device.deviceId,
video: false
},
'audio-container'
);
// 监听音量,并量化显示出来
setInterval(() => {
let volume = localStream.getAudioLevel();
let num = Math.ceil(28 * volume);
$('#mic-bar-container')
.children('.active')
.removeClass('active');
for (let i = 0; i < num; i++) {
$('#mic-bar-container')
.children()
.slice(0, i)
.addClass('active');
}
}, 100);
}
/**
* 系统信息展示
*/
async function startNetworkTesting() {
$('#network-testing-body').show();
$('#testing-report-btn').hide();
curTestingPageId = 'network-testing-body';
$('#network-testing')
.removeClass('icon-gray')
.addClass('icon-blue complete');
completedTestingPageIdList.push('network-testing-body');
completedTestingPageIdList = [...new Set(completedTestingPageIdList)];
networkQualityNum = 0;
$('#uplink-network')
.addClass('network-loading')
.text('');
// 获取系统信息
$('#system').empty();
let OSInfo = getOS();
$('<div></div>')
.text(OSInfo.osName)
.appendTo('#system');
// 获取浏览器及版本信息
$('#browser').empty();
let browser = getBroswer();
$('<div></div>')
.text(`${browser.broswer} ${browser.version}`)
.appendTo('#browser');
// 获取ip地址信息
// $('#ip').empty();
// let IPAddress = await getIPAddress();
// $('<div></div>').text(IPAddress).appendTo('#ip');
// networkTestingResult.IPAddress = IPAddress;
// 是否支持屏幕分享能力
$('#screen-share').empty();
let isScreenShareSupported = TRTC.isScreenShareSupported();
$('<div></div>')
.text(isScreenShareSupported ? '支持' : '不支持')
.appendTo('#screen-share');
// 上下行网络质量
presetting.login(false, async options => {
client = TRTC.createClient({ mode: 'rtc', ...options });
client.on('network-quality', event => {
networkQualityNum++;
// 收到3次'network-quality'事件的时候认为拿到了网络实际质量
if (networkQualityNum === 3) {
networkTestingResult.upLinkNetwork = event.uplinkNetworkQuality;
networkTestingResult.downLinkNetwork = event.downlinkNetworkQuality;
$('#uplink-network')
.removeClass('network-loading')
.text(NETWORK_QUALITY[String(networkTestingResult.upLinkNetwork)]);
$('#testing-report-btn').show();
client && client.leave();
client && client.off('network-quality');
}
});
await client.join({
roomId: options.roomId
});
await createLocalStream(
{
audio: true,
video: false
},
'audio-container'
);
await client.publish(localStream);
// 音频轨道静音
localStream.muteAudio();
});
}
/**
* 展示检测报告
*/
function showTestingReport() {
$('#device-testing').hide();
$('#network-testing-body').hide();
$('#device-testing-report').show();
curTestingPageId = 'device-testing-report';
// 摄像头检测结果
$('#camera-name').text(cameraTestingResult.device.label);
if (cameraTestingResult.statusResult) {
$('#camera-testing-result')
.text('正常')
.css('color', 'green');
} else {
$('#camera-testing-result')
.text('异常')
.css('color', 'red');
}
// 扬声器检测结果(safari浏览器不显示扬声器检测结果)
if (!isSafari) {
$('#voice-name').text(voiceTestingResult.device.label);
if (voiceTestingResult.statusResult) {
$('#voice-testing-result')
.text('正常')
.css('color', 'green');
} else {
$('#voice-testing-result')
.text('异常')
.css('color', 'red');
}
}
// 麦克风检测结果
$('#mic-name').text(micTestingResult.device.label);
if (micTestingResult.statusResult) {
$('#mic-testing-result')
.text('正常')
.css('color', 'green');
} else {
$('#mic-testing-result')
.text('异常')
.css('color', 'red');
}
// 网络检测结果
// $('#network-name').text(networkTestingResult.IPAddress);
$('#network-name').text('网络质量');
$('#network-testing-result')
.html(`${NETWORK_QUALITY[String(networkTestingResult.upLinkNetwork)]}`)
.css('color', `${Number(networkTestingResult.upLinkNetwork) > 3 ? 'red' : 'green'}`);
}
/**
* 结束设备检测,隐藏设备检测弹窗
*/
function finishDeviceTesting() {
$('#device-testing-root').hide();
$('#device-testing').hide();
$(`#${curTestingPageId}`).hide();
curTestingPageId = '';
completedTestingPageIdList = [];
// 停止摄像头/麦克风的流采集并释放摄像头/麦克风设备
localStream && localStream.close();
client && client.leave();
client && client.off('network-quality');
// 停止播放器的音乐
let audioPlayer = document.querySelector('#audio-player');
if (!audioPlayer.paused) {
audioPlayer.pause();
}
audioPlayer.currentTime = 0;
}
/**
* 恢复检测页面头部图标的状态
*/
function initTestingTabTitle() {
['camera', 'voice', 'mic', 'network'].forEach(item => {
$(`#${item}-testing`)
.removeClass('icon-blue complete')
.addClass('icon-gray');
});
}
/**
* 监听设备变化
*/
navigator.mediaDevices.ondevicechange = async function(event) {
// 当前在摄像头检测页
if (curTestingPageId === 'camera-testing-body') {
await updateCameraDeviceList();
return;
}
// 当前在扬声器检测页
if (curTestingPageId === 'voice-testing-body') {
await updateVoiceDeviceList();
return;
}
// 当前在麦克风检测页
if (curTestingPageId === 'mic-testing-body') {
await updateMicDeviceList();
return;
}
};
/**
* 抽离createStream的公共处理函数
*/
async function createLocalStream(constraints, container) {
localStream = TRTC.createStream(constraints);
try {
await localStream.initialize();
} catch (error) {
switch (error.name) {
case 'NotReadableError':
// 当系统或浏览器异常的时候,可能会出现此错误,您可能需要引导用户重启电脑/浏览器来尝试恢复。
alert('暂时无法访问摄像头/麦克风,请确保当前没有其他应用请求访问摄像头/麦克风,并重试');
return;
case 'NotAllowedError':
// 用户拒绝授权访问摄像头或麦克风 | 屏幕分享,您需要引导客户来授权访问
alert('用户已拒绝授权访问摄像头或麦克风');
return;
case 'NotFoundError':
// 找不到摄像头或麦克风设备
alert('找不到摄像头或麦克风设备');
return;
case 'OverConstrainedError':
alert(
'采集属性设置错误,如果您指定了 cameraId/microphoneId请确保它们是一个有效的非空字符串'
);
return;
default:
alert('未知错误');
return;
}
}
container && localStream.play(container);
}

1
dist/js/iconfont.js vendored Normal file

File diff suppressed because one or more lines are too long

88
dist/js/iminit.js vendored Normal file
View File

@@ -0,0 +1,88 @@
let options = {
SDKAppID: 1400435767 // 接入时需要将0替换为您的即时通信 IM 应用的 SDKAppID
};
let tim = TIM.create(options);
tim.setLogLevel(0);
// 监听事件,例如:
tim.on(TIM.EVENT.SDK_READY, function(event) {
// 收到离线消息和会话列表同步完毕通知,接入侧可以调用 sendMessage 等需要鉴权的接口
// event.name - TIM.EVENT.SDK_READY
});
tim.on(TIM.EVENT.MESSAGE_RECEIVED, function(event) {
// 收到推送的单聊、群聊、群提示、群系统通知的新消息,可通过遍历 event.data 获取消息列表数据并渲染到页面
// event.name - TIM.EVENT.MESSAGE_RECEIVED
// event.data - 存储 Message 对象的数组 - [Message]
});
tim.on(TIM.EVENT.MESSAGE_REVOKED, function(event) {
// 收到消息被撤回的通知
// event.name - TIM.EVENT.MESSAGE_REVOKED
// event.data - 存储 Message 对象的数组 - [Message] - 每个 Message 对象的 isRevoked 属性值为 true
});
tim.on(TIM.EVENT.MESSAGE_READ_BY_PEER, function(event) {
// SDK 收到对端已读消息的通知,即已读回执。使用前需要将 SDK 版本升级至 v2.7.0 或以上。仅支持单聊会话。
// event.name - TIM.EVENT.MESSAGE_READ_BY_PEER
// event.data - event.data - 存储 Message 对象的数组 - [Message] - 每个 Message 对象的 isPeerRead 属性值为 true
});
tim.on(TIM.EVENT.CONVERSATION_LIST_UPDATED, function(event) {
// 收到会话列表更新通知,可通过遍历 event.data 获取会话列表数据并渲染到页面
// event.name - TIM.EVENT.CONVERSATION_LIST_UPDATED
// event.data - 存储 Conversation 对象的数组 - [Conversation]
});
tim.on(TIM.EVENT.GROUP_LIST_UPDATED, function(event) {
// 收到群组列表更新通知,可通过遍历 event.data 获取群组列表数据并渲染到页面
// event.name - TIM.EVENT.GROUP_LIST_UPDATED
// event.data - 存储 Group 对象的数组 - [Group]
});
tim.on(TIM.EVENT.PROFILE_UPDATED, function(event) {
// 收到自己或好友的资料变更通知
// event.name - TIM.EVENT.PROFILE_UPDATED
// event.data - 存储 Profile 对象的数组 - [Profile]
});
tim.on(TIM.EVENT.BLACKLIST_UPDATED, function(event) {
// 收到黑名单列表更新通知
// event.name - TIM.EVENT.BLACKLIST_UPDATED
// event.data - 存储 userID 的数组 - [userID]
});
tim.on(TIM.EVENT.ERROR, function(event) {
// 收到 SDK 发生错误通知,可以获取错误码和错误信息
// event.name - TIM.EVENT.ERROR
// event.data.code - 错误码
// event.data.message - 错误信息
});
tim.on(TIM.EVENT.SDK_NOT_READY, function(event) {
// 收到 SDK 进入 not ready 状态通知,此时 SDK 无法正常工作
// event.name - TIM.EVENT.SDK_NOT_READY
});
tim.on(TIM.EVENT.KICKED_OUT, function(event) {
// 收到被踢下线通知
// event.name - TIM.EVENT.KICKED_OUT
// event.data.type - 被踢下线的原因,例如:
// - TIM.TYPES.KICKED_OUT_MULT_ACCOUNT 多实例登录被踢
// - TIM.TYPES.KICKED_OUT_MULT_DEVICE 多终端登录被踢
// - TIM.TYPES.KICKED_OUT_USERSIG_EXPIRED 签名过期被踢 v2.4.0起支持)。
});
tim.on(TIM.EVENT.NET_STATE_CHANGE, function(event) {
// 网络状态发生改变v2.5.0 起支持)。
// event.name - TIM.EVENT.NET_STATE_CHANGE
// event.data.state 当前网络状态,枚举值及说明如下:
// \- TIM.TYPES.NET_STATE_CONNECTED - 已接入网络
// \- TIM.TYPES.NET_STATE_CONNECTING - 连接中。很可能遇到网络抖动SDK 在重试。接入侧可根据此状态提示“当前网络不稳定”或“连接中”
// \- TIM.TYPES.NET_STATE_DISCONNECTED - 未接入网络。接入侧可根据此状态提示“当前网络不可用”。SDK 仍会继续重试若用户网络恢复SDK 会自动同步消息
});
genTestUserSig(window.mid).then((res)=>{
tim.login({userID: window.mid, userSig: res.data});
})
// 开始登录

51
dist/js/index.js vendored Normal file
View File

@@ -0,0 +1,51 @@
/* eslint-disable no-global-assign */
/* global $ TRTC Presetting deviceTestingInit cameraId micId */
const presetting = new Presetting();
presetting.init();
deviceTestingInit();
// check if browser is compatible with TRTC
TRTC.checkSystemRequirements().then(result => {
if (!result) {
alert('您的浏览器不兼容此应用!\n建议下载最新版Chrome浏览器');
window.location.href = 'http://www.google.cn/chrome/';
}
});
// setup logging stuffs
TRTC.Logger.setLogLevel(TRTC.Logger.LogLevel.DEBUG);
TRTC.Logger.enableUploadLog();
TRTC.getDevices()
.then(devices => {
devices.forEach(item => {
console.log('device: ' + item.kind + ' ' + item.label + ' ' + item.deviceId);
});
})
.catch(error => console.error('getDevices error observed ' + error));
// populate camera options
TRTC.getCameras().then(devices => {
devices.forEach(device => {
if (!cameraId) {
cameraId = device.deviceId;
}
let div = $('<div></div>');
div.attr('id', device.deviceId);
div.html(device.label);
div.appendTo('#camera-option');
});
});
// populate microphone options
TRTC.getMicrophones().then(devices => {
devices.forEach(device => {
if (!micId) {
micId = device.deviceId;
}
let div = $('<div></div>');
div.attr('id', device.deviceId);
div.html(device.label);
div.appendTo('#mic-option');
});
});

4
dist/js/jquery-3.2.1.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2442
dist/js/popper.js vendored Normal file

File diff suppressed because it is too large Load Diff

51
dist/js/presetting.js vendored Normal file
View File

@@ -0,0 +1,51 @@
/* global $ setBtnClickFuc genTestUserSig */
// preset before starting RTC
class Presetting {
init() {
// populate userId/roomId
$('#userId').val('user_30400097');
$('#roomId').val(parseInt(Math.random() * 100000));
const roomId = this.query('roomId');
const userId = this.query('userId');
if (roomId) {
$('#roomId').val(roomId);
}
if (userId) {
$('#userId').val(userId);
}
$('#main-video-btns').hide();
$('.mask').hide();
setBtnClickFuc();
}
query(name) {
const match = window.location.search.match(new RegExp('(\\?|&)' + name + '=([^&]*)(&|$)'));
return !match ? '' : decodeURIComponent(match[2]);
}
login(share, callback) {
let userId = window.mid;
if (share) {
userId = 'share_' + userId;
}
console.log(userId)
let sdkAppId;
let userSig;
let roomId = window.roomid;
genTestUserSig(userId).then((res)=>{
sdkAppId = res.id;
userSig = res.data
callback({
sdkAppId,
userId,
userSig,
roomId
});
})
}
}

341
dist/js/rtc-client.js vendored Normal file
View File

@@ -0,0 +1,341 @@
/* global $ TRTC getCameraId getMicrophoneId resetView isHidden shareUserId addMemberView removeView addVideoView */
class RtcClient {
constructor(options) {
this.sdkAppId_ = options.sdkAppId;
this.userId_ = options.userId;
this.userSig_ = options.userSig;
this.roomId_ = options.roomId;
this.isJoined_ = false;
this.isPublished_ = false;
this.isAudioMuted = false;
this.isVideoMuted = false;
this.localStream_ = null;
this.remoteStreams_ = [];
this.members_ = new Map();
// create a client for RtcClient
this.client_ = TRTC.createClient({
mode: 'rtc',
sdkAppId: this.sdkAppId_,
userId: this.userId_,
userSig: this.userSig_
});
this.handleEvents();
}
async join() {
if (this.isJoined_) {
console.warn('duplicate RtcClient.join() observed');
return;
}
try {
// join the room
await this.client_.join({
roomId: this.roomId_
});
console.log('join room success');
this.isJoined_ = true;
// create a local stream with audio/video from microphone/camera
if (getCameraId() && getMicrophoneId()) {
this.localStream_ = TRTC.createStream({
audio: true,
video: true,
userId: this.userId_,
cameraId: getCameraId(),
microphoneId: getMicrophoneId(),
mirror: true
});
} else {
// not to specify cameraId/microphoneId to avoid OverConstrainedError
this.localStream_ = TRTC.createStream({
audio: true,
video: true,
userId: this.userId_,
mirror: true
});
}
try {
// initialize the local stream and the stream will be populated with audio/video
await this.localStream_.initialize();
console.log('initialize local stream success');
this.localStream_.on('player-state-changed', event => {
console.log(`local stream ${event.type} player is ${event.state}`);
});
// publish the local stream
await this.publish();
this.localStream_.play('main-video');
$('#main-video-btns').show();
$('#mask_main').appendTo($('#player_' + this.localStream_.getId()));
} catch (e) {
console.error('failed to initialize local stream - ' + e);
}
} catch (e) {
console.error('join room failed! ' + e);
}
//更新成员状态
let states = this.client_.getRemoteMutedState();
for (let state of states) {
if (state.audioMuted) {
$('#' + state.userId)
.find('.member-audio-btn')
.attr('src', './img/mic-off.png');
}
if (state.videoMuted) {
$('#' + state.userId)
.find('.member-video-btn')
.attr('src', './img/camera-off.png');
$('#mask_' + this.members_.get(state.userId).getId()).show();
}
}
}
async leave() {
if (!this.isJoined_) {
console.warn('leave() - please join() firstly');
return;
}
// ensure the local stream is unpublished before leaving.
await this.unpublish();
// leave the room
await this.client_.leave();
this.localStream_.stop();
this.localStream_.close();
this.localStream_ = null;
this.isJoined_ = false;
resetView();
}
async publish() {
if (!this.isJoined_) {
console.warn('publish() - please join() firstly');
return;
}
if (this.isPublished_) {
console.warn('duplicate RtcClient.publish() observed');
return;
}
try {
await this.client_.publish(this.localStream_);
} catch (e) {
console.error('failed to publish local stream ' + e);
this.isPublished_ = false;
}
this.isPublished_ = true;
}
async unpublish() {
if (!this.isJoined_) {
console.warn('unpublish() - please join() firstly');
return;
}
if (!this.isPublished_) {
console.warn('RtcClient.unpublish() called but not published yet');
return;
}
await this.client_.unpublish(this.localStream_);
this.isPublished_ = false;
}
muteLocalAudio() {
this.localStream_.muteAudio();
}
unmuteLocalAudio() {
this.localStream_.unmuteAudio();
}
muteLocalVideo() {
this.localStream_.muteVideo();
}
unmuteLocalVideo() {
this.localStream_.unmuteVideo();
}
resumeStreams() {
this.localStream_.resume();
for (let stream of this.remoteStreams_) {
stream.resume();
}
}
handleEvents() {
this.client_.on('error', err => {
console.error(err);
alert(err);
location.reload();
});
this.client_.on('client-banned', err => {
console.error('client has been banned for ' + err);
if (!isHidden()) {
alert('您已被踢出房间');
location.reload();
} else {
document.addEventListener(
'visibilitychange',
() => {
if (!isHidden()) {
alert('您已被踢出房间');
location.reload();
}
},
false
);
}
});
// fired when a remote peer is joining the room
this.client_.on('peer-join', evt => {
const userId = evt.userId;
console.log('peer-join ' + userId);
if (userId !== shareUserId) {
addMemberView(userId);
}
});
// fired when a remote peer is leaving the room
this.client_.on('peer-leave', evt => {
const userId = evt.userId;
removeView(userId);
console.log('peer-leave ' + userId);
});
// fired when a remote stream is added
this.client_.on('stream-added', evt => {
const remoteStream = evt.stream;
const id = remoteStream.getId();
const userId = remoteStream.getUserId();
this.members_.set(userId, remoteStream);
console.log(`remote stream added: [${userId}] ID: ${id} type: ${remoteStream.getType()}`);
if (remoteStream.getUserId() === shareUserId) {
// don't need screen shared by us
this.client_.unsubscribe(remoteStream);
} else {
console.log('subscribe to this remote stream');
this.client_.subscribe(remoteStream);
}
});
// fired when a remote stream has been subscribed
this.client_.on('stream-subscribed', evt => {
const uid = evt.userId;
const remoteStream = evt.stream;
const id = remoteStream.getId();
this.remoteStreams_.push(remoteStream);
remoteStream.on('player-state-changed', event => {
console.log(`${event.type} player is ${event.state}`);
if (event.type == 'video' && event.state == 'STOPPED') {
$('#mask_' + remoteStream.getId()).show();
$('#' + remoteStream.getUserId())
.find('.member-video-btn')
.attr('src', 'img/camera-off.png');
}
if (event.type == 'video' && event.state == 'PLAYING') {
$('#mask_' + remoteStream.getId()).hide();
$('#' + remoteStream.getUserId())
.find('.member-video-btn')
.attr('src', 'img/camera-on.png');
}
});
addVideoView(id);
// objectFit 为播放的填充模式详细参考https://trtc-1252463788.file.myqcloud.com/web/docs/Stream.html#play
remoteStream.play(id, { objectFit: 'contain' });
//添加“摄像头未打开”遮罩
let mask = $('#mask_main').clone();
mask.attr('id', 'mask_' + id);
mask.appendTo($('#player_' + id));
mask.hide();
if (!remoteStream.hasVideo()) {
mask.show();
$('#' + remoteStream.getUserId())
.find('.member-video-btn')
.attr('src', 'img/camera-off.png');
}
console.log('stream-subscribed ID: ', id);
});
// fired when the remote stream is removed, e.g. the remote user called Client.unpublish()
this.client_.on('stream-removed', evt => {
const remoteStream = evt.stream;
const id = remoteStream.getId();
remoteStream.stop();
this.remoteStreams_ = this.remoteStreams_.filter(stream => {
return stream.getId() !== id;
});
removeView(id);
console.log(`stream-removed ID: ${id} type: ${remoteStream.getType()}`);
});
this.client_.on('stream-updated', evt => {
const remoteStream = evt.stream;
let uid = this.getUidByStreamId(remoteStream.getId());
if (!remoteStream.hasVideo()) {
$('#' + uid)
.find('.member-video-btn')
.attr('src', 'img/camera-off.png');
}
console.log(
'type: ' +
remoteStream.getType() +
' stream-updated hasAudio: ' +
remoteStream.hasAudio() +
' hasVideo: ' +
remoteStream.hasVideo() +
' uid: ' +
uid
);
});
this.client_.on('mute-audio', evt => {
console.log(evt.userId + ' mute audio');
$('#' + evt.userId)
.find('.member-audio-btn')
.attr('src', 'img/mic-off.png');
});
this.client_.on('unmute-audio', evt => {
console.log(evt.userId + ' unmute audio');
$('#' + evt.userId)
.find('.member-audio-btn')
.attr('src', 'img/mic-on.png');
});
this.client_.on('mute-video', evt => {
console.log(evt.userId + ' mute video');
$('#' + evt.userId)
.find('.member-video-btn')
.attr('src', 'img/camera-off.png');
let streamId = this.members_.get(evt.userId).getId();
if (streamId) {
$('#mask_' + streamId).show();
}
});
this.client_.on('unmute-video', evt => {
console.log(evt.userId + ' unmute video');
$('#' + evt.userId)
.find('.member-video-btn')
.attr('src', 'img/camera-on.png');
const stream = this.members_.get(evt.userId);
if (stream) {
let streamId = stream.getId();
if (streamId) {
$('#mask_' + streamId).hide();
}
}
});
}
showStreamState(stream) {
console.log('has audio: ' + stream.hasAudio() + ' has video: ' + stream.hasVideo());
}
getUidByStreamId(streamId) {
for (let [uid, stream] of this.members_) {
if (stream.getId() == streamId) {
return uid;
}
}
}
}

163
dist/js/share-client.js vendored Normal file
View File

@@ -0,0 +1,163 @@
/* global $ TRTC */
class ShareClient {
constructor(options) {
this.sdkAppId_ = options.sdkAppId;
this.userId_ = options.userId;
this.userSig_ = options.userSig;
this.roomId_ = options.roomId;
this.isJoined_ = false;
this.isPublished_ = false;
this.localStream_ = null;
this.client_ = TRTC.createClient({
mode: 'rtc',
sdkAppId: this.sdkAppId_,
userId: this.userId_,
userSig: this.userSig_,
/**
* disable receivers to avoid receiving remote streams as we only want to
* publish the screen stream
*/
disableReceiver: true
});
this.client_.setDefaultMuteRemoteStreams(true);
this.handleEvents();
}
async join() {
if (this.isJoined_) {
console.warn('duplicate RtcClient.join() observed');
return;
}
try {
await this.client_.join({
roomId: this.roomId_
});
console.log('ShareClient join room success');
this.isJoined_ = true;
// create a local stream for screen share
this.localStream_ = TRTC.createStream({
// disable audio as RtcClient already enable audio
audio: false,
// enable screen share
screen: true,
userId: this.userId_
});
try {
// initialize the local stream to populate the screen stream
await this.localStream_.initialize();
console.log('ShareClient initialize local stream for screen share success');
this.localStream_.on('player-state-changed', event => {
console.log(`local stream ${event.type} player is ${event.state}`);
});
this.localStream_.on('screen-sharing-stopped', event => {
console.log('share stream video track enned');
this.leave();
$('#screen-btn').attr('src', './img/screen-off.png');
});
// publish the screen share stream
await this.client_.publish(this.localStream_);
} catch (e) {
console.error('ShareClient failed to initialize local stream - ' + e);
//用户取消分享屏幕导致推流失败
await this.client_.leave();
this.isJoined_ = false;
$('#screen-btn').attr('src', 'img/screen-off.png');
}
} catch (e) {
console.error('ShareClient join room failed! ' + e);
}
}
async leave() {
if (!this.isJoined_) {
console.warn('leave() - please join() firstly');
return;
}
if (this.isPublished_) {
await this.client_.unpublish(this.localStream_);
this.isPublished_ = false;
}
await this.client_.leave();
if (this.localStream_) {
this.localStream_.close();
this.localStream_ = null;
}
this.isJoined_ = false;
}
handleEvents() {
this.client_.on('error', err => {
console.error(err);
alert(err);
});
this.client_.on('client-banned', err => {
console.error('client has been banned for ' + err);
});
// fired when a remote peer is joining the room
this.client_.on('peer-join', evt => {
const userId = evt.userId;
console.log('peer-join ' + userId);
});
// fired when a remote peer is leaving the room
this.client_.on('peer-leave', evt => {
const userId = evt.userId;
console.log('peer-leave ' + userId);
});
// fired when a remote stream is added
this.client_.on('stream-added', evt => {
const remoteStream = evt.stream;
const id = remoteStream.getId();
const userId = remoteStream.getUserId();
console.log(`remote stream added: [${userId}] ID: ${id} type: ${remoteStream.getType()}`);
console.log('subscribe to this remote stream');
});
// fired when a remote stream has been subscribed
this.client_.on('stream-subscribed', evt => {
const remoteStream = evt.stream;
const id = remoteStream.getId();
remoteStream.on('player-state-changed', event => {
console.log(`${event.type} player is ${event.state}`);
});
console.log('stream-subscribed ID: ', id);
});
// fired when the remote stream is removed, e.g. the remote user called Client.unpublish()
this.client_.on('stream-removed', evt => {
const remoteStream = evt.stream;
const id = remoteStream.getId();
console.log(`stream-removed ID: ${id} type: ${remoteStream.getType()}`);
});
this.client_.on('stream-updated', evt => {
const remoteStream = evt.stream;
console.log(
'type: ' +
remoteStream.getType() +
' stream-updated hasAudio: ' +
remoteStream.hasAudio() +
' hasVideo: ' +
remoteStream.hasVideo() +
' uid: ' +
remoteStream.getUserId()
);
});
this.client_.on('mute-audio', evt => {
console.log(evt.userId + ' mute audio');
});
this.client_.on('unmute-audio', evt => {
console.log(evt.userId + ' unmute audio');
});
this.client_.on('mute-video', evt => {
console.log(evt.userId + ' mute video');
});
this.client_.on('unmute-video', evt => {
console.log(evt.userId + ' unmute video');
});
}
}

1
dist/js/tim-js.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/js/trtc.js vendored Normal file

File diff suppressed because one or more lines are too long