1. 程式人生 > 實用技巧 >CEF+ChromiumWebBrowser+vue+elementUI 前後端互動(注意:有後端非前端主動觸發回撥前端vue前端)

CEF+ChromiumWebBrowser+vue+elementUI 前後端互動(注意:有後端非前端主動觸發回撥前端vue前端)

專案背景:

  專案技術方案定的是前後端分離,採用framework4.0+vue+elementUI 客戶端需要加殼(使用CEF+ChromiumWebBrowser),避免客戶端多樣,導致環境不支援;

  並且客戶端需要呼叫微軟硬體(鍵盤、語音)介面進行業務操作;

所遇到的場景:

  • 語音

    客戶端(前端)需要觸發呼叫;作業系統語音外設播報語音;

  • 鍵盤

    客戶端(前端)需要監聽鍵盤輸入按鍵,並在回車的時候,回撥前端js並將鍵盤輸入的字元傳給前端方法執行vue例項下指定方法;

程式碼實現

  • 語音實現

    後臺程式碼:    

  1 using System;
  2 using
System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Configuration; 5 using System.Data; 6 using System.Drawing; 7 using System.Linq; 8 using System.Net; 9 using System.Text; 10 using System.Threading.Tasks; 11 using System.Windows.Forms; 12 using CardReader; 13
using CefSharp; 14 using CefSharp.WinForms; 15 using FormDLL; 16 using Newtonsoft.Json; 17 using RestSharp; 18 namespace CefSharpOfQueue { 19 public partial class FormMain: Form { 20 public ChromiumWebBrowser chromeBrowser; 21 private Type voiceType; 22 private CardReader.CardReader cardReader;
23 private dynamic spVoice; 24 private string token; 25 public Control activeUserControl; 26 private Panel panelContent; 27 public FormMain() { 28 //初始化語音裝置 29 this.voiceType = Type.GetTypeFromProgID("SAPI.SpVoice"); 30 this.spVoice = Activator.CreateInstance(this.voiceType); 31 //初始化winform控制元件 32 InitializeComponent(); 33 this.FormBorderStyle = FormBorderStyle.None; 34 //winform全屏 35 this.WindowState = FormWindowState.Maximized; 36 //初始化chromium 37 InitializeChromium(); 38 // 註冊一個formMainProcess;用於前端呼叫後臺 39 chromeBrowser.RegisterJsObject("formMainProcess", new FormMainProcess(chromeBrowser, this)); 40 } 41 //放在初始化winform控制元件InitializeComponent 方法中 42 private void FormMain_Load(object sender, EventArgs e) { 43 //this.activeUserControl = this.AddControl(new ScanCard(this)); 44 this.cardReader = new CardReader.CardReader(2); 45 this.cardReader.CardRead += delegate(string cardCode) { 46 if(!string.IsNullOrWhiteSpace(cardCode)) { 47 //將獲取到的cardCode回傳給前端全域性變數 48 try { 49 chromeBrowser.GetBrowser().MainFrame.ExecuteJavaScriptAsync("Vue.prototype.$store.state.isShow=true;Vue.prototype.$store.state.queryCode='" + cardCode + "'"); 50 } catch { 51 //或者寫日誌 52 throw new Exception("error"); 53 } 54 } 55 }; 56 } 57 public void SpeakTxt(string msg) { 58 this.spVoice.speak(msg, 1); 59 } 60 public void InitializeChromium() { 61 // 獲取配置檔案裡的前端服務地址 62 string url = ConfigurationManager.AppSettings["ServiceAddress"]; 63 //建立chrome物件 64 chromeBrowser = new ChromiumWebBrowser(url); 65 // 將chrome物件新增進winform控制器 66 this.Controls.Add(chromeBrowser); 67 chromeBrowser.Dock = DockStyle.Fill; 68 // Allow the use of local resources in the browser 69 BrowserSettings browserSettings = new BrowserSettings(); 70 browserSettings.FileAccessFromFileUrls = CefState.Enabled; 71 browserSettings.UniversalAccessFromFileUrls = CefState.Enabled; 72 browserSettings.WebSecurity = CefState.Enabled; 73 // browserSettings.LegacyJavascriptBindingEnabled = true; 74 chromeBrowser.BrowserSettings = browserSettings; 75 // 網頁開始載入時的處理 76 chromeBrowser.FrameLoadStart += (sender, e) => { 77 string script = @"const loading = this.$loading({ 78 lock: true, 79 text: 'Loading', 80 spinner: 'el-icon-loading', 81 background: 'rgba(0, 0, 0, 0.7)' 82 }); 83 setTimeout(() => { 84 loading.close(); 85 }, 2000); 86 "; 87 e.Frame.ExecuteJavaScriptAsync(script); 88 }; 89 // 網頁載入完畢時的處理 90 chromeBrowser.FrameLoadEnd += (sender, e) => { 91 string script = "alert('載入完畢!');"; 92 e.Frame.ExecuteJavaScriptAsync(script); 93 }; 94 } 95 } 96 internal class FormMainProcess { 97 private FormMain _instanceMainForm = null; 98 private ChromiumWebBrowser _instanceBrowser = null; 99 public FormMainProcess(ChromiumWebBrowser originalBrowser, FormMain mainForm) { 100 _instanceBrowser = originalBrowser; 101 _instanceMainForm = mainForm; 102 } 103 /// <summary> 104 /// 播放語音 105 /// </summary> 106 /// <param name="message"></param> 107 public void speakMsg(string message) { 108 this._instanceMainForm.Invoke(new Action(delegate { 109 this._instanceMainForm.SpeakTxt(message); 110 })); 111 } 112 } 113 }

    前端程式碼:可在vue介面中script中任意一個方法中 使用後端註冊了的formMainProcess 物件,呼叫對應方法。如下:

 1 <template>
 2 ...
 3 </template>
 4 <script>
 5 ...
 6 methods: {
 7     testf(){
 8              //呼叫,播報資訊
 9                 formMainProcess.speakMsg(
10                     '測試語音ABCD'
11                 );
12     }
13 }
14 </script>