@lambo-design-mobile/lambo-js-bridge 1.0.0-beta.22 → 1.0.0-beta.23

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.
package/CHANGELOG.md CHANGED
@@ -1,4 +1,11 @@
1
1
  # Changelog
2
+ ## [1.0.0-beta.23](http://git.inspur.com/ecbh/lambo-design/lambo-design/-/compare/@lambo-design-mobile/lambo-js-bridge@1.0.0-beta.22...@lambo-design-mobile/lambo-js-bridge@1.0.0-beta.23) (2025-02-28)
3
+
4
+
5
+ ### ✨ Features | 新功能
6
+
7
+ * **@lambo-design-mobile/js-bridge:** 更改录音功能调用方式 ([2aa9dd0](http://git.inspur.com/ecbh/lambo-design/lambo-design/-/commit/2aa9dd033c77b2cdb8f14787f3420f903da7e961))
8
+
2
9
  ## [1.0.0-beta.22](http://git.inspur.com/ecbh/lambo-design/lambo-design/-/compare/@lambo-design-mobile/lambo-js-bridge@1.0.0-beta.21...@lambo-design-mobile/lambo-js-bridge@1.0.0-beta.22) (2025-02-21)
3
10
 
4
11
 
package/README.md CHANGED
@@ -324,50 +324,66 @@ async openLocation() {
324
324
  data() {
325
325
  return {
326
326
  audioUrl: null, // 用于存储录音文件的 URL
327
- fileName: '', // 录音文件名
328
- fileSize: 0, // 录音文件大小
329
- fileType: '', // 录音文件类型
330
327
  recordingStatus: "not started", // 用于记录当前录音状态
331
- recordingOptions: {
332
- isAuto: false, // 是否自动录音
333
- fftSize: 512, // FFT 大小
334
- fileName: 'audio.ogg', // 默认录音文件名
335
- silenceThreshold: 100, // 静音检测音量阈值
336
- silenceDuration: 1000, // 静音持续时长
337
- silenceDelay: 2000 // 静音检测延迟
338
- }
339
328
  };
340
329
  },
341
- async startRecording() {
342
- try {
343
- this.recordingStatus = 'recording'; // 设置录音状态为进行中
344
- const { audioUrl, file } = await this.$lamboJsBridge.startRecording(this.recordingOptions);
345
- this.audioUrl = audioUrl; // 存储录音文件URL
346
- this.fileName = file.name; // 存储文件名
347
- this.fileSize = file.size; // 存储文件大小
348
- this.fileType = file.type; // 存储文件类型
349
- console.log(this.recordingOptions.isAuto ? '自动录音已开始' : '录音已开始');
350
- } catch (error) {
351
- console.error('录音失败:', error);
352
- this.recordingStatus = 'failed'; // 设置录音状态为失败
353
- }
354
- },
355
- async startAutoRecording() {
356
- // 启动自动录音
357
- this.recordingOptions.isAuto = true;
358
- await this.startRecording(); // 调用startRecording方法进行录音
330
+ method:{
331
+ // 开始手动录音
332
+ async startRecording() {
333
+ // 清空之前的录音数据
334
+ this.audioUrl = null;
335
+ this.recordingStatus = 'recording';
336
+ try {
337
+ // 传入 { auto: false } 表示手动录音
338
+ const result = await this.$lamboJsBridge.startRecording({ auto: false });
339
+ console.log("录音开始成功:", result);
340
+ } catch (error) {
341
+ console.error("录音开始失败:", error);
342
+ this.recordingStatus = 'failed';
343
+ }
344
+ },
345
+
346
+ // 开始自动录音
347
+ async startAutoRecording() {
348
+ // 清空之前的录音数据
349
+ this.audioUrl = null;
350
+ this.recordingStatus = 'recording';
351
+ try {
352
+ // 传入 { auto: true } 表示启用自动录音
353
+ const result = await this.$lamboJsBridge.startRecording({ auto: true });
354
+ console.log("自动录音开始成功:", result);
355
+ } catch (error) {
356
+ console.error("自动录音开始失败:", error);
357
+ this.recordingStatus = 'failed';
358
+ }
359
+ },
360
+
361
+ // 停止录音
362
+ async stopRecording() {
363
+ try {
364
+ const result = await this.$lamboJsBridge.stopRecording();
365
+ console.log("录音停止成功:", result);
366
+ this.recordingStatus = 'stopped';
367
+ // 更新录音文件信息
368
+ this.audioUrl = result.fileUrl || result.msg;
369
+ // 如果你非要用全局函数更新,也可以调用它
370
+ this.updateAudioDisplay(result);
371
+ } catch (error) {
372
+ console.error("录音停止失败:", error);
373
+ this.recordingStatus = 'failed';
374
+ }
375
+ },
376
+
377
+ // 如果你希望借助类似全局函数的形式更新页面,可以这样定义:
378
+ updateAudioDisplay(data) {
379
+ // 更新组件中的数据,页面会自动响应
380
+ this.recordingStatus = 'stopped';
381
+ this.audioUrl = data.fileUrl;
382
+ },
359
383
  },
360
- async stopRecording() {
361
- try {
362
- await this.$lamboJsBridge.stopRecording(); // 调用接口停止录音
363
- this.recordingStatus = 'stopped'; // 设置录音状态为停止
364
- console.log('录音已停止');
365
- } catch (error) {
366
- console.error('停止录音失败:', error);
367
- this.recordingStatus = 'failed'; // 设置录音状态为失败
368
- }
384
+ mounted() {
385
+ window.updateAudioDisplay = this.updateAudioDisplay;
369
386
  },
370
-
371
387
  ```
372
388
 
373
389
  ### 参数说明
@@ -377,11 +393,6 @@ async stopRecording() {
377
393
  | 属性 | 类型 | 默认值 | 必填 | 支持平台 | 说明 |
378
394
  |-----------|--|----------|-----|----------|-------------------------------------------------------------|
379
395
  | isAuto | boolean | false | 否 | Yuntu | 是否开启自动录音。若为 true,则自动开始录音。 |
380
- | fftSize | number | 512 | 否 | Yuntu | FFT大小,用于声音信号处理。 |
381
- | fileName | string | 录音文件.ogg | 否 | Yuntu | 录音文件的默认文件名。 |
382
- | silenceThreshold | number | 20 | 否 | Yuntu | 静音检测音量阈值。 |
383
- | silenceDuration | number | 3000 | 否 | Yuntu | 静音持续时长。|
384
- | silenceDelay | number | 1000 | 否 | Yuntu | 静音检测延迟。 |
385
396
 
386
397
 
387
398
  ### 返回说明
@@ -390,11 +401,7 @@ async stopRecording() {
390
401
 
391
402
  | 属性 | 类型 | 默认值 | 必填 | 支持平台 | 说明 |
392
403
  |-----------|--|----------|-----|----------|-----------------|
393
- | audioUrl | string | | 是 | Yuntu | 录音文件的BlobURL |
394
- | file | Object | | 是 | Yuntu | 录音文件的详细信息 |
395
- | file.name | string | | 是 | Yuntu | 录音文件的名称 |
396
- | file.size | number | | 是 | Yuntu | 录音文件的大小,单位为字节 |
397
- | file.type | string | | 是 | Yuntu | 录音文件的类型 |
404
+ | audioUrl | string | | 是 | Yuntu | 录音文件的fileURL |
398
405
  <br>
399
406
 
400
407
  **录音状态** <br>
package/demo/index.vue CHANGED
@@ -29,7 +29,7 @@
29
29
  <pre v-show="openLocationResult"><code>{{ openLocationResult }}</code></pre>
30
30
  </demo-block>
31
31
  <demo-block title="文件预览">
32
- <a href="javascript:void(0);" @click="previewFile">点击这里预览文件</a>
32
+ <a href="javascript:void(0);" @click="filePreview">点击这里预览文件</a>
33
33
  </demo-block>
34
34
  <demo-block title="录音(仅在Flutter环境下可用)">
35
35
  <van-button @click="startRecording">开始录音</van-button>
@@ -50,12 +50,12 @@
50
50
  <div v-if="audioUrl">
51
51
  <h3>录音已完成</h3>
52
52
  <audio :src="audioUrl" controls></audio>
53
- <p>录音文件: {{ fileName }}</p>
54
- <p>文件大小: {{ fileSize }} 字节</p>
55
- <p>文件类型: {{ fileType }}</p>
56
53
  <p>文件地址:{{ audioUrl }}</p>
57
54
  </div>
58
55
  </demo-block>
56
+ <demo-block title="下载">
57
+ <van-button @click="downloadFile">下载文件</van-button>
58
+ </demo-block>
59
59
 
60
60
 
61
61
 
@@ -90,18 +90,8 @@ export default {
90
90
  photoPreviews: [],
91
91
  initKeyMessage: '', // 用于存储 initKey 的返回消息
92
92
  audioUrl: null, // 用于存储录音文件的 URL
93
- fileName: '', // 录音文件名
94
- fileSize: 0, // 录音文件大小
95
- fileType: '', // 录音文件类型
96
93
  recordingStatus: "not started", // 用于记录当前录音状态
97
- recordingOptions: {
98
- isAuto: false, // 是否自动录音
99
- fftSize: 512, // FFT 大小
100
- fileName: 'audio.ogg', // 默认录音文件名
101
- silenceThreshold: 100, // 静音检测音量阈值
102
- silenceDuration: 1000, // 静音持续时长
103
- silenceDelay: 2000 // 静音检测延迟
104
- }
94
+ downloadLink : null,
105
95
  };
106
96
  },
107
97
  computed: {
@@ -128,7 +118,7 @@ export default {
128
118
  weComId:this.weComId,
129
119
  agentId:this.agentId,
130
120
  dingTalkId:this.dingTalkId,
131
- pluginConfig:["localAuthPlugin","amapPlugin","tabBarPlugin","scanCodePlugin","filePreviewPlugin"],
121
+ pluginConfig:["localAuthPlugin","amapPlugin","tabBarPlugin","scanCodePlugin","filePreviewPlugin","autoRecordPlugin"],
132
122
  };
133
123
  this.$lamboJsBridge = new LamboJsBridge(options);
134
124
  await this.getPlatform();
@@ -144,40 +134,72 @@ export default {
144
134
  console.error('Error getting init info:', error);
145
135
  }
146
136
  },
137
+
138
+ // 开始手动录音
147
139
  async startRecording() {
140
+ // 清空之前的录音数据
141
+ this.audioUrl = null;
142
+ this.recordingStatus = 'recording';
148
143
  try {
149
- this.recordingStatus = 'recording';
150
- const { audioUrl, file } = await this.$lamboJsBridge.startRecording(this.recordingOptions);
151
- this.audioUrl = audioUrl;
152
- this.fileName = file.name;
153
- this.fileSize = file.size;
154
- this.fileType = file.type;
155
- console.log(this.recordingOptions.isAuto ? '自动录音已开始' : '录音已开始');
144
+ // 传入 { auto: false } 表示手动录音
145
+ const result = await this.$lamboJsBridge.startRecording({ auto: false });
146
+ console.log("录音开始成功:", result);
156
147
  } catch (error) {
157
- console.error('录音失败:', error);
148
+ console.error("录音开始失败:", error);
158
149
  this.recordingStatus = 'failed';
159
150
  }
160
151
  },
161
152
 
162
153
  // 开始自动录音
163
154
  async startAutoRecording() {
164
- // 更改 recordingOptions 中的 isAuto 值为 true
165
- this.recordingOptions.isAuto = true;
166
- await this.startRecording(); // 调用 startRecording
155
+ // 清空之前的录音数据
156
+ this.audioUrl = null;
157
+ this.recordingStatus = 'recording';
158
+ try {
159
+ // 传入 { auto: true } 表示启用自动录音
160
+ const result = await this.$lamboJsBridge.startRecording({ auto: true });
161
+ console.log("自动录音开始成功:", result);
162
+ } catch (error) {
163
+ console.error("自动录音开始失败:", error);
164
+ this.recordingStatus = 'failed';
165
+ }
167
166
  },
168
167
 
169
168
  // 停止录音
170
169
  async stopRecording() {
171
170
  try {
172
- await this.$lamboJsBridge.stopRecording();
171
+ const result = await this.$lamboJsBridge.stopRecording();
172
+ console.log("录音停止成功:", result);
173
173
  this.recordingStatus = 'stopped';
174
- console.log('录音已停止');
174
+ // 更新录音文件信息
175
+ this.audioUrl = result.fileUrl || result.msg;
176
+ // 如果你非要用全局函数更新,也可以调用它
177
+ this.updateAudioDisplay(result);
175
178
  } catch (error) {
176
- console.error('停止录音失败:', error);
179
+ console.error("录音停止失败:", error);
177
180
  this.recordingStatus = 'failed';
178
181
  }
179
182
  },
180
183
 
184
+ // 如果你希望借助类似全局函数的形式更新页面,可以这样定义:
185
+ updateAudioDisplay(data) {
186
+ // 更新组件中的数据,页面会自动响应
187
+ this.recordingStatus = 'stopped';
188
+ this.audioUrl = data.fileUrl;
189
+ },
190
+
191
+
192
+ async downloadFile(){
193
+ try {
194
+ const fileUrl = 'http://10.110.34.27/yc_scrm.apk'; // 你要下载的文件 URL
195
+ const fileName = '下载文件'; // 文件名
196
+ await this.$lamboJsBridge.downloadFile({ fileUrl, fileName });
197
+ console.log('Download initiated');
198
+ } catch (error){
199
+ console.error('Download failed:', error);
200
+ }
201
+ },
202
+
181
203
  async getLocation() {
182
204
  try {
183
205
  const options ={
@@ -259,7 +281,7 @@ export default {
259
281
  console.error('Error opening location:', error);
260
282
  }
261
283
  },
262
- async previewFile() {
284
+ async filePreview() {
263
285
  try {
264
286
  const options = {
265
287
  title: '预览文件.txt', // 文件的标题
@@ -283,6 +305,9 @@ export default {
283
305
  }
284
306
  },
285
307
  },
308
+ mounted() {
309
+ window.updateAudioDisplay = this.updateAudioDisplay;
310
+ },
286
311
  beforeRouteEnter (to, from, next) {
287
312
  next(vm => {
288
313
  if (from.name !== null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambo-design-mobile/lambo-js-bridge",
3
- "version": "1.0.0-beta.22",
3
+ "version": "1.0.0-beta.23",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "author": "lambo",
@@ -88,6 +88,10 @@ class LamboJsBridge {
88
88
  return this.platform.stopRecording(options);
89
89
  }
90
90
 
91
+ async downloadFile(options={}){
92
+ return this.platform.downloadFile(options);
93
+ }
94
+
91
95
  // 创建一个 Vue 插件
92
96
  static install(Vue) {
93
97
  // 将 LamboJsBridge 实例挂载到 Vue 原型上,全局可用
@@ -6,12 +6,7 @@ class YunTuAdapter {
6
6
  this.isInitialized = false;
7
7
  this.audioUrl = null; // 录音文件的 URL
8
8
  this.fileName = ''; // 录音文件名称
9
- this.fileSize = 0; // 录音文件大小
10
9
  this.fileType = ''; // 录音文件类型
11
- this.errorMessage = ''; // 错误信息
12
- this.recorder = null; // MediaRecorder 实例
13
- this.streams = null; // 音频流
14
- this.chunks = []; // 录音数据块
15
10
  this.initializePlugin(options.pluginConfig);
16
11
  }
17
12
 
@@ -33,144 +28,89 @@ class YunTuAdapter {
33
28
  }
34
29
  }
35
30
 
36
- // 启动录音
37
- async startRecording({
38
- isAuto = false,
39
- fftSize = 512,
40
- fileName = '录音文件.ogg',
41
- silenceThreshold = 20, // 静音检测的音量阈值
42
- silenceDuration = 3000, // 超过多少秒静音就停止录音
43
- silenceDelay = 1000 // 延迟多少秒开始静音检测
44
- }) {
45
- console.log("开始录音,模式:", isAuto ? "自动录音" : "普通录音");
46
- this.errorMessage = ''; // 清空错误信息
47
-
48
- try {
49
- const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
50
- console.log("成功获取麦克风权限,开始录音...");
51
- this.streams = stream;
52
-
53
- // 创建音频上下文
54
- this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
55
- console.log("创建音频上下文:", this.audioContext);
56
-
57
- // 创建音频分析器
58
- this.analyser = this.audioContext.createAnalyser();
59
- console.log("创建音频分析器:", this.analyser);
60
-
61
- const microphone = this.audioContext.createMediaStreamSource(stream);
62
- microphone.connect(this.analyser);
63
- this.analyser.fftSize = fftSize;
64
- console.log("音频分析器配置完成,FFT Size:", this.analyser.fftSize);
65
-
66
- // 创建 MediaRecorder 实例
67
- this.recorder = new MediaRecorder(stream);
68
- console.log("创建 MediaRecorder 实例:", this.recorder);
69
-
70
- // 监听数据可用事件
71
- this.recorder.ondataavailable = (e) => {
72
- console.log("收到录音数据块,大小:", e.data.size, "字节");
73
- this.chunks.push(e.data);
74
- };
75
-
76
- // 返回 Promise
77
- return new Promise((resolve, reject) => {
78
- // 监听录音停止事件
79
- this.recorder.onstop = () => {
80
- console.log("录音停止,生成音频文件...");
81
- const blob = new Blob(this.chunks, { type: 'audio/ogg' });
82
- this.audioUrl = URL.createObjectURL(blob); // 生成录音文件 URL
83
- const file = new File([blob], fileName, { type: 'audio/ogg' });
84
- this.fileName = file.name;
85
- this.fileSize = file.size;
86
- this.fileType = file.type;
87
- console.log("生成的音频文件:", file);
88
-
89
- // 返回包含音频 URL 和文件对象的对象
90
- resolve({
91
- audioUrl: this.audioUrl,
92
- file: file
93
- });
94
- };
95
-
96
- // 启动静音检测
97
- this.startSilenceDetection({
98
- silenceThreshold,
99
- silenceDuration,
100
- silenceDelay
101
- });
31
+ // 录音:开始录音(支持自动和手动模式)
32
+ async startRecording(options = { auto: false }) {
33
+ return new Promise((resolve, reject) => {
34
+ if (window.autoRecord && typeof window.autoRecord.startRecording === 'function') {
35
+ window.autoRecord.startRecording(
36
+ (result) => {
37
+ console.log("录音开始:", result);
38
+ resolve(result);
39
+ },
40
+ (error) => {
41
+ console.error("录音错误:", error);
42
+ reject(error);
43
+ },
44
+ JSON.stringify(options) // 传入参数:{auto: false} 表示手动录音,{auto: true} 表示自动录音
45
+ );
46
+ } else {
47
+ reject(new Error("autoRecord 接口不可用"));
48
+ }
49
+ });
50
+ }
102
51
 
103
- // 开始录音
104
- this.recorder.start();
105
- console.log("录音已开始");
106
- });
107
- } catch (err) {
108
- console.error("获取麦克风权限失败:", err);
109
- this.errorMessage = "无法访问麦克风,请检查权限设置";
110
- return Promise.reject(new Error(this.errorMessage)); // 返回错误
111
- }
52
+ // 录音:结束录音,并返回录音结果
53
+ async stopRecording() {
54
+ return new Promise((resolve, reject) => {
55
+ if (window.autoRecord && typeof window.autoRecord.stopRecording === 'function') {
56
+ window.autoRecord.stopRecording(
57
+ (result) => {
58
+ console.log("录音停止,返回结果:", result);
59
+ // 如果返回数据为字符串,则尝试解析为对象
60
+ try {
61
+ if (typeof result === "string") {
62
+ result = JSON.parse(result);
63
+ }
64
+ } catch (e) {
65
+ console.error("JSON.parse error:", e);
66
+ }
67
+ resolve(result);
68
+ },
69
+ (error) => {
70
+ console.error("录音结束错误:", error);
71
+ // 同样尝试解析错误信息
72
+ try {
73
+ if (typeof error === "string") {
74
+ error = JSON.parse(error);
75
+ }
76
+ } catch (e) {
77
+ console.error("JSON.parse error:", e);
78
+ }
79
+ reject(error);
80
+ }
81
+ );
82
+ } else {
83
+ reject(new Error("autoRecord 接口不可用"));
84
+ }
85
+ });
112
86
  }
113
87
 
114
- // 静音检测
115
- startSilenceDetection({
116
- silenceThreshold = 20, // 静音检测的音量阈值
117
- silenceDuration = 3000, // 超过多少秒静音就停止录音
118
- silenceDelay = 1000 // 延迟多少秒开始静音检测
119
- }) {
120
- console.log("启动静音检测...");
121
- const bufferLength = this.analyser.frequencyBinCount;
122
- const dataArray = new Uint8Array(bufferLength);
123
- let silenceStart = Date.now();
124
- let isSpeaking = false;
88
+ // 新增下载文件接口
89
+ async downloadFile({ fileUrl, fileName = 'downloadedFile' }) {
90
+ try {
91
+ const response = await fetch(fileUrl);
92
+ if (!response.ok) {
93
+ throw new Error(`Failed to fetch file from ${fileUrl}`);
94
+ }
125
95
 
126
- const checkVolume = () => {
127
- this.analyser.getByteFrequencyData(dataArray);
128
- const volume = Math.max(...dataArray);
129
- console.debug("当前音量:", volume);
96
+ const fileBlob = await response.blob();
130
97
 
131
- if (volume > silenceThreshold) { // 音量阈值
132
- console.debug("检测到声音,重置静音计时器");
133
- isSpeaking = true;
134
- silenceStart = Date.now();
135
- } else if (isSpeaking && Date.now() - silenceStart > silenceDuration) {
136
- // 超过指定静音时长
137
- console.log(`检测到持续 ${silenceDuration / 1000} 秒静音,停止录音`);
138
- this.stopRecording();
139
- return;
140
- }
98
+ // 创建一个下载的 Blob URL
99
+ const downloadUrl = URL.createObjectURL(fileBlob);
141
100
 
142
- if (this.recorder && this.recorder.state === 'recording') {
143
- requestAnimationFrame(checkVolume);
144
- }
145
- };
101
+ // 通过 window.open 来触发文件下载(无 <a> 标签)
102
+ window.open(downloadUrl, '_blank');
146
103
 
147
- // 延迟开始静音检测
148
- setTimeout(() => {
149
- if (this.recorder && this.recorder.state === 'recording') {
150
- console.log("静音检测正式开始");
151
- requestAnimationFrame(checkVolume);
152
- }
153
- }, silenceDelay);
154
- }
104
+ // 清理临时 URL
105
+ URL.revokeObjectURL(downloadUrl);
155
106
 
156
- // 停止录音
157
- async stopRecording() {
158
- console.log("停止录音...");
159
- if (this.recorder && this.recorder.state === 'recording') {
160
- this.recorder.stop();
161
- console.log("录音已停止");
162
- }
163
- if (this.streams) {
164
- this.streams.getTracks().forEach((track) => {
165
- track.stop();
166
- console.log("停止音频轨道:", track);
167
- });
107
+ console.log(`File "${fileName}" downloaded successfully.`);
108
+ } catch (error) {
109
+ console.error('Download failed:', error);
168
110
  }
169
- this.chunks = []; // 清空录音数据块
170
- this.audioContext.close();
171
- console.log("音频上下文已关闭");
172
111
  }
173
112
 
113
+
174
114
  async getPlatform() {
175
115
  return {
176
116
  platform: 'Yuntu'