trtc-cloud-js-sdk 1.0.13 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/.eslintrc.js +88 -0
  2. package/.prettierrc +5 -0
  3. package/CHANGELOG.md +58 -0
  4. package/build/jsdoc/clean-doc.js +12 -0
  5. package/build/jsdoc/fix-doc.js +141 -0
  6. package/build/jsdoc/jsdoc.json +42 -0
  7. package/build/package-bundle.js +29 -0
  8. package/build/rollup.config.dev.js +88 -0
  9. package/build/rollup.config.prod.js +93 -0
  10. package/build/rollup.js +359 -0
  11. package/build/template/npm-package/package.json +24 -0
  12. package/coverage/Chrome 103.0.5060 (Mac OS X 10.15.7)/base.css +213 -0
  13. package/coverage/Chrome 103.0.5060 (Mac OS X 10.15.7)/index.html +80 -0
  14. package/coverage/Chrome 103.0.5060 (Mac OS X 10.15.7)/prettify.css +1 -0
  15. package/coverage/Chrome 103.0.5060 (Mac OS X 10.15.7)/prettify.js +1 -0
  16. package/coverage/Chrome 103.0.5060 (Mac OS X 10.15.7)/sort-arrow-sprite.png +0 -0
  17. package/coverage/Chrome 103.0.5060 (Mac OS X 10.15.7)/sorter.js +158 -0
  18. package/examples/apiExample/.env +2 -0
  19. package/examples/apiExample/README.md +70 -0
  20. package/examples/apiExample/package-lock.json +30915 -0
  21. package/examples/apiExample/package.json +51 -0
  22. package/examples/apiExample/public/audio.js +195 -0
  23. package/examples/apiExample/public/audio.js.map +7 -0
  24. package/examples/apiExample/public/av_processing.js +1 -0
  25. package/examples/apiExample/public/basic/av_processing.wasm +0 -0
  26. package/examples/apiExample/public/basic/worker.js +10434 -0
  27. package/examples/apiExample/public/favicon.ico +0 -0
  28. package/examples/apiExample/public/index.html +47 -0
  29. package/examples/apiExample/public/logo192.png +0 -0
  30. package/examples/apiExample/public/logo512.png +0 -0
  31. package/examples/apiExample/public/manifest.json +25 -0
  32. package/examples/apiExample/public/robots.txt +3 -0
  33. package/examples/apiExample/src/App.css +37 -0
  34. package/examples/apiExample/src/App.js +25 -0
  35. package/examples/apiExample/src/api/http.js +127 -0
  36. package/examples/apiExample/src/api/nav.js +44 -0
  37. package/examples/apiExample/src/components/BasicInfoComponent.css +16 -0
  38. package/examples/apiExample/src/components/BasicInfoComponent.js +27 -0
  39. package/examples/apiExample/src/config/gen-test-user-sig.js +64 -0
  40. package/examples/apiExample/src/config/lib-generate-test-usersig.min.js +7052 -0
  41. package/examples/apiExample/src/config/nav.js +136 -0
  42. package/examples/apiExample/src/home.js +16 -0
  43. package/examples/apiExample/src/index.css +21 -0
  44. package/examples/apiExample/src/index.js +12 -0
  45. package/examples/apiExample/src/logo.svg +1 -0
  46. package/examples/apiExample/src/page/basic/screen-share/index.css +52 -0
  47. package/examples/apiExample/src/page/basic/screen-share/index.js +223 -0
  48. package/examples/apiExample/src/page/basic/setDevice/index.js +262 -0
  49. package/examples/apiExample/src/page/basic/setDevice/index.scss +93 -0
  50. package/examples/apiExample/src/page/basic/video-call/index.js +521 -0
  51. package/examples/apiExample/src/page/basic/video-call/index.scss +93 -0
  52. package/examples/apiExample/src/page/basic/video-call-init/index.js +382 -0
  53. package/examples/apiExample/src/page/basic/video-call-init/index.scss +93 -0
  54. package/examples/apiExample/src/page/basic/video-live/index.css +37 -0
  55. package/examples/apiExample/src/page/basic/video-live/index.js +188 -0
  56. package/examples/apiExample/src/page/layout.js +22 -0
  57. package/examples/apiExample/src/page/layout.scss +76 -0
  58. package/examples/apiExample/src/utils/utils.js +35 -0
  59. package/examples/jsExample/assets/css/bootstrap-material-design.css +12169 -0
  60. package/examples/jsExample/assets/css/bootstrap-material-design.min.css +8 -0
  61. package/examples/jsExample/assets/css/common.css +48 -0
  62. package/examples/jsExample/assets/icon/iconfont.js +1 -0
  63. package/examples/jsExample/assets/js/bootstrap-material-design.js +6939 -0
  64. package/examples/jsExample/assets/js/bootstrap-material-design.js.map +1 -0
  65. package/examples/jsExample/assets/js/bootstrap-material-design.min.js +1 -0
  66. package/examples/jsExample/assets/js/graph.js +695 -0
  67. package/examples/jsExample/assets/js/jquery-3.2.1.min.js +4 -0
  68. package/examples/jsExample/assets/js/jquery-3.2.1.slim.min.js +4 -0
  69. package/examples/jsExample/assets/js/lib-generate-test-usersig.min.js +2 -0
  70. package/examples/jsExample/assets/js/popper.js +2442 -0
  71. package/examples/jsExample/index.html +57 -0
  72. package/examples/jsExample/rtc/css/common.css +82 -0
  73. package/examples/jsExample/rtc/index.html +107 -0
  74. package/examples/jsExample/rtc/js/index.js +142 -0
  75. package/examples/vueDemo/LICENSE +21 -0
  76. package/examples/vueDemo/README.md +144 -0
  77. package/examples/vueDemo/README_EN.md +136 -0
  78. package/examples/vueDemo/av_processing.wasm +0 -0
  79. package/examples/vueDemo/index.html +23 -0
  80. package/examples/vueDemo/package-lock.json +1375 -0
  81. package/examples/vueDemo/package.json +36 -0
  82. package/examples/vueDemo/src/App.vue +12 -0
  83. package/examples/vueDemo/src/api/index.js +59 -0
  84. package/examples/vueDemo/src/assets/css/color-dark.css +28 -0
  85. package/examples/vueDemo/src/assets/css/icon.css +4 -0
  86. package/examples/vueDemo/src/assets/css/main.css +177 -0
  87. package/examples/vueDemo/src/assets/img/img.jpg +0 -0
  88. package/examples/vueDemo/src/assets/img/login-bg.jpg +0 -0
  89. package/examples/vueDemo/src/components/Header.vue +172 -0
  90. package/examples/vueDemo/src/components/Sidebar.vue +117 -0
  91. package/examples/vueDemo/src/components/Tags.vue +174 -0
  92. package/examples/vueDemo/src/components/tendency.vue +206 -0
  93. package/examples/vueDemo/src/components/trtc/main-menu.vue +50 -0
  94. package/examples/vueDemo/src/components/trtc/nav-bar.vue +53 -0
  95. package/examples/vueDemo/src/components/trtc/show-screen-capture.vue +118 -0
  96. package/examples/vueDemo/src/components/trtc/trtc-state-check.vue +117 -0
  97. package/examples/vueDemo/src/config/gen-test-user-sig.js +67 -0
  98. package/examples/vueDemo/src/config/lib-generate-test-usersig.min.js +7052 -0
  99. package/examples/vueDemo/src/main.js +11 -0
  100. package/examples/vueDemo/src/plugins/element.js +17 -0
  101. package/examples/vueDemo/src/router/index.js +73 -0
  102. package/examples/vueDemo/src/store/sidebar.js +17 -0
  103. package/examples/vueDemo/src/store/tags.js +48 -0
  104. package/examples/vueDemo/src/utils/i18n.js +24 -0
  105. package/examples/vueDemo/src/utils/request.js +34 -0
  106. package/examples/vueDemo/src/utils/utils.js +35 -0
  107. package/examples/vueDemo/src/views/Home.vue +46 -0
  108. package/examples/vueDemo/src/views/I18n.vue +40 -0
  109. package/examples/vueDemo/src/views/Icon.vue +229 -0
  110. package/examples/vueDemo/src/views/basic/trtc.vue +194 -0
  111. package/examples/vueDemo/src/views/feature/index.vue +259 -0
  112. package/examples/vueDemo/src/views/github/index.vue +243 -0
  113. package/examples/vueDemo/src/views/improve/live-index.vue +256 -0
  114. package/examples/vueDemo/src/views/improve/live-room-anchor.vue +689 -0
  115. package/examples/vueDemo/src/views/improve/live-room-audience.vue +383 -0
  116. package/examples/vueDemo/src/views/sdkAppId/index.vue +284 -0
  117. package/examples/vueDemo/vite.config.js +18 -0
  118. package/examples/vueDemo/worker.js +22 -0
  119. package/karma.conf.js +99 -0
  120. package/package.json +57 -7
  121. package/scripts/publish.js +86 -0
  122. package/src/Camera.ts +80 -0
  123. package/src/Mic.ts +145 -0
  124. package/src/common/IError.ts +6 -0
  125. package/src/common/ITRTCCloud.ts +68 -0
  126. package/src/common/constants.ts +116 -0
  127. package/src/common/trtc-code.ts +43 -0
  128. package/src/common/trtc-define.ts +1007 -0
  129. package/src/common/trtc-event.ts +29 -0
  130. package/src/index.ts +1672 -0
  131. package/src/utils/environment.js +297 -0
  132. package/src/utils/raf.js +131 -0
  133. package/src/utils/time.js +22 -0
  134. package/src/utils/utils.ts +71 -0
  135. package/src/utils/uuid.js +12 -0
  136. package/test/unit/env.test.js +25 -0
  137. package/test/unit/get-user-media.test.js +40 -0
  138. package/test/unit/ice-parser.test.js +23 -0
  139. package/test/unit/sdp.test.js +45 -0
  140. package/test/unit/signal.test.js +78 -0
  141. package/tsconfig.json +32 -0
  142. package/trtc-cloud-js-sdk.js +0 -1
  143. /package/{README.md → build/template/npm-package/README.md} +0 -0
@@ -0,0 +1,194 @@
1
+ <template>
2
+ <div class="content-container">
3
+ <div class="params-container">
4
+ <el-input v-model="userId" placeholder="Please input userId">
5
+ <template #prepend>UserId</template>
6
+ </el-input>
7
+ <el-input v-model="roomId" placeholder="Please input roomId" class="params-item">
8
+ <template #prepend>RoomId</template>
9
+ </el-input>
10
+
11
+ <div class="operate-area">
12
+ <div class="operate-group">
13
+ <el-button type="primary" plain @click="handleEnterRoom">进房</el-button>
14
+ <el-button type="primary" plain @click="handleExitRoom">退房</el-button>
15
+ </div>
16
+ <div class="operate-group">
17
+ <el-button type="primary" plain @click="handleStartLocalPreview">打开视频</el-button>
18
+ <el-button type="primary" plain @click="handleStopLocalPreview">关闭视频</el-button>
19
+ </div>
20
+ <div class="operate-group">
21
+ <el-button type="primary" plain @click="handleStartLocalAudio">打开音频</el-button>
22
+ <el-button type="primary" plain @click="handleStopLocalAudio">关闭音频</el-button>
23
+ </div>
24
+ </div>
25
+ </div>
26
+ <div class="view-container">
27
+ <div id="local-view-container"></div>
28
+ <div v-for="(userId, idx) in remoteUserList" :id="userId" :key="userId + '-' + idx" class="remote-view-container">
29
+ </div>
30
+ </div>
31
+ </div>
32
+ </template>
33
+
34
+ <script>
35
+ console.warn('=============')
36
+ import { defineComponent, toRefs, reactive, onMounted, onUnmounted, watch, nextTick } from 'vue';
37
+ import TRTCCloud, { TRTCAppScene, TRTCParams, TRTCVideoStreamType } from 'trtc-cloud-js-sdk';
38
+ import genTestUserSig from '@/config/gen-test-user-sig';
39
+ import { validParams } from '@/utils/utils';
40
+ const trtcCloud = new TRTCCloud();
41
+ const LOG_PREFIX = '[Video Call]';
42
+ let preRemoteUserIdList = [];
43
+
44
+ const TRTCCall = defineComponent({
45
+ name: 'TTTCCall',
46
+ components: {},
47
+ setup() {
48
+ const data = reactive({
49
+ sdkAppId: 0,
50
+ userId: 'TRTCCloud_' + parseInt(Math.random() * 100000),
51
+ roomId: parseInt(Math.random() * 100000) + '',
52
+ remoteUserList: [],
53
+ });
54
+ // Registers a callback to be called after the component has been mounted
55
+ onMounted(() => {
56
+ // 注册监听事件
57
+ trtcCloud.on('onError', (error) => {
58
+ console.error('onError ', error);
59
+ });
60
+ trtcCloud.on('onEnterRoom', (res) => { });
61
+ trtcCloud.on('onExitRoom', (res) => { });
62
+ trtcCloud.on('onRemoteUserEnterRoom', (res) => { });
63
+ trtcCloud.on('onRemoteUserLeaveRoom', (res) => { });
64
+ trtcCloud.on('onUserVideoAvailable', async (userId, available) => {
65
+ if (available) {
66
+ if (preRemoteUserIdList.indexOf(userId) === -1) {
67
+ preRemoteUserIdList = [...preRemoteUserIdList, userId];
68
+ }
69
+ } else {
70
+ preRemoteUserIdList = preRemoteUserIdList.filter((str) => str !== userId);
71
+ }
72
+ data.remoteUserList = preRemoteUserIdList;
73
+ await nextTick();
74
+ if (available) {
75
+ const domElement = document.getElementById(userId);
76
+ domElement && await trtcCloud.startRemoteView(userId, domElement, TRTCVideoStreamType.TRTCVideoStreamTypeBig);
77
+ }
78
+ });
79
+ trtcCloud.on('onUserAudioAvailable', (res) => { });
80
+ trtcCloud.on('onFirstVideoFrame', (res) => { });
81
+ trtcCloud.on('onUserVoiceVolume', (res) => { });
82
+ trtcCloud.on('onUserSubStreamAvailable', (res) => { });
83
+ });
84
+ // 进房
85
+ const handleEnterRoom = async () => {
86
+ const { sdkappid: sdkAppId, userSig } = genTestUserSig(data.userId);
87
+ data.sdkAppId = sdkAppId;
88
+ data.userSig = userSig;
89
+ // handleStartLocalPreview();
90
+ const trtcParams = new TRTCParams();
91
+ trtcParams.userId = data.userId;
92
+ trtcParams.sdkAppId = sdkAppId;
93
+ trtcParams.userSig = userSig;
94
+ trtcParams.roomId = +data.roomId;
95
+ console.warn('-- 开发进房')
96
+ await trtcCloud.enterRoom(trtcParams, TRTCAppScene.TRTCAppSceneVideoCall);
97
+ // await trtcCloud.startLocalAudio();
98
+ };
99
+ // 打开视频
100
+ const handleStartLocalPreview = async () => {
101
+ const localVideoWrapper = document.getElementById('local-view-container');
102
+ await trtcCloud.startLocalPreview(localVideoWrapper);
103
+ };
104
+ // 关闭视频
105
+ const handleStopLocalPreview = async () => {
106
+ await trtcCloud.stopLocalPreview();
107
+ };
108
+ // 打开音频
109
+ const handleStartLocalAudio = async () => {
110
+ await trtcCloud.startLocalAudio();
111
+ };
112
+ // 关闭音频
113
+ const handleStopLocalAudio = async () => {
114
+ await trtcCloud.topLocalAudio();
115
+ };
116
+ // 退房
117
+ const handleExitRoom = async () => {
118
+ dataReset();
119
+ await handleStopLocalPreview();
120
+ await handleStopLocalAudio();
121
+ trtcCloud.exitRoom();
122
+ unsubscribeEvents();
123
+ };
124
+ // onUnmounted
125
+ onUnmounted(() => {
126
+ handleExitRoom();
127
+ });
128
+ // data reset
129
+ const dataReset = () => {
130
+ data.remoteUserList = [];
131
+ preRemoteUserIdList = [];
132
+ };
133
+ // 解除所有的事件绑定
134
+ const unsubscribeEvents = () => {
135
+ trtcCloud.off('*');
136
+ };
137
+
138
+ return {
139
+ ...toRefs(data),
140
+ handleEnterRoom,
141
+ handleExitRoom,
142
+ handleStartLocalPreview,
143
+ handleStopLocalPreview,
144
+ handleStartLocalAudio,
145
+ handleStopLocalAudio,
146
+ };
147
+ }
148
+ });
149
+ export default TRTCCall;
150
+ </script>
151
+ <style lang="less" scoped>
152
+ .content-container {
153
+ display: flex;
154
+ flex-direction: raw;
155
+
156
+ .params-container {
157
+ margin: 8px 4px;
158
+ width: 260px;
159
+
160
+ .params-item {
161
+ margin-top: 4px;
162
+ }
163
+
164
+ .operate-area {
165
+ margin-top: 8px;
166
+
167
+ .operate-group {
168
+ display: flex;
169
+ justify-content: space-between;
170
+ margin-top: 4px;
171
+ }
172
+
173
+ .operate-group:first-child {
174
+ margin-top: 0px;
175
+ }
176
+ }
177
+ }
178
+
179
+ .view-container {
180
+ margin-top: 8px;
181
+
182
+ #local-view-container,
183
+ .remote-view-container {
184
+ width: 360px;
185
+ height: 240px;
186
+ margin-bottom: 8px;
187
+ }
188
+ }
189
+ }
190
+
191
+ .el-button {
192
+ width: 120px;
193
+ }
194
+ </style>
@@ -0,0 +1,259 @@
1
+ <template>
2
+ <div class="fillcontain">
3
+ <div class="query-container">
4
+ <div class="query-project-name">
5
+ <label for="project-name">项目:</label>
6
+ <el-select class="query-select-container" v-model="selectValue" placeholder="请选择" id="project-name"
7
+ @change="getFeature">
8
+ <el-option v-for="(item, idx) in selectProjectNameList" :key="item.value + '-' + idx" :label="item.name"
9
+ :value="item.value">
10
+ </el-option>
11
+ </el-select>
12
+ </div>
13
+
14
+ <label for="date-range" class="date-range-label">日期选择:</label>
15
+ <el-date-picker class="date-range" v-model="dateRange" type="daterange" @blur="getFeature" placeholder="选择日期范围">
16
+ </el-date-picker>
17
+ </div>
18
+ <tendency :sevenDate='sevenDate' :sevenDay='sevenDay' :title='graphicTitle' :legend="legend" :loading="loading"
19
+ :graphType="graphType">
20
+ </tendency>
21
+ <div v-if="featureContent" class="feature-content">{{ featureContent }}</div>
22
+ <div class="table_container">
23
+ <el-table v-loading="tableLoading" :data="tableData" style="width: 100%" border>
24
+ <el-table-column v-for="(item, index) in headerTable" :key="index" :label="item.label" :prop="item.name">
25
+ </el-table-column>
26
+ </el-table>
27
+ </div>
28
+ </div>
29
+ </template>
30
+
31
+ <script>
32
+ import dayjs from "dayjs";
33
+ import tendency from '@/components/tendency.vue';
34
+ import {
35
+ getProjectName,
36
+ getFeatureList,
37
+ } from "@/api/index";
38
+ import { getUrlParam } from "@/utils/utils";
39
+
40
+ export default {
41
+ data() {
42
+ return {
43
+ headerTable: [
44
+ {
45
+ label: "统计项",
46
+ name: "name",
47
+ },
48
+ {
49
+ label: "渗透率占比",
50
+ name: "value",
51
+ },
52
+ {
53
+ label: "计算规则",
54
+ name: "calculateRule",
55
+ },
56
+ ],
57
+ tableData: [],
58
+ graphicTitle: '渗透率',
59
+ sevenDay: [],
60
+ sevenDate: [],
61
+ legend: [],
62
+ selectProjectNameList: [],
63
+ preSelectValue: '', // 前面选择的项目名称, 用于对比选择是否改变, 从而减少请求
64
+ selectValue: '',
65
+ preDateRange: [], // 前面选择的日期选择范围, 用于对比时间是否改变, 从而减少请求
66
+ dateRange: [(new Date()).getTime() - 7 * 24 * 60 * 60 * 1000, (new Date()).getTime()], // 默认最近一周
67
+ loading: false,
68
+ tableLoading: false,
69
+ graphType: 'bar',
70
+ featureContent: '', // 渗透率字符串
71
+ };
72
+ },
73
+ created() {
74
+ this.initData();
75
+ },
76
+ mounted() {
77
+ const fromSource = getUrlParam('from') || '';
78
+ // 访问来源于小马时,隐藏侧边栏、项目选择项
79
+ if (fromSource === 'bi') {
80
+ document.querySelector('.sidebar').style.display = 'none'; // 隐藏侧边栏
81
+ document.querySelector('.header').style.display = 'none'; // 隐藏 header
82
+ document.querySelector('.tags').style.display = 'none'; // 隐藏 tags
83
+ document.querySelector('.query-project-name').style.display = 'none'; // 隐藏 select
84
+ document.querySelector('.content-box').style.position = 'static';
85
+ }
86
+ },
87
+ components: {
88
+ tendency,
89
+ },
90
+ methods: {
91
+ async initData() {
92
+ try {
93
+ await this.getProjectNameList();
94
+ await this.getFeature();
95
+ } catch (err) {
96
+ console.log("获取数据失败", err);
97
+ }
98
+ },
99
+ // 获取所有的项目名称列表
100
+ async getProjectNameList() {
101
+ const response = await getProjectName({ type: 'internal', source: 'feature' });
102
+ this.selectProjectNameList = response.data && response.data.projectNameList || [];
103
+ // 项目名称处理
104
+ const projectName = getUrlParam('projectName') || '';
105
+
106
+ this.selectValue = projectName.length > 0
107
+ ? projectName
108
+ : this.selectProjectNameList.length > 0
109
+ ? this.selectProjectNameList[0].name
110
+ : '';
111
+ this.preSelectValue = this.selectValue;
112
+ // 查询时间处理
113
+ let startTime = getUrlParam('startTime') || '';
114
+ let endTime = getUrlParam('endTime') || '';
115
+ startTime = startTime.includes('-') ? startTime : +startTime;
116
+ endTime = endTime.includes('-') ? endTime : +endTime;
117
+ // 字符串时间('2022-08-03 12:12:04')、时间戳时间(1658592000000),转成日期时间戳
118
+ if (startTime && endTime) { // url 中同时包含 startTime、endTime
119
+ startTime = dayjs(dayjs(startTime).format('YYYY-MM-DD HH:mm:ss')).valueOf();
120
+ endTime = dayjs(dayjs(endTime).format('YYYY-MM-DD HH:mm:ss')).valueOf();
121
+ } else if (!startTime && !endTime) { // url 中没有 startTime、endTime
122
+ startTime = (new Date()).getTime() - 15 * 24 * 60 * 60 * 1000;
123
+ endTime = (new Date()).getTime();
124
+ } else if (startTime && !endTime) { // url 中有 startTime 没有 endTime
125
+ startTime = dayjs(dayjs(startTime).format('YYYY-MM-DD')).valueOf();
126
+ endTime = dayjs(dayjs(startTime + 15 * 24 * 60 * 60 * 1000).format('YYYY-MM-DD')).valueOf();
127
+ } else if (!startTime && endTime) { // url 中没有 startTime 有 endTime
128
+ endTime = dayjs(dayjs(endTime).format('YYYY-MM-DD HH:mm:ss')).valueOf();
129
+ startTime = dayjs(dayjs(endTime - 15 * 24 * 60 * 60 * 1000).format('YYYY-MM-DD')).valueOf();
130
+ }
131
+ this.dateRange = [startTime, endTime];
132
+ },
133
+ // 获取新增 sdkAppId 数据
134
+ async getFeature() {
135
+ this.legend = [];
136
+ this.sevenDay = [];
137
+ this.sevenDate = [];
138
+ this.tableData = [];
139
+ this.featureContent = '';
140
+ const projectName = this.selectValue;
141
+ if (!projectName) {
142
+ return;
143
+ }
144
+ let startTimeStamps, endTimeStamps;
145
+ if (this.dateRange.length > 0) {
146
+ startTimeStamps = dayjs(dayjs(this.dateRange[0]).format('YYYY-MM-DD')).valueOf();
147
+ endTimeStamps = dayjs(dayjs(this.dateRange[1]).format('YYYY-MM-DD')).valueOf();
148
+ }
149
+ // 项目选择未改变且查询时间段未改变时, 不请求新的数据
150
+ if ((projectName === this.preSelectValue) && (this.preDateRange.join(',') === `${startTimeStamps},${endTimeStamps}`)) {
151
+ return;
152
+ }
153
+ this.preSelectValue = projectName;
154
+ this.preDateRange = [startTimeStamps, endTimeStamps];
155
+
156
+ try {
157
+ this.loading = true;
158
+ this.tableLoading = true;
159
+ const response = await getFeatureList({
160
+ projectName,
161
+ startTimeStamps,
162
+ endTimeStamps,
163
+ });
164
+ this.loading = false;
165
+ this.tableLoading = false;
166
+ if (response.code === 0) {
167
+ this.$message.success(`${response.message}`);
168
+ const { total, prefixContent, featureDataList, sdkAppId } = response.data || {};
169
+ this.featureContent = prefixContent;
170
+ this.graphicTitle = `${this.selectValue} 渗透率(${sdkAppId})`;
171
+ // this.legend = projectNameList;
172
+ this.sevenDay = featureDataList.map(obj => obj.name);
173
+ this.sevenDate = [featureDataList.map(obj => +(obj.value.replace('%', '')))];
174
+ this.tableData = featureDataList;
175
+ } else {
176
+ this.$message.error(`${response.message}`);
177
+ }
178
+ } catch (error) {
179
+ this.loading = false;
180
+ this.tableLoading = false;
181
+ }
182
+ },
183
+ },
184
+ };
185
+ </script>
186
+
187
+ <style lang="less">
188
+ .query-container {
189
+ display: flex;
190
+ padding: 20px;
191
+ align-items: center;
192
+
193
+ .date-range-label {
194
+ margin-left: 12px;
195
+ }
196
+
197
+ .query-select-container {
198
+ width: 260px;
199
+ }
200
+ }
201
+
202
+ .feature-content {
203
+ font-size: 12px;
204
+ color: #666;
205
+ padding: 0px 30px 10px;
206
+ }
207
+
208
+ .demo-table-expand {
209
+ font-size: 0;
210
+ }
211
+
212
+ .demo-table-expand label {
213
+ width: 90px;
214
+ color: #99a9bf;
215
+ }
216
+
217
+ .demo-table-expand .el-form-item {
218
+ margin-right: 0;
219
+ margin-bottom: 0;
220
+ width: 50%;
221
+ }
222
+
223
+ .table_container {
224
+ padding: 0px 20px 20px;
225
+ }
226
+
227
+ .Pagination {
228
+ display: flex;
229
+ justify-content: flex-start;
230
+ margin-top: 8px;
231
+ }
232
+
233
+ .avatar-uploader .el-upload {
234
+ border: 1px dashed #d9d9d9;
235
+ border-radius: 6px;
236
+ cursor: pointer;
237
+ position: relative;
238
+ overflow: hidden;
239
+ }
240
+
241
+ .avatar-uploader .el-upload:hover {
242
+ border-color: #20a0ff;
243
+ }
244
+
245
+ .avatar-uploader-icon {
246
+ font-size: 28px;
247
+ color: #8c939d;
248
+ width: 120px;
249
+ height: 120px;
250
+ line-height: 120px;
251
+ text-align: center;
252
+ }
253
+
254
+ .avatar {
255
+ width: 120px;
256
+ height: 120px;
257
+ display: block;
258
+ }
259
+ </style>
@@ -0,0 +1,243 @@
1
+ <template>
2
+ <div class="fillcontain">
3
+ <div class="query-container">
4
+ <div class="query-project-name">
5
+ <label for="project-name">仓库名:</label>
6
+ <el-select class="query-select-container" v-model="selectValue" placeholder="请选择" id="project-name"
7
+ @change="getGithubData">
8
+ <el-option v-for="(item, idx) in selectRepositoriesList" :key="item.value + '-' + idx" :label="item.name"
9
+ :value="item.value">
10
+ </el-option>
11
+ </el-select>
12
+ </div>
13
+ <label for="date-range" class="date-range-label">日期选择:</label>
14
+ <el-date-picker id="date-range" v-model="dateRange" type="daterange" @blur="getGithubData" placeholder="选择日期范围">
15
+ </el-date-picker>
16
+ </div>
17
+ <div v-if="tendencyList.length > 0">
18
+ <tendency v-for="(item, idx) in tendencyList" :key="idx" :sevenDate='item.list' :sevenDay='sevenDay'
19
+ :title='item.title' :legend="item.legend" :loading="loading" :domId="item.domId">
20
+ </tendency>
21
+ </div>
22
+ </div>
23
+ </template>
24
+
25
+ <script>
26
+ import dayjs from "dayjs";
27
+ import tendency from '@/components/tendency.vue';
28
+ import {
29
+ getRepositoriesList,
30
+ getGithubDataList,
31
+ } from "@/api/index";
32
+ import { getUrlParam } from "@/utils/utils";
33
+
34
+ export default {
35
+ data() {
36
+ return {
37
+ headerTable: [],
38
+ graphicTitle: 'Clone',
39
+ sevenDay: [],
40
+ sevenDate: [],
41
+ tendencyList: [],
42
+ legend: [],
43
+ selectRepositoriesList: [],
44
+ preSelectValue: [], // 前面选择的项目名称, 用于对比选择是否改变, 从而减少请求
45
+ selectValue: [],
46
+ preDateRange: [], // 前面选择的日期选择范围, 用于对比时间是否改变, 从而减少请求
47
+ dateRange: [(new Date()).getTime() - 30 * 24 * 60 * 60 * 1000, (new Date()).getTime()], // 默认最近一周
48
+ loading: false,
49
+ };
50
+ },
51
+ created() {
52
+ this.initData();
53
+ },
54
+ mounted() {
55
+ const fromSource = getUrlParam('from') || '';
56
+ // 访问来源于小马时,隐藏侧边栏、项目选择项
57
+ if (fromSource === 'bi') {
58
+ document.querySelector('.sidebar').style.display = 'none'; // 隐藏侧边栏
59
+ document.querySelector('.header').style.display = 'none'; // 隐藏 header
60
+ document.querySelector('.tags').style.display = 'none'; // 隐藏 tags
61
+ document.querySelector('.query-project-name').style.display = 'none'; // 隐藏 select
62
+ document.querySelector('.content-box').style.position = 'static';
63
+ }
64
+ },
65
+ components: {
66
+ tendency,
67
+ },
68
+ methods: {
69
+ async initData() {
70
+ try {
71
+ await this.getRepositories();
72
+ await this.getGithubData();
73
+ } catch (err) {
74
+ console.log("获取数据失败", err);
75
+ }
76
+ },
77
+ // 获取所有的项目名称列表
78
+ async getRepositories() {
79
+ const response = await getRepositoriesList();
80
+ const { repositoriesList = [] } = response.data || {};
81
+ this.selectRepositoriesList = repositoriesList.map(str => ({ name: str, value: str }));
82
+
83
+ // 项目名称处理
84
+ const projectName = getUrlParam('projectName') || '';
85
+ this.selectValue = projectName.length > 0 ? projectName : this.selectRepositoriesList[0].value;
86
+ this.preSelectValue = this.selectValue;
87
+ // 查询时间处理
88
+ let startTime = getUrlParam('startTime') || '';
89
+ let endTime = getUrlParam('endTime') || '';
90
+ startTime = startTime.includes('-') ? startTime : +startTime;
91
+ endTime = endTime.includes('-') ? endTime : +endTime;
92
+ // 字符串时间('2022-08-03 12:12:04')、时间戳时间(1658592000000),转成日期时间戳
93
+ if (startTime && endTime) { // url 中同时包含 startTime、endTime
94
+ startTime = dayjs(dayjs(startTime).format('YYYY-MM-DD HH:mm:ss')).valueOf();
95
+ endTime = dayjs(dayjs(endTime).format('YYYY-MM-DD HH:mm:ss')).valueOf();
96
+ } else if (!startTime && !endTime) { // url 中没有 startTime、endTime
97
+ startTime = (new Date()).getTime() - 30 * 24 * 60 * 60 * 1000;
98
+ endTime = (new Date()).getTime();
99
+ } else if (startTime && !endTime) { // url 中有 startTime 没有 endTime
100
+ startTime = dayjs(dayjs(startTime).format('YYYY-MM-DD')).valueOf();
101
+ endTime = dayjs(dayjs(startTime + 30 * 24 * 60 * 60 * 1000).format('YYYY-MM-DD')).valueOf();
102
+ } else if (!startTime && endTime) { // url 中没有 startTime 有 endTime
103
+ endTime = dayjs(dayjs(endTime).format('YYYY-MM-DD HH:mm:ss')).valueOf();
104
+ startTime = dayjs(dayjs(endTime - 30 * 24 * 60 * 60 * 1000).format('YYYY-MM-DD')).valueOf();
105
+ }
106
+ this.dateRange = [startTime, endTime];
107
+ },
108
+ // 获取新增 sdkAppId 数据
109
+ async getGithubData() {
110
+ const repoName = this.selectValue;
111
+ if (!repoName) {
112
+ return;
113
+ }
114
+ let startTimeStamps, endTimeStamps;
115
+ if (this.dateRange.length > 0) {
116
+ startTimeStamps = dayjs(dayjs(this.dateRange[0]).format('YYYY-MM-DD')).valueOf();
117
+ endTimeStamps = dayjs(dayjs(this.dateRange[1]).format('YYYY-MM-DD')).valueOf();
118
+ }
119
+ // 项目选择未改变且查询时间段未改变时, 不请求新的数据
120
+ if ((repoName === this.preSelectValue) && (this.preDateRange.join(',') === `${startTimeStamps},${endTimeStamps}`)) {
121
+ return;
122
+ }
123
+ this.preSelectValue = repoName;
124
+ this.preDateRange = [startTimeStamps, endTimeStamps];
125
+
126
+ try {
127
+ this.loading = true;
128
+ const response = await getGithubDataList({
129
+ repoName,
130
+ startTime: startTimeStamps,
131
+ endTime: endTimeStamps,
132
+ });
133
+ let tendencyList = [{ title: 'Clone', domId: 'Clone' }, { title: 'View', domId: 'View' }, { title: 'Popular', domId: 'Popular' }, { title: 'Referrer', domId: 'Referrer' }];
134
+ const { list = [] } = response.data || {};
135
+ this.sevenDay = list.map(obj => dayjs(+obj.timestamp).format('YYYY-MM-DD'));
136
+
137
+ list.forEach((obj, index) => {
138
+ const { clone, views, popular, referrer } = obj;
139
+ // clone 数据
140
+ tendencyList[0].legend = ['cloneCount', 'cloneUniques'];
141
+ tendencyList[0].cloneCountList = index > 0 ? [...tendencyList[0].cloneCountList, clone.count] : [clone.count];
142
+ tendencyList[0].cloneUniquesList = index > 0 ? [...tendencyList[0].cloneUniquesList, clone.uniques] : [clone.uniques];
143
+ // views 数据
144
+ tendencyList[1].legend = ['viewCount', 'viewUniques'];
145
+ tendencyList[1].viewCountList = index > 0 ? [...tendencyList[1].viewCountList, views.count] : [views.count];
146
+ tendencyList[1].viewUniquesList = index > 0 ? [...tendencyList[1].viewUniquesList, views.uniques] : [views.uniques];
147
+ // popular 数据
148
+ tendencyList[2].legend = popular.map(obj => obj.path.split('/').slice(-3).join('/'));
149
+ tendencyList[2].popularCountList = index > 0 ? [...tendencyList[2].popularCountList, popular.map(obj => obj.count)] : [popular.map(obj => obj.count)];
150
+ tendencyList[2].popularUniquesList = index > 0 ? [...tendencyList[2].popularUniquesList, popular.map(obj => obj.uniques)] : [popular.map(obj => obj.uniques)];
151
+ // referrer 数据
152
+ tendencyList[3].legend = referrer.map(obj => obj.referrer);
153
+ tendencyList[3].referrerCountList = index > 0 ? [...tendencyList[3].referrerCountList, referrer.map(obj => obj.count)] : [referrer.map(obj => obj.count)];
154
+ tendencyList[3].referrerUniquesList = index > 0 ? [...tendencyList[3].referrerUniquesList, referrer.map(obj => obj.uniques)] : [referrer.map(obj => obj.uniques)];
155
+ });
156
+ tendencyList[0].list = [tendencyList[0].cloneCountList, tendencyList[0].cloneUniquesList];
157
+ tendencyList[1].list = [tendencyList[1].viewCountList, tendencyList[1].viewUniquesList];
158
+ tendencyList[2].popularCountList = tendencyList[2].popularCountList[0].map((val, idx) => tendencyList[2].popularCountList.map(arr => arr[idx]));
159
+ tendencyList[2].popularUniquesList = tendencyList[2].popularUniquesList[0].map((val, idx) => tendencyList[2].popularUniquesList.map(arr => arr[idx]));
160
+ tendencyList[2].list = tendencyList[2].popularCountList;
161
+ tendencyList[3].referrerCountList = tendencyList[3].referrerCountList[0].map((val, idx) => tendencyList[3].referrerCountList.map(arr => arr[idx]));
162
+ tendencyList[3].referrerUniquesList = tendencyList[3].referrerUniquesList[0].map((val, idx) => tendencyList[3].referrerUniquesList.map(arr => arr[idx]));
163
+ tendencyList[3].list = tendencyList[3].referrerCountList;
164
+ this.tendencyList = tendencyList;
165
+
166
+ this.loading = false;
167
+ } catch (error) {
168
+ this.loading = false;
169
+ }
170
+ },
171
+ },
172
+ };
173
+ </script>
174
+
175
+ <style lang="less">
176
+ // @import "../style/mixin";
177
+
178
+ .query-container {
179
+ display: flex;
180
+ padding: 20px;
181
+ align-items: center;
182
+
183
+ .date-range-label {
184
+ margin-left: 12px;
185
+ }
186
+
187
+ .query-select-container {
188
+ width: 260px;
189
+ }
190
+ }
191
+
192
+ .demo-table-expand {
193
+ font-size: 0;
194
+ }
195
+
196
+ .demo-table-expand label {
197
+ width: 90px;
198
+ color: #99a9bf;
199
+ }
200
+
201
+ .demo-table-expand .el-form-item {
202
+ margin-right: 0;
203
+ margin-bottom: 0;
204
+ width: 50%;
205
+ }
206
+
207
+ .table_container {
208
+ padding: 20px;
209
+ }
210
+
211
+ .Pagination {
212
+ display: flex;
213
+ justify-content: flex-start;
214
+ margin-top: 8px;
215
+ }
216
+
217
+ .avatar-uploader .el-upload {
218
+ border: 1px dashed #d9d9d9;
219
+ border-radius: 6px;
220
+ cursor: pointer;
221
+ position: relative;
222
+ overflow: hidden;
223
+ }
224
+
225
+ .avatar-uploader .el-upload:hover {
226
+ border-color: #20a0ff;
227
+ }
228
+
229
+ .avatar-uploader-icon {
230
+ font-size: 28px;
231
+ color: #8c939d;
232
+ width: 120px;
233
+ height: 120px;
234
+ line-height: 120px;
235
+ text-align: center;
236
+ }
237
+
238
+ .avatar {
239
+ width: 120px;
240
+ height: 120px;
241
+ display: block;
242
+ }
243
+ </style>