mirror of
https://github.com/tl-open-source/tl-rtc-file.git
synced 2025-09-27 03:46:11 +08:00
feat: 目录结构优化重整
feat: 支持单独发送文件 feat: 支持文本私聊 feat: 支持seafile网盘暂存文件 feat: 支持直播房间 feat: 支持取件码下载文件 feat: 支持预览视频文件 feat: 支持报错告警 feat: 调整补充启动logo feat: 调整补充免责协议 feat: 调整补充配置中的版本号 feat: 调整优化开源协议 feat: 调整补充定制收费服务 feat: 调整优化服务端代码 feat: 调整优化批量发送逻辑 feat: 调整优化样式体验 feat: 调整优化conf中ws, manage相关配置 feat: 调整优化文件发送时间间隔为1秒钟 feat: 调整优化文件发送体验 feat: 调整优化选择文件逻辑 feat: 调整优化启动文件/命令 feat: 调整优化socket配置区分 feat: 调整优化分享进入房间 feat: 调整优化右上角消息提示 feat: 调整删除npm依赖 feat: 调整删除首次弹窗 feat: 即将支持远程cavas画笔 feat: 即将支持远程控制
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -42,5 +42,7 @@ node_modules
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
res/js/*.min.*
|
||||
res/css/*.min.*
|
||||
svr/res/js/*.min.*
|
||||
svr/res/css/*.min.*
|
||||
|
||||
svr/test/*
|
||||
|
27
DISCLAIMER.md
Normal file
27
DISCLAIMER.md
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
# 免责声明
|
||||
1.1 如使用本演示网站/开源项目,即表示您已同意本条款。我们 (开源项目维护团队) 始终在不断更改和改进我们的服务。我们可能会增加或删除功能,也可能暂停或彻底停止某项服务。您可以随时停止使用我们的服务,我们也可以随时对我们的服务增加新的限制。
|
||||
|
||||
1.2 该网站/开源项目的使用者在使用本演示网站/开源项目前,应仔细阅读以下条款并同意遵守。使用本演示网站/开源项目将被视为对本免责协议的接受和遵守。
|
||||
|
||||
## 演示网站/开源项目的性质
|
||||
2.1 本演示网站/开源项目旨在帮助大家学习webrtc,提供一个学习/演示demo环境,和基础功能代码入门教学
|
||||
|
||||
2.2 本演示网站/开源项目提供的服务旨在为用户提供数据传输功能演示,包括但不限于文件传输、直播、音视频通话、远程屏幕共享、聊天等功能的演示。
|
||||
|
||||
2.3 使用者应理解,本演示网站/开源项目仅提供技术支持演示,不对数据传输的准确性、及时性、完整性、安全性或合法性负责。使用者应自行承担使用本演示网站/开源项目的风险。
|
||||
|
||||
## 使用者责任
|
||||
3.1 使用者应承担使用本演示网站/开源项目的全部责任和风险。对于使用者通过本演示网站/开源项目进行的任何操作、行为或后果,本演示网站/开源项目不承担任何责任。
|
||||
|
||||
3.2 使用者不得利用本演示网站/开源项目进行任何违法、侵权、威胁、诽谤、骚扰、破坏性或其他不当行为。若使用者违反上述规定,本演示网站/开源项目有权立即终止或限制使用者的访问权限。
|
||||
|
||||
3.3 本演示网站使用者严禁上传违法违规内容,包括但不限于:色情低俗、政治敏感、、暴力、恶意软件、诈骗、贩卖公民隐私,上传上述内容将永久封禁账号或 IP 地址,并可能承担承担刑事责任
|
||||
|
||||
## 免责条款
|
||||
4.1 本演示网站/开源项目不对任何由于使用本演示网站/开源项目而引起的任何直接、间接、附带、特殊、惩罚性或后续的损害承担责任,包括但不限于利润损失、商业中断、计算机系统故障、数据丢失或其他经济损失。
|
||||
|
||||
4.2 本演示网站/开源项目不对任何第三方通过本演示网站/开源项目发布、提供或传输的任何内容的准确性、合法性、安全性或可靠性负责。
|
||||
|
||||
## 免责声明的范围
|
||||
本免责协议适用于使用本演示网站/开源项目的所有用户,无论其身份或目的。该免责协议的内容适用于因使用本演示网站/开源项目而产生的一切事项,包括但不限于使用本演示网站/开源项目的内容、服务或信息所引起的任何纠纷、损失或损害。
|
10
Dockerfile
10
Dockerfile
@@ -1,10 +1,14 @@
|
||||
FROM node:14-alpine
|
||||
|
||||
ADD . /home/tlrtcfile
|
||||
|
||||
WORKDIR /home/tlrtcfile
|
||||
|
||||
RUN npm install
|
||||
ADD . .
|
||||
|
||||
RUN npm conf set registry https://registry.npm.taobao.org; \
|
||||
npm install; \
|
||||
npm install -g pm2; \
|
||||
cd /home/tlrtcfile/svr/build/webpack/ \
|
||||
npm install;
|
||||
|
||||
EXPOSE 9092 8444
|
||||
|
||||
|
85
LICENSE
85
LICENSE
@@ -1,72 +1,21 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
MIT License
|
||||
|
||||
1. Definitions.
|
||||
Copyright (c) 2022 iamtsm
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
31
PAY.md
Normal file
31
PAY.md
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
# 开源项目定制服务收费标准 (v1.0.3.2023)
|
||||
|
||||
- **联系方式:** 1905333456 (qq)
|
||||
- **GitHub:** https://github.com/iamtsm
|
||||
|
||||
|
||||
## 项目定制服务
|
||||
|
||||
### 1. 项目功能定制
|
||||
- **服务内容:** 对项目进行功能定制或扩展
|
||||
- **价格:** 按功能大小,紧急程度,耗时,定制内容是否允许开源,等情况收费
|
||||
|
||||
### 2. 定制开发支持
|
||||
- **服务内容:** 提供定制开发技术支持,可协助部署安装相关事项,或协助自行开发,细节问题答疑
|
||||
- **价格:** 一杯咖啡
|
||||
|
||||
## 收费模式
|
||||
- **按小时计费:** 根据实际工作时间计算费用,目前个人定制功能2小时起,每小时200~300,企业定制另谈
|
||||
- **阶段性付费:** 确认开发前,预付1/3,开发完成付1/3,交付上线1/3
|
||||
|
||||
## 付款方式
|
||||
- 微信支付
|
||||
- 赞赏码支付
|
||||
- 支付宝支付
|
||||
|
||||
## 交付时间
|
||||
根据项目的复杂性和工作量,具体的交付时间将在项目定制阶段与客户协商确定,一般会在预估的时间内,如有延期会提前告知。
|
||||
|
||||
## 其他备注
|
||||
此收费标准仅限开发功能,以及交付上线收取的费用,不包括后期维护以及后续功能迭代。
|
100
README.md
100
README.md
@@ -13,61 +13,59 @@
|
||||
|
||||
#### 优点 : 分片传输,跨终端,不限平台,方便使用,内网不限速,支持私有部署,支持多文件拖拽发送
|
||||
|
||||
#### 扩展 : 扩展了许多丰富的小功能,如本地屏幕录制,远程屏幕共享,远程音视频通话,密码房间,中继服务设置,webrtc检测,文字传输,公共聊天,丰富的后台管理,集成了企微机器人告警通知,实时执行日志展示... 等等
|
||||
#### 扩展 : 扩展了许多丰富的小功能,如本地屏幕录制,远程屏幕共享,远程音视频通话,直播,取件码,密码房间,中继服务设置,webrtc检测,文字传输,公共聊天,丰富的后台管理,集成了企微机器人告警通知,实时执行日志展示... 等等
|
||||
|
||||
#### 说明 : 示例网站是在公网环境中,为了更好的展示传输功能,所以默认开启了中继服务,如果各位是验证能否走p2p传输,只需关闭中继服务,且p2p检测后,如果能看到内网环境ip,webrtc连接大概率可以走p2p,跑到10M/s轻轻松松,公网环境下的内网用户一般情况下来说也会自动识别到的,如果内网速度慢,可以反馈留言,会尽快优化处理
|
||||
#### 说明 : 示例网站是在公网环境中,为了更好的展示传输功能,所以默认开启了中继服务,如果各位是验证能否走p2p传输,只需关闭中继服务,且p2p检测后,如果能看到内网环境ip,webrtc连接大概率可以走p2p,公网环境下的内网用户一般情况下来说也会自动识别到的,如果内网速度慢,可以反馈留言,会尽快优化处理
|
||||
|
||||
#### 体验 : https://im.iamtsm.cn/file
|
||||
|
||||
**qq交流群 : 624214498**
|
||||
|
||||
[EN-DOC](doc/README_EN.md)
|
||||
|
||||
## 准备
|
||||
|
||||
安装node,npm后进入项目目录
|
||||
安装node-14.x,npm后进入项目目录运行下面命令
|
||||
|
||||
npm install
|
||||
`cd svr/`
|
||||
|
||||
进入build目录 : cd build/webpack/
|
||||
`npm install`
|
||||
|
||||
安装一些依赖 : npm install
|
||||
`cd build/webpack/`
|
||||
|
||||
`npm install`
|
||||
|
||||
首次运行/自行开发页面,需要启动下面两个命令
|
||||
|
||||
`cd build/webpack/`
|
||||
|
||||
`npm run dev` (打包开发环境min) 或者 `npm run pro` 打包生产环境min
|
||||
|
||||
|
||||
如果需要自行开发修改res目录文件, 保持下面两个后台命令开启一个即可
|
||||
## 启动
|
||||
|
||||
npm run dev 打包开发环境min
|
||||
http形式启动以下两个服务
|
||||
|
||||
npm run pro 打包生产环境min
|
||||
api服务: `npm run lapi`
|
||||
|
||||
## 测试环境
|
||||
socket服务 : `npm run lsocket`
|
||||
|
||||
启动以下两个服务
|
||||
或者https形式启动一下两个服务
|
||||
|
||||
本地启动file-res : npm run dev
|
||||
api服务: `npm run sapi`
|
||||
|
||||
本地启动file-socket : npm run devsocket
|
||||
socket服务 : `npm run ssocket`
|
||||
|
||||
## 线上环境 (需要配置wss)
|
||||
选一种模式启动即可
|
||||
|
||||
启动以下两个服务
|
||||
## 配置数据库 (默认关闭)
|
||||
|
||||
公网环境启动file-res : npm run svr
|
||||
|
||||
公网环境启动file-socket : npm run svrsocket
|
||||
修改conf/cfg.json中相应数据库配置即可, 如open, dbName, host, port, user, pwd 等
|
||||
|
||||
|
||||
## 配置db
|
||||
## 配置websocket (ws/wss)
|
||||
|
||||
修改conf/cfg.json中相应db配置即可, 如open, dbName, host, port, user, pwd 等
|
||||
修改conf/cfg.json中相应ws配置,或者wss配置
|
||||
|
||||
|
||||
## 配置wss
|
||||
|
||||
修改conf/cfg.json中相应ws配置即可,如port, ws_online等
|
||||
|
||||
|
||||
## 配置turnserver (私有部署)
|
||||
## 配置turnserver (中继服务)
|
||||
|
||||
ubuntu:
|
||||
|
||||
@@ -81,7 +79,7 @@
|
||||
|
||||
## Docker
|
||||
|
||||
修改conf/cfg.json中的ws_online的ip地址(有更好的办法可以反馈下)
|
||||
修改conf/cfg.json中的ws/wss的ip地址(有更好的办法可以反馈下)
|
||||
|
||||
docker build -t iamtsm/tl-rtc-file .
|
||||
|
||||
@@ -91,9 +89,9 @@
|
||||
|
||||
## 管理后台
|
||||
|
||||
前提 : 需要开启db配置
|
||||
前提 : 需要开启数据库配置
|
||||
|
||||
修改conf/cfg.json中的router.manage的room和password,默认房间号和密码都是tlrtcfile
|
||||
修改conf/cfg.json中的manage的room和password,默认房间号和密码都是tlrtcfile
|
||||
|
||||
访问 : http://localhost:9092 或者 http://本机ip:9092
|
||||
|
||||
@@ -109,17 +107,31 @@
|
||||
|
||||

|
||||
|
||||
|
||||
## 引用致谢
|
||||
|
||||
### [scroxt](https://github.com/chenjianfang/scroxt)
|
||||
|
||||
### [layui](https://github.com/layui/layui)
|
||||
|
||||
### [webpack](https://github.com/webpack/webpack)
|
||||
|
||||
### [swiper](https://github.com/nolimits4web/swiper)
|
||||
|
||||
## License
|
||||
|
||||
### Apache License 2.0
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 iamtsm
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
## 免责声明
|
||||
|
||||
[免责声明](DISCLAIMER.md)
|
11024
build/webpack/package-lock.json
generated
11024
build/webpack/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,75 +0,0 @@
|
||||
{
|
||||
"name": "webpack",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "webpack.config.js",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.6.0",
|
||||
"@babel/plugin-proposal-class-properties": "^7.5.5",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.10.4",
|
||||
"@babel/plugin-transform-runtime": "^7.6.0",
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@babel/preset-env": "^7.12.7",
|
||||
"@vue/babel-plugin-transform-vue-jsx": "^1.2.1",
|
||||
"ansi-colors": "^4.1.1",
|
||||
"autoprefixer": "^9.6.1",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"babel-loader": "^8.0.6",
|
||||
"cache-loader": "^2.0.1",
|
||||
"chalk": "^2.4.2",
|
||||
"chokidar": "^2.1.8",
|
||||
"commander": "^6.2.0",
|
||||
"concat-with-sourcemaps": "^1.1.0",
|
||||
"cross-env": "^5.2.1",
|
||||
"css-loader": "^2.1.0",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-config-airbnb-base": "^13.2.0",
|
||||
"eslint-formatter-friendly": "^6.0.0",
|
||||
"eslint-loader": "^2.2.1",
|
||||
"eslint-plugin-babel": "^5.3.0",
|
||||
"eslint-plugin-import": "^2.18.2",
|
||||
"eslint-plugin-vue": "^5.2.3",
|
||||
"fancy-log": "^1.3.3",
|
||||
"file-loader": "^3.0.1",
|
||||
"glob": "^7.1.4",
|
||||
"glob-base": "^0.3.0",
|
||||
"happypack": "^5.0.1",
|
||||
"hard-source-webpack-plugin": "^0.13.1",
|
||||
"mini-css-extract-plugin": "^0.5.0",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.4",
|
||||
"parallel-webpack": "^2.6.0",
|
||||
"postcss": "^7.0.18",
|
||||
"postcss-flexbugs-fixes": "^4.2.1",
|
||||
"postcss-loader": "^4.1.0",
|
||||
"postcss-preset-env": "^6.7.0",
|
||||
"sass": "^1.26.10",
|
||||
"sass-loader": "^9.0.3",
|
||||
"sass-resources-loader": "^2.0.3",
|
||||
"style-loader": "^2.0.0",
|
||||
"svg-sprite-loader": "^4.2.5-drop-webpack-version-detector.0",
|
||||
"svgo": "^1.3.0",
|
||||
"svgo-loader": "^2.2.1",
|
||||
"terser-webpack-plugin": "^5.0.3",
|
||||
"thread-loader": "^2.1.3",
|
||||
"ts-loader": "^5.4.5",
|
||||
"uglifyjs-webpack-plugin": "^2.2.0",
|
||||
"url-loader": "^4.1.1",
|
||||
"vue-eslint-parser": "^6.0.4",
|
||||
"vue-loader": "^15.9.5",
|
||||
"vue-template-compiler": "^2.6.6",
|
||||
"webpack": "^4.44.2",
|
||||
"webpack-cli": "^4.2.0",
|
||||
"webpack-merge": "^4.2.2",
|
||||
"webpack-watched-glob-entries-plugin": "^2.1.6",
|
||||
"yargs": "^16.1.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"dev": "node buildDev.js",
|
||||
"pro": "node buildPro.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
1
client/README.md
Normal file
1
client/README.md
Normal file
@@ -0,0 +1 @@
|
||||
# tl-rtc-file-tool-client
|
101
conf/cfg.json
101
conf/cfg.json
@@ -1,101 +0,0 @@
|
||||
{
|
||||
"ws": {
|
||||
"port": 8444,
|
||||
"ssl_port": 8444,
|
||||
"ws_online": ""
|
||||
},
|
||||
"node": {
|
||||
"port": 9092
|
||||
},
|
||||
"webrtc": {
|
||||
"iceServers": [{
|
||||
"urls": "stun:stun.xten.com"
|
||||
}],
|
||||
"iceTransportPolicy": "all",
|
||||
"options": {
|
||||
"offerToReceiveAudio": 1,
|
||||
"offerToReceiveVideo": 1
|
||||
}
|
||||
},
|
||||
"openai" : {
|
||||
"apiKeys" :[]
|
||||
},
|
||||
"oss" : {
|
||||
"seafile" : {
|
||||
"repoid" : "",
|
||||
"host" : "",
|
||||
"username" : "",
|
||||
"password" : ""
|
||||
},
|
||||
"alyun" : {
|
||||
|
||||
},
|
||||
"qiniuyun" : {
|
||||
|
||||
}
|
||||
},
|
||||
"router": {
|
||||
"filter": {
|
||||
"whiteDir": [
|
||||
|
||||
],
|
||||
"whiteFile": [
|
||||
"router.js"
|
||||
]
|
||||
},
|
||||
"res": {
|
||||
"/": "res/",
|
||||
"/static": "static/"
|
||||
},
|
||||
"manage": {
|
||||
"room": "tlrtcfile",
|
||||
"password": "tlrtcfile"
|
||||
}
|
||||
},
|
||||
"notify": {
|
||||
"open": false,
|
||||
"qiwei": [
|
||||
|
||||
]
|
||||
},
|
||||
"db" : {
|
||||
"open" : false,
|
||||
"mysql" : {
|
||||
"host" : "your db host",
|
||||
"port" : 3306,
|
||||
"dbName" : "your dbName",
|
||||
"user" : "your name",
|
||||
"password" : "your pwd",
|
||||
"other" : {
|
||||
"sequelize" : {
|
||||
"dialect": "mysql",
|
||||
"host": "your ip",
|
||||
"port": 3306,
|
||||
"logging": false,
|
||||
"pool": {
|
||||
"max": 5,
|
||||
"min": 0,
|
||||
"acquire": 30000,
|
||||
"idle": 10000
|
||||
},
|
||||
"timezone": "+08:00",
|
||||
"define": {
|
||||
"freezeTableName": true,
|
||||
"underscored": true,
|
||||
"charset": "utf8",
|
||||
"collate": "utf8_general_ci",
|
||||
"timestamps": false,
|
||||
"paranoid": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"oracle": {
|
||||
"host": "localhost",
|
||||
"port": 3306,
|
||||
"user": "root",
|
||||
"password": "xxxx",
|
||||
"other": {}
|
||||
}
|
||||
}
|
||||
}
|
134
doc/README_EN.md
134
doc/README_EN.md
@@ -1,4 +1,4 @@
|
||||
# tl-rtc-file-tool
|
||||
# tl-rtc-file-tool [More than just file transfer, starting from file transfer]
|
||||
|
||||
[](https://webrtc.org.cn/)
|
||||
[](https://github.com/iamtsm/tl-rtc-file/)
|
||||
@@ -6,106 +6,132 @@
|
||||
[](https://github.com/iamtsm/tl-rtc-file/)
|
||||
[](https://github.com/iamtsm/tl-rtc-file/)
|
||||
|
||||
#### demo : https://im.iamtsm.cn/file
|
||||
|
||||
## Table of Contents
|
||||
#### Background: Consolidated from the topic of the 20-year graduation project
|
||||
|
||||
- [Prepare](#Prepare)
|
||||
#### Introduction: (tl webrtc datachannel filetools) Transfer files on the web using WebRTC, supporting the transfer of large files.
|
||||
|
||||
- [Debug](#Debug)
|
||||
#### Advantages: Fragmented transmission, cross-platform, platform-independent, easy to use, unlimited speed in the intranet, support for private deployment, support for multiple file drag and drop sending.
|
||||
|
||||
- [Production](#Production)
|
||||
#### Extensions: Extended with many rich features such as local screen recording, remote screen sharing, remote audio and video calls, live streaming, pickup codes, password-protected rooms, relay service settings, WebRTC detection, text transmission, public chat, rich backend management, integration of Enterprise WeChat robot alert notification, real-time execution log display, and more.
|
||||
|
||||
- [Database-Configuration](#Database-Configuration)
|
||||
#### Instructions: The example website is in a public network environment. In order to better demonstrate the transmission function, the relay service is enabled by default. If you want to verify whether P2P transmission is possible, simply disable the relay service. After the P2P detection, if you can see the internal network IP, the WebRTC connection can most likely go through P2P. In general, users in the internal network environment in the public network environment will also be automatically recognized. If the internal network speed is slow, you can leave feedback and it will be optimized and processed as soon as possible.
|
||||
|
||||
- [Wss-Configuration](#Wss-Configuration)
|
||||
#### Experience: https://im.iamtsm.cn/file
|
||||
|
||||
- [TurnServer-Configuration](#TurnServer-Configuration)
|
||||
**QQ Communication Group: 624214498**
|
||||
|
||||
- [Overview](#Overview)
|
||||
## Preparation
|
||||
|
||||
- [中文说明](#Chinese)
|
||||
Install node-14.x and npm, then enter the project directory and run the following commands:
|
||||
|
||||
### Prepare
|
||||
`cd svr/`
|
||||
|
||||
Before this you need to install `node` and `npm`。
|
||||
`npm install`
|
||||
|
||||
If already installed `node` and `npm`, enter the project directory and execute `npm install`, enter the build directory to install node dependencies `npm install`。
|
||||
`cd build/webpack/`
|
||||
|
||||
If you want to modify the web resource code, keep webpack running in the background。
|
||||
`npm install`
|
||||
|
||||
debug environment uses `npm run dev`
|
||||
For the first run or self-developed pages, you need to start the following two commands:
|
||||
|
||||
production environment uses `npm run pro`
|
||||
`cd build/webpack/`
|
||||
|
||||
### Debug
|
||||
`npm run dev` (package for development environment min) or `npm run pro` (package for production environment min)
|
||||
|
||||
debugging environment starts the web `npm run dev`
|
||||
## Start
|
||||
|
||||
debugging environment starts the file socket `npm run devsocket`
|
||||
Start the following two services in HTTP format:
|
||||
|
||||
### Production
|
||||
API service: `npm run lapi`
|
||||
|
||||
##### If you want to deploy in a public network environment, you need to configure wss
|
||||
Socket service: `npm run lsocket`
|
||||
|
||||
Production environment starts the web `npm run svr`
|
||||
Or start the following two services in HTTPS format:
|
||||
|
||||
Production environment starts the file socket `npm run svrsocket`
|
||||
API service: `npm run sapi`
|
||||
|
||||
Socket service: `npm run ssocket`
|
||||
|
||||
### Database-Configuration
|
||||
Choose one mode to start.
|
||||
|
||||
If you want to configure open database related, you can modify the configuration in conf/cfg.json。`open, dbName, host, port, user, pwd ...`
|
||||
## Configure Database (Default: Disabled)
|
||||
|
||||
Modify the corresponding database configuration in conf/cfg.json, such as open, dbName, host, port, user, pwd, etc.
|
||||
|
||||
### Wss-Configuration
|
||||
## Configure WebSocket (WS/WSS)
|
||||
|
||||
If you want to configure open database related, you can modify the configuration ws in conf/cfg.json。`port, ws_online ...`
|
||||
Modify the corresponding WS configuration or WSS configuration in conf/cfg.json.
|
||||
|
||||
## Configure TURN Server (Relay Service)
|
||||
|
||||
### TurnServer-Configuration
|
||||
Ubuntu:
|
||||
|
||||
1. install coturn ( ubuntu )
|
||||
1. sudo apt-get install coturn # Install coturn.
|
||||
|
||||
sudo apt-get install coturn
|
||||
2. cp conf/turn/turnserver.conf /etc/turnserver.conf # Modify the configuration file, modify the file content as needed.
|
||||
|
||||
2. modify conf/turn/turnserver.conf and execute
|
||||
3. chmod +x bin/genTurnUser.sh && ./
|
||||
|
||||
cp conf/turn/turnserver.conf /etc/turnserver.conf
|
||||
genTurnUser.sh # Modify the file content as needed.
|
||||
|
||||
3. modify bin/genTurnUser.sh and execute
|
||||
4. chmod +x bin/startTurnServer.sh && ./startTurnServer.sh # Start turnserver, modify the file content as needed.
|
||||
|
||||
chomd +x bin/genTurnUser.sh && ./genTurnUser.sh
|
||||
## Docker
|
||||
|
||||
4. modify bin/startTurnServer.sh and execute
|
||||
Modify the IP address of ws/wss in conf/cfg.json (feedback is welcome if there is a better way).
|
||||
|
||||
chomd +x bin/startTurnServer.sh
|
||||
docker build -t iamtsm/tl-rtc-file .
|
||||
|
||||
5. start turn server
|
||||
docker run -p 9092:9092 -p 8444:8444 --name local -d iamtsm/tl-rtc-file
|
||||
|
||||
./startTurnServer.sh
|
||||
Access: http://localhost:9092 or http://localhost-ip:9092
|
||||
|
||||
## Admin Panel
|
||||
|
||||
### Overview
|
||||
Prerequisite: Database configuration needs to be enabled.
|
||||
|
||||
Modify the room and password of manage in conf/cfg.json. The default room number and password are both tlrtcfile.
|
||||
|
||||
Access: http://localhost:9092 or http://localhost-ip:9092
|
||||
|
||||
Enter the configured room number and password to enter the admin panel.
|
||||
|
||||
PS: If you need to configure Enterprise WeChat notification, modify the qiwei array in conf/cfg.json of notify and enter the key of the Enterprise WeChat robot.
|
||||
|
||||
## Chat-GPT
|
||||
|
||||
Modify openai.apiKeys in conf/cfg.json and fill in your own apiKey generated by your OpenAI account.
|
||||
|
||||
## Overview Diagram
|
||||
|
||||

|
||||
|
||||
|
||||
## Thanks
|
||||
|
||||
### [scroxt](https://github.com/chenjianfang/scroxt)
|
||||
|
||||
### [layui](https://github.com/layui/layui)
|
||||
|
||||
### [webpack](https://github.com/webpack/webpack)
|
||||
|
||||
### [swiper](https://github.com/nolimits4web/swiper)
|
||||
|
||||
## License
|
||||
|
||||
#### Apache License 2.0
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 iamtsm
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
### Chinese
|
||||
## Disclaimer
|
||||
|
||||
[中文说明](README_ZN.md)
|
||||
[Disclaimer](DISCLAIMER.md)
|
@@ -1,7 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
npm run dev & npm run devsocket
|
||||
|
||||
cd /home/tlrtcfile/svr
|
||||
|
||||
pm2 start npm --name=tlapi -- run sapi
|
||||
|
||||
pm2 start npm --name=tlsocket -- run ssocket
|
||||
|
||||
cd build/webpack
|
||||
|
||||
pm2 start npm --name=tlbuild -- run pro
|
||||
|
||||
pm2 logs
|
||||
|
||||
|
||||
|
||||
|
47
local.js
47
local.js
@@ -1,47 +0,0 @@
|
||||
const express = require("express");
|
||||
const conf = require("./conf/cfg.json");
|
||||
const fileApiRouters = require("./src/controller/router")();
|
||||
let resRouter = conf.router.res;
|
||||
const db = require("./src/tables/db"); //db
|
||||
|
||||
let app = express();
|
||||
console.log("api init start ...")
|
||||
|
||||
//res
|
||||
for (let key in resRouter) {
|
||||
app.use(key, express.static(resRouter[key]));
|
||||
}
|
||||
|
||||
//file api
|
||||
for (let key in fileApiRouters) {
|
||||
app.use(key, fileApiRouters[key])
|
||||
}
|
||||
|
||||
if (!conf.db.open) {// 没开db
|
||||
|
||||
app.use(async function (req, res, next) {
|
||||
req.ctx = {};
|
||||
req.ctx.tables = {};
|
||||
req.ctx.dbClient = {};
|
||||
await next();
|
||||
})
|
||||
app.listen(conf.node.port);
|
||||
console.log("express init done ...")
|
||||
console.log("web server runing on ", conf.node.port, " successful");
|
||||
} else { // 开了db
|
||||
|
||||
(async () => {
|
||||
let { tables, dbClient } = await db.excute(conf)
|
||||
console.log("db init done ...")
|
||||
app.use(async function (req, res, next) {
|
||||
req.ctx = {};
|
||||
req.ctx.tables = tables;
|
||||
req.ctx.dbClient = dbClient;
|
||||
await next();
|
||||
})
|
||||
|
||||
app.listen(conf.node.port);
|
||||
console.log("express init done ...")
|
||||
console.log("web server runing on ", conf.node.port, " successful");
|
||||
})();
|
||||
}
|
1439
package-lock.json
generated
1439
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
40
package.json
40
package.json
@@ -1,40 +0,0 @@
|
||||
{
|
||||
"name": "tl-rtc-file",
|
||||
"version": "1.0.0",
|
||||
"description": "webrtc, p2p,file",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"dev": "node local",
|
||||
"svr": "node server",
|
||||
"devsocket": "node localsocket",
|
||||
"svrsocket": "node serversocket"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": ""
|
||||
},
|
||||
"keywords": [
|
||||
"none"
|
||||
],
|
||||
"author": "iamtsm",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"request": "^2.88.2",
|
||||
"cookie-parser": "^1.4.5",
|
||||
"dottie": "^2.0.2",
|
||||
"ejs": "^3.1.3",
|
||||
"express": "^4.17.1",
|
||||
"inflection": "^1.12.0",
|
||||
"moment-timezone": "^0.5.31",
|
||||
"mysql2": "^2.1.0",
|
||||
"retry-as-promised": "^3.2.0",
|
||||
"sequelize": "^6.1.0",
|
||||
"sequelize-pool": "^6.0.0",
|
||||
"socket.io": "^2.3.0",
|
||||
"toposort-class": "^1.0.1",
|
||||
"validator": "^13.1.1",
|
||||
"wkx": "^0.5.0",
|
||||
"openai": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 123 KiB |
@@ -1,67 +0,0 @@
|
||||
const dog = require("./../../dao/dog/dog");
|
||||
|
||||
/**
|
||||
* 操作记录
|
||||
* @param {*} data
|
||||
*/
|
||||
async function dogData(data) {
|
||||
let req = {
|
||||
ctx: {
|
||||
tables: data.tables
|
||||
},
|
||||
params: data
|
||||
};
|
||||
let res = 0;
|
||||
|
||||
try {
|
||||
res = await dog.addDogData(req, null);
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
return res && res.dataValues ? res.dataValues.id : 0
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取最近10条公共聊天室数据
|
||||
* @param {*} data
|
||||
*/
|
||||
async function getDogChating10Info(data) {
|
||||
let req = {
|
||||
ctx: {
|
||||
tables: data.tables,
|
||||
dbClient: data.dbClient
|
||||
}
|
||||
};
|
||||
|
||||
return await dog.getDogChating10Info(req, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取操作数据信息
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
async function getDogManageInfo(data){
|
||||
let req = {
|
||||
ctx: {
|
||||
tables: data.tables,
|
||||
dbClient: data.dbClient,
|
||||
sockets: data.sockets
|
||||
},
|
||||
params: {
|
||||
limit: 10,
|
||||
day: data.day,
|
||||
}
|
||||
}
|
||||
return await dog.getDogManageInfo(req, null);
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
dogData,
|
||||
getDogChating10Info,
|
||||
getDogManageInfo
|
||||
}
|
@@ -1,70 +0,0 @@
|
||||
const conf = require("../../../conf/cfg.json");
|
||||
const request = require('request');
|
||||
const qiwei = conf.notify.qiwei;
|
||||
const open = conf.notify.open;
|
||||
|
||||
// 统计企微机器人发送map
|
||||
const qiweiMap = {}
|
||||
for (let key in qiwei) {
|
||||
qiweiMap[qiwei[key]] = {
|
||||
time: new Date().valueOf(),
|
||||
count: 0
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 企业微信通知
|
||||
* @param {*} msg
|
||||
*/
|
||||
function requestMsg(msg) {
|
||||
if(!open){
|
||||
return
|
||||
}
|
||||
let finalKey = "";
|
||||
for (let key in qiweiMap) {
|
||||
// 单个还没达到20次,直接用
|
||||
if (qiweiMap[key].count < 20) {
|
||||
qiweiMap[key].count += 1;
|
||||
finalKey = key;
|
||||
break;
|
||||
} else {
|
||||
//达到20次,看看时间如果在1分钟内,说明达到限制,直接跳过
|
||||
if ((new Date().valueOf() / 1000) - (qiweiMap[key].time / 1000) <= 60) {
|
||||
continue;
|
||||
} else {
|
||||
//达到20次,但是时间超过1分钟,我们尝试清零
|
||||
qiweiMap[key].count = 1;
|
||||
qiweiMap[key].time = new Date().valueOf()
|
||||
finalKey = key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (finalKey === '' && qiwei.length > 0) {
|
||||
finalKey = qiwei[0];
|
||||
}
|
||||
|
||||
msg = msg + `机器人KEY: ${finalKey}\n`;
|
||||
msg = msg + `机器人KEY列表: ${JSON.stringify(qiweiMap)}\n`;
|
||||
|
||||
request({
|
||||
url: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=" + finalKey,
|
||||
method: "POST",
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
msgtype: "markdown",
|
||||
markdown: {
|
||||
content: msg,
|
||||
}
|
||||
})
|
||||
}, function (error, response, body) {
|
||||
console.log('提示成功!', qiweiMap);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
requestMsg
|
||||
}
|
@@ -1,117 +0,0 @@
|
||||
const room = require("./../../dao/room/room");
|
||||
|
||||
/**
|
||||
* 创建/加入房间数据入库
|
||||
* @param {*} data
|
||||
*/
|
||||
async function createJoinRoom(data) {
|
||||
let req = {
|
||||
ctx: {
|
||||
tables: data.tables
|
||||
},
|
||||
params: {
|
||||
uid: "1",
|
||||
uname: "user",
|
||||
rname: data.roomName,
|
||||
sid: data.socketId,
|
||||
pwd: data.password,
|
||||
ip: data.ip,
|
||||
device: data.device,
|
||||
url: data.url || "",
|
||||
content: JSON.stringify(data.content)
|
||||
}
|
||||
};
|
||||
|
||||
let res = await room.createJoinRoom(req, null);
|
||||
|
||||
return res && res.dataValues ? res.dataValues.id : 0
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 退出房间
|
||||
* @param {*} data
|
||||
*/
|
||||
async function exitRoom(data) {
|
||||
let req = {
|
||||
ctx: {
|
||||
tables: data.tables
|
||||
},
|
||||
params: {
|
||||
sid: data.sid
|
||||
}
|
||||
};
|
||||
|
||||
let res = await room.exitRoomBySid(req, null);
|
||||
console.log("退出成功 : ", data, res)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新管理后台频道设置信息
|
||||
* @param {*} data
|
||||
*/
|
||||
async function updateManageRoom(data) {
|
||||
let req = {
|
||||
ctx: {
|
||||
tables: data.tables
|
||||
},
|
||||
params: {
|
||||
id: data.id,
|
||||
content: data.content
|
||||
}
|
||||
};
|
||||
|
||||
return await room.updateRoomContent(req, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取管理后台频道设置信息
|
||||
* 管理频道房间号不存在就创建
|
||||
* @param {*} data
|
||||
*/
|
||||
async function getOrCreateManageRoom(data) {
|
||||
let req = {
|
||||
ctx: {
|
||||
tables: data.tables
|
||||
},
|
||||
params: {
|
||||
sid: data.socketId,
|
||||
ip: data.ip,
|
||||
device: data.device,
|
||||
content: data.content
|
||||
}
|
||||
};
|
||||
|
||||
return await room.getOrCreateManageRoom(req, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取加入/创建房间统计信息
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
async function getRoomHistoryInfo(data){
|
||||
let req = {
|
||||
ctx: {
|
||||
tables: data.tables,
|
||||
sockets : data.sockets,
|
||||
dbClient : data.dbClient
|
||||
},
|
||||
params: {
|
||||
limit : 10,
|
||||
day : data.day
|
||||
}
|
||||
};
|
||||
|
||||
return await room.getRoomHistoryInfo(req, null);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getOrCreateManageRoom,
|
||||
updateManageRoom,
|
||||
exitRoom,
|
||||
createJoinRoom,
|
||||
getRoomHistoryInfo
|
||||
}
|
@@ -1,33 +0,0 @@
|
||||
const utils = require("../../utils/utils");
|
||||
const conf = require("../../../conf/cfg.json");
|
||||
const wsConf = conf.ws;
|
||||
const webrtcConf = conf.webrtc;
|
||||
|
||||
|
||||
/**
|
||||
* 获取ip地址,初始化等相关配置
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
*/
|
||||
function initData(req, res) {
|
||||
let regexIP = /^((?:(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d))$/;
|
||||
let ip = utils.getLocalIP();
|
||||
if (!regexIP.test(ip)) {
|
||||
ip = utils.getClientIP(req)
|
||||
}
|
||||
if (!regexIP.test(ip)) {
|
||||
ip = "127.0.0.1"
|
||||
}
|
||||
|
||||
let data = {
|
||||
wsHost: wsConf.ws_online ? wsConf.ws_online : "ws://" + ip + ":" + wsConf.port,
|
||||
rtcConfig: { iceServers: webrtcConf.iceServers },
|
||||
options: webrtcConf.options
|
||||
};
|
||||
|
||||
res.json(data)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
initData,
|
||||
}
|
@@ -1,183 +0,0 @@
|
||||
const utils = require("../../utils/utils");
|
||||
const dbOpen = require("../../../conf/cfg.json").db.open;
|
||||
|
||||
/**
|
||||
* 添加操作dog数据
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @param {*} next
|
||||
*/
|
||||
async function addDogData(req, res, next) {
|
||||
let ctx = req.ctx || {};
|
||||
let params = req.params || {};
|
||||
|
||||
let data = await ctx.tables.Dog.create({
|
||||
name: params.name,
|
||||
room_id: params.roomId,
|
||||
socket_id: params.socketId,
|
||||
device: params.device,
|
||||
flag: params.flag,
|
||||
content: params.content,
|
||||
handshake: params.handshake
|
||||
});
|
||||
|
||||
if (res) {
|
||||
res.json(data)
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取操作统计信息
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @param {*} next
|
||||
*/
|
||||
async function getDogManageInfo(req, res, next) {
|
||||
let ctx = req.ctx || {};
|
||||
let params = req.params || {};
|
||||
let data = {
|
||||
transferFileToday: 0,
|
||||
transferFileAll: 0,
|
||||
transferFileSizeTodady: 0,
|
||||
transferTxtTodady: 0,
|
||||
transferTxtAll: 0,
|
||||
transferCommTxtToday: 0,
|
||||
transferCommTxtAll: 0,
|
||||
fileList: [],
|
||||
txtList: [],
|
||||
commTxtList: [],
|
||||
};
|
||||
|
||||
let day;
|
||||
try {
|
||||
day = new Date(params.day)
|
||||
} catch (e) {
|
||||
day = new Date()
|
||||
}
|
||||
let chooseDay = utils.formateDateTime(day, "yyyy-MM-dd");
|
||||
let nextDay = utils.getNextDay(chooseDay);
|
||||
|
||||
//某日传输聚合列表
|
||||
const [transferListToday, metadata] = await ctx.dbClient.query(`select name, room_id, content, handshake, created_at from dog where created_at >= "${chooseDay}" and created_at <= "${nextDay}" order by created_at desc`);
|
||||
|
||||
//发送文件
|
||||
let fileTransferList = transferListToday.filter(element => {
|
||||
return element.name === '准备发送文件'
|
||||
})
|
||||
data.transferFileToday += fileTransferList.length;
|
||||
fileTransferList.forEach(element => {
|
||||
let content = JSON.parse(element.content);
|
||||
data.fileList.push({
|
||||
room: element.room_id || content.room,
|
||||
name: content.name,
|
||||
size: parseInt(content.size / 1024 / 1024) === 0 ? (content.size / 1024 / 1024).toFixed(2) : parseInt(content.size / 1024 / 1024),
|
||||
createTime: utils.formateDateTime(new Date(element.created_at), "yyyy-MM-dd hh:mm:ss"),
|
||||
})
|
||||
data.transferFileSizeTodady += content.size
|
||||
})
|
||||
data.transferFileSizeTodady = parseInt(data.transferFileSizeTodady / 1024 / 1024)
|
||||
|
||||
|
||||
//发送文本内容
|
||||
let txtTransferList = transferListToday.filter(element => {
|
||||
return element.name === '发送文本内容'
|
||||
})
|
||||
data.transferTxtTodady += txtTransferList.length;
|
||||
txtTransferList.forEach(element => {
|
||||
let content = JSON.parse(element.content);
|
||||
data.txtList.push({
|
||||
room: element.room_id || content.room,
|
||||
content: content.content,
|
||||
size: content.content.length,
|
||||
createTime: utils.formateDateTime(new Date(element.created_at), "yyyy-MM-dd hh:mm:ss"),
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
//公共聊天室
|
||||
let commTxtTransferList = transferListToday.filter(element => {
|
||||
return element.name === '公共聊天室'
|
||||
})
|
||||
data.transferCommTxtToday += commTxtTransferList.length;
|
||||
commTxtTransferList.forEach(element => {
|
||||
data.commTxtList.push({
|
||||
room: element.room_id,
|
||||
content: element.content,
|
||||
size: element.content.length,
|
||||
createTime: utils.formateDateTime(new Date(element.created_at), "yyyy-MM-dd hh:mm:ss"),
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
//全部数量统计
|
||||
const [transferAll, metadata1] = await ctx.dbClient.query(`select name, count(*) as user from dog group by name`);
|
||||
transferAll.forEach(element => {
|
||||
if (element.name === '准备发送文件') {
|
||||
data.transferFileAll += element.user
|
||||
}
|
||||
if (element.name === '发送文本内容') {
|
||||
data.transferTxtAll += element.user
|
||||
}
|
||||
if (element.name === '公共聊天室') {
|
||||
data.transferCommTxtAll += element.user
|
||||
}
|
||||
})
|
||||
|
||||
data.chooseDay = chooseDay;
|
||||
|
||||
if (res) {
|
||||
res.json(data)
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始获取最近10条公共聊天记录
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @param {*} next
|
||||
*/
|
||||
async function getDogChating10Info(req, res, next) {
|
||||
let ctx = req.ctx || {};
|
||||
|
||||
const [list, metadata] = await ctx.dbClient.query(`select name, room_id, content, socket_id, created_at from dog where name = '公共聊天室' order by created_at desc limit 10`);
|
||||
|
||||
let resList = []
|
||||
list.forEach(element => {
|
||||
resList.push({
|
||||
room: element.room_id,
|
||||
msg: element.content,
|
||||
socketId: element.socket_id,
|
||||
time: utils.formateDateTime(new Date(element.created_at), "yyyy-MM-dd hh:mm:ss"),
|
||||
})
|
||||
});
|
||||
|
||||
resList = resList.reverse()
|
||||
|
||||
if (res) {
|
||||
res.json(resList)
|
||||
} else {
|
||||
return resList;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = dbOpen ? {
|
||||
addDogData,
|
||||
getDogManageInfo,
|
||||
getDogChating10Info
|
||||
} : {
|
||||
addDogData : () => {
|
||||
return {}
|
||||
},
|
||||
getDogManageInfo : () => {
|
||||
return {}
|
||||
},
|
||||
getDogChating10Info : () => {
|
||||
return [];
|
||||
}
|
||||
}
|
@@ -1,277 +0,0 @@
|
||||
|
||||
const utils = require("../../utils/utils");
|
||||
const cfg = require("../../../conf/cfg.json")
|
||||
const manageConfig = cfg.router.manage;
|
||||
const dbOpen = cfg.db.open;
|
||||
|
||||
// 默认开关数据
|
||||
const defaultSwitchData = {
|
||||
openSendBug: true,
|
||||
openScreen: true,
|
||||
openOnlineUser: true,
|
||||
openShareRoom: true,
|
||||
openAiChat: true,
|
||||
openGetCodeFile: true,
|
||||
openVideoShare: true,
|
||||
openPasswordRoom: true,
|
||||
openScreenShare: true,
|
||||
openFileTransfer: true,
|
||||
openTxtTransfer: true,
|
||||
openTurnServer: true,
|
||||
openNetworkIcon: true,
|
||||
openUseTurnIcon: true,
|
||||
openCommRoom: true,
|
||||
openRefleshRoom: true,
|
||||
openNotice: true,
|
||||
allowNumber: true,
|
||||
allowChinese: true,
|
||||
allowSymbol: true,
|
||||
noticeMsgList: [],
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理后台特殊房间入口、配置信息
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @param {*} next
|
||||
*/
|
||||
async function getOrCreateManageRoom(req, res, next) {
|
||||
let ctx = req.ctx || {};
|
||||
let params = req.params || {};
|
||||
let data = {};
|
||||
|
||||
let manageRoomList = await ctx.tables.Room.findAll({
|
||||
where: {
|
||||
rname: manageConfig.room,
|
||||
flag: 1
|
||||
}
|
||||
});
|
||||
|
||||
if (manageRoomList.length === 0) {
|
||||
data = await ctx.tables.Room.create({
|
||||
rcode: utils.genRoom(),
|
||||
rname: manageConfig.room,
|
||||
flag: 1,
|
||||
sid: params.sid,
|
||||
ip: params.ip,
|
||||
device: params.device,
|
||||
content: JSON.stringify(defaultSwitchData)
|
||||
});
|
||||
|
||||
console.log("创建管理房间配置成功")
|
||||
|
||||
manageRoomList = await ctx.tables.Room.findAll({
|
||||
where: {
|
||||
rname: manageConfig.room,
|
||||
flag: 1
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
manageRoomList = manageRoomList.length >= 1 ? manageRoomList[0] : manageRoomList
|
||||
|
||||
if (res) {
|
||||
res.json(manageRoomList)
|
||||
} else {
|
||||
return manageRoomList;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取房间统计信息
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @param {*} next
|
||||
*/
|
||||
async function getRoomHistoryInfo(req, res, next) {
|
||||
let ctx = req.ctx || {};
|
||||
let params = req.params || {};
|
||||
let sockets = ctx.sockets || {};
|
||||
let data = {
|
||||
createRoomToday: 0,
|
||||
createRoomAll: 0,
|
||||
joinRoomTodady: 0,
|
||||
joinRoomAll: 0,
|
||||
onlineRoomList: [],
|
||||
todayRoomList: [],
|
||||
userAgentIpList: []
|
||||
};
|
||||
|
||||
//当前在线房间列表
|
||||
for (let room in sockets.adapter.rooms) {
|
||||
if (room.length > 15) {
|
||||
continue
|
||||
}
|
||||
data.onlineRoomList.push({
|
||||
status: "在线",
|
||||
room: room,
|
||||
userNumber: sockets.adapter.rooms[room] ? Object.keys(sockets.adapter.rooms[room].sockets).length : 0,
|
||||
createTime: sockets.adapter.rooms[room].createTime
|
||||
})
|
||||
}
|
||||
|
||||
let day;
|
||||
try {
|
||||
day = new Date(params.day)
|
||||
} catch (e) {
|
||||
day = new Date()
|
||||
}
|
||||
let chooseDay = utils.formateDateTime(day, "yyyy-MM-dd");
|
||||
let nextDay = utils.getNextDay(chooseDay);
|
||||
|
||||
// 某日房间聚合列表,数量统计
|
||||
const [roomCoutingListToday, metadata] = await ctx.dbClient.query(
|
||||
`select rname, any_value(created_at) as created_at, count(*) as user from room where created_at >= "${chooseDay}" and created_at <= "${nextDay}" group by rname order by created_at desc`);
|
||||
|
||||
data.createRoomToday += roomCoutingListToday.length;
|
||||
roomCoutingListToday.forEach(element => {
|
||||
data.joinRoomTodady += element.user;
|
||||
data.todayRoomList.push({
|
||||
room: element.rname,
|
||||
count: element.user,
|
||||
createTime: utils.formateDateTime(new Date(element.created_at), "yyyy-MM-dd hh:mm:ss"),
|
||||
})
|
||||
});
|
||||
|
||||
// 全部数量统计
|
||||
const [roomCoutingListAll, metadata1] = await ctx.dbClient.query(`select count(*) as user from room group by rname`);
|
||||
data.createRoomAll += roomCoutingListAll.length;
|
||||
roomCoutingListAll.forEach(element => {
|
||||
data.joinRoomAll += element.user
|
||||
});
|
||||
|
||||
// 某日房间设备统计列表
|
||||
const [roomListAgent, metadata2] = await ctx.dbClient.query(`select rname, content, created_at from room where created_at >= "${utils.formateDateTime(new Date(), "yyyy-MM-dd")}" order by created_at desc`);
|
||||
roomListAgent.forEach(element => {
|
||||
let content = JSON.parse(element.content);
|
||||
if (content && content.handshake) {
|
||||
data.userAgentIpList.push({
|
||||
room: element.rname,
|
||||
userAgent: content.handshake.headers['user-agent'],
|
||||
Ip: content.handshake.headers['x-real-ip'] || content.handshake.headers['x-forwarded-for'] || content.handshake.headers['host'],
|
||||
createTime: utils.formateDateTime(new Date(element.created_at), "yyyy-MM-dd hh:mm:ss"),
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
data.chooseDay = chooseDay;
|
||||
|
||||
if (res) {
|
||||
res.json(data)
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建/加入房间
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @param {*} next
|
||||
*/
|
||||
async function createJoinRoom(req, res, next) {
|
||||
let ctx = req.ctx || {};
|
||||
let params = req.params || {};
|
||||
let data = {};
|
||||
|
||||
data = await ctx.tables.Room.create({
|
||||
uid: params.uid,
|
||||
uname: params.uname,
|
||||
rcode: utils.genRoom(),
|
||||
rname: params.rname,
|
||||
sid: params.sid,
|
||||
ip: params.ip,
|
||||
device: params.device,
|
||||
url: params.url,
|
||||
content: params.content
|
||||
});
|
||||
|
||||
if (res) {
|
||||
res.json(data)
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新房间
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @param {*} next
|
||||
*/
|
||||
async function updateRoomContent(req, res, next) {
|
||||
let ctx = req.ctx || {};
|
||||
let params = req.params || {};
|
||||
|
||||
let data = await ctx.tables.Room.update({
|
||||
content: params.content,
|
||||
}, {
|
||||
where: {
|
||||
id: params.id,
|
||||
flag: 1
|
||||
}
|
||||
});
|
||||
|
||||
if (res) {
|
||||
res.json(data)
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 退出房间
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @param {*} next
|
||||
*/
|
||||
async function exitRoomBySid(req, res, next) {
|
||||
let ctx = req.ctx || {};
|
||||
let params = req.params || {};
|
||||
|
||||
console.log(ctx.tables)
|
||||
|
||||
let data = await ctx.tables.Room.update({
|
||||
status: 1
|
||||
}, {
|
||||
where: {
|
||||
sid: params.sid
|
||||
}
|
||||
});
|
||||
|
||||
if (res) {
|
||||
res.json(data)
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = dbOpen ? {
|
||||
getRoomHistoryInfo,
|
||||
createJoinRoom,
|
||||
updateRoomContent,
|
||||
exitRoomBySid,
|
||||
getOrCreateManageRoom
|
||||
} : {
|
||||
getRoomHistoryInfo: () => {
|
||||
return {}
|
||||
},
|
||||
createJoinRoom: () => {
|
||||
return {}
|
||||
},
|
||||
updateRoomContent: () => {
|
||||
return {}
|
||||
},
|
||||
exitRoomBySid: () => {
|
||||
return {}
|
||||
},
|
||||
getOrCreateManageRoom: () => {
|
||||
return {
|
||||
content: JSON.stringify(defaultSwitchData)
|
||||
}
|
||||
},
|
||||
}
|
@@ -1,89 +0,0 @@
|
||||
const rtcDisConnect = require("./rtcDisConnect/disconnect");
|
||||
const rtcOffer = require("./rtcOffer/offer");
|
||||
const rtcAnswer = require("./rtcAnswer/answer");
|
||||
const rtcCandidate = require("./rtcCandidate/candidate");
|
||||
const rtcCount = require("./rtcCount/count");
|
||||
const rtcExit = require("./rtcExit/exit");
|
||||
const rtcCommData = require("./rtcCommData/commData");
|
||||
const rtcCreateJoin = require("./rtcCreateJoin/createJoin");
|
||||
const rtcManageConfirm = require("./rtcManage/confirm");
|
||||
const rtcManageChange = require("./rtcManage/change");
|
||||
const rtcManageReload = require("./rtcManage/reload");
|
||||
const rtcMessage = require("./rtcMessage/message");
|
||||
const rtcChating = require("./rtcChating/chating");
|
||||
const rtcOpenai = require("./rtcOpenai/openai");
|
||||
|
||||
module.exports = (io, socket, tables, dbClient) => {
|
||||
|
||||
rtcCount.count(io, socket, tables, dbClient, {})
|
||||
|
||||
// 断开连接
|
||||
socket.on('disconnect', (data)=>{
|
||||
rtcDisConnect.disconnect(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// webrtc offer 消息
|
||||
socket.on('offer', (data) => {
|
||||
rtcOffer.offer(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// webrtc answer 消息
|
||||
socket.on('answer', (data) => {
|
||||
rtcAnswer.answer(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// webrtc candidate 消息
|
||||
socket.on('candidate', (data) => {
|
||||
rtcCandidate.candidate(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 在线人数统计
|
||||
socket.on('count', (data) => {
|
||||
rtcCount.count(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 退出房间
|
||||
socket.on('exit', (data) => {
|
||||
rtcExit.exit(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 获取初始数据
|
||||
socket.on("getCommData", (data) => {
|
||||
rtcCommData.commData(io, socket, tables, dbClient, data)
|
||||
})
|
||||
|
||||
// 创建或加入房间
|
||||
socket.on('createAndJoin', (data) => {
|
||||
rtcCreateJoin.createJoin(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 管理后台登陆验证
|
||||
socket.on('manageConfirm', (data) => {
|
||||
rtcManageConfirm.confirm(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 管理后台修改数据
|
||||
socket.on('manageChange', (data) => {
|
||||
rtcManageChange.change(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 管理后台刷新
|
||||
socket.on('manageReload', (data) => {
|
||||
rtcManageReload.reload(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 公共消息
|
||||
socket.on('message', (data) => {
|
||||
rtcMessage.message(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 公共聊天频道
|
||||
socket.on('chatingComm', (data) => {
|
||||
rtcChating.chating(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// openai聊天
|
||||
socket.on('openai', (data) => {
|
||||
rtcOpenai.openai(io, socket, tables, dbClient, data)
|
||||
});
|
||||
}
|
@@ -1,89 +0,0 @@
|
||||
const bussinessRoom = require("./../../bussiness/room/room")
|
||||
const bussinessDog = require("./../../bussiness/dog/dog")
|
||||
const rtcMessage = require("./../rtcMessage/message");
|
||||
const utils = require("./../../utils/utils");
|
||||
|
||||
// 公共聊天数据缓存
|
||||
let chatingComm = null
|
||||
// 开关数据缓存
|
||||
let cacheSwitchData = null
|
||||
|
||||
|
||||
/**
|
||||
* 获取初始数据
|
||||
* @param {*} io socketio对象
|
||||
* @param {*} socket 单个socket连接
|
||||
* @param {*} tables 数据表对象
|
||||
* @param {*} dbClient sequelize-orm对象
|
||||
* @param {*} data event参数
|
||||
* @returns
|
||||
*/
|
||||
async function commData(io, socket, tables, dbClient, data){
|
||||
let {handshake, userAgent, ip} = utils.getSocketClientInfo(socket);
|
||||
|
||||
let manageInfo = await bussinessRoom.getOrCreateManageRoom({
|
||||
tables: tables,
|
||||
sid: socket.id,
|
||||
ip: ip,
|
||||
device: userAgent,
|
||||
content: ""
|
||||
})
|
||||
let switchData = JSON.parse(manageInfo.content)
|
||||
if(switchData){
|
||||
cacheSwitchData = switchData
|
||||
}
|
||||
|
||||
if(!chatingComm){
|
||||
chatingComm = await bussinessDog.getDogChating10Info({
|
||||
tables, dbClient
|
||||
});
|
||||
}
|
||||
|
||||
rtcMessage.message(io, socket, tables, dbClient, {
|
||||
emitType: "commData",
|
||||
switchData: switchData,
|
||||
chatingCommData: chatingComm || [],
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 chatingComm
|
||||
* @returns
|
||||
*/
|
||||
function getChatingComm(){
|
||||
return chatingComm;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新 chatingComm
|
||||
* @returns
|
||||
*/
|
||||
function setChatingComm(data){
|
||||
chatingComm = data
|
||||
return chatingComm;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 cacheSwitchData
|
||||
* @returns
|
||||
*/
|
||||
function getCacheSwitchData(){
|
||||
return cacheSwitchData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新 cacheSwitchData
|
||||
* @param {*} data
|
||||
*/
|
||||
function setCacheSwitchData(data){
|
||||
cacheSwitchData = data
|
||||
return cacheSwitchData;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
commData,
|
||||
getCacheSwitchData,
|
||||
setCacheSwitchData,
|
||||
getChatingComm,
|
||||
setChatingComm
|
||||
}
|
@@ -1,82 +0,0 @@
|
||||
const bussinessDog = require("./../../bussiness/dog/dog")
|
||||
const rtcMessage = require("./../rtcMessage/message");
|
||||
const bussinessNotify = require("./../../bussiness/notify/notifySocketEvent")
|
||||
const rtcCommData = require("./../rtcCommData/commData");
|
||||
const utils = require("./../../utils/utils");
|
||||
const bussinessOpenai = require("./../../bussiness/openai/openai")
|
||||
|
||||
/**
|
||||
* 公共聊天频道
|
||||
* @param {*} io socketio对象
|
||||
* @param {*} socket 单个socket连接
|
||||
* @param {*} tables 数据表对象
|
||||
* @param {*} dbClient sequelize-orm对象
|
||||
* @param {*} data event参数
|
||||
* @returns
|
||||
*/
|
||||
async function openai(io, socket, tables, dbClient, data){
|
||||
let cacheSwitchData = rtcCommData.getCacheSwitchData()
|
||||
|
||||
if(!cacheSwitchData.openAiChat){
|
||||
rtcMessage.message(io, socket, tables, dbClient, {
|
||||
room: data.room,
|
||||
emitType: "tips",
|
||||
to: socket.id,
|
||||
msg: "当前功能已暂时关闭,有问题可以加群交流"
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
let {roomId = "10086", content, value} = data;
|
||||
if(value){
|
||||
value = value.substr(0, 1000)
|
||||
}
|
||||
|
||||
// 有上下文,结合上下文
|
||||
if(content){
|
||||
content = content.substr(0, 5000);
|
||||
content += "。\n,假定以上的内容是提问者和你的对话,结合上面的语境回答下面的问题,并且注意如果提问内容或者你的回答内容涉及政治,请回复 “我已经被设置关闭涉政问答功能”。提问内容为 : "+value;
|
||||
}else{
|
||||
// 没有就默认
|
||||
content = value;
|
||||
}
|
||||
|
||||
let {handshake, userAgent, ip} = utils.getSocketClientInfo(socket);
|
||||
|
||||
data.time = new Date().toLocaleString()
|
||||
data.type = "openai";
|
||||
data.content = await bussinessOpenai.openaiChat(content, roomId);
|
||||
data.value = "";
|
||||
|
||||
let to = socket.id;
|
||||
let otherSocket = io.sockets.connected[to];
|
||||
if(otherSocket){
|
||||
otherSocket.emit("openaiAnswer", data);
|
||||
}
|
||||
|
||||
await bussinessDog.dogData({
|
||||
name: opName.openaiChat,
|
||||
tables: tables,
|
||||
roomId: roomId,
|
||||
socketId: data.socketId,
|
||||
device: userAgent,
|
||||
flag: 0,
|
||||
content: decodeURIComponent(data.content),
|
||||
handshake: JSON.stringify(handshake),
|
||||
ip: ip
|
||||
});
|
||||
|
||||
bussinessNotify.sendOpenaiChatNotify({
|
||||
title: opName.openaiChat,
|
||||
room: roomId,
|
||||
keys : JSON.stringify(bussinessOpenai.apiKeysStatus()),
|
||||
content: content,
|
||||
answer : message.content,
|
||||
userAgent: userAgent,
|
||||
ip: ip
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
openai
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
1
svr/README.md
Normal file
1
svr/README.md
Normal file
@@ -0,0 +1 @@
|
||||
# tl-rtc-file-tool-svr
|
4371
svr/build/webpack/package-lock.json
generated
Normal file
4371
svr/build/webpack/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
31
svr/build/webpack/package.json
Normal file
31
svr/build/webpack/package.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "webpack",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "webpack.config.js",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"css-loader": "^2.1.0",
|
||||
"thread-loader": "^2.1.3",
|
||||
"babel-loader": "^8.0.6",
|
||||
"@babel/core": "^7.6.0",
|
||||
"ansi-colors": "^4.1.1",
|
||||
"concat-with-sourcemaps": "^1.1.0",
|
||||
"fancy-log": "^1.3.3",
|
||||
"glob": "^7.1.4",
|
||||
"glob-base": "^0.3.0",
|
||||
"mini-css-extract-plugin": "^0.5.0",
|
||||
"uglifyjs-webpack-plugin": "^2.2.0",
|
||||
"webpack": "^4.44.2",
|
||||
"webpack-merge": "^4.2.2",
|
||||
"yargs": "^16.1.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"dev": "node buildDev.js",
|
||||
"pro": "node buildPro.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "MIT"
|
||||
}
|
105
svr/conf/cfg.json
Normal file
105
svr/conf/cfg.json
Normal file
@@ -0,0 +1,105 @@
|
||||
{
|
||||
"version": "10.0.5",
|
||||
"ws": {
|
||||
"port": 8444,
|
||||
"host": "ws://127.0.0.1:8444",
|
||||
"control_port": 8445,
|
||||
"control_host": "ws://127.0.0.1:8445"
|
||||
},
|
||||
"wss" : {
|
||||
"port": 8444,
|
||||
"host": "wss://域名 || wss://ip:8444",
|
||||
"control_port": 8445,
|
||||
"control_host": "wss://域名 || wss://ip:8445"
|
||||
},
|
||||
"api": {
|
||||
"port": 9092,
|
||||
"router": {
|
||||
"filter": {
|
||||
"whiteDir": [ ],
|
||||
"whiteFile": [ "router.js" ]
|
||||
},
|
||||
"res": {
|
||||
"/": "res/",
|
||||
"/static": "static/"
|
||||
}
|
||||
}
|
||||
},
|
||||
"manage": {
|
||||
"room": "tlrtcfile",
|
||||
"password": "tlrtcfile"
|
||||
},
|
||||
"webrtc": {
|
||||
"iceServers": [{
|
||||
"urls": "stun:stun.xten.com"
|
||||
}],
|
||||
"iceTransportPolicy": "all",
|
||||
"options": {
|
||||
"offerToReceiveAudio": 1,
|
||||
"offerToReceiveVideo": 1
|
||||
}
|
||||
},
|
||||
"openai" : {
|
||||
"apiKeys" : [
|
||||
|
||||
]
|
||||
},
|
||||
"oss" : {
|
||||
"seafile" : {
|
||||
"repoid" : "存储库id",
|
||||
"host" : "seafile私有网盘域名",
|
||||
"username" : "账号",
|
||||
"password" : "密码"
|
||||
},
|
||||
"alyun" : {
|
||||
|
||||
},
|
||||
"qiniuyun" : {
|
||||
|
||||
}
|
||||
},
|
||||
"notify": {
|
||||
"open": false,
|
||||
"qiwei": {
|
||||
"normal" : [
|
||||
"填写企业微信机器人key"
|
||||
],
|
||||
"error" : [
|
||||
"填写企业微信机器人key"
|
||||
]
|
||||
}
|
||||
},
|
||||
"db": {
|
||||
"open" : false,
|
||||
"mysql": {
|
||||
"host": "host地址",
|
||||
"port": 3306,
|
||||
"dbName": "数据库名称",
|
||||
"user": "用户名",
|
||||
"password": "密码",
|
||||
"other": {
|
||||
"sequelize": {
|
||||
"dialect": "mysql",
|
||||
"host": "host地址",
|
||||
"port": 3306,
|
||||
"logging": false,
|
||||
"pool": {
|
||||
"max": 5,
|
||||
"min": 0,
|
||||
"acquire": 30000,
|
||||
"idle": 10000
|
||||
},
|
||||
"timezone": "+08:00",
|
||||
"define": {
|
||||
"freezeTableName": true,
|
||||
"underscored": true,
|
||||
"charset": "utf8",
|
||||
"collate": "utf8_general_ci",
|
||||
"timestamps": false,
|
||||
"paranoid": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
52
svr/localapi.js
Normal file
52
svr/localapi.js
Normal file
@@ -0,0 +1,52 @@
|
||||
const express = require("express");
|
||||
const conf = require("./conf/cfg.json");
|
||||
const fileApiRouters = require("./src/controller/router")();
|
||||
const db = require("./src/tables/db"); //db
|
||||
const utils = require("./src/utils/utils");
|
||||
const resRouter = conf.api.router.res;
|
||||
|
||||
//打印logo
|
||||
utils.tlConsoleIcon()
|
||||
|
||||
let app = express();
|
||||
utils.tlConsole("api init start ...")
|
||||
|
||||
if (!conf.db.open) {// 没开db
|
||||
|
||||
app.use(async function (req, res, next) {
|
||||
req.ctx = {};
|
||||
req.ctx.tables = {};
|
||||
req.ctx.dbClient = {};
|
||||
await next();
|
||||
})
|
||||
|
||||
//res
|
||||
for (let key in resRouter) app.use(key, express.static(resRouter[key]));
|
||||
//file api
|
||||
for (let key in fileApiRouters) app.use(key, fileApiRouters[key])
|
||||
|
||||
app.listen(conf.api.port);
|
||||
utils.tlConsole("express init done ...")
|
||||
utils.tlConsole("api server runing on ", conf.api.port, " successful")
|
||||
} else { // 开了db
|
||||
|
||||
(async () => {
|
||||
let { tables, dbClient } = await db.excute(conf)
|
||||
utils.tlConsole("db init done ...")
|
||||
app.use(async function (req, res, next) {
|
||||
req.ctx = {};
|
||||
req.ctx.tables = tables;
|
||||
req.ctx.dbClient = dbClient;
|
||||
await next();
|
||||
})
|
||||
|
||||
//res
|
||||
for (let key in resRouter) app.use(key, express.static(resRouter[key]));
|
||||
//file api
|
||||
for (let key in fileApiRouters) app.use(key, fileApiRouters[key])
|
||||
|
||||
app.listen(conf.api.port);
|
||||
utils.tlConsole("express init done ...")
|
||||
utils.tlConsole("api server runing on ", conf.api.port, " successful")
|
||||
})();
|
||||
}
|
29
svr/localcontrolsocket.js
Normal file
29
svr/localcontrolsocket.js
Normal file
@@ -0,0 +1,29 @@
|
||||
const http = require('http'); // http
|
||||
const socketIO = require('socket.io'); //socket
|
||||
const db = require("./src/tables/db"); //db
|
||||
const conf = require("./conf/cfg.json"); //conf
|
||||
const socket = require("./src/socket/index") //socket handler
|
||||
const utils = require("./src/utils/utils");
|
||||
|
||||
//打印logo
|
||||
utils.tlConsoleIcon()
|
||||
|
||||
// 远程控制,Socket连接监听
|
||||
let io = socketIO.listen(http.createServer().listen(conf.ws.control_port));
|
||||
|
||||
if (!conf.db.open) {// 没开db
|
||||
|
||||
utils.tlConsole("db not open ...")
|
||||
socket.excute({}, {}, io);
|
||||
utils.tlConsole("control socket init done ...")
|
||||
utils.tlConsole("control socket server listen on ", conf.ws.control_port, " successful");
|
||||
} else { // 开了db
|
||||
|
||||
(async () => {
|
||||
let { tables, dbClient } = await db.excute(conf)
|
||||
utils.tlConsole("db init done ...")
|
||||
socket.excute(tables, dbClient, io);
|
||||
utils.tlConsole("control socket init done ...")
|
||||
utils.tlConsole("control socket server listen on ", conf.ws.control_port, " successful");
|
||||
})();
|
||||
}
|
@@ -3,23 +3,27 @@ const socketIO = require('socket.io'); //socket
|
||||
const db = require("./src/tables/db"); //db
|
||||
const conf = require("./conf/cfg.json"); //conf
|
||||
const socket = require("./src/socket/index") //socket handler
|
||||
const utils = require("./src/utils/utils");
|
||||
|
||||
//打印logo
|
||||
utils.tlConsoleIcon()
|
||||
|
||||
// Socket连接监听
|
||||
let io = socketIO.listen(http.createServer().listen(conf.ws.port));
|
||||
|
||||
if (!conf.db.open) {// 没开db
|
||||
|
||||
console.log("db not open ...")
|
||||
utils.tlConsole("db not open ...")
|
||||
socket.excute({}, {}, io);
|
||||
console.log("socket init done ...")
|
||||
console.log("socket server listen on ", conf.ws.port, " successful");
|
||||
utils.tlConsole("socket init done ...")
|
||||
utils.tlConsole("socket server listen on ", conf.ws.port, " successful");
|
||||
} else { // 开了db
|
||||
|
||||
(async () => {
|
||||
let { tables, dbClient } = await db.excute(conf)
|
||||
console.log("db init done ...")
|
||||
utils.tlConsole("db init done ...")
|
||||
socket.excute(tables, dbClient, io);
|
||||
console.log("socket init done ...")
|
||||
console.log("socket server listen on ", conf.ws.port, " successful");
|
||||
utils.tlConsole("socket init done ...")
|
||||
utils.tlConsole("socket server listen on ", conf.ws.port, " successful");
|
||||
})();
|
||||
}
|
2357
svr/package-lock.json
generated
Normal file
2357
svr/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
38
svr/package.json
Normal file
38
svr/package.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "tl-rtc-file",
|
||||
"version": "1.0.0",
|
||||
"description": "webrtc, p2p,file",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"lapi": "cross-env ENV_MODE=local node localapi",
|
||||
"lsocket": "cross-env ENV_MODE=local node localsocket",
|
||||
"lcsocket": "cross-env ENV_MODE=local node localcontrolsocket",
|
||||
"sapi": "cross-env ENV_MODE=server node serverapi",
|
||||
"ssocket": "cross-env ENV_MODE=server node serversocket",
|
||||
"scsockert": "cross-env ENV_MODE=server node servercontrolsocket",
|
||||
"test": "cross-env mocha ./test/test.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": ""
|
||||
},
|
||||
"keywords": [
|
||||
"none"
|
||||
],
|
||||
"author": "iamtsm",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cross-env": "^5.2.0",
|
||||
"express": "^4.17.1",
|
||||
"mocha": "^10.2.0",
|
||||
"mysql2": "^2.1.0",
|
||||
"openai": "^1.0.0",
|
||||
"request": "^2.88.2",
|
||||
"sequelize": "^6.1.0",
|
||||
"sequelize-pool": "^6.0.0",
|
||||
"socket.io": "^2.3.0",
|
||||
"pngjs": "^7.0.0",
|
||||
"robotjs": "^0.6.0"
|
||||
},
|
||||
"devDependencies": {}
|
||||
}
|
@@ -5,6 +5,10 @@ html {
|
||||
background-image: linear-gradient(to right, #C5EDFF, #E6F7FF, #E6F7FF, #E6F7FF, #E6F7FF, #C5EDFF, #C5EDFF);
|
||||
}
|
||||
|
||||
#iamtsm{
|
||||
transition: all 1s;
|
||||
}
|
||||
|
||||
html *,
|
||||
html *::before,
|
||||
html *::after {
|
||||
@@ -230,6 +234,13 @@ body {
|
||||
transition: color 0.8s;
|
||||
}
|
||||
|
||||
.tl-rtc-file-tool-mobile i{
|
||||
padding-top : 0 !important;
|
||||
margin-bottom: 15px;
|
||||
padding:5px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.tl-rtc-file-tool b {
|
||||
margin: 10px 10px 10px 0;
|
||||
letter-spacing: 2px;
|
||||
@@ -519,12 +530,12 @@ body {
|
||||
.tl-rtc-file-mask-media-list {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
left: -150%;
|
||||
height: 100%;
|
||||
width: 50%;
|
||||
background: white;
|
||||
z-index: 10000;
|
||||
box-shadow: 0 0px 20px rgb(0 0 0 / 40%);
|
||||
box-shadow: 0 0px 20px rgb(0 0 0 / 8%);
|
||||
transition: all 1s;
|
||||
-moz-transition: all 1s;
|
||||
-webkit-transition: all 1s;
|
||||
@@ -658,11 +669,11 @@ body {
|
||||
.tl-rtc-file-mask-log-list {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
left: -150%;
|
||||
height: 100%;
|
||||
width: 50%;
|
||||
background: white;
|
||||
z-index: 10000;
|
||||
z-index: 100000;
|
||||
box-shadow: 0 0px 20px rgb(0 0 0 / 40%);
|
||||
transition: all 1s;
|
||||
-moz-transition: all 1s;
|
||||
@@ -908,3 +919,47 @@ body {
|
||||
word-break: break-all;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tl-rtc-file-tool-mobile-title{
|
||||
position: absolute;
|
||||
word-break: keep-all;
|
||||
margin: 0 !important;
|
||||
margin-left: 6px !important;
|
||||
bottom: 0;
|
||||
-webkit-transform-origin-x: 0;
|
||||
transform: scale(0.6);
|
||||
-webkit-transform: scale(0.6);
|
||||
}
|
||||
|
||||
#tl-rtc-file-code-share{
|
||||
word-break: break-all;
|
||||
padding: 0px 50px 0px 50px;
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
color: #635555;
|
||||
font-family: cursive;
|
||||
}
|
||||
|
||||
#tl-rtc-file-code-share-image img{
|
||||
width: 60%;
|
||||
margin-left: 20%;
|
||||
}
|
||||
|
||||
#tl-rtc-file-room-share{
|
||||
word-break: break-all;
|
||||
padding: 0px 50px 0px 50px;
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
color: black;
|
||||
font-family: cursive;
|
||||
}
|
||||
|
||||
#tl-rtc-file-room-share-image img{
|
||||
width: 60%;
|
||||
margin-left: 20%;
|
||||
}
|
||||
|
||||
.isMediaing{
|
||||
width: 50%;
|
||||
margin-left: 50%;
|
||||
}
|
57
svr/res/disclaimer.html
Normal file
57
svr/res/disclaimer.html
Normal file
@@ -0,0 +1,57 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>tl-rtc-file</title>
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||
<link href="/image/44826979.png" rel="shortcut icon" type="image/x-icon">
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
margin-left: 15%;
|
||||
margin-top: 50px;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
border-bottom: 1px solid #eaecef;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 20px;
|
||||
border-bottom: 1px solid #eaecef;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1 style="text-align: center;margin-bottom: 20px;">tl-rtc-file开源项目/演示网站服务条款</h1>
|
||||
<h1>免责声明</h1>
|
||||
<p>1.1 如使用本演示网站/开源项目,即表示您已同意本条款。我们 (开源项目维护团队) 始终在不断更改和改进我们的服务。我们可能会增加或删除功能,也可能暂停或彻底停止某项服务。您可以随时停止使用我们的服务,我们也可以随时对我们的服务增加新的限制。</p>
|
||||
<p>1.2 该网站/开源项目的使用者在使用本演示网站/开源项目前,应仔细阅读以下条款并同意遵守。使用本演示网站/开源项目将被视为对本免责协议的接受和遵守。</p>
|
||||
|
||||
<h2>演示网站/开源项目的性质</h2>
|
||||
<p>2.1 本演示网站/开源项目旨在帮助大家学习webrtc,提供一个学习/演示demo环境,和基础功能代码入门教学</p>
|
||||
<p>2.2 本网站/开源项目提供的服务旨在为用户提供数据传输功能演示,包括但不限于文件传输、直播、音视频通话、远程屏幕共享、聊天等功能的演示。</p>
|
||||
<p>2.3 使用者应理解,本演示网站/开源项目仅提供技术支持演示,不对数据传输的准确性、及时性、完整性、安全性或合法性负责。使用者应自行承担使用本演示网站/开源项目的风险。</p>
|
||||
|
||||
<h2>使用者责任</h2>
|
||||
<p>3.1 使用者应承担使用本演示网站/开源项目的全部责任和风险。对于使用者通过本演示网站/开源项目进行的任何操作、行为或后果,本网站/开源项目不承担任何责任。</p>
|
||||
<p>3.2 使用者不得利用本演示网站/开源项目进行任何违法、侵权、威胁、诽谤、骚扰、破坏性或其他不当行为。若使用者违反上述规定,本网站/开源项目有权立即终止或限制使用者的访问权限。</p>
|
||||
<p>3.3 本网站使用者严禁上传违法违规内容,包括但不限于:色情低俗、政治敏感、、暴力、恶意软件、诈骗、贩卖公民隐私,上传上述内容将永久封禁账号或 IP 地址,并可能承担承担刑事责任。</p>
|
||||
|
||||
<h2>免责条款</h2>
|
||||
<p>4.1 本网站/开源项目不对任何由于使用本演示网站/开源项目而引起的任何直接、间接、附带、特殊、惩罚性或后续的损害承担责任,包括但不限于利润损失、商业中断、计算机系统故障、数据丢失或其他经济损失。</p>
|
||||
<p>4.2 本网站/开源项目不对任何第三方通过本演示网站/开源项目发布、提供或传输的任何内容的准确性、合法性、安全性或可靠性负责。</p>
|
||||
|
||||
<h2>免责声明的范围</h2>
|
||||
<p>本免责协议适用于使用本网站/开源项目的所有用户,无论其身份或目的。该免责协议的内容适用于因使用本演示网站/开源项目而产生的一切事项,包括但不限于使用的内容、服务或信息所引起的任何纠纷、损失或损害。</p>
|
||||
</body>
|
||||
</html>
|
@@ -9,7 +9,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||
<script src="static/layui/layui.js" v="layui" e="layui"></script>
|
||||
<link rel="stylesheet" type="text/css" href="static/layui/css/layui.css" />
|
||||
<link href="https://qnproxy.iamtsm.cn/44826979.png" rel="shortcut icon" type="image/x-icon">
|
||||
<link href="/image/44826979.png" rel="shortcut icon" type="image/x-icon">
|
||||
</head>
|
||||
|
||||
<style>
|
||||
@@ -116,17 +116,17 @@
|
||||
}
|
||||
|
||||
.layui-layer-title{
|
||||
border-top-right-radius: 15px;
|
||||
border-top-left-radius: 15px;
|
||||
border-top-right-radius: 8px;
|
||||
border-top-left-radius: 8px;
|
||||
}
|
||||
|
||||
.layui-layer, .layui-layer-content{
|
||||
border-radius: 15px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.layui-layer-content{
|
||||
border-bottom-right-radius: 15px;
|
||||
border-bottom-left-radius: 15px;
|
||||
border-bottom-right-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -152,6 +152,7 @@
|
||||
</div>
|
||||
<div class="tl-rtc-file-intro-tag">
|
||||
<span class="layui-badge layui-bg-blue">文件传输</span>
|
||||
<span class="layui-badge layui-bg-black">文件暂存</span>
|
||||
<span class="layui-badge layui-bg-green">音视频通话</span>
|
||||
<span class="layui-badge layui-bg-orange">远程屏幕共享</span>
|
||||
<span class="layui-badge layui-bg-cyan">本地屏幕录制</span>
|
||||
@@ -186,27 +187,14 @@
|
||||
window.donate = function(){
|
||||
if(window.layer){
|
||||
layer.open({
|
||||
type: 1
|
||||
type: 2
|
||||
, title: false
|
||||
, closeBtn: false
|
||||
, area: '300px;'
|
||||
, shade: 0.8
|
||||
, area: ['80%','80%']
|
||||
, shade: 0.5
|
||||
, shadeClose : true
|
||||
, id: 'layui-info-msg'
|
||||
, btn: ['知道了']
|
||||
, btnAlign: 'c'
|
||||
, moveType: 1
|
||||
, content: `
|
||||
<div style="padding: 30px; line-height: 22px; background-color: #475a97; color: #fff; font-weight: bold;">
|
||||
<div style="text-align: center;line-height: 40px;">如需支持功能定制,或技术支持,加群联系我即可</div>
|
||||
<div style="text-align: center;line-height: 40px;">
|
||||
qq群交流群 :
|
||||
<b> <a style="color: #c6b7ef;font-size: 16px;" target="_blank" href="https://jq.qq.com/?_wv=1027&k=TKCwMBjN">624214498</a> </b>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
, success: function (layero) {
|
||||
|
||||
}
|
||||
, content: 'pay.html'
|
||||
});
|
||||
}
|
||||
}
|
@@ -116,17 +116,17 @@
|
||||
}
|
||||
|
||||
.layui-layer-title{
|
||||
border-top-right-radius: 15px;
|
||||
border-top-left-radius: 15px;
|
||||
border-top-right-radius: 8px;
|
||||
border-top-left-radius: 8px;
|
||||
}
|
||||
|
||||
.layui-layer, .layui-layer-content{
|
||||
border-radius: 15px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.layui-layer-content{
|
||||
border-bottom-right-radius: 15px;
|
||||
border-bottom-left-radius: 15px;
|
||||
border-bottom-right-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -165,7 +165,7 @@
|
||||
|
||||
|
||||
<div class="tl-rtc-file-goto">
|
||||
<a href="" target="_blank">
|
||||
<a href="/" target="_blank">
|
||||
<button type="button" class="layui-btn tl-rtc-file-goto-btn">
|
||||
Try Now
|
||||
</button>
|
||||
@@ -189,27 +189,14 @@
|
||||
window.donate = function(){
|
||||
if(window.layer){
|
||||
layer.open({
|
||||
type: 1
|
||||
type: 2
|
||||
, title: false
|
||||
, closeBtn: false
|
||||
, area: '300px;'
|
||||
, shade: 0.8
|
||||
, area: ['80%','80%']
|
||||
, shade: 0.5
|
||||
, shadeClose : true
|
||||
, id: 'layui-info-msg'
|
||||
, btn: ['ok']
|
||||
, btnAlign: 'c'
|
||||
, moveType: 1
|
||||
, content: `
|
||||
<div style="padding: 30px; line-height: 22px; background-color: #475a97; color: #fff; font-weight: bold;">
|
||||
<div style="text-align: center;line-height: 30px;">If you need support or feature customization or help, just add a qq group to contact me</div>
|
||||
<div style="text-align: center;line-height: 40px;">
|
||||
qq number :
|
||||
<b> <a style="color: #c6b7ef;font-size: 16px;" target="_blank" href="https://jq.qq.com/?_wv=1027&k=TKCwMBjN">624214498</a> </b>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
, success: function (layero) {
|
||||
|
||||
}
|
||||
, content: 'pay.html'
|
||||
});
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
BIN
svr/res/image/coffee.jpeg
Normal file
BIN
svr/res/image/coffee.jpeg
Normal file
Binary file not shown.
After Width: | Height: | Size: 123 KiB |
@@ -9,8 +9,8 @@
|
||||
|
||||
<link rel="stylesheet" href="static/layui/css/layui.css" media="all">
|
||||
<link rel="stylesheet" href="static/layui/css/admin.css" media="all">
|
||||
<link rel="stylesheet" href="/css/comm.min.css" media="all">
|
||||
<link rel="stylesheet" href="/css/index.min.css" media="all">
|
||||
<link rel="stylesheet" href="css/comm.min.css" media="all">
|
||||
<link rel="stylesheet" href="css/index.min.css" media="all">
|
||||
<link rel="stylesheet" href="static/css/swiper-bundle.min.css" media="all">
|
||||
<link rel="stylesheet" href="static/css/default.min.css">
|
||||
<link rel="stylesheet" href="static/css/pdf_viewer.min.css">
|
||||
@@ -25,22 +25,28 @@
|
||||
<script type="text/javascript" src="static/js/pdf_viewer.min.js"></script>
|
||||
<script type="text/javascript" src="static/js/jszip.min.js"></script>
|
||||
<script type="text/javascript" src="static/js/docx-preview.min.js"></script>
|
||||
|
||||
<link href="/image/44826979.png" rel="shortcut icon" type="image/x-icon">
|
||||
<script type="text/javascript" src="static/js/qrcode.min.js"></script>
|
||||
<link href="image/44826979.png" rel="shortcut icon" type="image/x-icon">
|
||||
|
||||
<script>
|
||||
window.Bus = new Vue({});
|
||||
window.prefix = "";
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<body >
|
||||
<div id="tl-rtc-file-app" v-cloak>
|
||||
|
||||
<div class="tl-rtc-file-notification-container" id="notificationContainer"></div>
|
||||
|
||||
<!-- 顶部图标 -->
|
||||
<div class="tl-rtc-file-header-tool">
|
||||
<a title="免责声明" @click="openDisclaimer">
|
||||
<svg viewBox="0 0 1034 1024" p-id="2678" width="128" height="128" style="width: 16px;height: 18px;margin-right: 10px;margin-bottom: 2px;">
|
||||
<path
|
||||
d="M1011.982 842.518 606.673 140.565c-49.575-85.822-130.595-85.822-180.157 0L21.205 842.518c-49.562 85.91-9.015 155.99 90.04 155.99l810.693 0C1020.997 998.507 1061.502 928.423 1011.982 842.518zM460.924 339.737c14.565-15.747 33.082-23.622 55.665-23.622 22.595 0 41.095 7.792 55.675 23.307 14.485 15.55 21.725 34.997 21.725 58.382 0 20.12-30.235 168.07-40.32 275.704l-72.825 0c-8.845-107.635-41.652-255.584-41.652-275.704C439.194 374.774 446.446 355.407 460.924 339.737zM571.244 851.538c-15.32 14.92-33.55 22.355-54.65 22.355-21.095 0-39.33-7.435-54.647-22.355-15.275-14.885-22.867-32.915-22.867-54.09 0-21.065 7.592-39.29 22.867-54.565 15.317-15.28 33.552-22.92 54.647-22.92 21.1 0 39.33 7.64 54.65 22.92 15.265 15.275 22.875 33.5 22.875 54.565C594.119 818.623 586.509 836.653 571.244 851.538z"
|
||||
fill="#db2121" p-id="2679"></path>
|
||||
</svg>
|
||||
</a>
|
||||
<a title="中继服务已启用" id="useTurn" v-show="switchData.openUseTurnIcon && useTurn" @click="useTurnMsg">
|
||||
<svg viewBox="0 0 1130 1024" p-id="8399" width="128" height="128"
|
||||
style="width: 20px;height: 20px;margin-right: 10px;">
|
||||
@@ -171,7 +177,7 @@
|
||||
|
||||
<!-- 顶部标题 -->
|
||||
<div class="tl-rtc-file-header-intro">
|
||||
<div class="tl-rtc-file-header-intro-txt" @click="clickLogs">注 : 示例站点仅用于学习用途, 请勿他用</div>
|
||||
<div class="tl-rtc-file-header-intro-txt">注 : 示例站点仅用于学习用途, 请勿他用</div>
|
||||
<div class="tl-rtc-file-header-intro-qq">qq交流群 : <a target="_blank"
|
||||
href="https://jq.qq.com/?_wv=1027&k=TKCwMBjN">624214498</a> </div>
|
||||
<div class="tl-rtc-file-header-user-online">
|
||||
@@ -193,11 +199,11 @@
|
||||
<i class="layui-icon layui-icon-release tl-rtc-file-send-file-tool-i-one"></i>
|
||||
<i class="layui-icon layui-icon-release tl-rtc-file-send-file-tool-i-two"></i>
|
||||
<i class="layui-icon layui-icon-release tl-rtc-file-send-file-tool-i-three" :style="{
|
||||
left: sendFileList.length > 0 ? '10px' :'0'
|
||||
left: sendFileRecoderList.length > 0 ? '10px' :'0'
|
||||
}"></i>
|
||||
<span v-show="sendFileList.length > 0" style="position: relative;right: -9px;"
|
||||
<span v-show="sendFileRecoderList.length > 0" style="position: relative;right: -9px;"
|
||||
class="layui-badge tl-rtc-file-msg-dot layui-anim layui-anim-rotate layui-anim-loop">
|
||||
{{Math.min(sendFileList.length, 99)}}
|
||||
{{Math.min(sendFileRecoderList.length, 99)}}
|
||||
</div>
|
||||
<div>
|
||||
<button v-show="hasManInRoom" @click="clickSendFile" type="button"
|
||||
@@ -213,11 +219,11 @@
|
||||
<i class="layui-icon layui-icon-reply-fill tl-rtc-file-send-txt-tool-i-one"></i>
|
||||
<i class="layui-icon layui-icon-reply-fill tl-rtc-file-send-txt-tool-i-two"></i>
|
||||
<i class="layui-icon layui-icon-reply-fill tl-rtc-file-send-txt-tool-i-three":style="{
|
||||
left: receiveTxtList.length > 0 ? '10px' :'0'
|
||||
left: receiveChatRoomList.length > 0 ? '10px' :'0'
|
||||
}"></i>
|
||||
<span v-show="receiveTxtList.length > 0" style="position: relative;right: -7px;"
|
||||
<span v-show="receiveChatRoomList.length > 0" style="position: relative;right: -7px;"
|
||||
class="layui-badge tl-rtc-file-msg-dot layui-anim layui-anim-rotate layui-anim-loop">
|
||||
{{Math.min(receiveTxtList.length, 99)}}
|
||||
{{Math.min(receiveChatRoomList.length, 99)}}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
@@ -234,60 +240,105 @@
|
||||
<div class="swiper-wrapper">
|
||||
<div class="layui-col-xs3 swiper-slide" @click="openChatingComm"
|
||||
:class="switchData.openCommRoom ? '':'tl-rtc-file-tool-disabled'">
|
||||
<div class="tl-rtc-file-tool">
|
||||
<i :style="(clientWidth < 450) ? 'padding:5px;font-size: 18px' : '' "
|
||||
class="layui-icon layui-icon-reply-fill"></i>
|
||||
<b v-show="clientWidth >= 450">公共聊天</b>
|
||||
<span v-show="chatingCommList.length > 0" class="layui-badge tl-rtc-file-msg-dot"
|
||||
<div class="tl-rtc-file-tool tl-rtc-file-tool-mobile" v-if="clientWidth < 450">
|
||||
<i class="layui-icon layui-icon-reply-fill"></i>
|
||||
<b class="tl-rtc-file-tool-mobile-title">公共聊天</b>
|
||||
<span v-show="receiveChatCommList.length > 0" class="layui-badge tl-rtc-file-msg-dot"
|
||||
style="right: 5px; top: 4px; width: 7px; height: 7px;position: relative;"></span>
|
||||
</div>
|
||||
<div class="tl-rtc-file-tool" v-else>
|
||||
<i class="layui-icon layui-icon-reply-fill"></i>
|
||||
<b >公共聊天</b>
|
||||
<span v-show="receiveChatCommList.length > 0" class="layui-badge tl-rtc-file-msg-dot"
|
||||
style="right: 5px; top: 4px; width: 7px; height: 7px;position: relative;"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-xs3 swiper-slide" @click="startScreenShare"
|
||||
:class="switchData.openScreenShare ? '':'tl-rtc-file-tool-disabled'">
|
||||
<div class="tl-rtc-file-tool">
|
||||
<i :style="(clientWidth < 450) ? 'padding:5px;font-size: 18px' : '' "
|
||||
class="layui-icon layui-icon-chart-screen" id="screenShareIcon"></i>
|
||||
<b v-show="clientWidth >= 450">屏幕共享</b>
|
||||
<div class="tl-rtc-file-tool tl-rtc-file-tool-mobile" v-if="clientWidth < 450">
|
||||
<i class="layui-icon layui-icon-chart-screen" id="screenShareIcon"></i>
|
||||
<b class="tl-rtc-file-tool-mobile-title">屏幕共享</b>
|
||||
</div>
|
||||
<div class="tl-rtc-file-tool" v-else>
|
||||
<i class="layui-icon layui-icon-chart-screen" id="screenShareIcon"></i>
|
||||
<b>屏幕共享</b>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-xs3 swiper-slide" @click="startVideoShare"
|
||||
:class="switchData.openVideoShare ? '':'tl-rtc-file-tool-disabled'">
|
||||
<div class="tl-rtc-file-tool">
|
||||
<i :style="(clientWidth < 450) ? 'padding:5px;font-size: 18px' : '' "
|
||||
class="layui-icon layui-icon-video" id="videoShareIcon"></i>
|
||||
<b v-show="clientWidth >= 450">视频通话</b>
|
||||
<div class="tl-rtc-file-tool tl-rtc-file-tool-mobile" v-if="clientWidth < 450">
|
||||
<i class="layui-icon layui-icon-video" id="videoShareIcon"></i>
|
||||
<b class="tl-rtc-file-tool-mobile-title">视频通话</b>
|
||||
</div>
|
||||
<div class="tl-rtc-file-tool" v-else>
|
||||
<i class="layui-icon layui-icon-video" id="videoShareIcon"></i>
|
||||
<b>视频通话</b>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-xs3 swiper-slide" @click="startScreen"
|
||||
:class="switchData.openScreen ? '':'tl-rtc-file-tool-disabled'">
|
||||
<div class="tl-rtc-file-tool">
|
||||
<i :style="(clientWidth < 450) ? 'padding:5px;font-size: 18px' : '' "
|
||||
class="layui-icon layui-icon-radio" id="screenIcon"></i>
|
||||
<b v-show="clientWidth >= 450">屏幕录制</b>
|
||||
<div class="layui-col-xs3 swiper-slide" @click="startLiveShare"
|
||||
:class="switchData.openLiveShare ? '':'tl-rtc-file-tool-disabled'">
|
||||
<div class="tl-rtc-file-tool tl-rtc-file-tool-mobile" v-if="clientWidth < 450">
|
||||
<i class="layui-icon layui-icon-fire" id="liveShareIcon"></i>
|
||||
<b class="tl-rtc-file-tool-mobile-title">开启直播</b>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-xs3 swiper-slide" @click="openaiChat"
|
||||
:class="switchData.openAiChat ? '':'tl-rtc-file-tool-disabled'">
|
||||
<div class="tl-rtc-file-tool">
|
||||
<i :style="(clientWidth < 450) ? 'padding:5px;font-size: 18px' : '' "
|
||||
class="layui-icon layui-icon-fire"></i>
|
||||
<b v-show="clientWidth >= 450">AI 聊天</b>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-xs3 swiper-slide" @click="startPassword"
|
||||
:class="switchData.openPasswordRoom ? '':'tl-rtc-file-tool-disabled'">
|
||||
<div class="tl-rtc-file-tool">
|
||||
<i :style="(clientWidth < 450) ? 'padding:5px;font-size: 18px' : '' "
|
||||
class="layui-icon layui-icon-key"></i>
|
||||
<b v-show="clientWidth >= 450">密码房间</b>
|
||||
<div class="tl-rtc-file-tool" v-else>
|
||||
<i class="layui-icon layui-icon-fire" id="liveShareIcon"></i>
|
||||
<b>开启直播</b>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-xs3 swiper-slide" @click="getCodeFile"
|
||||
:class="switchData.openGetCodeFile ? '':'tl-rtc-file-tool-disabled'">
|
||||
<div class="tl-rtc-file-tool">
|
||||
<i :style="(clientWidth < 450) ? 'padding:5px;font-size: 18px' : '' "
|
||||
class="layui-icon layui-icon-email"></i>
|
||||
<b v-show="clientWidth >= 450">取件码</b>
|
||||
<div class="tl-rtc-file-tool tl-rtc-file-tool-mobile" v-if="clientWidth < 450">
|
||||
<i class="layui-icon layui-icon-email"></i>
|
||||
<b class="tl-rtc-file-tool-mobile-title">取件号码</b>
|
||||
</div>
|
||||
<div class="tl-rtc-file-tool" v-else>
|
||||
<i class="layui-icon layui-icon-email"></i>
|
||||
<b>取件号码</b>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-xs3 swiper-slide" @click="startPassword"
|
||||
:class="switchData.openPasswordRoom ? '':'tl-rtc-file-tool-disabled'">
|
||||
<div class="tl-rtc-file-tool tl-rtc-file-tool-mobile" v-if="clientWidth < 450">
|
||||
<i class="layui-icon layui-icon-key"></i>
|
||||
<b class="tl-rtc-file-tool-mobile-title">密码房间</b>
|
||||
</div>
|
||||
<div class="tl-rtc-file-tool" v-else>
|
||||
<i class="layui-icon layui-icon-key"></i>
|
||||
<b>密码房间</b>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-xs3 swiper-slide" @click="startScreen"
|
||||
:class="switchData.openScreen ? '':'tl-rtc-file-tool-disabled'">
|
||||
<div class="tl-rtc-file-tool tl-rtc-file-tool-mobile" v-if="clientWidth < 450">
|
||||
<i class="layui-icon layui-icon-radio" id="screenIcon"></i>
|
||||
<b class="tl-rtc-file-tool-mobile-title">屏幕录制</b>
|
||||
</div>
|
||||
<div class="tl-rtc-file-tool" v-else>
|
||||
<i class="layui-icon layui-icon-radio" id="screenIcon"></i>
|
||||
<b>屏幕录制</b>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-xs3 swiper-slide" @click="openaiChat"
|
||||
:class="switchData.openAiChat ? '':'tl-rtc-file-tool-disabled'">
|
||||
<div class="tl-rtc-file-tool tl-rtc-file-tool-mobile" v-if="clientWidth < 450">
|
||||
<i class="layui-icon layui-icon-service"></i>
|
||||
<b class="tl-rtc-file-tool-mobile-title" style="letter-spacing: 0px;">ChatGPT</b>
|
||||
</div>
|
||||
<div class="tl-rtc-file-tool" v-else>
|
||||
<i class="layui-icon layui-icon-service"></i>
|
||||
<b>ChatGPT</b>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-xs3 swiper-slide" @click="startRemoteDraw"
|
||||
:class="switchData.openRemoteDraw ? '':'tl-rtc-file-tool-disabled'">
|
||||
<div class="tl-rtc-file-tool tl-rtc-file-tool-mobile" v-if="clientWidth < 450">
|
||||
<i class="layui-icon layui-icon-console" id="remoteDrawIcon"></i>
|
||||
<b class="tl-rtc-file-tool-mobile-title">远程画笔</b>
|
||||
</div>
|
||||
<div class="tl-rtc-file-tool" v-else>
|
||||
<i class="layui-icon layui-icon-console" id="remoteDrawIcon"></i>
|
||||
<b>远程画笔</b>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -328,21 +379,21 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="tl-rtc-file-user-body-right">
|
||||
<i v-show="sendFileHistoryList.length > 0" title="文件发送记录" class="layui-icon layui-icon-time"
|
||||
<i v-show="sendFileRecoderHistoryList.length > 0" title="文件发送记录" class="layui-icon layui-icon-time"
|
||||
@click="clickSendFileHistory"></i>
|
||||
<i v-show="sendFileHistoryList.length === 0" title="文件发送记录"
|
||||
<i v-show="sendFileRecoderHistoryList.length === 0" title="文件发送记录"
|
||||
class="layui-icon layui-icon-time layui-disabled" @click="clickSendFileHistory"></i>
|
||||
<span v-show="sendFileHistoryList.length > 0" style="left: 20px;"
|
||||
<span v-show="sendFileRecoderHistoryList.length > 0" style="left: 20px;"
|
||||
class="layui-badge tl-rtc-file-msg-dot layui-anim layui-anim-rotate layui-anim-loop">
|
||||
{{Math.min(sendFileHistoryList.length, 99)}}
|
||||
{{Math.min(sendFileRecoderHistoryList.length, 99)}}
|
||||
</span>
|
||||
<i v-show="receiveFileList.length > 0" title="接收文件" class="layui-icon layui-icon-print"
|
||||
<i v-show="receiveFileRecoderList.length > 0" title="接收文件" class="layui-icon layui-icon-print"
|
||||
@click="clickReceiveFile"></i>
|
||||
<i v-show="receiveFileList.length === 0" title="接收文件"
|
||||
<i v-show="receiveFileRecoderList.length === 0" title="接收文件"
|
||||
class="layui-icon layui-icon-print layui-disabled" @click="clickReceiveFile"></i>
|
||||
<span v-show="receiveFileList.length > 0"
|
||||
<span v-show="receiveFileRecoderList.length > 0"
|
||||
class="layui-badge tl-rtc-file-msg-dot layui-anim layui-anim-rotate layui-anim-loop">
|
||||
{{Math.min(receiveFileList.length, 99)}}
|
||||
{{Math.min(receiveFileRecoderList.length, 99)}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -383,8 +434,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="tl-rtc-file-user-body-right">
|
||||
<i title="发送文件" @click="sendFileToSingle" class="layui-icon layui-icon-release"></i>
|
||||
<i title="发送文本" @click="sendChatToSingle" class="layui-icon layui-icon-reply-fill"></i>
|
||||
<i title="发送文本" @click="startChatRoomSingle(remote)" class="layui-icon layui-icon-reply-fill"></i>
|
||||
<span v-show="remote.receiveChatRoomSingleList.length > 0" style="right: -7px;"
|
||||
class="layui-badge tl-rtc-file-msg-dot layui-anim layui-anim-rotate layui-anim-loop">
|
||||
{{Math.min(remote.receiveChatRoomSingleList.length, 99)}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -415,36 +468,36 @@
|
||||
</div>
|
||||
|
||||
<div v-show="socketId === 0" class="tl-rtc-file-receive-list-icon">
|
||||
<i v-show="receiveFileList.length > 0" title="文件箱"
|
||||
<i v-show="receiveFileRecoderList.length > 0" title="文件箱"
|
||||
class="layui-icon layui-icon-print tl-rtc-file-receive-list-icon" @click="clickReceiveFile"></i>
|
||||
<i v-show="receiveFileList.length === 0" title="文件箱"
|
||||
<i v-show="receiveFileRecoderList.length === 0" title="文件箱"
|
||||
class="layui-icon layui-icon-print tl-rtc-file-receive-list-icon layui-disabled"
|
||||
@click="clickReceiveFile"></i>
|
||||
<span v-show="receiveFileList.length > 0" style="top: -40px; right: 0px;"
|
||||
<span v-show="receiveFileRecoderList.length > 0" style="top: -40px; right: 0px;"
|
||||
class="layui-badge tl-rtc-file-msg-dot layui-anim layui-anim-rotate layui-anim-loop">
|
||||
{{Math.min(receiveFileList.length, 99)}}
|
||||
{{Math.min(receiveFileRecoderList.length, 99)}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 待发送文件列表 -->
|
||||
<div id="send-file-list" class="tl-rtc-file-mask-send-file-list"
|
||||
<div id="send-file-list" :class="isMediaing? 'isMediaing': '' " class="tl-rtc-file-mask-send-file-list"
|
||||
:style="{top: sendFileMaskHeightNum + '%'}">
|
||||
<div class="layui-card" style="border-radius: 15px;">
|
||||
<div class="layui-card-header">
|
||||
待发送({{chooseFileList.length}})- 共{{Object.keys(remoteMap).length}}人 - 共需发送{{sendFileList.length}}次
|
||||
待发送({{chooseFileList.length}})- 共{{Object.keys(remoteMap).length}}人 - 共需发送{{sendFileRecoderList.length}}次
|
||||
<i @click="clickSendFile" class="layui-icon layui-icon-close"
|
||||
style="cursor: pointer; right: 10px;position: absolute;"></i>
|
||||
</div>
|
||||
<div class="layui-upload-drag tl-rtc-file-choose-file-list" id="chooseFileList">
|
||||
<i class="layui-icon" style="color:black;"></i>
|
||||
<i class="layui-icon layui-icon-upload" style="color:black;"></i>
|
||||
<p style="color: #00000087; font-weight: bold;">点击选取文件,或将文件拖拽到此处,支持多文件拖拽发送,重新选择文件后将覆盖之前选取的文件</p>
|
||||
</div>
|
||||
|
||||
<div class="layui-row tl-rtc-file-send-list-all"
|
||||
:style="{height: sendFileListHeight+'px',overflowY: (sendFileList.length > 1 ? 'scroll' : 'none') }">
|
||||
<div class="layui-col-xs12 tl-rtc-file-send-list send-file-item" v-for="file, index in sendFileList" :id="'send-file-item'+index">
|
||||
<div class="tl-rtc-file-send" :style="{'--progress': file.process + '%'}">
|
||||
:style="{height: sendFileRecoderHeight+'px',overflowY: (sendFileRecoderList.length > 1 ? 'scroll' : 'none') }">
|
||||
<div class="layui-col-xs12 tl-rtc-file-send-list send-file-item" v-for="file, index in sendFileRecoderList" :id="'send-file-item'+index">
|
||||
<div class="tl-rtc-file-send" :style="{'--progress': file.progress + '%'}">
|
||||
<div class="tl-rtc-file-send-body">
|
||||
<svg v-if="typeInArr(['image','png','jpg','webp','gif','jpeg','svg'], file.type)"
|
||||
viewBox="0 0 1426 1024" p-id="20575" width="28" height="28">
|
||||
@@ -538,28 +591,63 @@
|
||||
名称: {{file.name}}, 类型: {{file.type === '' ? '未知类型' : file.type}}, 大小: {{getFileSizeStr(file.size)}}
|
||||
</b>
|
||||
<b class="tl-rtc-file-send-body-left-id">
|
||||
发送给: {{file.id}} - {{file.nickName}} - {{file.process}}% - {{file.cost}}s
|
||||
发送给: {{file.nickName}} - {{file.id}} - {{file.progress}}% - {{file.cost}}s
|
||||
</b>
|
||||
<b class="tl-rtc-file-send-body-left-icon">
|
||||
<a v-show="file.done" title="已发送">
|
||||
<i class="layui-icon layui-icon-release layui-disabled"></i>
|
||||
<a v-show="!file.done && file.progress > 0" title="发送中">
|
||||
<i class="layui-icon layui-disabled layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i>
|
||||
<span class="layui-disabled" style="top: -2px; margin-right: 5px; left: -5px; position: relative;">[发送中]</span>
|
||||
</a>
|
||||
|
||||
<a v-show="!file.done && file.progress === 0 && !isSending" title="单独发送" @click="sendFileToSingle(file)" >
|
||||
<i class="layui-icon layui-icon-release"></i>
|
||||
<span style="top: -2px; margin-right: 5px; left: -5px; position: relative;">[发送]</span>
|
||||
</a>
|
||||
|
||||
<a v-show="!file.done" title="单独发送" @click="initSendFileToSingle" >
|
||||
<i class="layui-icon layui-icon-release"></i>
|
||||
<span style="top: -2px; margin-right: 5px; left: -5px; position: relative;">[发送]</span>
|
||||
<a v-show="!file.done && file.progress === 0 && isSending" title="单独发送">
|
||||
<i class="layui-icon layui-icon-release layui-disabled"></i>
|
||||
<span class="layui-disabled" style="top: -2px; margin-right: 5px; left: -5px; position: relative;">[发送]</span>
|
||||
</a>
|
||||
|
||||
<a v-show="file.done" title="已发送">
|
||||
<i class="layui-icon layui-icon-release layui-disabled"></i>
|
||||
<span class="layui-disabled" style="top: -2px; margin-right: 5px; left: -5px; position: relative;">[已发送]</span>
|
||||
</a>
|
||||
|
||||
<a title="预览文件" @click="previewSendFile(file.index)">
|
||||
<i class="layui-icon layui-icon-camera" style="font-size: 18px;"></i>
|
||||
<span style="top: -2px; margin-right: 5px; left: -5px; position: relative;">[预览]</span>
|
||||
</a>
|
||||
|
||||
<a v-show="file.upload === 'wait'" title="暂存文件" @click="prepareCodeFile(file)">
|
||||
<i class="layui-icon layui-icon-upload-circle" style="font-size: 15px;"></i>
|
||||
<span style="top: -2px; margin-right: 5px; left: -5px; position: relative;">[暂存]</span>
|
||||
</a>
|
||||
|
||||
<a v-show="file.upload === 'uploading'" title="暂存中">
|
||||
<i class="layui-icon layui-disabled layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop" style="font-size: 15px;"></i>
|
||||
<span class="layui-disabled" style="top: -2px; margin-right: 5px; left: -5px; position: relative;">[暂存中]</span>
|
||||
</a>
|
||||
|
||||
<a v-show="file.upload === 'fail'" title="暂存失败">
|
||||
<i class="layui-icon layui-icon-close-fill layui-disabled" style="font-size: 15px;"></i>
|
||||
<span class="layui-disabled" style="top: -2px; margin-right: 5px; left: -5px; position: relative;">[暂存失败]</span>
|
||||
</a>
|
||||
|
||||
<a v-show="file.upload === 'done'" title="已暂存">
|
||||
<i class="layui-icon layui-icon-ok-circle layui-disabled" style="font-size: 15px;"></i>
|
||||
<span class="layui-disabled" style="top: -2px; margin-right: 5px; left: -5px; position: relative;">[已暂存]</span>
|
||||
</a>
|
||||
|
||||
<a v-show="file.upload === 'done'" title="查看取件码" @click="getCodeFileCode(file)">
|
||||
<i class="layui-icon layui-icon-share" style="font-size: 15px;"></i>
|
||||
<span style="top: -2px; margin-right: 5px; left: -5px; position: relative;">[取件码]</span>
|
||||
</a>
|
||||
</b>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tl-rtc-file-send-body-right">
|
||||
<i v-show="file.process === 0 || file.process === 100"
|
||||
<i v-show="file.progress === 0 || file.progress === 100"
|
||||
class="layui-icon layui-icon-close" @click="deleteSendFile(index)"
|
||||
style="top: -26px;"></i>
|
||||
</div>
|
||||
@@ -570,23 +658,27 @@
|
||||
<!-- 一键发送 -->
|
||||
<div>
|
||||
<div v-show="canSendFile">
|
||||
<button class="tl-rtc-file-send-file-list-btn" @click="initSendFile">
|
||||
<button v-if="!isSending && !isSendAllWaiting" class="tl-rtc-file-send-file-list-btn" @click="initSendFile">
|
||||
<i class="layui-icon layui-icon-release"></i>
|
||||
<div>一键发送</div>
|
||||
</button>
|
||||
<button v-else class="tl-rtc-file-send-file-list-btn layui-disabled">
|
||||
<i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i>
|
||||
<div>发送中...</div>
|
||||
</button>
|
||||
</div>
|
||||
<div v-show="sendFileHistoryList.length > 0">
|
||||
<div v-show="sendFileRecoderHistoryList.length > 0">
|
||||
<button class="tl-rtc-file-send-file-history-list-btn" @click="clickSendFileHistory">
|
||||
<i class="layui-icon layui-icon-time"></i>
|
||||
<div>发送记录</div>
|
||||
<span style="top:0;right: 0;" class="layui-badge tl-rtc-file-msg-dot layui-anim layui-anim-rotate layui-anim-loop">
|
||||
{{Math.min(sendFileHistoryList.length, 99)}}
|
||||
{{Math.min(sendFileRecoderHistoryList.length, 99)}}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div v-show="chooseFileList.length > 0">
|
||||
<button class="tl-rtc-file-send-file-choose-list-btn" @click="clickChooseFile" :style="{
|
||||
bottom: sendFileHistoryList.length > 0 ? '14%' : '2%'
|
||||
bottom: sendFileRecoderHistoryList.length > 0 ? '14%' : '2%'
|
||||
}">
|
||||
<i class="layui-icon layui-icon-templeate-1"></i>
|
||||
<div>已选文件</div>
|
||||
@@ -599,7 +691,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 已选文件列表 -->
|
||||
<div id="send-file-list-choose" class="tl-rtc-file-mask-send-file-list"
|
||||
<div id="send-file-list-choose" :class="isMediaing? 'isMediaing': '' " class="tl-rtc-file-mask-send-file-list"
|
||||
:style="{top: chooseFileMaskHeightNum + '%'}">
|
||||
<div class="layui-card" style="border-radius: 15px;">
|
||||
<div class="layui-card-header">
|
||||
@@ -608,9 +700,9 @@
|
||||
style="cursor: pointer; right: 10px;position: absolute;"></i>
|
||||
</div>
|
||||
<div class="layui-row tl-rtc-file-send-list-all"
|
||||
:style="{height: chooseFileListHeight+'px',overflowY: (chooseFileList.length > 1 ? 'scroll' : 'none') }">
|
||||
:style="{height: chooseFileHeight+'px',overflowY: (chooseFileList.length > 1 ? 'scroll' : 'none') }">
|
||||
<div class="layui-col-xs12 tl-rtc-file-send-list" v-for="file, index in chooseFileList">
|
||||
<div class="tl-rtc-file-send" :style="{'--progress': file.process + '%'}">
|
||||
<div class="tl-rtc-file-send" :style="{'--progress': file.progress + '%'}">
|
||||
<div class="tl-rtc-file-send-body">
|
||||
<svg v-if="typeInArr(['image','png','jpg','webp','gif','jpeg','svg'], file.type)"
|
||||
viewBox="0 0 1426 1024" p-id="20575" width="28" height="28">
|
||||
@@ -712,18 +804,18 @@
|
||||
</div>
|
||||
|
||||
<!-- 发送文件历史记录列表 -->
|
||||
<div id="send-file-list-history" class="tl-rtc-file-mask-send-file-list"
|
||||
<div id="send-file-list-history" :class="isMediaing? 'isMediaing': '' " class="tl-rtc-file-mask-send-file-list"
|
||||
:style="{top: sendFileHistoryMaskHeightNum + '%'}">
|
||||
<div class="layui-card" style="border-radius: 15px;">
|
||||
<div class="layui-card-header">
|
||||
文件发送历史记录 - 共发送({{sendFileHistoryList.length}})次
|
||||
文件发送历史记录 - 共发送({{sendFileRecoderHistoryList.length}})次
|
||||
<i @click="clickSendFileHistory" class="layui-icon layui-icon-close"
|
||||
style="cursor: pointer; right: 10px;position: absolute;"></i>
|
||||
</div>
|
||||
<div class="layui-row tl-rtc-file-send-list-all"
|
||||
:style="{height: sendFileHistoryListHeight+'px',overflowY: (sendFileHistoryList.length > 1 ? 'scroll' : 'none') }">
|
||||
<div class="layui-col-xs12 tl-rtc-file-send-list" v-for="file, index in sendFileHistoryList">
|
||||
<div class="tl-rtc-file-send" :style="{'--progress': file.process + '%'}">
|
||||
:style="{height: sendFileRecoderHistoryHeight+'px',overflowY: (sendFileRecoderHistoryList.length > 1 ? 'scroll' : 'none') }">
|
||||
<div class="layui-col-xs12 tl-rtc-file-send-list" v-for="file, index in sendFileRecoderHistoryList">
|
||||
<div class="tl-rtc-file-send" :style="{'--progress': file.progress + '%'}">
|
||||
<div class="tl-rtc-file-send-body">
|
||||
<svg v-if="typeInArr(['image','png','jpg','webp','gif','jpeg','svg'], file.type)"
|
||||
viewBox="0 0 1426 1024" p-id="20575" width="28" height="28">
|
||||
@@ -817,7 +909,7 @@
|
||||
名称: {{file.name}}, 类型: {{file.type === '' ? '未知类型' : file.type}}, 大小: {{getFileSizeStr(file.size)}}
|
||||
</b>
|
||||
<b class="tl-rtc-file-send-body-left-id">
|
||||
发送给: {{file.id}} - {{file.nickName}} - {{file.process}}% - {{file.cost}}s
|
||||
发送给: {{file.nickName}} - {{file.id}} - {{file.progress}}% - {{file.cost}}s
|
||||
</b>
|
||||
</div>
|
||||
</div>
|
||||
@@ -828,18 +920,18 @@
|
||||
</div>
|
||||
|
||||
<!-- 已接收文件列表 -->
|
||||
<div id="receive-file-list" class="tl-rtc-file-mask-send-file-list"
|
||||
<div id="receive-file-list" :class="isMediaing? 'isMediaing': '' " class="tl-rtc-file-mask-send-file-list"
|
||||
:style="{top: receiveFileMaskHeightNum + '%'}">
|
||||
<div class="layui-card" style="border-radius: 15px;">
|
||||
<div class="layui-card-header">
|
||||
已接收文件列表 - 共接收{{receiveFileList.length}}个文件
|
||||
已接收文件列表 - 共接收{{receiveFileRecoderList.length}}个文件
|
||||
<i @click="clickReceiveFile" class="layui-icon layui-icon-close"
|
||||
style="cursor: pointer; right: 10px;position: absolute;"></i>
|
||||
</div>
|
||||
<div class="layui-row tl-rtc-file-send-list-all"
|
||||
:style="{height: receiveFileListHeight+'px',overflowY: (receiveFileList.length > 1 ? 'scroll' : 'none')}">
|
||||
<div class="layui-col-xs12 tl-rtc-file-send-list" v-for="file in receiveFileList">
|
||||
<div class="tl-rtc-file-send" :style="{'--progress': file.process + '%'}">
|
||||
:style="{height: receiveFileHeight+'px',overflowY: (receiveFileRecoderList.length > 1 ? 'scroll' : 'none')}">
|
||||
<div class="layui-col-xs12 tl-rtc-file-send-list" v-for="file in receiveFileRecoderList">
|
||||
<div class="tl-rtc-file-send" :style="{'--progress': file.progress + '%'}">
|
||||
<div class="tl-rtc-file-send-body">
|
||||
<svg v-if="typeInArr(['image','png','jpg','webp','gif','jpeg','svg'], file.type)"
|
||||
viewBox="0 0 1426 1024" p-id="20575" width="28" height="28">
|
||||
@@ -932,7 +1024,7 @@
|
||||
名称: {{file.name}}, 类型: {{file.type === '' ? '未知类型' : file.type}}, 大小: {{getFileSizeStr(file.size)}}
|
||||
</b>
|
||||
<b class="tl-rtc-file-send-body-left-id">
|
||||
文件来自: {{file.id}} - {{file.nickName}} - {{file.process}}% - {{file.cost}}s
|
||||
文件来自: {{file.nickName}} - {{file.id}} - {{file.progress}}% - {{file.cost}}s
|
||||
</b>
|
||||
<b class="tl-rtc-file-send-body-left-icon">
|
||||
<a :href="file.href" :download="file.name">
|
||||
@@ -947,7 +1039,125 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="tl-rtc-file-send-body-right">
|
||||
<i class="layui-icon layui-icon-close" style="top: -26px;"></i>
|
||||
<!-- <i class="layui-icon layui-icon-close" style="top: -26px;"></i> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 暂存文件列表 -->
|
||||
<div id="code-file-list" :class="isMediaing? 'isMediaing': '' " class="tl-rtc-file-mask-send-file-list"
|
||||
:style="{top: codeFileMaskHeightNum + '%'}">
|
||||
<div class="layui-card" style="border-radius: 15px;">
|
||||
<div class="layui-card-header">
|
||||
总共收到暂存文件 - ({{receiveCodeFileList.length}}) 个
|
||||
<i @click="clickCodeFile()" class="layui-icon layui-icon-close"
|
||||
style="cursor: pointer; right: 10px;position: absolute;"></i>
|
||||
</div>
|
||||
|
||||
<div class="layui-row tl-rtc-file-send-list-all"
|
||||
:style="{height: codeFileHeight+'px',overflowY: (receiveCodeFileList.length > 1 ? 'scroll' : 'none') }">
|
||||
<div class="layui-col-xs12 tl-rtc-file-send-list" v-for="file, index in receiveCodeFileList">
|
||||
<div class="tl-rtc-file-send">
|
||||
<div class="tl-rtc-file-send-body">
|
||||
<svg v-if="typeInArr(['image','png','jpg','webp','gif','jpeg','svg'], file.type)"
|
||||
viewBox="0 0 1426 1024" p-id="20575" width="28" height="28">
|
||||
<path
|
||||
d="M241.01111082 62h960.00000028c65.99999971 0 119.99999971 54 119.99999972 119.99999971v660.00000058c0 65.99999971-54 119.99999971-119.99999972 119.99999971h-960.00000028c-65.99999971 0-119.99999971-54-119.99999972-119.99999971V181.99999971c0-65.99999971 54-119.99999971 119.99999972-119.99999971z"
|
||||
fill="#2F77F1" p-id="20576"></path>
|
||||
<path d="M331.01111082 271.99999971m-90 0a90 90 0 1 0 180 0 90 90 0 1 0-180 0Z"
|
||||
fill="#AFFCFE" p-id="20577"></path>
|
||||
<path
|
||||
d="M1321.01111082 748.99999971v-74.99999971L1052.5111111 446.00000029c-11.99999971-9-29.99999971-9-38.99999971 1.49999942L736.01111082 723.5 503.5111111 566c-7.49999971-7.49999971-18-10.50000029-28.50000028-7.49999971L131.51111139 737c-4.5 1.50000029-7.49999971 2.99999971-10.50000029 4.5v49.5c6.00000029 4.5 15.00000029 7.49999971 24.00000029 4.5l325.49999943-173.99999971 243 166.5c6.00000029 6.00000029 13.5 9 21.00000057 9s15.00000029-2.99999971 20.99999971-9l279-279 277.49999972 235.49999942c2.99999971 2.99999971 6.00000029 4.5 9 4.5z"
|
||||
fill="#AFFCFE" p-id="20578"></path>
|
||||
</svg>
|
||||
<svg v-else-if="typeInArr(['text','json'], file.type)" viewBox="0 0 1024 1024"
|
||||
p-id="17341" width="28" height="28">
|
||||
<path
|
||||
d="M967.111111 281.6V910.222222c0 62.862222-50.915556 113.777778-113.777778 113.777778H170.666667c-62.862222 0-113.777778-50.915556-113.777778-113.777778V113.777778c0-62.862222 50.915556-113.777778 113.777778-113.777778h514.844444L967.111111 281.6z"
|
||||
fill="#406bd3" p-id="17342"></path>
|
||||
<path
|
||||
d="M685.511111 167.822222V0L967.111111 281.6H799.288889c-62.862222 0-113.777778-50.915556-113.777778-113.777778"
|
||||
fill="#4B80CB" p-id="17343"></path>
|
||||
<path
|
||||
d="M344.177778 485.575111h312.888889V426.666667h-312.888889zM471.153778 770.019556h58.908444v-284.444445h-58.908444z"
|
||||
fill="#FFFFFF" p-id="17344"></path>
|
||||
</svg>
|
||||
<svg v-else-if="typeInArr(['video','mp4','mpeg','audio','wav','quicktime'], file.type)"
|
||||
viewBox="0 0 1241 1024" p-id="2500" width="28" height="28">
|
||||
<path
|
||||
d="M193.84646453 62h872.72727276c60.00000029 0 109.09090898 49.09090869 109.09090899 109.09090898v681.81818204c0 60.00000029-49.09090869 109.09090898-109.09090899 109.09090898H193.84646453c-60.00000029 0-109.09090898-49.09090869-109.09090898-109.09090898V171.09090898c0-60.00000029 49.09090869-109.09090898 109.09090898-109.09090898z"
|
||||
fill="#406bd3" p-id="2501"></path>
|
||||
<path
|
||||
d="M84.75555555 225.63636348h1090.90909072v54.54545449H84.75555555v-54.5454545z m673.63636377 340.90909101c9.5454545 5.4545458 15.00000029 16.36363653 15.0000003 27.27272725s-5.4545458 21.81818145-15.0000003 27.27272724L589.30101004 726.09090928c-9.5454545 5.4545458-21.81818145 5.4545458-31.36363594-1e-8-9.5454545-5.4545458-16.36363653-16.36363653-15.00000029-27.27272724V490.18181855c0-10.90909073 5.4545458-21.81818145 15.00000029-27.27272724 9.5454545-5.4545458 21.81818145-5.4545458 31.36363594 0L758.39191932 566.54545449z"
|
||||
fill="#AFFCFE" p-id="2502"></path>
|
||||
</svg>
|
||||
<svg v-else-if="typeInArr(['zip','7z','rar','compressed'], file.type)"
|
||||
viewBox="0 0 1024 1024" p-id="6130" width="28" height="28">
|
||||
<path
|
||||
d="M590.222222 73.955556L859.022222 342.254933V876.088889c0 37.700267-30.5664 68.266667-68.266666 68.266667H233.244444c-37.700267 0-68.266667-30.5664-68.266666-68.266667V142.222222c0-37.700267 30.5664-68.266667 68.266666-68.266666h356.977778z m-11.764622 28.444444H233.244444a39.822222 39.822222 0 0 0-39.799466 38.456889L193.422222 142.222222v733.866667a39.822222 39.822222 0 0 0 38.456889 39.799467L233.244444 915.911111h557.511112a39.822222 39.822222 0 0 0 39.799466-38.456889L830.577778 876.088889V354.053689L578.4576 102.4z"
|
||||
fill="#406bd3" p-id="6131"></path>
|
||||
<path
|
||||
d="M854.755556 370.648178h-215.1424c-45.528178 0-82.551467-36.431644-83.5072-81.737956l-0.017067-1.792V73.955556h28.444444v213.162666c0 29.895111 23.819378 54.232178 53.515378 55.062756l1.564445 0.022755h215.1424v28.444445z"
|
||||
fill="#9254DE" p-id="6132"></path>
|
||||
<path
|
||||
d="M56.888889 489.244444m28.444444 0l853.333334 0q28.444444 0 28.444444 28.444445l0 284.444444q0 28.444444-28.444444 28.444445l-853.333334 0q-28.444444 0-28.444444-28.444445l0-284.444444q0-28.444444 28.444444-28.444445Z"
|
||||
fill="#9254DE" p-id="6133"></path>
|
||||
<path
|
||||
d="M452.124444 756.622222v-38.4h-82.944l82.176-124.672v-27.648H320.796444v38.144h74.24l-82.176 124.928V756.622222h139.264z m77.056 0V565.902222h-45.824V756.622222h45.824z m89.6 0v-63.232h22.272c40.448 0 75.264-19.968 75.264-65.28 0-47.104-34.56-62.208-76.288-62.208h-67.072V756.622222h45.824z m19.968-99.328h-19.968v-55.04h18.688c22.016 0 34.304 6.656 34.304 25.856 0 18.688-10.752 29.184-33.024 29.184z"
|
||||
fill="#FFFFFF" p-id="6134"></path>
|
||||
</svg>
|
||||
<svg v-else-if="typeInArr(['pdf'], file.type)" viewBox="0 0 1024 1024" p-id="15904"
|
||||
width="28" height="28">
|
||||
<path
|
||||
d="M581.290667 0a42.666667 42.666667 0 0 1 28.117333 10.538667l314.709333 275.370666a42.666667 42.666667 0 0 1 14.549334 32.128V469.333333a85.333333 85.333333 0 0 1 85.333333 85.333334v213.333333a85.333333 85.333333 0 0 1-85.333333 85.333333v42.666667a128 128 0 0 1-120.490667 127.786667L810.666667 1024H213.333333a128 128 0 0 1-127.786666-120.490667L85.333333 896v-42.666667a85.333333 85.333333 0 0 1-85.333333-85.333333v-213.333333a85.333333 85.333333 0 0 1 85.333333-85.333334V128A128 128 0 0 1 205.824 0.213333L213.333333 0h367.957334zM853.333333 853.333333H170.666667v42.666667a42.666667 42.666667 0 0 0 37.674666 42.368L213.333333 938.666667h597.333334a42.666667 42.666667 0 0 0 42.368-37.674667L853.333333 896v-42.666667z m-338.432-316.842666h-100.266666V810.666667h100.266666c44.501333 0 77.952-12.288 100.992-36.864 21.845333-23.424 33.024-56.832 33.024-100.224 0-43.776-11.136-77.184-33.024-100.224-23.04-24.576-56.490667-36.864-100.992-36.864z m338.432 0h-162.218666V810.666667h44.928v-121.344H853.333333v-38.4h-117.248v-76.032H853.333333v-38.4z m-576.512 0H170.666667V810.666667h37.418666v-105.216H276.053333c66.816 0 100.224-28.416 100.224-84.864 0-56.064-33.450667-84.096-99.498666-84.096z m229.589334 38.4c34.218667 0 59.136 7.68 74.88 23.424 15.36 15.36 23.04 40.704 23.04 75.264 0 33.792-7.68 58.752-23.04 74.88-15.744 15.744-40.704 23.808-74.88 23.808h-46.848v-197.376h46.848z m-233.045334 0c19.541333 0 34.133333 3.456 43.349334 10.752 9.216 6.912 14.208 18.432 14.208 34.944 0 16.512-4.565333 28.416-13.824 35.712-9.216 6.912-23.808 10.752-43.776 10.752h-65.28v-92.16h65.28zM512 85.333333H213.333333a42.666667 42.666667 0 0 0-42.368 37.674667L170.666667 128v341.333333h682.666666V384h-213.333333a128 128 0 0 1-127.146667-113.066667l-0.64-7.424L512 256V85.333333z m85.333333 18.474667V256a42.666667 42.666667 0 0 0 37.674667 42.368L640 298.666667h167.338667L597.333333 103.808z"
|
||||
fill="#008df0" p-id="15905"></path>
|
||||
</svg>
|
||||
<svg v-else-if="typeInArr(['excel','word','powerpoint','sheet'], file.type)"
|
||||
viewBox="0 0 1024 1024" p-id="7241" width="28" height="28">
|
||||
<path
|
||||
d="M145.6 0C100.8 0 64 35.2 64 80v862.4C64 987.2 100.8 1024 145.6 1024h732.8c44.8 0 81.6-36.8 81.6-81.6V324.8L657.6 0h-512z"
|
||||
fill="#406bd3" p-id="7242"></path>
|
||||
<path d="M960 326.4v16H755.2s-100.8-20.8-99.2-108.8c0 0 4.8 92.8 97.6 92.8H960z"
|
||||
fill="#0F93D0" p-id="7243"></path>
|
||||
<path d="M657.6 0v233.6c0 25.6 17.6 92.8 97.6 92.8H960L657.6 0z" fill="#FFFFFF"
|
||||
opacity=".5" p-id="7244"></path>
|
||||
<path
|
||||
d="M291.2 862.4h-48c-9.6 0-17.6-8-17.6-17.6v-158.4c0-9.6 8-16 17.6-16h48c60.8 0 99.2 41.6 99.2 96s-38.4 96-99.2 96z m0-171.2h-41.6v148.8h41.6c48 0 75.2-33.6 75.2-73.6 0-41.6-27.2-75.2-75.2-75.2z m232 174.4c-57.6 0-96-43.2-96-99.2s38.4-99.2 96-99.2c56 0 94.4 41.6 94.4 99.2 0 56-38.4 99.2-94.4 99.2z m0-177.6c-43.2 0-70.4 33.6-70.4 78.4 0 44.8 27.2 76.8 70.4 76.8 41.6 0 70.4-32 70.4-76.8S564.8 688 523.2 688z m294.4 6.4c1.6 1.6 3.2 4.8 3.2 8 0 6.4-4.8 11.2-11.2 11.2-3.2 0-6.4-1.6-8-3.2-11.2-14.4-30.4-22.4-48-22.4-41.6 0-73.6 32-73.6 78.4 0 44.8 32 76.8 73.6 76.8 17.6 0 35.2-6.4 48-20.8 1.6-3.2 4.8-4.8 8-4.8 6.4 0 11.2 6.4 11.2 12.8 0 3.2-1.6 4.8-3.2 8-14.4 16-35.2 27.2-64 27.2-56 0-99.2-40-99.2-99.2s43.2-99.2 99.2-99.2c28.8 0 49.6 11.2 64 27.2z"
|
||||
fill="#FFFFFF" p-id="7245"></path>
|
||||
</svg>
|
||||
<svg v-else-if="typeInArr(['javascript','css','java','php','c++','python','html'], file.type)"
|
||||
viewBox="0 0 1024 1024" p-id="8268" width="28" height="28">
|
||||
<path
|
||||
d="M921.6 0H102.4a102.4 102.4 0 0 0-102.4 102.4v819.2a102.4 102.4 0 0 0 102.4 102.4h819.2a102.4 102.4 0 0 0 102.4-102.4V102.4a102.4 102.4 0 0 0-102.4-102.4zM341.504 636.416a22.016 22.016 0 1 1-31.232 31.232l-140.8-140.8a22.016 22.016 0 0 1 0-31.232l140.8-140.8a22.016 22.016 0 0 1 31.232 0 22.528 22.528 0 0 1 0 31.744L216.576 512z m329.728-390.656L392.704 801.28a23.04 23.04 0 0 1-31.744 8.704 23.04 23.04 0 0 1-8.192-31.744l278.016-556.032a23.552 23.552 0 0 1 40.448 23.552z m183.296 281.088L713.728 665.6a22.528 22.528 0 0 1-31.744 0 22.016 22.016 0 0 1 0-31.232L807.424 512l-125.44-125.44a22.528 22.528 0 1 1 31.744-31.744l140.8 140.8a22.016 22.016 0 0 1 0 31.232z"
|
||||
fill="#406bd3" p-id="8269"></path>
|
||||
</svg>
|
||||
<svg v-else viewBox="0 0 1031 1024" p-id="3200" width="28" height="28">
|
||||
<path
|
||||
d="M323.166237 0a156.541149 156.541149 0 0 0-156.541149 156.541149v648.253224a156.541149 156.541149 0 0 0 156.541149 156.541149h488.110668a156.541149 156.541149 0 0 0 156.541149-156.541149v-482.588511A59.303165 59.303165 0 0 0 950.531301 279.709261L687.868699 17.526846a59.543259 59.543259 0 0 0-42.016413-17.526846z"
|
||||
fill="#406bd3" p-id="3201"></path>
|
||||
<path
|
||||
d="M950.531301 279.709261L687.868699 17.526846a58.102696 58.102696 0 0 0-30.491911-16.086283 5.762251 5.762251 0 0 0-6.722626 6.002344V135.652989a182.951465 182.951465 0 0 0 182.951465 182.951466H960.375147a6.002345 6.002345 0 0 0 5.76225-6.96272A56.902227 56.902227 0 0 0 950.531301 279.709261z"
|
||||
fill="#2A58D8" p-id="3202"></path>
|
||||
<path
|
||||
d="M840.328253 288.112544h116.925674a51.860258 51.860258 0 0 0-6.722626-8.403283L687.868699 17.526846a66.746073 66.746073 0 0 0-7.923095-6.482532v116.68558A160.382649 160.382649 0 0 0 840.328253 288.112544z"
|
||||
fill="#C6E1FF" p-id="3203"></path>
|
||||
<path
|
||||
d="M412.481125 459.779601A160.142556 160.142556 0 0 1 456.178195 341.893552a155.820868 155.820868 0 0 1 116.205392-43.216881 152.939742 152.939742 0 0 1 105.161079 35.773974 120.046893 120.046893 0 0 1 40.095662 93.636577q0 58.822978-78.750762 123.408206a111.163423 111.163423 0 0 0-48.018757 87.634232v12.244783H535.409144v-6.482532a195.676436 195.676436 0 0 1 9.123564-69.867292 164.944431 164.944431 0 0 1 42.016413-50.899883l22.328722-19.68769A112.363892 112.363892 0 0 0 654.255569 423.765533a70.347479 70.347479 0 0 0-24.009379-55.461664 88.594607 88.594607 0 0 0-61.464009-21.608441q-96.037515 0-97.237984 112.363892z m196.876905 283.070575a41.296131 41.296131 0 0 1-40.095662 42.736694h-12.965064a41.296131 41.296131 0 0 1-39.855569-42.736694 41.056038 41.056038 0 0 1 39.855569-42.4966h12.965064a41.296131 41.296131 0 0 1 40.095662 42.4966z"
|
||||
fill="#F5F6FA" p-id="3204"></path>
|
||||
</svg>
|
||||
|
||||
<div class="tl-rtc-file-send-body-left">
|
||||
<b class="tl-rtc-file-send-body-left-nick">
|
||||
名称: {{file.name}} - 类型: {{file.type === '' ? '未知类型' : file.type}} - 大小: {{getFileSizeStr(file.size)}} - 取件码: {{file.code}}
|
||||
</b>
|
||||
<b class="tl-rtc-file-send-body-left-id">
|
||||
来自: {{file.fromRoom}} - {{file.fromNickName}} - 时间: {{file.createTime}}
|
||||
<a :href="file.download" style="color:rgb(117 124 204); font-weight: bold;margin-left: 5px;"> [点我下载] </a>
|
||||
</b>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -956,7 +1166,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 执行日志 -->
|
||||
<div class="tl-rtc-file-mask-log-list" :style="{left: logMaskHeightNum + '%'}">
|
||||
<div id="logMask" class="tl-rtc-file-mask-log-list" :style="{left: logMaskHeightNum + '%'}">
|
||||
<div class="layui-col-sm2" style="width: 100%;">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">
|
||||
@@ -1004,11 +1214,11 @@
|
||||
</div>
|
||||
|
||||
<!-- 音视频 -->
|
||||
<div class="tl-rtc-file-mask-media-list" :style="{left: mediaVideoMaskHeightNum + '%'}">
|
||||
<div id="videoMask" class="tl-rtc-file-mask-media-list" :style="{left: mediaVideoMaskHeightNum + '%'}">
|
||||
<div class="layui-col-sm2" style="width: 100%;">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">
|
||||
音视频通话
|
||||
多人音视频通话
|
||||
<i @click="startVideoShare" class="layui-icon layui-icon-close"
|
||||
style="cursor: pointer; right: 10px;position: absolute;"></i>
|
||||
</div>
|
||||
@@ -1024,11 +1234,11 @@
|
||||
</div>
|
||||
|
||||
<!-- 屏幕共享 -->
|
||||
<div class="tl-rtc-file-mask-media-list" :style="{left: mediaScreenMaskHeightNum + '%'}">
|
||||
<div id="screenMask" class="tl-rtc-file-mask-media-list" :style="{left: mediaScreenMaskHeightNum + '%'}">
|
||||
<div class="layui-col-sm2" style="width: 100%;">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header" style="text-align: left;">
|
||||
屏幕共享
|
||||
多人屏幕共享
|
||||
<i @click="startScreenShare" class="layui-icon layui-icon-close"
|
||||
style="cursor: pointer; right: 10px;position: absolute;"></i>
|
||||
</div>
|
||||
@@ -1043,13 +1253,34 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 直播 -->
|
||||
<div id="liveMask" class="tl-rtc-file-mask-media-list" :style="{left: mediaLiveMaskHeightNum + '%'}">
|
||||
<div class="layui-col-sm2" style="width: 100%;">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header" style="text-align: left;">
|
||||
单人直播间
|
||||
<i @click="startLiveShare" class="layui-icon layui-icon-close"
|
||||
style="cursor: pointer; right: 10px;position: absolute;"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-card">
|
||||
<div :style="{height: logsHeight+'px',overflowY: 'scroll'}">
|
||||
<div class="layui-card-body">
|
||||
<div class="tl-rtc-file-mask-media-container " id="mediaLiveRoomList"> </div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="/js/comm.min.js"></script>
|
||||
<script type="text/javascript" src="/js/videoShare.min.js"></script>
|
||||
<script type="text/javascript" src="/js/screen.min.js"></script>
|
||||
<script type="text/javascript" src="/js/screenShare.min.js"></script>
|
||||
<script type="text/javascript" src="/js/index.min.js"></script>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="js/comm.min.js"></script>
|
||||
<script type="text/javascript" src="js/videoShare.min.js"></script>
|
||||
<script type="text/javascript" src="js/liveShare.min.js"></script>
|
||||
<script type="text/javascript" src="js/screen.min.js"></script>
|
||||
<script type="text/javascript" src="js/screenShare.min.js"></script>
|
||||
<script type="text/javascript" src="js/index.min.js"></script>
|
||||
<script src="static/layui/layui.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -1063,39 +1294,6 @@
|
||||
window.dropdown = layui.dropdown;
|
||||
window.carousel = layui.carousel;
|
||||
window.util = layui.util;
|
||||
|
||||
let alert = window.localStorage.getItem("tl-rtc-file-alert")
|
||||
if (!alert) {
|
||||
layer.open({
|
||||
type: 1
|
||||
, title: false
|
||||
, closeBtn: false
|
||||
, area: '300px;'
|
||||
, shade: 0.8
|
||||
, id: 'layui-info-msg'
|
||||
, btn: ['知道了', "不再提示"]
|
||||
, btnAlign: 'c'
|
||||
, moveType: 1
|
||||
, content: `
|
||||
<div style="padding: 30px; line-height: 22px; background-color: #393D49; color: #fff; font-weight: 300;border-radius:8px;">
|
||||
<div style="text-align: center;line-height: 20px;font-size:12px;word-break: keep-all;">当前项目代码已完整开源,推荐自行搭建
|
||||
<a style="color: #e87171;font-size:15px;font-weight: 800; text-decoration: underline;"
|
||||
href="https://github.com/iamtsm/tl-rtc-file" target="_blank"> 去github点个赞支持下 </a>
|
||||
</div>
|
||||
<div style="text-align: center;line-height: 40px;">1. 双方输入相同房间号加入</div>
|
||||
<div style="text-align: center;line-height: 40px;"><b>* 双方先加入房间再选文件! *</b></div>
|
||||
<div style="text-align: center;line-height: 40px;">2. 双方选择需要的文件发送</div>
|
||||
<div style="text-align: center;line-height: 26px;word-break: keep-all;color: #e87171;">5. 中继服务器配置带宽不高,大约500kb/s ~ 600kb/s,(有需要可 <a style="color: wheat;" target="_blank" href="https://blog.iamtsm.cn">联系我</a> 提高带宽)</div>
|
||||
</div>
|
||||
`
|
||||
, success: function (layero) {
|
||||
|
||||
},
|
||||
btn2: function (index, layero) {
|
||||
window.localStorage.setItem("tl-rtc-file-alert", true)
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
@@ -1,4 +1,15 @@
|
||||
window.tlrtcfile = {
|
||||
getRequestHashArgs : function (key) {
|
||||
let query = decodeURIComponent(window.location.hash.substring(1));
|
||||
let args = query.split("&");
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
let pair = args[i].split("=");
|
||||
if(pair[0] === key){
|
||||
return pair[1];
|
||||
}
|
||||
}
|
||||
return "";
|
||||
},
|
||||
containChinese: function (str) {
|
||||
return /[\u4E00-\u9FA5\uF900-\uFA2D]/.test(str);
|
||||
},
|
||||
@@ -209,6 +220,116 @@ window.tlrtcfile = {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
getWebrtcStats: async function (peerConnection) {
|
||||
if (!peerConnection) {
|
||||
return "RTCPeerConnection is not available";
|
||||
}
|
||||
if (!peerConnection.getStats) {
|
||||
return "RTCStatsReport is not available";
|
||||
}
|
||||
|
||||
let result = { }
|
||||
|
||||
let stats = await peerConnection.getStats(null);
|
||||
|
||||
stats.forEach((report) => {
|
||||
if (!report.type) return;
|
||||
let data = {}
|
||||
Object.keys(report).forEach((statName) => {
|
||||
data[statName] = report[statName]
|
||||
});
|
||||
result[report.type] = {
|
||||
kind : report.kind,
|
||||
data : data
|
||||
}
|
||||
});
|
||||
|
||||
return result
|
||||
},
|
||||
copyTxt: function (id, content) {
|
||||
let that = this;
|
||||
document.querySelector("#" + id).setAttribute("data-clipboard-text", content);
|
||||
var clipboard = new ClipboardJS('#' + id);
|
||||
clipboard.on('success', function (e) {
|
||||
e.clearSelection();
|
||||
if (window.layer) {
|
||||
layer.msg("复制内容成功!")
|
||||
}
|
||||
});
|
||||
},
|
||||
getQrCode : function(id, content){
|
||||
const qrcode = new QRCode(id, {
|
||||
text: content, // 二维码内容
|
||||
width: 300,
|
||||
height: 300,
|
||||
colorDark : "#000000", // 码的颜色
|
||||
colorLight : "#ffffff", // 码的背景色
|
||||
correctLevel : QRCode.CorrectLevel.H // 高度容错
|
||||
});
|
||||
},
|
||||
getOpEventData: function(callback){
|
||||
window.addEventListener('click', function (event) {
|
||||
callback("click", event)
|
||||
})
|
||||
window.addEventListener('contextmenu', function (event) {
|
||||
// event.preventDefault();
|
||||
callback("contextmenu", event)
|
||||
})
|
||||
window.addEventListener('mousemove', function (event) {
|
||||
callback("mousemove", event)
|
||||
})
|
||||
window.addEventListener('mousedown', function () {
|
||||
callback("mousedown", null)
|
||||
})
|
||||
window.addEventListener('mouseup', function() {
|
||||
callback("mouseup", null)
|
||||
})
|
||||
window.addEventListener('wheel', function(event) {
|
||||
callback("wheel", event)
|
||||
})
|
||||
window.addEventListener('keydown', function (event) {
|
||||
callback("keydown", event)
|
||||
})
|
||||
window.addEventListener('keyup', function (event) {
|
||||
callback("keyup", event)
|
||||
})
|
||||
},
|
||||
drawMousePath: function (coordinates) {
|
||||
if (window.layer) {
|
||||
layer.open({
|
||||
type: 1,
|
||||
area: ["80%", "80%"],
|
||||
title: "鼠标路径绘制",
|
||||
content: ` <div id="tl-rtc-file-mouse-draw" style="height: 100%;"> </div> `,
|
||||
success: function (layero, index) {
|
||||
document.querySelector(".layui-layer-content").style.borderRadius = "15px"
|
||||
// 获取 canvas 元素
|
||||
const canvas = document.createElement('canvas');
|
||||
let dom = document.getElementById("tl-rtc-file-mouse-draw");
|
||||
canvas.setAttribute("style","height: 100%; width: 100%;")
|
||||
canvas.height = document.querySelector(".layui-layer-content").clientHeight;
|
||||
canvas.width = document.querySelector(".layui-layer-content").clientWidth;
|
||||
dom.appendChild(canvas);
|
||||
const context = canvas.getContext("2d");
|
||||
|
||||
// 设置画笔样式
|
||||
context.lineWidth = 1;
|
||||
context.strokeStyle = "red";
|
||||
context.fillStyle = "red";
|
||||
|
||||
// 开始绘制路径
|
||||
context.beginPath();
|
||||
context.moveTo(coordinates[0].x, coordinates[0].y);
|
||||
|
||||
for (let i = 1; i < coordinates.length; i++) {
|
||||
context.lineTo(coordinates[i].x, coordinates[i].y);
|
||||
}
|
||||
// 完成路径绘制
|
||||
context.stroke();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
scrollToBottom: function (dom, duration, timeout) {
|
||||
let start = dom.scrollTop;
|
||||
let end = dom.scrollHeight - dom.clientHeight;
|
File diff suppressed because it is too large
Load Diff
155
svr/res/js/liveShare.js
Normal file
155
svr/res/js/liveShare.js
Normal file
@@ -0,0 +1,155 @@
|
||||
var liveShare = new Vue({
|
||||
el: '#liveShareApp',
|
||||
data: function () {
|
||||
return {
|
||||
stream: null,
|
||||
times: 0,
|
||||
interverlId: 0,
|
||||
track: null,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getMediaPlay: function () {
|
||||
let media = null;
|
||||
let constraints = {
|
||||
// 音频轨道
|
||||
audio:true,
|
||||
// 视频轨道
|
||||
video: {
|
||||
// 前后置
|
||||
facingMode: true ? "user" : "environment",
|
||||
// 分辨率
|
||||
width: {
|
||||
ideal : parseInt((document.documentElement.clientWidth - 20) / 2),
|
||||
max : document.documentElement.clientWidth,
|
||||
min : 100
|
||||
},
|
||||
height: {
|
||||
ideal : parseInt((document.documentElement.clientHeight - 20) / 2),
|
||||
max : document.documentElement.clientHeight,
|
||||
min : 100
|
||||
},
|
||||
// 码率
|
||||
frameRate: {
|
||||
ideal: 30,
|
||||
max: 50
|
||||
},
|
||||
// 指定设备
|
||||
// deviceId: "",
|
||||
},
|
||||
};
|
||||
if(window.navigator.mediaDevices && window.navigator.mediaDevices.getUserMedia){
|
||||
media = window.navigator.mediaDevices.getUserMedia(constraints);
|
||||
} else if (window.navigator.mozGetUserMedia) {
|
||||
media = navagator.mozGetUserMedia(constraints);
|
||||
} else if (window.navigator.getUserMedia) {
|
||||
media = window.navigator.getUserMedia(constraints)
|
||||
} else if (window.navigator.webkitGetUserMedia) {
|
||||
media = new Promise((resolve, reject) => {
|
||||
window.navigator.webkitGetUserMedia(constraints, (res) => {
|
||||
resolve(res)
|
||||
}, (err) => {
|
||||
reject(err)
|
||||
});
|
||||
})
|
||||
}
|
||||
return media
|
||||
},
|
||||
startLiveShare: async function (id, callback) {
|
||||
let that = this;
|
||||
|
||||
let msgData = {
|
||||
"Requested device not found" : "没有检测到摄像头或麦克风"
|
||||
}
|
||||
let msg = "获取设备权限失败";
|
||||
|
||||
if (this.stream == null) {
|
||||
try {
|
||||
this.stream = await this.getMediaPlay();
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
msg = msgData[error.message]
|
||||
}
|
||||
}
|
||||
|
||||
if (this.stream == null) {
|
||||
if (window.layer) {
|
||||
layer.msg("获取设备权限失败")
|
||||
}
|
||||
window.Bus.$emit("changeLiveShareState", false)
|
||||
if (callback) {
|
||||
callback()
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$("#mediaLiveRoomList").append(`
|
||||
<div class="tl-rtc-file-mask-media-video">
|
||||
<video id="selfMediaShareVideo" autoplay playsinline onclick="tlrtcfile.openFullVideo(this, 'live', 'self')"></video>
|
||||
</div>
|
||||
`);
|
||||
var video = document.querySelector("#selfMediaShareVideo");
|
||||
video.srcObject = this.stream
|
||||
video.addEventListener('loadedmetadata', function() {
|
||||
// ios 微信浏览器兼容问题
|
||||
video.play();
|
||||
document.addEventListener('WeixinJSBridgeReady', function () {
|
||||
video.play();
|
||||
}, false);
|
||||
});
|
||||
|
||||
//计算时间
|
||||
this.interverlId = setInterval(() => {
|
||||
that.times += 1;
|
||||
window.Bus.$emit("changeLiveShareTimes", that.times)
|
||||
|
||||
$("#liveShareIcon").css("color", "#fb0404")
|
||||
$("#liveShareTimes").css("color", "#fb0404")
|
||||
setTimeout(() => {
|
||||
$("#liveShareIcon").css("color", "#ffffff")
|
||||
$("#liveShareTimes").css("color", "#ffffff")
|
||||
}, 500)
|
||||
}, 1000);
|
||||
|
||||
if (window.layer) {
|
||||
layer.msg("开始直播,再次点击按钮即可结束直播")
|
||||
}
|
||||
|
||||
this.stream.getTracks().forEach(function (track) {
|
||||
that.track = track;
|
||||
if (callback) {
|
||||
callback(track, that.stream)
|
||||
}
|
||||
});
|
||||
},
|
||||
stopLiveShare: function () {
|
||||
if (this.stream) {
|
||||
this.stream.getTracks().forEach(track => track.stop());
|
||||
}
|
||||
|
||||
clearInterval(this.interverlId);
|
||||
|
||||
window.Bus.$emit("changeLiveShareTimes", 0);
|
||||
|
||||
if (window.layer) {
|
||||
layer.msg("直播结束,本次直播时长 " + this.times + "秒")
|
||||
}
|
||||
setTimeout(() => {
|
||||
$("#liveShareIcon").css("color", "#000000")
|
||||
}, 1000);
|
||||
|
||||
this.stream = null;
|
||||
this.times = 0;
|
||||
|
||||
return;
|
||||
},
|
||||
getLiveShareTrackAndStream: function (callback) {
|
||||
callback(this.track, this.stream)
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
window.Bus.$on("startLiveShare", this.startLiveShare);
|
||||
window.Bus.$on("stopLiveShare", this.stopLiveShare);
|
||||
window.Bus.$on("getLiveShareTrackAndStream", this.getLiveShareTrackAndStream);
|
||||
}
|
||||
})
|
@@ -31,7 +31,7 @@ var screenShare = new Vue({
|
||||
}
|
||||
return media
|
||||
},
|
||||
startScreenShare: async function (id, callback) {
|
||||
startScreenShare: async function (callback) {
|
||||
let that = this;
|
||||
|
||||
if(this.stream == null){
|
@@ -55,7 +55,7 @@ var videoShare = new Vue({
|
||||
}
|
||||
return media
|
||||
},
|
||||
startVideoShare: async function (id, callback) {
|
||||
startVideoShare: async function (callback) {
|
||||
let that = this;
|
||||
|
||||
let msgData = {
|
83
svr/res/pay.html
Normal file
83
svr/res/pay.html
Normal file
@@ -0,0 +1,83 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>tl-rtc-file</title>
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||
<link href="/image/44826979.png" rel="shortcut icon" type="image/x-icon">
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
margin-left: 10%;
|
||||
margin-top: 50px;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
border-bottom: 1px solid #eaecef;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 20px;
|
||||
border-bottom: 1px solid #eaecef;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-top: 0;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>开源项目定制服务收费标准 (v1.0.3.2023)</h1>
|
||||
|
||||
<h2>联系方式:</h2>
|
||||
<p>QQ : 1905333456 </p>
|
||||
<p>GitHub:<a href="https://github.com/iamtsm">https://github.com/iamtsm</a></p>
|
||||
|
||||
<h2>项目定制服务</h2>
|
||||
|
||||
<h3>1. 项目功能定制</h3>
|
||||
<ul>
|
||||
<li><strong>服务内容:</strong>对项目进行功能定制或扩展</li>
|
||||
<li><strong>价格:</strong>按功能大小,紧急程度,耗时,定制内容是否允许开源,等情况收费</li>
|
||||
</ul>
|
||||
|
||||
<h3>2. 定制开发支持</h3>
|
||||
<ul>
|
||||
<li><strong>服务内容:</strong>提供定制开发技术支持,可协助部署安装相关事项,或协助自行开发,细节问题答疑</li>
|
||||
<li><strong>价格:</strong>一杯咖啡</li>
|
||||
</ul>
|
||||
|
||||
<h2>收费模式</h2>
|
||||
<ul>
|
||||
<li><strong>按小时计费:</strong>根据实际工作时间计算费用,目前个人定制功能2小时起,每小时200~300,企业定制另谈</li>
|
||||
<li><strong>阶段性付费:</strong>确认开发前,预付1/3,开发完成付1/3,交付上线1/3</li>
|
||||
</ul>
|
||||
|
||||
<h2>付款方式</h2>
|
||||
<ul>
|
||||
<li>微信支付</li>
|
||||
<li>赞赏码支付</li>
|
||||
<li>支付宝支付</li>
|
||||
</ul>
|
||||
|
||||
<h2>交付时间</h2>
|
||||
<p>根据项目的复杂性和工作量,具体的交付时间将在项目定制阶段与客户协商确定,一般会在预估的时间内,如有延期会提前告知。</p>
|
||||
|
||||
<h2>其他备注</h2>
|
||||
<p>此收费标准仅限开发功能,以及交付上线收取的费用,不包括后期维护以及后续功能迭代。</p>
|
||||
</body>
|
||||
</html>
|
@@ -3,17 +3,15 @@ const fs = require('fs');
|
||||
const https = require('https');
|
||||
const conf = require("./conf/cfg.json");
|
||||
const fileApiRouters = require("./src/controller/router")();
|
||||
let resRouter = conf.router.res;
|
||||
const db = require("./src/tables/db");
|
||||
const utils = require("./src/utils/utils");
|
||||
const resRouter = conf.api.router.res;
|
||||
|
||||
//打印logo
|
||||
utils.tlConsoleIcon()
|
||||
|
||||
let app = express();
|
||||
console.log("api init start ...")
|
||||
|
||||
//res
|
||||
for(let key in resRouter) app.use(key,express.static(resRouter[key]));
|
||||
|
||||
//file api
|
||||
for(let key in fileApiRouters) app.use(key,fileApiRouters[key])
|
||||
utils.tlConsole("api init start ...")
|
||||
|
||||
if (!conf.db.open) {// 没开db
|
||||
|
||||
@@ -23,19 +21,25 @@ if (!conf.db.open) {// 没开db
|
||||
req.ctx.dbClient = {};
|
||||
await next();
|
||||
})
|
||||
|
||||
//res
|
||||
for(let key in resRouter) app.use(key,express.static(resRouter[key]));
|
||||
//file api
|
||||
for(let key in fileApiRouters) app.use(key,fileApiRouters[key])
|
||||
|
||||
let options = {
|
||||
key: fs.readFileSync('./conf/keys/server.key'),
|
||||
cert: fs.readFileSync('./conf/keys/server.crt')
|
||||
}
|
||||
https.createServer(options,app).listen(conf.node.port);
|
||||
console.log("express init done ...")
|
||||
console.log("web server runing on ", conf.node.port, " successful");
|
||||
https.createServer(options,app).listen(conf.api.port);
|
||||
utils.tlConsole("express init done ...")
|
||||
utils.tlConsole("api server runing on ", conf.api.port, " successful");
|
||||
|
||||
} else {// 开了db
|
||||
|
||||
(async () => {
|
||||
let { tables, dbClient } = await db.excute(conf)
|
||||
console.log("db init done ...")
|
||||
utils.tlConsole("db init done ...")
|
||||
app.use(async function (req, res, next) {
|
||||
req.ctx = {};
|
||||
req.ctx.tables = tables;
|
||||
@@ -43,15 +47,17 @@ if (!conf.db.open) {// 没开db
|
||||
await next();
|
||||
})
|
||||
|
||||
//res
|
||||
for(let key in resRouter) app.use(key,express.static(resRouter[key]));
|
||||
//file api
|
||||
for(let key in fileApiRouters) app.use(key,fileApiRouters[key])
|
||||
|
||||
let options = {
|
||||
key: fs.readFileSync('./conf/keys/server.key'),
|
||||
cert: fs.readFileSync('./conf/keys/server.crt')
|
||||
}
|
||||
https.createServer(options,app).listen(conf.node.port);
|
||||
console.log("express init done ...")
|
||||
console.log("web server runing on ", conf.node.port, " successful");
|
||||
https.createServer(options,app).listen(conf.api.port);
|
||||
utils.tlConsole("express init done ...")
|
||||
utils.tlConsole("api server runing on ", conf.api.port, " successful");
|
||||
})();
|
||||
|
||||
}
|
||||
|
||||
console.log("web server runing on ",conf.node.port," successful");
|
37
svr/servercontrolsocket.js
Normal file
37
svr/servercontrolsocket.js
Normal file
@@ -0,0 +1,37 @@
|
||||
const https = require('https');
|
||||
const socketIO = require('socket.io');
|
||||
const fs = require('fs');
|
||||
const db = require("./src/tables/db");
|
||||
const conf = require("./conf/cfg.json");
|
||||
const socket = require("./src/socket/index")
|
||||
const utils = require("./src/utils/utils");
|
||||
|
||||
//打印logo
|
||||
utils.tlConsoleIcon()
|
||||
|
||||
//远程控制,Socket连接监听
|
||||
let options = {
|
||||
key: fs.readFileSync('./conf/keys/server.key'),
|
||||
cert: fs.readFileSync('./conf/keys/server.crt')
|
||||
}
|
||||
let io = socketIO.listen(
|
||||
https.createServer(options).listen(conf.wss.control_port)
|
||||
);
|
||||
|
||||
if (!conf.db.open) {// 没开db
|
||||
|
||||
utils.tlConsole("db not open ...")
|
||||
socket.excute({}, {}, io);
|
||||
utils.tlConsole("control socket init done ...")
|
||||
utils.tlConsole("control socket server listen on ", conf.wss.control_port, " successful");
|
||||
|
||||
} else {// 开了db
|
||||
|
||||
(async () => {
|
||||
let { tables, dbClient } = await db.excute(conf)
|
||||
utils.tlConsole("db init done ...")
|
||||
socket.excute(tables, dbClient, io);
|
||||
utils.tlConsole("control socket init done ...")
|
||||
utils.tlConsole("control socket server listen on ", conf.wss.control_port, " successful");
|
||||
})();
|
||||
}
|
@@ -4,6 +4,10 @@ const fs = require('fs');
|
||||
const db = require("./src/tables/db");
|
||||
const conf = require("./conf/cfg.json");
|
||||
const socket = require("./src/socket/index")
|
||||
const utils = require("./src/utils/utils");
|
||||
|
||||
//打印logo
|
||||
utils.tlConsoleIcon()
|
||||
|
||||
//Socket连接监听
|
||||
let options = {
|
||||
@@ -11,23 +15,23 @@ let options = {
|
||||
cert: fs.readFileSync('./conf/keys/server.crt')
|
||||
}
|
||||
let io = socketIO.listen(
|
||||
https.createServer(options).listen(conf.ws.ssl_port)
|
||||
https.createServer(options).listen(conf.wss.port)
|
||||
);
|
||||
|
||||
if (!conf.db.open) {// 没开db
|
||||
|
||||
console.log("db not open ...")
|
||||
utils.tlConsole("db not open ...")
|
||||
socket.excute({}, {}, io);
|
||||
console.log("socket init done ...")
|
||||
console.log("socket server listen on ", conf.ws.port, " successful");
|
||||
utils.tlConsole("socket init done ...")
|
||||
utils.tlConsole("socket server listen on ", conf.wss.port, " successful");
|
||||
|
||||
} else {// 开了db
|
||||
|
||||
(async () => {
|
||||
let { tables, dbClient } = await db.excute(conf)
|
||||
console.log("db init done ...")
|
||||
utils.tlConsole("db init done ...")
|
||||
socket.excute(tables, dbClient, io);
|
||||
console.log("socket init done ...")
|
||||
console.log("socket server listen on ", conf.ws.port, " successful");
|
||||
utils.tlConsole("socket init done ...")
|
||||
utils.tlConsole("socket server listen on ", conf.wss.port, " successful");
|
||||
})();
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
const bussinessDog = require("./../../bussiness/dog/dog")
|
||||
const daoDog = require("./../../dao/dog/dog")
|
||||
const cfg = require("../../../conf/cfg.json");
|
||||
const dbOpen = cfg.db.open
|
||||
|
||||
@@ -11,12 +11,10 @@ async function getDataPageHtml(data) {
|
||||
if (!dbOpen) {
|
||||
return 'db配置未开启';
|
||||
}
|
||||
let resData = await bussinessDog.getDogManageInfo({
|
||||
tables: data.tables,
|
||||
dbClient: data.dbClient,
|
||||
sockets: data.sockets,
|
||||
let resData = await daoDog.getDogManageInfo({
|
||||
day: data.day,
|
||||
})
|
||||
}, data.tables, data.dbClient)
|
||||
|
||||
return `
|
||||
<style>
|
||||
.layui-layer{
|
||||
@@ -120,6 +118,23 @@ async function getDataPageHtml(data) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-sm6 layui-col-md3">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">
|
||||
{{chooseDay}}暂存文件
|
||||
<span class="layui-badge layui-bg-orange layuiadmin-badge">天</span>
|
||||
</div>
|
||||
<div class="layui-card-body layuiadmin-card-list">
|
||||
|
||||
<p class="layuiadmin-big-font">{{transferCodeFileToday}}次</p>
|
||||
<p>
|
||||
总计暂存文件
|
||||
<span class="layuiadmin-span-color">{{transferCodeFileAll}}次
|
||||
<i class="layui-inline layui-icon layui-icon-top" style="font-size: 25px;"></i></span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-col-sm12">
|
||||
<div class="layui-row layui-col-space15">
|
||||
@@ -178,6 +193,25 @@ async function getDataPageHtml(data) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-col-sm12">
|
||||
<div class="layui-row layui-col-space15">
|
||||
<div class="layui-col-sm12">
|
||||
<div class="room-recent-title">{{chooseDay}}文件暂存列表</div>
|
||||
<table class="layui-table">
|
||||
<thead> <tr> <th>房间频道</th> <th>文件名称</th> <th>取件码</th> <th>暂存时间</th> </tr> </thead>
|
||||
<tbody>
|
||||
<tr v-for="file in codeFileList">
|
||||
<td>{{file.room}}</td>
|
||||
<td><pre>{{file.name}} - {{file.type}} - {{file.size}}</pre></td>
|
||||
<td>{{file.code}}</td>
|
||||
<td>{{file.createTime}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
const bussinessRoom = require("./../../bussiness/room/room")
|
||||
const daoRoom = require("./../../dao/room/room")
|
||||
const cfg = require("../../../conf/cfg.json");
|
||||
const dbOpen = cfg.db.open
|
||||
|
||||
@@ -11,12 +11,9 @@ async function getRoomPageHtml(data) {
|
||||
if (!dbOpen) {
|
||||
return 'db配置未开启';
|
||||
}
|
||||
let resData = await bussinessRoom.getRoomHistoryInfo({
|
||||
tables: data.tables,
|
||||
dbClient: data.dbClient,
|
||||
sockets: data.sockets,
|
||||
let resData = await daoRoom.getRoomHistoryInfo({
|
||||
day: data.day,
|
||||
})
|
||||
}, data.tables, data.dbClient, data.sockets)
|
||||
|
||||
return `
|
||||
<style>
|
@@ -1,4 +1,4 @@
|
||||
const bussinessRoom = require("./../../bussiness/room/room")
|
||||
const daoRoom = require("./../../dao/room/room")
|
||||
const cfg = require("../../../conf/cfg.json");
|
||||
const dbOpen = cfg.db.open
|
||||
|
||||
@@ -11,36 +11,11 @@ async function getSettingPageHtml(data) {
|
||||
if (!dbOpen) {
|
||||
return 'db配置未开启';
|
||||
}
|
||||
let resData = await bussinessRoom.getOrCreateManageRoom({
|
||||
tables: data.tables,
|
||||
rname: data.room,
|
||||
let resData = await daoRoom.getOrCreateManageRoom({
|
||||
sid: data.socketId,
|
||||
ip: data.ip,
|
||||
device: data.userAgent,
|
||||
content: JSON.stringify({
|
||||
openSendBug: true,
|
||||
openScreen: true,
|
||||
openOnlineUser: true,
|
||||
openShareRoom: true,
|
||||
openAiChat: true,
|
||||
openGetCodeFile: true,
|
||||
openVideoShare: true,
|
||||
openPasswordRoom: true,
|
||||
openScreenShare: true,
|
||||
openFileTransfer: true,
|
||||
openTxtTransfer: true,
|
||||
openTurnServer: true,
|
||||
openNetworkIcon: true,
|
||||
openUseTurnIcon: true,
|
||||
openCommRoom: true,
|
||||
openRefleshRoom: true,
|
||||
openNotice: true,
|
||||
allowNumber: true,
|
||||
allowChinese: true,
|
||||
allowSymbol: true,
|
||||
noticeMsgList:[]
|
||||
})
|
||||
})
|
||||
}, data.tables, data.dbClient)
|
||||
|
||||
return `
|
||||
<style>
|
||||
@@ -99,6 +74,11 @@ async function getSettingPageHtml(data) {
|
||||
<input type="checkbox" name="openVideoShare" title="开启音视频通话" lay-skin="primary">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block">
|
||||
<input type="checkbox" name="openLiveShare" title="开启直播功能" lay-skin="primary">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block">
|
||||
<input type="checkbox" name="openPasswordRoom" title="开启密码房间" lay-skin="primary">
|
138
svr/src/bussiness/notify/notify.js
Normal file
138
svr/src/bussiness/notify/notify.js
Normal file
@@ -0,0 +1,138 @@
|
||||
const conf = require("../../../conf/cfg.json");
|
||||
const request = require('request');
|
||||
const qiweiNormal = conf.notify.qiwei.normal;
|
||||
const qiweiError = conf.notify.qiwei.error;
|
||||
const open = conf.notify.open;
|
||||
const utils = require("../../../src/utils/utils");
|
||||
|
||||
|
||||
// 统计企微机器人发送normal map
|
||||
const qiweiNormalMap = {}
|
||||
for (let key in qiweiNormal) {
|
||||
qiweiNormalMap[qiweiNormal[key]] = {
|
||||
time: new Date().valueOf(),
|
||||
count: 0
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 企业微信通知
|
||||
* 正常通知
|
||||
* @param {*} msg
|
||||
*/
|
||||
function requestMsg(msg) {
|
||||
if(!open){
|
||||
return
|
||||
}
|
||||
let finalKey = "";
|
||||
for (let key in qiweiNormalMap) {
|
||||
// 单个还没达到20次,直接用
|
||||
if (qiweiNormalMap[key].count < 20) {
|
||||
qiweiNormalMap[key].count += 1;
|
||||
finalKey = key;
|
||||
break;
|
||||
} else {
|
||||
//达到20次,看看时间如果在1分钟内,说明达到限制,直接跳过
|
||||
if ((new Date().valueOf() / 1000) - (qiweiNormalMap[key].time / 1000) <= 60) {
|
||||
continue;
|
||||
} else {
|
||||
//达到20次,但是时间超过1分钟,我们尝试清零
|
||||
qiweiNormalMap[key].count = 1;
|
||||
qiweiNormalMap[key].time = new Date().valueOf()
|
||||
finalKey = key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (finalKey === '' && qiweiNormal.length > 0) {
|
||||
finalKey = qiweiNormal[0];
|
||||
}
|
||||
|
||||
msg = msg + `机器人KEY: ${finalKey}\n`;
|
||||
msg = msg + `机器人KEY列表: ${JSON.stringify(qiweiNormalMap)}\n`;
|
||||
|
||||
request({
|
||||
url: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=" + finalKey,
|
||||
method: "POST",
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
msgtype: "markdown",
|
||||
markdown: {
|
||||
content: msg,
|
||||
}
|
||||
})
|
||||
}, function (error, response, body) {
|
||||
utils.tlConsole('提示成功!', qiweiNormalMap);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 统计企微机器人发送error map
|
||||
const qiweiErrorMap = {}
|
||||
for (let key in qiweiError) {
|
||||
qiweiErrorMap[qiweiError[key]] = {
|
||||
time: new Date().valueOf(),
|
||||
count: 0
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 企业微信通知
|
||||
* 错误通知
|
||||
* @param {*} msg
|
||||
*/
|
||||
function requestErrorMsg(msg) {
|
||||
if(!open){
|
||||
return
|
||||
}
|
||||
let finalKey = "";
|
||||
for (let key in qiweiErrorMap) {
|
||||
// 单个还没达到20次,直接用
|
||||
if (qiweiErrorMap[key].count < 20) {
|
||||
qiweiErrorMap[key].count += 1;
|
||||
finalKey = key;
|
||||
break;
|
||||
} else {
|
||||
//达到20次,看看时间如果在1分钟内,说明达到限制,直接跳过
|
||||
if ((new Date().valueOf() / 1000) - (qiweiErrorMap[key].time / 1000) <= 60) {
|
||||
continue;
|
||||
} else {
|
||||
//达到20次,但是时间超过1分钟,我们尝试清零
|
||||
qiweiErrorMap[key].count = 1;
|
||||
qiweiErrorMap[key].time = new Date().valueOf()
|
||||
finalKey = key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (finalKey === '' && qiweiNormal.length > 0) {
|
||||
finalKey = qiweiNormal[0];
|
||||
}
|
||||
|
||||
msg = msg + `机器人KEY: ${finalKey}\n`;
|
||||
msg = msg + `机器人KEY列表: ${JSON.stringify(qiweiErrorMap)}\n`;
|
||||
|
||||
request({
|
||||
url: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=" + finalKey,
|
||||
method: "POST",
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
msgtype: "markdown",
|
||||
markdown: {
|
||||
content: msg,
|
||||
}
|
||||
})
|
||||
}, function (error, response, body) {
|
||||
utils.tlConsole('提示成功!', qiweiErrorMap);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
requestMsg, requestErrorMsg
|
||||
}
|
@@ -62,7 +62,7 @@ function sendFileDoneNotify(data) {
|
||||
* 发送文本内容通知
|
||||
* @param {*} data
|
||||
*/
|
||||
function sendTxtNotify(data) {
|
||||
function sendChatingRoomNotify(data) {
|
||||
let notifyMsg = `## <font color='info'>文件传输通知</font> - <font color="warning">${data.title}</font>` +
|
||||
` - <font color="comment">${data.room}</font>\n` +
|
||||
`库记录ID: ${data.recoderId}\n` +
|
||||
@@ -161,6 +161,35 @@ function sendStopVideoShareNotify(data) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发送开始直播通知
|
||||
* @param {*} data
|
||||
*/
|
||||
function sendStartLiveShareNotify(data) {
|
||||
let notifyMsg = `## <font color='info'>文件传输通知</font> - <font color="warning">${data.title}</font>` +
|
||||
` - <font color="comment">${data.room}</font>\n` +
|
||||
`当前时间: ${utils.formateDateTime(new Date(), "yyyy-MM-dd hh:mm:ss")}\n` +
|
||||
`访问IP: ${data.ip}\n` +
|
||||
`访问设备: ${data.userAgent}\n`;
|
||||
notify.requestMsg(notifyMsg)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发送停止直播通知
|
||||
* @param {*} data
|
||||
*/
|
||||
function sendStopLiveShareNotify(data) {
|
||||
let notifyMsg = `## <font color='info'>文件传输通知</font> - <font color="warning">${data.title}</font>` +
|
||||
` - <font color="comment">${data.room}</font>\n` +
|
||||
`通话时长: ${data.cost}秒\n` +
|
||||
`当前时间: ${utils.formateDateTime(new Date(), "yyyy-MM-dd hh:mm:ss")}\n` +
|
||||
`访问IP: ${data.ip}\n` +
|
||||
`访问设备: ${data.userAgent}\n`;
|
||||
notify.requestMsg(notifyMsg)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发送取件码通知
|
||||
* @param {*} data
|
||||
@@ -274,6 +303,21 @@ function sendManageUpdateFailedNotify(data) {
|
||||
* @param {*} data
|
||||
*/
|
||||
function sendCreateJoinRoomNotify(data) {
|
||||
let notifyMsg = `## <font color='info'>文件传输通知</font> - <font color="warning">${data.title}</font>` +
|
||||
` - <font color="comment">${data.room}</font>\n` +
|
||||
`库记录ID: ${data.recoderId}\n` +
|
||||
`连接方ID: ${data.socketId}\n` +
|
||||
`当前时间: ${utils.formateDateTime(new Date(), "yyyy-MM-dd hh:mm:ss")}\n` +
|
||||
`访问IP: ${data.ip}\n` +
|
||||
`访问设备: ${data.userAgent}\n`;
|
||||
notify.requestMsg(notifyMsg)
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送创建/加入密码房间通知
|
||||
* @param {*} data
|
||||
*/
|
||||
function sendCreateJoinPasswordRoomNotify(data) {
|
||||
let notifyMsg = `## <font color='info'>文件传输通知</font> - <font color="warning">${data.title}</font>` +
|
||||
` - <font color="comment">${data.room}</font>\n` +
|
||||
`库记录ID: ${data.recoderId}\n` +
|
||||
@@ -302,11 +346,79 @@ function sendExitRoomNotify(data) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 准备添加取件码文件通知
|
||||
* @param {*} data
|
||||
*/
|
||||
function prepareCodeFileNotify(data) {
|
||||
let notifyMsg = `## <font color='info'>文件传输通知</font> - <font color="warning">${data.title}</font>` +
|
||||
` - <font color="comment">${data.room}</font>\n` +
|
||||
`发送方ID: ${data.from}\n` +
|
||||
`上传地址: ${data.link}\n` +
|
||||
`文件名称: ${data.name}\n` +
|
||||
`文件类型: ${data.type}\n` +
|
||||
`文件大小: ${data.size} == (${data.size / 1024 / 1024}M)\n` +
|
||||
`当前时间: ${utils.formateDateTime(new Date(), "yyyy-MM-dd hh:mm:ss")}\n` +
|
||||
`访问IP: ${data.ip}\n` +
|
||||
`访问设备: ${data.userAgent}\n`;
|
||||
notify.requestMsg(notifyMsg)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 添加取件码文件通知
|
||||
* @param {*} data
|
||||
*/
|
||||
function addCodeFileNotify(data) {
|
||||
let notifyMsg = `## <font color='info'>文件传输通知</font> - <font color="warning">${data.title}</font>` +
|
||||
` - <font color="comment">${data.room}</font>\n` +
|
||||
`发送方ID: ${data.from}\n` +
|
||||
`文件ID: ${data.ossFileId}\n` +
|
||||
`文件名称: ${data.ossFileName}\n` +
|
||||
`下载链接: ${data.donwloadLink}\n` +
|
||||
`文件类型: ${data.type}\n` +
|
||||
`文件大小: ${data.size} == (${data.size / 1024 / 1024}M)\n` +
|
||||
`当前时间: ${utils.formateDateTime(new Date(), "yyyy-MM-dd hh:mm:ss")}\n` +
|
||||
`访问IP: ${data.ip}\n` +
|
||||
`访问设备: ${data.userAgent}\n`;
|
||||
notify.requestMsg(notifyMsg)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取取件码文件通知
|
||||
* @param {*} data
|
||||
*/
|
||||
function getCodeFileNotify(data) {
|
||||
let notifyMsg = `## <font color='info'>文件传输通知</font> - <font color="warning">${data.title}</font>` +
|
||||
` - <font color="comment">${data.room}</font>\n` +
|
||||
`发送方ID: ${data.from}\n` +
|
||||
`取件码ID: ${data.code}\n` +
|
||||
`当前时间: ${utils.formateDateTime(new Date(), "yyyy-MM-dd hh:mm:ss")}\n` +
|
||||
`访问IP: ${data.ip}\n` +
|
||||
`访问设备: ${data.userAgent}\n`;
|
||||
notify.requestMsg(notifyMsg)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 报错告警
|
||||
* @param {*} data
|
||||
*/
|
||||
function sendSystemErrorMsg(data) {
|
||||
let notifyMsg = `## <font color='info'>文件传输报错</font> - <font color="warning">${data.title}</font>` +
|
||||
` - <font color="comment">${data.room}</font>\n` +
|
||||
`发送方ID: ${data.from}\n` +
|
||||
`当前时间: ${utils.formateDateTime(new Date(), "yyyy-MM-dd hh:mm:ss")}\n` +
|
||||
`报错信息: ${data.msg}\n`;
|
||||
notify.requestErrorMsg(notifyMsg)
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
sendExitRoomNotify,
|
||||
sendCreateJoinRoomNotify,
|
||||
sendCreateJoinPasswordRoomNotify,
|
||||
sendManageUpdateFailedNotify,
|
||||
sendManageUpdateInfoNotify,
|
||||
sendManageLoginSuccessNotify,
|
||||
@@ -318,10 +430,16 @@ module.exports = {
|
||||
sendStartScreenShareNotify,
|
||||
sendStopVideoShareNotify,
|
||||
sendStartVideoShareNotify,
|
||||
sendTxtNotify,
|
||||
sendStartLiveShareNotify,
|
||||
sendStopLiveShareNotify,
|
||||
sendChatingRoomNotify,
|
||||
sendCodeFileNotify,
|
||||
sendFileDoneNotify,
|
||||
sendFileInfoNotify,
|
||||
sendChatingNotify,
|
||||
sendOpenaiChatNotify
|
||||
sendOpenaiChatNotify,
|
||||
addCodeFileNotify,
|
||||
getCodeFileNotify,
|
||||
prepareCodeFileNotify,
|
||||
sendSystemErrorMsg
|
||||
}
|
@@ -5,6 +5,8 @@
|
||||
|
||||
const request = require('request')
|
||||
const openai = require('../../../conf/cfg.json').openai
|
||||
const utils = require("../../..//src/utils/utils");
|
||||
|
||||
let keysMap = {}
|
||||
|
||||
/**
|
||||
@@ -112,7 +114,7 @@ async function openaiChat(msg, roomId){
|
||||
let maxCount = 0;
|
||||
while (maxCount++ < 100000) {
|
||||
const res = await openaiChatApi( apiKey, msg )
|
||||
console.log("res : ",res)
|
||||
utils.tlConsole("res : ",res)
|
||||
result += res.choices[0].text.substring(res.choices[0].text.indexOf("\n")+1);
|
||||
if(result.startsWith("\n")){
|
||||
result = result.substring(1);
|
||||
@@ -130,8 +132,6 @@ async function openaiChat(msg, roomId){
|
||||
}
|
||||
|
||||
|
||||
// (async()=>{console.log(await openaiChat("1加1等于几"))})()
|
||||
|
||||
module.exports = {
|
||||
openaiChat, apiKeysStatus
|
||||
}
|
0
svr/src/bussiness/oss/oss.js
Normal file
0
svr/src/bussiness/oss/oss.js
Normal file
44
svr/src/controller/comm/comm.js
Normal file
44
svr/src/controller/comm/comm.js
Normal file
@@ -0,0 +1,44 @@
|
||||
const utils = require("../../utils/utils");
|
||||
const conf = require("../../../conf/cfg.json");
|
||||
const webrtcConf = conf.webrtc;
|
||||
|
||||
/**
|
||||
* 获取ip地址,初始化等相关配置
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
*/
|
||||
function initData(req, res) {
|
||||
|
||||
if(process.env.ENV_MODE === 'local'){
|
||||
|
||||
let regexIP = /^((?:(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d))$/;
|
||||
let ip = utils.getLocalIP();
|
||||
if (!regexIP.test(ip)) {
|
||||
ip = utils.getClientIP(req)
|
||||
}
|
||||
if (!regexIP.test(ip)) {
|
||||
ip = "127.0.0.1"
|
||||
}
|
||||
|
||||
let data = {
|
||||
wsHost: conf.ws.host || ip,
|
||||
rtcConfig: { iceServers: webrtcConf.iceServers },
|
||||
options: webrtcConf.options
|
||||
};
|
||||
|
||||
res.json(data)
|
||||
}else if(process.env.ENV_MODE === 'server'){
|
||||
|
||||
let data = {
|
||||
wsHost: conf.wss.host,
|
||||
rtcConfig: { iceServers: webrtcConf.iceServers },
|
||||
options: webrtcConf.options
|
||||
};
|
||||
|
||||
res.json(data)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
initData,
|
||||
}
|
14
svr/src/controller/file/index.js
Normal file
14
svr/src/controller/file/index.js
Normal file
@@ -0,0 +1,14 @@
|
||||
const express = require('express');
|
||||
const file = require("../../dao/file/file")
|
||||
|
||||
module.exports = function () {
|
||||
const router = express.Router();
|
||||
|
||||
router.get("/file", (req, res) => {
|
||||
res.json({
|
||||
dog : "request file api ok!"
|
||||
})
|
||||
});
|
||||
|
||||
return router;
|
||||
}
|
@@ -1,14 +1,15 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const cfg = require("../../conf/cfg.json");
|
||||
const utils = require("../../src/utils/utils");
|
||||
|
||||
module.exports = () => {
|
||||
let routers = {};
|
||||
let handlerConf = cfg.router.filter;
|
||||
let dirs = fs.readdirSync(__dirname);
|
||||
for (let file of dirs) {
|
||||
//过滤文件夹和文件
|
||||
if (handlerConf.whiteDir.includes(file) || handlerConf.whiteFile.includes(file)) continue;
|
||||
if (cfg.api.router.filter.whiteDir.includes(file)
|
||||
|| cfg.api.router.filter.whiteFile.includes(file)) continue;
|
||||
try {
|
||||
//添加router
|
||||
let stat = fs.statSync(path.join(__dirname, file, 'index.js'));
|
||||
@@ -16,7 +17,7 @@ module.exports = () => {
|
||||
routers["/api/" + file] = require("./" + file + '/index')();
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
utils.tlConsole(e);
|
||||
}
|
||||
}
|
||||
return routers;
|
234
svr/src/dao/dog/dog.js
Normal file
234
svr/src/dao/dog/dog.js
Normal file
@@ -0,0 +1,234 @@
|
||||
const utils = require("../../utils/utils");
|
||||
const dbOpen = require("../../../conf/cfg.json").db.open;
|
||||
|
||||
|
||||
/**
|
||||
* 添加操作dog数据
|
||||
* @param {*} params
|
||||
* @param {*} tables
|
||||
* @param {*} dbClient
|
||||
* @returns
|
||||
*/
|
||||
async function addDogData(params, tables, dbClient) {
|
||||
try{
|
||||
if(!tables || !dbClient){
|
||||
return {};
|
||||
}
|
||||
if(!params){
|
||||
params = {};
|
||||
}
|
||||
|
||||
let data = await tables.Dog.create({
|
||||
name: params.name,
|
||||
room_id: params.roomId,
|
||||
socket_id: params.socketId,
|
||||
device: params.device,
|
||||
flag: params.flag,
|
||||
content: params.content,
|
||||
handshake: params.handshake
|
||||
});
|
||||
|
||||
return data && data.dataValues ? data.dataValues.id : 0;
|
||||
}catch(e){
|
||||
console.error(e);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取操作统计信息
|
||||
* @param {*} params
|
||||
* @param {*} tables
|
||||
* @param {*} dbClient
|
||||
* @returns
|
||||
*/
|
||||
async function getDogManageInfo(params, tables, dbClient) {
|
||||
try{
|
||||
if(!tables || !dbClient){
|
||||
return {};
|
||||
}
|
||||
|
||||
if(!params){
|
||||
params = {};
|
||||
}
|
||||
|
||||
let data = {
|
||||
transferFileToday: 0,
|
||||
transferFileAll: 0,
|
||||
transferFileSizeTodady: 0,
|
||||
transferTxtTodady: 0,
|
||||
transferTxtAll: 0,
|
||||
transferCommTxtToday: 0,
|
||||
transferCommTxtAll: 0,
|
||||
transferCodeFileToday: 0,
|
||||
transferCodeFileAll: 0,
|
||||
fileList: [],
|
||||
txtList: [],
|
||||
commTxtList: [],
|
||||
codeFileList : [],
|
||||
};
|
||||
|
||||
let day;
|
||||
try {
|
||||
day = new Date(params.day)
|
||||
} catch (e) {
|
||||
day = new Date()
|
||||
}
|
||||
let chooseDay = utils.formateDateTime(day, "yyyy-MM-dd");
|
||||
let nextDay = utils.getNextDay(chooseDay);
|
||||
|
||||
//某日传输聚合列表
|
||||
const [transferListToday, metadata] = await dbClient.query(`select name, room_id, content, created_at from dog where created_at >= "${chooseDay}" and created_at <= "${nextDay}" order by created_at desc`);
|
||||
|
||||
//发送文件
|
||||
let fileTransferList = transferListToday.filter(element => {
|
||||
return element.name === '准备发送文件'
|
||||
})
|
||||
data.transferFileToday += fileTransferList.length;
|
||||
fileTransferList.forEach(element => {
|
||||
let content = JSON.parse(element.content);
|
||||
data.fileList.push({
|
||||
room: element.room_id || content.room,
|
||||
name: content.name,
|
||||
size: parseInt(content.size / 1024 / 1024) === 0 ? (content.size / 1024 / 1024).toFixed(2) : parseInt(content.size / 1024 / 1024),
|
||||
createTime: utils.formateDateTime(new Date(element.created_at), "yyyy-MM-dd hh:mm:ss"),
|
||||
})
|
||||
data.transferFileSizeTodady += content.size
|
||||
})
|
||||
data.transferFileSizeTodady = parseInt(data.transferFileSizeTodady / 1024 / 1024)
|
||||
|
||||
|
||||
//发送文本内容
|
||||
let txtTransferList = transferListToday.filter(element => {
|
||||
return element.name === '发送文本内容'
|
||||
})
|
||||
data.transferTxtTodady += txtTransferList.length;
|
||||
txtTransferList.forEach(element => {
|
||||
let content = JSON.parse(element.content);
|
||||
data.txtList.push({
|
||||
room: element.room_id || content.room,
|
||||
content: decodeURIComponent(content.content),
|
||||
size: content.content.length,
|
||||
createTime: utils.formateDateTime(new Date(element.created_at), "yyyy-MM-dd hh:mm:ss"),
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
//公共聊天室
|
||||
let commTxtTransferList = transferListToday.filter(element => {
|
||||
return element.name === '公共聊天室'
|
||||
})
|
||||
data.transferCommTxtToday += commTxtTransferList.length;
|
||||
commTxtTransferList.forEach(element => {
|
||||
data.commTxtList.push({
|
||||
room: element.room_id,
|
||||
content: element.content,
|
||||
size: element.content.length,
|
||||
createTime: utils.formateDateTime(new Date(element.created_at), "yyyy-MM-dd hh:mm:ss"),
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
//暂存文件列表
|
||||
let codeFileTransferList = transferListToday.filter(element => {
|
||||
return element.name === '添加取件码文件'
|
||||
})
|
||||
data.transferCodeFileToday += codeFileTransferList.length;
|
||||
codeFileTransferList.forEach(element => {
|
||||
let content = JSON.parse(element.content);
|
||||
data.codeFileList.push({
|
||||
room: element.room_id,
|
||||
name: element.name,
|
||||
code: content.ossFileId,
|
||||
type: content.type,
|
||||
size : utils.getFileSizeStr(content.size),
|
||||
createTime: utils.formateDateTime(new Date(element.created_at), "yyyy-MM-dd hh:mm:ss"),
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
//全部数量统计
|
||||
const [transferAll, metadata1] = await dbClient.query(`select name, count(*) as user from dog group by name`);
|
||||
transferAll.forEach(element => {
|
||||
if (element.name === '准备发送文件') {
|
||||
data.transferFileAll += element.user
|
||||
}
|
||||
if (element.name === '发送文本内容') {
|
||||
data.transferTxtAll += element.user
|
||||
}
|
||||
if (element.name === '公共聊天室') {
|
||||
data.transferCommTxtAll += element.user
|
||||
}
|
||||
if (element.name === '添加取件码文件') {
|
||||
data.transferCodeFileAll += element.user
|
||||
}
|
||||
})
|
||||
|
||||
data.chooseDay = chooseDay;
|
||||
|
||||
return data;
|
||||
|
||||
}catch(e){
|
||||
console.error(e);
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取操作统计信息
|
||||
* @param {*} params
|
||||
* @param {*} tables
|
||||
* @param {*} dbClient
|
||||
* @returns
|
||||
*/
|
||||
async function getDogChating10Info(params, tables, dbClient) {
|
||||
try{
|
||||
if(!tables || !dbClient){
|
||||
return [];
|
||||
}
|
||||
if(!params){
|
||||
params = {};
|
||||
}
|
||||
const limit = params.limit || 10;
|
||||
|
||||
const sql = `select name, room_id, content, socket_id, created_at from dog where name = '公共聊天室' order by created_at desc limit ${limit}`;
|
||||
const [list,] = await dbClient.query(sql);
|
||||
|
||||
let resultList = []
|
||||
list.forEach(element => {
|
||||
resultList.push({
|
||||
room: element.room_id,
|
||||
msg: element.content,
|
||||
socketId: element.socket_id,
|
||||
time: utils.formateDateTime(new Date(element.created_at), "yyyy-MM-dd hh:mm:ss"),
|
||||
})
|
||||
});
|
||||
|
||||
resultList = resultList.reverse()
|
||||
|
||||
return resultList;
|
||||
}catch(e){
|
||||
console.error(e);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = dbOpen ? {
|
||||
addDogData,
|
||||
getDogManageInfo,
|
||||
getDogChating10Info,
|
||||
} : {
|
||||
addDogData : () => {
|
||||
return {}
|
||||
},
|
||||
getDogManageInfo : () => {
|
||||
return {}
|
||||
},
|
||||
getDogChating10Info : () => {
|
||||
return [];
|
||||
},
|
||||
}
|
171
svr/src/dao/file/file.js
Normal file
171
svr/src/dao/file/file.js
Normal file
@@ -0,0 +1,171 @@
|
||||
const cfg = require("../../../conf/cfg.json");
|
||||
const sequelizeObj = require('sequelize');
|
||||
const utils = require("../../utils/utils");
|
||||
const dbOpen = cfg.db.open;
|
||||
|
||||
/**
|
||||
* 添加取件码记录
|
||||
* @param {*} params
|
||||
* @param {*} tables
|
||||
* @param {*} dbClient
|
||||
* @returns
|
||||
*/
|
||||
async function addCodeFile(params, tables, dbClient) {
|
||||
try{
|
||||
if(!tables || !dbClient){
|
||||
return {};
|
||||
}
|
||||
if(!params){
|
||||
params = {};
|
||||
}
|
||||
|
||||
if(!params.code){
|
||||
return {}
|
||||
}
|
||||
|
||||
let files = await tables.File.findAll({
|
||||
where: {
|
||||
code: params.code,
|
||||
}
|
||||
});
|
||||
|
||||
if(files && files.length > 0){
|
||||
return {}
|
||||
}
|
||||
|
||||
let data = await tables.File.create({
|
||||
room_id: params.roomId,
|
||||
code: params.code,
|
||||
name : params.name,
|
||||
oss_name : params.ossName,
|
||||
download: params.download,
|
||||
content: params.content,
|
||||
});
|
||||
|
||||
return data && data.dataValues ? data.dataValues.id : 0;
|
||||
|
||||
}catch(e){
|
||||
console.error(e);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取取件码记录
|
||||
* @param {*} params
|
||||
* @param {*} tables
|
||||
* @param {*} dbClient
|
||||
* @returns
|
||||
*/
|
||||
async function getCodeFile(params, tables, dbClient) {
|
||||
try{
|
||||
if(!tables || !dbClient){
|
||||
return {};
|
||||
}
|
||||
if(!params){
|
||||
params = {};
|
||||
}
|
||||
|
||||
if(!params.code){
|
||||
return {};
|
||||
}
|
||||
|
||||
let files = await tables.File.findAll({
|
||||
where: {
|
||||
code: params.code,
|
||||
}
|
||||
});
|
||||
|
||||
if (!files || files.length === 0) {
|
||||
return {}
|
||||
}
|
||||
|
||||
let file = files[0]
|
||||
|
||||
let content = JSON.parse(file.content)
|
||||
|
||||
let data = {
|
||||
name : file.name,
|
||||
code: file.code,
|
||||
download : file.download,
|
||||
type : content.type,
|
||||
size : content.size,
|
||||
fromNickName : content.nickName,
|
||||
fromRoom : content.room,
|
||||
createTime: utils.formateDateTime(new Date(file.createdAt), "yyyy-MM-dd hh:mm:ss"),
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
}catch(e){
|
||||
console.error(e);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据文件名称前缀搜索文件
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @param {*} next
|
||||
*/
|
||||
async function searchCodeFile(req, res, next) {
|
||||
try{
|
||||
if(!tables || !dbClient){
|
||||
return {};
|
||||
}
|
||||
if(!params){
|
||||
params = {};
|
||||
}
|
||||
|
||||
if(!params.name){
|
||||
return [];
|
||||
}
|
||||
|
||||
let files = await tables.File.findAll({
|
||||
where: {
|
||||
name: {
|
||||
[sequelizeObj.Op.like] : '%' + params.name + '%'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!files || files.length === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
files.forEach(file => {
|
||||
let content = JSON.parse(file.content);
|
||||
list.push({
|
||||
name : file.name,
|
||||
code: file.code,
|
||||
download : file.download,
|
||||
type : content.type,
|
||||
createTime: utils.formateDateTime(new Date(file.createdAt), "yyyy-MM-dd hh:mm:ss"),
|
||||
})
|
||||
});
|
||||
|
||||
return list;
|
||||
|
||||
}catch(e){
|
||||
console.error(e);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = dbOpen ? {
|
||||
addCodeFile, getCodeFile, searchCodeFile
|
||||
} : {
|
||||
addCodeFile : function(){
|
||||
return {}
|
||||
},
|
||||
getCodeFile : function(){
|
||||
return {}
|
||||
},
|
||||
searchCodeFile : function(){
|
||||
return []
|
||||
}
|
||||
}
|
313
svr/src/dao/room/room.js
Normal file
313
svr/src/dao/room/room.js
Normal file
@@ -0,0 +1,313 @@
|
||||
|
||||
const utils = require("../../utils/utils");
|
||||
const cfg = require("../../../conf/cfg.json")
|
||||
const manageConfig = cfg.manage;
|
||||
const dbOpen = cfg.db.open;
|
||||
|
||||
// 默认开关数据
|
||||
const defaultSwitchData = {
|
||||
openSendBug: true,
|
||||
openScreen: true,
|
||||
openOnlineUser: true,
|
||||
openShareRoom: true,
|
||||
openAiChat: true,
|
||||
openGetCodeFile: true,
|
||||
openVideoShare: true,
|
||||
openLiveShare: true,
|
||||
openPasswordRoom: true,
|
||||
openScreenShare: true,
|
||||
openFileTransfer: true,
|
||||
openTxtTransfer: true,
|
||||
openTurnServer: true,
|
||||
openNetworkIcon: true,
|
||||
openUseTurnIcon: true,
|
||||
openCommRoom: true,
|
||||
openRefleshRoom: true,
|
||||
openNotice: true,
|
||||
allowNumber: true,
|
||||
allowChinese: true,
|
||||
allowSymbol: true,
|
||||
noticeMsgList: [],
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 管理后台特殊房间入口、配置信息
|
||||
* @param {*} params
|
||||
* @param {*} tables
|
||||
* @param {*} dbClient
|
||||
* @returns
|
||||
*/
|
||||
async function getOrCreateManageRoom(params, tables, dbClient) {
|
||||
try{
|
||||
if(!tables || !dbClient){
|
||||
return {};
|
||||
}
|
||||
if(!params){
|
||||
params = {};
|
||||
}
|
||||
|
||||
let manageRoomList = await tables.Room.findAll({
|
||||
where: {
|
||||
rname: manageConfig.room,
|
||||
flag: 1
|
||||
}
|
||||
});
|
||||
|
||||
if (manageRoomList.length === 0) {
|
||||
let res = await tables.Room.create({
|
||||
rcode: utils.genRoom(),
|
||||
rname: manageConfig.room,
|
||||
flag: 1,
|
||||
sid: params.sid,
|
||||
ip: params.ip,
|
||||
device: params.device,
|
||||
content: JSON.stringify(defaultSwitchData)
|
||||
});
|
||||
|
||||
utils.tlConsole("创建管理房间配置成功")
|
||||
|
||||
manageRoomList = await tables.Room.findAll({
|
||||
where: {
|
||||
rname: manageConfig.room,
|
||||
flag: 1
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return manageRoomList.length >= 1 ? manageRoomList[0].dataValues : {};
|
||||
|
||||
}catch(e){
|
||||
console.error(e);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取房间统计信息
|
||||
* @param {*} params
|
||||
* @param {*} tables
|
||||
* @param {*} dbClient
|
||||
* @param {*} sockets
|
||||
* @returns
|
||||
*/
|
||||
async function getRoomHistoryInfo(params, tables, dbClient, sockets) {
|
||||
try{
|
||||
if(!tables || !dbClient || !sockets){
|
||||
return {};
|
||||
}
|
||||
if(!params){
|
||||
params = {};
|
||||
}
|
||||
|
||||
let data = {
|
||||
createRoomToday: 0,
|
||||
createRoomAll: 0,
|
||||
joinRoomTodady: 0,
|
||||
joinRoomAll: 0,
|
||||
onlineRoomList: [],
|
||||
todayRoomList: [],
|
||||
userAgentIpList: []
|
||||
};
|
||||
|
||||
//当前在线房间列表
|
||||
for (let room in sockets.adapter.rooms) {
|
||||
if (room.length > 15) {
|
||||
continue
|
||||
}
|
||||
data.onlineRoomList.push({
|
||||
status: "在线",
|
||||
room: room,
|
||||
userNumber: sockets.adapter.rooms[room] ? Object.keys(sockets.adapter.rooms[room].sockets).length : 0,
|
||||
createTime: sockets.adapter.rooms[room].createTime
|
||||
})
|
||||
}
|
||||
|
||||
let day;
|
||||
try {
|
||||
day = new Date(params.day)
|
||||
} catch (e) {
|
||||
day = new Date()
|
||||
}
|
||||
let chooseDay = utils.formateDateTime(day, "yyyy-MM-dd");
|
||||
let nextDay = utils.getNextDay(chooseDay);
|
||||
|
||||
// 某日房间聚合列表,数量统计
|
||||
const [roomCoutingListToday, metadata] = await dbClient.query(
|
||||
`select rname, any_value(created_at) as created_at, count(*) as user from room where created_at >= "${chooseDay}" and created_at <= "${nextDay}" group by rname order by created_at desc`);
|
||||
|
||||
data.createRoomToday += roomCoutingListToday.length;
|
||||
roomCoutingListToday.forEach(element => {
|
||||
data.joinRoomTodady += element.user;
|
||||
data.todayRoomList.push({
|
||||
room: element.rname,
|
||||
count: element.user,
|
||||
createTime: utils.formateDateTime(new Date(element.created_at), "yyyy-MM-dd hh:mm:ss"),
|
||||
})
|
||||
});
|
||||
|
||||
// 全部数量统计
|
||||
const [roomCoutingListAll, metadata1] = await dbClient.query(`select count(*) as user from room group by rname`);
|
||||
data.createRoomAll += roomCoutingListAll.length;
|
||||
roomCoutingListAll.forEach(element => {
|
||||
data.joinRoomAll += element.user
|
||||
});
|
||||
|
||||
// 某日房间设备统计列表
|
||||
const [roomListAgent, metadata2] = await dbClient.query(`select rname, content, created_at from room where created_at >= "${utils.formateDateTime(new Date(), "yyyy-MM-dd")}" order by created_at desc`);
|
||||
roomListAgent.forEach(element => {
|
||||
let content = JSON.parse(element.content);
|
||||
if (content && content.handshake) {
|
||||
data.userAgentIpList.push({
|
||||
room: element.rname,
|
||||
userAgent: content.handshake.headers['user-agent'],
|
||||
Ip: content.handshake.headers['x-real-ip'] || content.handshake.headers['x-forwarded-for'] || content.handshake.headers['host'],
|
||||
createTime: utils.formateDateTime(new Date(element.created_at), "yyyy-MM-dd hh:mm:ss"),
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
data.chooseDay = chooseDay;
|
||||
|
||||
return data;
|
||||
}catch(e){
|
||||
console.error(e);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 加入房间
|
||||
* @param {*} params
|
||||
* @param {*} tables
|
||||
* @param {*} dbClient
|
||||
* @returns
|
||||
*/
|
||||
async function createJoinRoom(params, tables, dbClient) {
|
||||
try{
|
||||
if(!tables || !dbClient){
|
||||
return {};
|
||||
}
|
||||
if(!params){
|
||||
params = {};
|
||||
}
|
||||
|
||||
let data = await tables.Room.create({
|
||||
uid: params.uid,
|
||||
uname: params.uname,
|
||||
rcode: utils.genRoom(),
|
||||
rname: params.rname,
|
||||
sid: params.sid,
|
||||
ip: params.ip,
|
||||
device: params.device,
|
||||
url: params.url,
|
||||
content: params.content
|
||||
});
|
||||
|
||||
utils.tlConsole("加入房间 : ", params.uname, params.sid, params.rname)
|
||||
|
||||
return data && data.dataValues ? data.dataValues.id : 0;
|
||||
}catch(e){
|
||||
console.error(e);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新房间
|
||||
* @param {*} params
|
||||
* @param {*} tables
|
||||
* @param {*} dbClient
|
||||
* @returns
|
||||
*/
|
||||
async function updateRoomContent(params, tables, dbClient) {
|
||||
try{
|
||||
if(!tables || !dbClient){
|
||||
return {};
|
||||
}
|
||||
if(!params){
|
||||
params = {};
|
||||
}
|
||||
|
||||
let data = await tables.Room.update({
|
||||
content: params.content,
|
||||
}, {
|
||||
where: {
|
||||
id: params.id,
|
||||
flag: 1
|
||||
}
|
||||
});
|
||||
|
||||
utils.tlConsole("更新房间 : ", params, data)
|
||||
|
||||
return data;
|
||||
|
||||
}catch(e){
|
||||
console.error(e);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 退出房间
|
||||
* @param {*} params
|
||||
* @param {*} tables
|
||||
* @param {*} dbClient
|
||||
* @returns
|
||||
*/
|
||||
async function exitRoomBySid(params, tables, dbClient) {
|
||||
try{
|
||||
if(!tables || !dbClient){
|
||||
return {};
|
||||
}
|
||||
if(!params){
|
||||
params = {};
|
||||
}
|
||||
|
||||
let data = await tables.Room.update({
|
||||
status: 1
|
||||
}, {
|
||||
where: {
|
||||
sid: params.sid
|
||||
}
|
||||
});
|
||||
|
||||
utils.tlConsole("退出房间 : ", params, data)
|
||||
|
||||
return 0;
|
||||
}catch(e){
|
||||
console.error(e);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = dbOpen ? {
|
||||
getRoomHistoryInfo,
|
||||
createJoinRoom,
|
||||
updateRoomContent,
|
||||
exitRoomBySid,
|
||||
getOrCreateManageRoom
|
||||
} : {
|
||||
getRoomHistoryInfo: () => {
|
||||
return {}
|
||||
},
|
||||
createJoinRoom: () => {
|
||||
return {}
|
||||
},
|
||||
updateRoomContent: () => {
|
||||
return {}
|
||||
},
|
||||
exitRoomBySid: () => {
|
||||
return {}
|
||||
},
|
||||
getOrCreateManageRoom: () => {
|
||||
return {
|
||||
content: JSON.stringify(defaultSwitchData)
|
||||
}
|
||||
},
|
||||
}
|
127
svr/src/socket/connect.js
Normal file
127
svr/src/socket/connect.js
Normal file
@@ -0,0 +1,127 @@
|
||||
const rtcDisConnect = require("./rtcDisConnect/disconnect");
|
||||
const rtcOffer = require("./rtcOffer/offer");
|
||||
const rtcAnswer = require("./rtcAnswer/answer");
|
||||
const rtcCandidate = require("./rtcCandidate/candidate");
|
||||
const rtcCount = require("./rtcCount/count");
|
||||
const rtcExit = require("./rtcExit/exit");
|
||||
const rtcCommData = require("./rtcCommData/commData");
|
||||
const rtcCreateJoin = require("./rtcCreateJoin/createJoin");
|
||||
const rtcManageConfirm = require("./rtcManage/confirm");
|
||||
const rtcManageChange = require("./rtcManage/change");
|
||||
const rtcManageReload = require("./rtcManage/reload");
|
||||
const rtcMessage = require("./rtcMessage/message");
|
||||
const rtcChatingComm = require("./rtcChatingComm/chatingComm");
|
||||
const rtcChatingRoom = require("./rtcChatingRoom/chatingRoom");
|
||||
const rtcOpenai = require("./rtcOpenai/openai");
|
||||
const rtcControl = require("./rtcControl/control");
|
||||
const rtcDraw = require("./rtcDraw/draw");
|
||||
const rtcPrepareCodeFile = require("./rtcCodeFile/prepareCodeFile");
|
||||
const rtcAddCodeFile = require("./rtcCodeFile/addCodeFile");
|
||||
const rtcGetCodeFile = require("./rtcCodeFile/getCodeFile");
|
||||
const rtcServerEvent = require("./rtcConstant").rtcServerEvent
|
||||
|
||||
|
||||
module.exports = (io, socket, tables, dbClient) => {
|
||||
|
||||
rtcCount.count(io, socket, tables, dbClient, {})
|
||||
|
||||
// 断开连接
|
||||
socket.on(rtcServerEvent.disconnect, (data)=>{
|
||||
rtcDisConnect.disconnect(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// webrtc offer 消息
|
||||
socket.on(rtcServerEvent.offer, (data) => {
|
||||
rtcOffer.offer(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// webrtc answer 消息
|
||||
socket.on(rtcServerEvent.answer, (data) => {
|
||||
rtcAnswer.answer(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// webrtc candidate 消息
|
||||
socket.on(rtcServerEvent.candidate, (data) => {
|
||||
rtcCandidate.candidate(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 在线人数统计
|
||||
socket.on(rtcServerEvent.count, (data) => {
|
||||
rtcCount.count(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 退出房间
|
||||
socket.on(rtcServerEvent.exit, (data) => {
|
||||
rtcExit.exit(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 获取初始数据
|
||||
socket.on(rtcServerEvent.getCommData, (data) => {
|
||||
rtcCommData.getCommData(io, socket, tables, dbClient, data)
|
||||
})
|
||||
|
||||
// 创建或加入房间
|
||||
socket.on(rtcServerEvent.createAndJoin, (data) => {
|
||||
rtcCreateJoin.createJoin(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 管理后台登陆验证
|
||||
socket.on(rtcServerEvent.manageConfirm, (data) => {
|
||||
rtcManageConfirm.confirm(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 管理后台修改数据
|
||||
socket.on(rtcServerEvent.manageChange, (data) => {
|
||||
rtcManageChange.change(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 管理后台刷新
|
||||
socket.on(rtcServerEvent.manageReload, (data) => {
|
||||
rtcManageReload.reload(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 公共消息
|
||||
socket.on(rtcServerEvent.message, (data) => {
|
||||
rtcMessage.message(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 公共聊天频道
|
||||
socket.on(rtcServerEvent.chatingComm, (data) => {
|
||||
rtcChatingComm.chatingComm(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 房间内聊天,群聊/私聊
|
||||
socket.on(rtcServerEvent.chatingRoom, (data) => {
|
||||
rtcChatingRoom.chatingRoom(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// openai聊天
|
||||
socket.on(rtcServerEvent.openai, (data) => {
|
||||
rtcOpenai.openai(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 远程控制
|
||||
socket.on(rtcServerEvent.control, (data) => {
|
||||
rtcControl.control(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// canvas画图
|
||||
socket.on(rtcServerEvent.draw, (data) => {
|
||||
rtcDraw.draw(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 准备添加取件码文件,获取上传链接
|
||||
socket.on(rtcServerEvent.prepareCodeFile, (data) => {
|
||||
rtcPrepareCodeFile.prepareCodeFile(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 添加取件码文件
|
||||
socket.on(rtcServerEvent.addCodeFile, (data) => {
|
||||
rtcAddCodeFile.addCodeFile(io, socket, tables, dbClient, data)
|
||||
});
|
||||
|
||||
// 获取取件码文件
|
||||
socket.on(rtcServerEvent.getCodeFile, (data) => {
|
||||
rtcGetCodeFile.getCodeFile(io, socket, tables, dbClient, data)
|
||||
});
|
||||
}
|
@@ -1,7 +1,9 @@
|
||||
const connect = require("./connect");
|
||||
const rtcConstant = require("./rtcConstant");
|
||||
const rtcServerEvent = rtcConstant.rtcServerEvent
|
||||
|
||||
/**
|
||||
* 执行器
|
||||
* socket事件初始化入口
|
||||
* @param {*} tables
|
||||
* @param {*} dbClient
|
||||
* @param {*} io
|
||||
@@ -13,7 +15,7 @@ async function excute(tables, dbClient, io) {
|
||||
return;
|
||||
}
|
||||
|
||||
io.sockets.on('connection', function (socket) {
|
||||
io.sockets.on(rtcServerEvent.connection, function (socket) {
|
||||
connect(io, socket, tables, dbClient)
|
||||
});
|
||||
}
|
@@ -1,3 +1,6 @@
|
||||
const rtcConstant = require("../rtcConstant");
|
||||
const rtcClientEvent = rtcConstant.rtcClientEvent
|
||||
|
||||
/**
|
||||
* webrtc answer
|
||||
* 转发answer消息至room其他客户端 [from,to,room,sdp]
|
||||
@@ -13,7 +16,7 @@ async function answer(io, socket, tables, dbClient, data){
|
||||
if (!otherClient) {
|
||||
return;
|
||||
}
|
||||
otherClient.emit('answer', data);
|
||||
otherClient.emit(rtcClientEvent.answer, data);
|
||||
}
|
||||
|
||||
module.exports = {
|
@@ -1,3 +1,6 @@
|
||||
const rtcConstant = require("../rtcConstant");
|
||||
const rtcClientEvent = rtcConstant.rtcClientEvent
|
||||
|
||||
/**
|
||||
* webrtc candidate
|
||||
* 转发candidate消息至room其他客户端 [from,to,room,candidate[sdpMid,sdpMLineIndex,sdp]]
|
||||
@@ -13,7 +16,7 @@ async function candidate(io, socket, tables, dbClient, data){
|
||||
if (!otherClient){
|
||||
return;
|
||||
}
|
||||
otherClient.emit('candidate', data);
|
||||
otherClient.emit(rtcClientEvent.candidate, data);
|
||||
}
|
||||
|
||||
module.exports = {
|
@@ -1,8 +1,9 @@
|
||||
const bussinessDog = require("./../../bussiness/dog/dog")
|
||||
const rtcMessage = require("./../rtcMessage/message");
|
||||
const bussinessNotify = require("./../../bussiness/notify/notifySocketEvent")
|
||||
const rtcCommData = require("./../rtcCommData/commData");
|
||||
const utils = require("./../../utils/utils");
|
||||
const daoDog = require("./../../dao/dog/dog")
|
||||
const bussinessNotify = require("../../bussiness/notify/notifyHandler")
|
||||
const rtcCommData = require("../rtcCommData/commData");
|
||||
const utils = require("../../utils/utils");
|
||||
const rtcConstant = require("../rtcConstant");
|
||||
const rtcClientEvent = rtcConstant.rtcClientEvent
|
||||
|
||||
/**
|
||||
* 公共聊天频道
|
||||
@@ -13,18 +14,17 @@ const utils = require("./../../utils/utils");
|
||||
* @param {*} data event参数
|
||||
* @returns
|
||||
*/
|
||||
async function chating(io, socket, tables, dbClient, data){
|
||||
async function chatingComm(io, socket, tables, dbClient, data){
|
||||
try {
|
||||
let cacheSwitchData = rtcCommData.getCacheSwitchData()
|
||||
let chatingComm = rtcCommData.getChatingComm()
|
||||
|
||||
if(!cacheSwitchData.openCommRoom){
|
||||
rtcMessage.message(io, socket, tables, dbClient, {
|
||||
socket.emit(rtcClientEvent.tips, {
|
||||
room: data.room,
|
||||
emitType: "tips",
|
||||
to: socket.id,
|
||||
msg: "当前功能已暂时关闭,有问题可以加群交流"
|
||||
})
|
||||
});
|
||||
return
|
||||
}
|
||||
|
||||
@@ -38,13 +38,12 @@ async function chating(io, socket, tables, dbClient, data){
|
||||
}
|
||||
rtcCommData.setChatingComm(chatingComm);
|
||||
|
||||
io.sockets.emit("chatingComm", data);
|
||||
io.sockets.emit(rtcClientEvent.chatingComm, data);
|
||||
|
||||
let {handshake, userAgent, ip} = utils.getSocketClientInfo(socket);
|
||||
|
||||
let recoderId = await bussinessDog.dogData({
|
||||
let recoderId = await daoDog.addDogData({
|
||||
name: "公共聊天室",
|
||||
tables: tables,
|
||||
roomId: data.room,
|
||||
socketId: data.socketId,
|
||||
device: userAgent,
|
||||
@@ -52,10 +51,10 @@ async function chating(io, socket, tables, dbClient, data){
|
||||
content: decodeURIComponent(data.msg),
|
||||
handshake: JSON.stringify(handshake),
|
||||
ip: ip
|
||||
});
|
||||
}, tables, dbClient);
|
||||
|
||||
bussinessNotify.sendChatingNotify({
|
||||
title: '公共聊天频道',
|
||||
title: "公共聊天室",
|
||||
room: data.room,
|
||||
recoderId: recoderId,
|
||||
msgRecoderId: recoderId,
|
||||
@@ -65,16 +64,27 @@ async function chating(io, socket, tables, dbClient, data){
|
||||
ip: ip
|
||||
})
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
rtcMessage.message(io, socket, tables, dbClient, {
|
||||
utils.tlConsole(e)
|
||||
socket.emit(rtcClientEvent.tips, {
|
||||
room: data.room,
|
||||
emitType: "tips",
|
||||
to: socket.id,
|
||||
msg: "系统错误"
|
||||
});
|
||||
bussinessNotify.sendSystemErrorMsg({
|
||||
title: "socket-chatingComm",
|
||||
room: data.room,
|
||||
from : socket.id,
|
||||
msg : JSON.stringify({
|
||||
message: e.message,
|
||||
fileName: e.fileName,
|
||||
lineNumber: e.lineNumber,
|
||||
stack: e.stack,
|
||||
name: e.name
|
||||
}, null, '\t')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
chating
|
||||
chatingComm
|
||||
}
|
94
svr/src/socket/rtcChatingRoom/chatingRoom.js
Normal file
94
svr/src/socket/rtcChatingRoom/chatingRoom.js
Normal file
@@ -0,0 +1,94 @@
|
||||
const daoDog = require("./../../dao/dog/dog")
|
||||
const bussinessNotify = require("./../../bussiness/notify/notifyHandler")
|
||||
const utils = require("./../../utils/utils");
|
||||
const rtcConstant = require("../rtcConstant");
|
||||
const rtcClientEvent = rtcConstant.rtcClientEvent
|
||||
|
||||
/**
|
||||
* 房间内聊天 群聊/私聊
|
||||
* 指定了to : 就会发送给指定的用户
|
||||
* 没有指定to : 广播给除了自己外的房间内的所有用户
|
||||
* @param {*} io socketio对象
|
||||
* @param {*} socket 单个socket连接
|
||||
* @param {*} tables 数据表对象
|
||||
* @param {*} dbClient sequelize-orm对象
|
||||
* @param {*} data event参数
|
||||
* @returns
|
||||
*/
|
||||
async function chatingRoom(io, socket, tables, dbClient, data){
|
||||
try {
|
||||
|
||||
let {handshake, userAgent, ip} = utils.getSocketClientInfo(socket);
|
||||
|
||||
await daoDog.addDogData({
|
||||
name: "发送文本内容",
|
||||
roomId: data.room || "",
|
||||
socketId: "",
|
||||
device: userAgent,
|
||||
flag: 0,
|
||||
content: JSON.stringify(data),
|
||||
handshake: JSON.stringify(handshake),
|
||||
ip: ip
|
||||
}, tables, dbClient);
|
||||
|
||||
bussinessNotify.sendChatingRoomNotify({
|
||||
title: "发送文本内容",
|
||||
room: data.room,
|
||||
from: data.from,
|
||||
recoderId: data.recoderId,
|
||||
content: data.content,
|
||||
userAgent: userAgent,
|
||||
ip: ip
|
||||
})
|
||||
|
||||
// 指定发送
|
||||
if(data.to && data.to !== ''){
|
||||
let toOtherSocket = io.sockets.connected[data.to];
|
||||
if(toOtherSocket){
|
||||
toOtherSocket.emit(rtcClientEvent.chatingRoom, data);
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 没指定,走广播(除了自己)
|
||||
let clientsInRoom = io.sockets.adapter.rooms[data.room];
|
||||
if (!clientsInRoom) {
|
||||
return
|
||||
}
|
||||
let otherSocketIds = Object.keys(clientsInRoom.sockets);
|
||||
for (let i = 0; i < otherSocketIds.length; i++) {
|
||||
if(data.from === otherSocketIds[i]){ //跳过自己
|
||||
continue;
|
||||
}
|
||||
let otherSocket = io.sockets.connected[otherSocketIds[i]];
|
||||
if(!otherSocket){
|
||||
continue;
|
||||
}
|
||||
otherSocket.emit(rtcClientEvent.chatingRoom, data);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
utils.tlConsole(e)
|
||||
socket.emit("tips", {
|
||||
room: data.room,
|
||||
to: socket.id,
|
||||
msg: "系统错误"
|
||||
});
|
||||
bussinessNotify.sendSystemErrorMsg({
|
||||
title: "socket-chatingRoom",
|
||||
room: data.room,
|
||||
from : socket.id,
|
||||
msg : JSON.stringify({
|
||||
message: e.message,
|
||||
fileName: e.fileName,
|
||||
lineNumber: e.lineNumber,
|
||||
stack: e.stack,
|
||||
name: e.name
|
||||
}, null, '\t')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
chatingRoom
|
||||
}
|
116
svr/src/socket/rtcCodeFile/addCodeFile.js
Normal file
116
svr/src/socket/rtcCodeFile/addCodeFile.js
Normal file
@@ -0,0 +1,116 @@
|
||||
const rtcConstant = require("../rtcConstant");
|
||||
const rtcClientEvent = rtcConstant.rtcClientEvent
|
||||
const daoDog = require("./../../dao/dog/dog")
|
||||
const daoFile = require("./../../dao/file/file")
|
||||
const bussinessNotify = require("./../../bussiness/notify/notifyHandler")
|
||||
const utils = require("./../../utils/utils");
|
||||
const seafile = require("./../../bussiness/oss/seafile")
|
||||
const rtcCommData = require("./../rtcCommData/commData");
|
||||
|
||||
/**
|
||||
* 添加取件码文件
|
||||
* @param {*} io socketio对象
|
||||
* @param {*} socket 单个socket连接
|
||||
* @param {*} tables 数据表对象
|
||||
* @param {*} dbClient sequelize-orm对象
|
||||
* @param {*} data event参数
|
||||
* @returns
|
||||
*/
|
||||
async function addCodeFile(io, socket, tables, dbClient, data){
|
||||
try{
|
||||
let cacheSwitchData = rtcCommData.getCacheSwitchData()
|
||||
|
||||
if(!cacheSwitchData.openGetCodeFile){
|
||||
socket.emit(rtcClientEvent.tips, {
|
||||
room: data.room,
|
||||
to: socket.id,
|
||||
msg: "当前功能已暂时关闭,有问题可以加群交流"
|
||||
});
|
||||
return
|
||||
}
|
||||
|
||||
let {handshake, userAgent, ip} = utils.getSocketClientInfo(socket);
|
||||
|
||||
const ossToken = await seafile.seafileGetToken();
|
||||
|
||||
let donwloadLink = ""
|
||||
|
||||
if(ossToken){
|
||||
let shareLink = await seafile.seafileCreateShareLink(ossToken, {
|
||||
name : data.ossFileName,
|
||||
can_edit : false,
|
||||
can_download : true,
|
||||
expire_days : 1
|
||||
});
|
||||
if(shareLink){
|
||||
donwloadLink = seafile.seafileGetDownLoadLink(shareLink.token);
|
||||
}
|
||||
}
|
||||
|
||||
data.donwloadLink = donwloadLink;
|
||||
|
||||
utils.tlConsole("获取下载链接成功 : ",donwloadLink)
|
||||
|
||||
bussinessNotify.addCodeFileNotify({
|
||||
title: "添加取件码文件",
|
||||
room: data.room,
|
||||
from: data.from,
|
||||
name: data.name,
|
||||
type: data.type,
|
||||
size: data.size,
|
||||
ossFileId : data.ossFileId,
|
||||
ossFileName : data.ossFileName,
|
||||
donwloadLink : data.donwloadLink,
|
||||
userAgent: userAgent,
|
||||
ip: ip
|
||||
})
|
||||
|
||||
await daoDog.addDogData({
|
||||
name: "添加取件码文件",
|
||||
roomId: data.room || "",
|
||||
socketId: socket.id,
|
||||
device: userAgent,
|
||||
flag: 0,
|
||||
content: JSON.stringify(data),
|
||||
handshake: JSON.stringify(handshake),
|
||||
ip: ip
|
||||
}, tables, dbClient);
|
||||
|
||||
await daoFile.addCodeFile({
|
||||
roomId: data.room || "",
|
||||
code: data.ossFileId,
|
||||
name : data.name,
|
||||
ossName : data.ossFileName,
|
||||
download: data.donwloadLink,
|
||||
content: JSON.stringify(data),
|
||||
}, tables, dbClient)
|
||||
|
||||
//不返回下载链接
|
||||
delete data.donwloadLink;
|
||||
socket.emit(rtcClientEvent.addCodeFile, data);
|
||||
|
||||
}catch(e){
|
||||
utils.tlConsole(e)
|
||||
socket.emit("tips", {
|
||||
room: data.room,
|
||||
to: socket.id,
|
||||
msg: "系统错误"
|
||||
});
|
||||
bussinessNotify.sendSystemErrorMsg({
|
||||
title: "socket-addCodeFile",
|
||||
room: data.room,
|
||||
from : socket.id,
|
||||
msg : JSON.stringify({
|
||||
message: e.message,
|
||||
fileName: e.fileName,
|
||||
lineNumber: e.lineNumber,
|
||||
stack: e.stack,
|
||||
name: e.name
|
||||
}, null, '\t')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
addCodeFile
|
||||
}
|
89
svr/src/socket/rtcCodeFile/getCodeFile.js
Normal file
89
svr/src/socket/rtcCodeFile/getCodeFile.js
Normal file
@@ -0,0 +1,89 @@
|
||||
const rtcConstant = require("../rtcConstant");
|
||||
const rtcClientEvent = rtcConstant.rtcClientEvent
|
||||
const daoDog = require("./../../dao/dog/dog")
|
||||
const bussinessNotify = require("./../../bussiness/notify/notifyHandler")
|
||||
const utils = require("./../../utils/utils");
|
||||
const daoFile = require("./../../dao/file/file")
|
||||
const rtcCommData = require("./../rtcCommData/commData");
|
||||
|
||||
/**
|
||||
* 取件码取件
|
||||
* @param {*} io socketio对象
|
||||
* @param {*} socket 单个socket连接
|
||||
* @param {*} tables 数据表对象
|
||||
* @param {*} dbClient sequelize-orm对象
|
||||
* @param {*} data event参数
|
||||
* @returns
|
||||
*/
|
||||
async function getCodeFile(io, socket, tables, dbClient, data){
|
||||
try{
|
||||
let cacheSwitchData = rtcCommData.getCacheSwitchData()
|
||||
|
||||
if(!cacheSwitchData.openGetCodeFile){
|
||||
socket.emit(rtcClientEvent.tips, {
|
||||
room: data.room,
|
||||
to: socket.id,
|
||||
msg: "当前功能已暂时关闭,有问题可以加群交流"
|
||||
});
|
||||
return
|
||||
}
|
||||
|
||||
let {handshake, userAgent, ip} = utils.getSocketClientInfo(socket);
|
||||
|
||||
let codeFile = await daoFile.getCodeFile({
|
||||
code : data.code
|
||||
}, tables, dbClient)
|
||||
|
||||
if(codeFile){
|
||||
Object.assign(data, codeFile)
|
||||
}
|
||||
|
||||
utils.tlConsole("取件码取件 : ",data)
|
||||
|
||||
bussinessNotify.getCodeFileNotify({
|
||||
title: "取件码取件",
|
||||
room: data.room,
|
||||
from: data.from,
|
||||
code : data.code,
|
||||
userAgent: userAgent,
|
||||
ip: ip
|
||||
})
|
||||
|
||||
await daoDog.addDogData({
|
||||
name: "取件码取件",
|
||||
roomId: data.room || "",
|
||||
socketId: socket.id,
|
||||
device: userAgent,
|
||||
flag: 0,
|
||||
content: JSON.stringify(data),
|
||||
handshake: JSON.stringify(handshake),
|
||||
ip: ip
|
||||
}, tables, dbClient);
|
||||
|
||||
socket.emit(rtcClientEvent.getCodeFile, data);
|
||||
|
||||
}catch(e){
|
||||
utils.tlConsole(e)
|
||||
socket.emit("tips", {
|
||||
room: data.room,
|
||||
to: socket.id,
|
||||
msg: "系统错误"
|
||||
});
|
||||
bussinessNotify.sendSystemErrorMsg({
|
||||
title: "socket-getCodeFile",
|
||||
room: data.room,
|
||||
from : socket.id,
|
||||
msg : JSON.stringify({
|
||||
message: e.message,
|
||||
fileName: e.fileName,
|
||||
lineNumber: e.lineNumber,
|
||||
stack: e.stack,
|
||||
name: e.name
|
||||
}, null, '\t')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getCodeFile
|
||||
}
|
108
svr/src/socket/rtcCodeFile/prepareCodeFile.js
Normal file
108
svr/src/socket/rtcCodeFile/prepareCodeFile.js
Normal file
@@ -0,0 +1,108 @@
|
||||
const rtcConstant = require("../rtcConstant");
|
||||
const rtcClientEvent = rtcConstant.rtcClientEvent
|
||||
const daoDog = require("./../../dao/dog/dog")
|
||||
const bussinessNotify = require("./../../bussiness/notify/notifyHandler")
|
||||
const utils = require("./../../utils/utils");
|
||||
const seafile = require("./../../bussiness/oss/seafile")
|
||||
const rtcCommData = require("./../rtcCommData/commData");
|
||||
|
||||
/**
|
||||
* 生成取件码上传链接
|
||||
* @param {*} io socketio对象
|
||||
* @param {*} socket 单个socket连接
|
||||
* @param {*} tables 数据表对象
|
||||
* @param {*} dbClient sequelize-orm对象
|
||||
* @param {*} data event参数
|
||||
* @returns
|
||||
*/
|
||||
async function prepareCodeFile(io, socket, tables, dbClient, data){
|
||||
try{
|
||||
|
||||
let cacheSwitchData = rtcCommData.getCacheSwitchData()
|
||||
|
||||
if(!cacheSwitchData.openGetCodeFile){
|
||||
socket.emit(rtcClientEvent.tips, {
|
||||
room: data.room,
|
||||
to: socket.id,
|
||||
msg: "当前功能已暂时关闭,有问题可以加群交流"
|
||||
});
|
||||
return
|
||||
}
|
||||
|
||||
let {handshake, userAgent, ip} = utils.getSocketClientInfo(socket);
|
||||
|
||||
let fileSize = data.size || 0;
|
||||
|
||||
if(fileSize > 1024 * 1024 * 10){
|
||||
socket.emit("tips", {
|
||||
room: data.room,
|
||||
to: socket.id,
|
||||
msg: "文件太大,暂不支持"
|
||||
});
|
||||
return
|
||||
}
|
||||
|
||||
const ossToken = await seafile.seafileGetToken();
|
||||
|
||||
data.uploadLink = "";
|
||||
|
||||
if(ossToken){
|
||||
let uploadLink = await seafile.seafileGetUploadLink(ossToken);
|
||||
uploadLink = uploadLink.replace(/^(\s|\")+|(\s|\")+$/g, '') + "?ret-json=1";
|
||||
data.uploadLink = uploadLink;
|
||||
data.replace = 0;
|
||||
data.parent_dir = "/";
|
||||
}
|
||||
|
||||
utils.tlConsole("获取上传链接成功 : ",data.uploadLink)
|
||||
|
||||
bussinessNotify.prepareCodeFileNotify({
|
||||
title: "生成取件码上传链接",
|
||||
room: data.room,
|
||||
from: data.from,
|
||||
name: data.name,
|
||||
type: data.type,
|
||||
size: data.size,
|
||||
link : data.uploadLink,
|
||||
userAgent: userAgent,
|
||||
ip: ip
|
||||
})
|
||||
|
||||
await daoDog.addDogData({
|
||||
name: "生成取件码上传链接",
|
||||
roomId: data.room || "",
|
||||
socketId: socket.id,
|
||||
device: userAgent,
|
||||
flag: 0,
|
||||
content: JSON.stringify(data),
|
||||
handshake: JSON.stringify(handshake),
|
||||
ip: ip
|
||||
}, tables, dbClient);
|
||||
|
||||
socket.emit(rtcClientEvent.prepareCodeFile, data);
|
||||
|
||||
}catch(e){
|
||||
utils.tlConsole(e)
|
||||
socket.emit("tips", {
|
||||
room: data.room,
|
||||
to: socket.id,
|
||||
msg: "系统错误"
|
||||
});
|
||||
bussinessNotify.sendSystemErrorMsg({
|
||||
title: "socket-prepareCodeFile",
|
||||
room: data.room,
|
||||
from : socket.id,
|
||||
msg : JSON.stringify({
|
||||
message: e.message,
|
||||
fileName: e.fileName,
|
||||
lineNumber: e.lineNumber,
|
||||
stack: e.stack,
|
||||
name: e.name
|
||||
}, null, '\t')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
prepareCodeFile
|
||||
}
|
109
svr/src/socket/rtcCommData/commData.js
Normal file
109
svr/src/socket/rtcCommData/commData.js
Normal file
@@ -0,0 +1,109 @@
|
||||
const daoRoom = require("./../../dao/room/room")
|
||||
const daoDog = require("./../../dao/dog/dog")
|
||||
const utils = require("./../../utils/utils");
|
||||
const rtcConstant = require("../rtcConstant");
|
||||
const rtcClientEvent = rtcConstant.rtcClientEvent
|
||||
|
||||
// 公共聊天数据缓存
|
||||
let chatingComm = null
|
||||
// 开关数据缓存
|
||||
let cacheSwitchData = null
|
||||
|
||||
/**
|
||||
* 获取初始数据
|
||||
* @param {*} io socketio对象
|
||||
* @param {*} socket 单个socket连接
|
||||
* @param {*} tables 数据表对象
|
||||
* @param {*} dbClient sequelize-orm对象
|
||||
* @param {*} data event参数
|
||||
* @returns
|
||||
*/
|
||||
async function getCommData(io, socket, tables, dbClient, data){
|
||||
try{
|
||||
|
||||
let {handshake, userAgent, ip} = utils.getSocketClientInfo(socket);
|
||||
|
||||
let manageInfo = await daoRoom.getOrCreateManageRoom({
|
||||
sid: socket.id,
|
||||
ip: ip,
|
||||
device: userAgent,
|
||||
}, tables, dbClient)
|
||||
let switchData = JSON.parse(manageInfo.content)
|
||||
if(switchData){
|
||||
cacheSwitchData = switchData
|
||||
}
|
||||
|
||||
if(!chatingComm){
|
||||
chatingComm = await daoDog.getDogChating10Info({
|
||||
limit : 10
|
||||
}, tables, dbClient);
|
||||
}
|
||||
|
||||
socket.emit(rtcClientEvent.commData,{
|
||||
switchData : switchData,
|
||||
chatingCommData : chatingComm || []
|
||||
});
|
||||
|
||||
}catch(e){
|
||||
utils.tlConsole(e)
|
||||
socket.emit("tips", {
|
||||
room: data.room,
|
||||
to: socket.id,
|
||||
msg: "系统错误"
|
||||
});
|
||||
bussinessNotify.sendSystemErrorMsg({
|
||||
title: "socket-commData",
|
||||
room: data.room,
|
||||
from : socket.id,
|
||||
msg : JSON.stringify({
|
||||
message: e.message,
|
||||
fileName: e.fileName,
|
||||
lineNumber: e.lineNumber,
|
||||
stack: e.stack,
|
||||
name: e.name
|
||||
}, null, '\t')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 chatingComm
|
||||
* @returns
|
||||
*/
|
||||
function getChatingComm(){
|
||||
return chatingComm;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新 chatingComm
|
||||
* @returns
|
||||
*/
|
||||
function setChatingComm(data){
|
||||
chatingComm = data
|
||||
return chatingComm;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 cacheSwitchData
|
||||
* @returns
|
||||
*/
|
||||
function getCacheSwitchData(){
|
||||
return cacheSwitchData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新 cacheSwitchData
|
||||
* @param {*} data
|
||||
*/
|
||||
function setCacheSwitchData(data){
|
||||
cacheSwitchData = data
|
||||
return cacheSwitchData;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getCommData,
|
||||
getCacheSwitchData,
|
||||
setCacheSwitchData,
|
||||
getChatingComm,
|
||||
setChatingComm
|
||||
}
|
146
svr/src/socket/rtcConstant.js
Normal file
146
svr/src/socket/rtcConstant.js
Normal file
@@ -0,0 +1,146 @@
|
||||
|
||||
/**
|
||||
* 服务端监听事件
|
||||
* event事件名称
|
||||
*/
|
||||
const rtcServerEvent = {
|
||||
//socket连接
|
||||
connection : "connection",
|
||||
//socket断开连接
|
||||
disconnect : "disconnect",
|
||||
//webrtc offer
|
||||
offer : "offer",
|
||||
//webrtc answer
|
||||
answer : "answer",
|
||||
//webrtc candidate
|
||||
candidate : "candidate",
|
||||
//在线人数
|
||||
count : "count",
|
||||
//退出
|
||||
exit : "exit",
|
||||
//获取初始化数据
|
||||
getCommData : "getCommData",
|
||||
//加入/创建房间
|
||||
createAndJoin : "createAndJoin",
|
||||
//检查管理员房间密码
|
||||
manageConfirm : "manageConfirm",
|
||||
//管理员修改数据
|
||||
manageChange : "manageChange",
|
||||
//管理员刷新页面数据
|
||||
manageReload : "manageReload",
|
||||
//通用公共消息
|
||||
message : "message",
|
||||
//公共聊天
|
||||
chatingComm : "chatingComm",
|
||||
//chatgpt
|
||||
openai : "openai",
|
||||
//远程控制
|
||||
control : "control",
|
||||
//canvas画图
|
||||
draw : "draw",
|
||||
//房间内聊天, 群聊/私聊
|
||||
chatingRoom : "chatingRoom",
|
||||
//准备添加取件码文件,获取上传链接
|
||||
prepareCodeFile : "prepareCodeFile",
|
||||
//添加取件码文件
|
||||
addCodeFile : "addCodeFile",
|
||||
//获取取件码文件
|
||||
getCodeFile : "getCodeFile",
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务端监听事件
|
||||
* message event子事件
|
||||
*/
|
||||
let rtcServerMessageEvent = {
|
||||
//准备发送文件
|
||||
sendFileInfo : "sendFileInfo",
|
||||
//发送文件完毕
|
||||
sendDone : "sendDone",
|
||||
//反馈bug
|
||||
sendBugs : "sendBugs",
|
||||
//开始录屏
|
||||
startScreen : "startScreen",
|
||||
//结束录屏
|
||||
stopScreen : "stopScreen",
|
||||
//开始屏幕共享
|
||||
startScreenShare : "startScreenShare",
|
||||
//结束共享
|
||||
stopScreenShare : "stopScreenShare",
|
||||
//开始音视频
|
||||
startVideoShare : "startVideoShare",
|
||||
//结束音视频
|
||||
stopVideoShare : "stopVideoShare",
|
||||
//开始直播
|
||||
startLiveShare : "startLiveShare",
|
||||
// 结束直播
|
||||
stopLiveShare : "stopLiveShare",
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户端监听事件
|
||||
* event事件名称
|
||||
*/
|
||||
let rtcClientEvent = {
|
||||
//创建房间
|
||||
created : "created",
|
||||
//加入房间
|
||||
joined : "joined",
|
||||
//webrtc offer
|
||||
offer : "offer",
|
||||
//webrtc answer
|
||||
answer : "answer",
|
||||
//webrtc candidate
|
||||
candidate : "candidate",
|
||||
//退出
|
||||
exit : "exit",
|
||||
//人数
|
||||
count : "count",
|
||||
//提示
|
||||
tips : "tips",
|
||||
//ai回复
|
||||
openaiAnswer : "openaiAnswer",
|
||||
//初始化数据
|
||||
commData : "commData",
|
||||
//公共聊天
|
||||
chatingComm : "chatingComm",
|
||||
//检查管理员房间密码
|
||||
manageCheck : "manageCheck",
|
||||
//管理员页面
|
||||
manage : "manage",
|
||||
//远程控制
|
||||
control : "control",
|
||||
//画图
|
||||
draw : "draw",
|
||||
//房间内聊天, 群聊/私聊
|
||||
chatingRoom : "chatingRoom",
|
||||
//准备添加取件码文件,获取上传链接
|
||||
prepareCodeFile : "prepareCodeFile",
|
||||
//添加取件码文件
|
||||
addCodeFile : "addCodeFile",
|
||||
//获取取件码文件
|
||||
getCodeFile : "getCodeFile",
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户端监听事件
|
||||
* message event子事件
|
||||
*/
|
||||
let rtcClientMessageEvent = {
|
||||
//准备发送文件
|
||||
sendFileInfo : "sendFileInfo",
|
||||
//准备接受文件
|
||||
sendFileInfoAck : "sendFileInfoAck",
|
||||
//停止屏幕共享
|
||||
stopScreenShare : "stopScreenShare",
|
||||
// 停止音视频
|
||||
stopVideoShare : "stopVideoShare",
|
||||
//停止直播
|
||||
stopLiveShare : "stopLiveShare",
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
rtcServerEvent, rtcServerMessageEvent,
|
||||
rtcClientEvent, rtcClientMessageEvent,
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user