跨平台桌面开发新选择:Wails 3 初体验及在 FRP 管理客户端中的选型实践

为什么选择了Wails 3 ? Wails 3 最大的改变在于它不再强绑定于某个特定的前端框架,且引入了多窗口支持和更轻量级的 Runtime。它允许你在不启动主窗口的情况下运行后端服务,这正是我们实现“系统托盘”和“后台演示服务”的基础。 在 v2 中,我们习惯于自动生成的 wailsjs 文件夹。但在 v3 中,这一逻辑被进一步标准化。 当你运行开发指令时,Wails 会扫描你的 Go 结构体方法,并将其映射为前端可以调用的 JavaScript 函数。这个过程在 v3 中被称为 Generate 过程。 Wails 3 通信灵魂 我们在前端调用在后端定义的 HandleConnect 返回自定义结构体,这在 Wails 3 中是前后端通信的灵魂。 在 Wails 3 开发中,最核心的动作就是:后端做功,前端表现。 当你调用 MoleService.HandleConnect() 时,Go 后端会产生一个结果。在本项目中,我们需要同时返回一个 Code(状态码)和一个 Content(数据内容)。 为了实现这一点,我们定义了一个结构体: type Response struct { Code int; Content string } 虽然 Go 内部使用的是结构体,但前端 JavaScript 只能读懂 JSON 对象。Wails 3 内部会自动帮你完成这个“翻译”过程。 但是,如果你想让前端看到的字段名是小写的(例如 res.code 而不是 res.Code),你必须在 Go 结构体定义时加上“注解”。 type Response struct { Code int `json:"code"` Content string `json:"content"` } 记住,所有通过 bindings 调用的 Go 方法,在前端返回的都是一个 Promise 对象。这意味着你必须使用 await 或者 .then() 来接收数据,否则你拿到的将是一个永不开启的“盲盒”。 ...

2025-11-01 · 4 min · Eagle

私有化语音验证码方案:基于 Asterisk 与 Go 的 SIP 通信及 AGI 脚本实战

音频文件处理 我们使用手机上的录音机来录制音频文件。 Android 录音机录制的音频文件格式为 mp3,如果是 amr 格式,请使用豆子工具音频格式转换功能,转成 mp3 格式文件。 IOS 录音机录制的音频文件格式为 m4a,请使用豆子工具音频格式转换功能,转成 mp3 格式文件。 我们还需要使用 ffmpeg 将 mp3 文件转成 g711a 格式文件。这个 mp3 转 g711a 功能后续会集成到豆子工具中。 mp3 转 g711a 命令: ffmpeg -i test.mp3 -acodec pcm_alaw -f alaw -ac 1 -ar 8000 -vn test.alaw 使用 ffplay 播放测试 ffplay -i test.alaw -f alaw -ac 1 -ar 8000 将制作好的音频文件存放在 asterisk sounds 目录,就可以在拨号计划中使用 Playback 应用调用它了。 配置实时数据库 今天讲解 Asterisk 如何实时将 SIP 用户写入 sqlite3 数据库。 先定义数据库表结构,我当前使用的 PJSIP 协议。 CREATE TABLE ps_endpoints ( id VARCHAR(40) NOT NULL, transport VARCHAR(40), aors VARCHAR(200), auth VARCHAR(40), context VARCHAR(40), disallow VARCHAR(200), allow VARCHAR(200), direct_media varchar(5) check(direct_media in ('yes','no')), connected_line_method varchar(10) check(connected_line_method in ('invite','reinvite','update')), direct_media_method varchar(10) check(direct_media_method in ('invite','reinvite','update')), direct_media_glare_mitigation varchar(20) check(direct_media_glare_mitigation in ('none','outgoing','incoming')), disable_direct_media_on_nat varchar(5) check(disable_direct_media_on_nat in ('yes','no')), dtmf_mode varchar(20) check(dtmf_mode in ('rfc4733','inband','info')), external_media_address VARCHAR(40), force_rport varchar(5) check(force_rport in ('yes','no')), ice_support varchar(5) check(ice_support in ('yes','no')), identify_by varchar(10) check(identify_by in ('username')), mailboxes VARCHAR(40), moh_suggest VARCHAR(40), outbound_auth VARCHAR(40), outbound_proxy VARCHAR(40), rewrite_contact varchar(5) check(rewrite_contact in ('yes','no')), rtp_ipv6 varchar(5) check(rtp_ipv6 in ('yes','no')), rtp_symmetric varchar(5) check(rtp_symmetric in ('yes','no')), send_diversion varchar(5) check(send_diversion in ('yes','no')), send_pai varchar(5) check(send_pai in ('yes','no')), send_rpid varchar(5) check(send_rpid in ('yes','no')), timers_min_se INTEGER, timers varchar(20) check(timers in ('forced','no','required','yes')), timers_sess_expires INTEGER, callerid VARCHAR(40), callerid_privacy varchar(40) check(callerid_privacy in ('allowed_not_screened','allowed_passed_screened','allowed_failed_screened','allowed','prohib_not_screened','prohib_passed_screened','prohib_failed_screened','prohib','unavailable')), callerid_tag VARCHAR(40), `100rel` varchar(20) check(`100rel` in ('no','required','yes')), aggregate_mwi varchar(5) check(aggregate_mwi in ('yes','no')), trust_id_inbound varchar(5) check(trust_id_inbound in ('yes','no')), trust_id_outbound varchar(5) check(trust_id_outbound in ('yes','no')), use_ptime varchar(5) check(use_ptime in ('yes','no')), use_avpf varchar(5) check(use_avpf in ('yes','no')), media_encryption varchar(10) check(media_encryption in ('no','sdes','dtls')), inband_progress varchar(5) check(inband_progress in ('yes','no')), call_group VARCHAR(40), pickup_group VARCHAR(40), named_call_group VARCHAR(40), named_pickup_group VARCHAR(40), device_state_busy_at INTEGER, fax_detect varchar(5) check(fax_detect in ('yes','no')), t38_udptl varchar(5) check(t38_udptl in ('yes','no')), t38_udptl_ec varchar(20) check(t38_udptl_ec in ('none','fec','redundancy')), t38_udptl_maxdatagram INTEGER, t38_udptl_nat varchar(5) check(t38_udptl_nat in ('yes','no')), t38_udptl_ipv6 varchar(5) check(t38_udptl_ipv6 in ('yes','no')), tone_zone VARCHAR(40), language VARCHAR(40), one_touch_recording varchar(5) check(one_touch_recording in ('yes','no')), record_on_feature VARCHAR(40), record_off_feature VARCHAR(40), rtp_engine VARCHAR(40), allow_transfer varchar(5) check(allow_transfer in ('yes','no')), allow_subscribe varchar(5) check(allow_subscribe in ('yes','no')), sdp_owner VARCHAR(40), sdp_session VARCHAR(40), tos_audio INTEGER, tos_video INTEGER, cos_audio INTEGER, cos_video INTEGER, sub_min_expiry INTEGER, from_domain VARCHAR(40), from_user VARCHAR(40), mwi_fromuser VARCHAR(40), dtls_verify VARCHAR(40), dtls_rekey VARCHAR(40), dtls_cert_file VARCHAR(200), dtls_private_key VARCHAR(200), dtls_cipher VARCHAR(200), dtls_ca_file VARCHAR(200), dtls_ca_path VARCHAR(200), dtls_setup varchar(20) check(dtls_setup in ('active','passive','actpass')), srtp_tag_32 varchar(5) check(srtp_tag_32 in ('yes','no')), UNIQUE (id) ); CREATE INDEX ps_endpoints_id ON ps_endpoints (id); CREATE TABLE ps_auths ( id VARCHAR(40) NOT NULL, auth_type varchar(10) check(auth_type in ('md5','userpass')), nonce_lifetime INTEGER, md5_cred VARCHAR(40), password VARCHAR(80), realm VARCHAR(40), username VARCHAR(40), UNIQUE (id) ); CREATE INDEX ps_auths_id ON ps_auths (id); CREATE TABLE ps_aors ( id VARCHAR(40) NOT NULL, contact VARCHAR(40), default_expiration INTEGER, mailboxes VARCHAR(80), max_contacts INTEGER, minimum_expiration INTEGER, remove_existing varchar(5) check(remove_existing in ('yes','no')), qualify_frequency INTEGER, authenticate_qualify varchar(5) check(authenticate_qualify in ('yes','no')), UNIQUE (id) ); CREATE INDEX ps_aors_id ON ps_aors (id); PJSIP 测试数据: ...

2022-08-21 · 5 min · Eagle