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>                

 

posted @ 2020-08-13 09:21  泰景女婿  阅读(462)  评论(0编辑  收藏