feat(weixin): 微信iLink扫码登录——面板触发+二维码显示+状态轮询+确认热连接
适配器: login_admin.go(StartLogin 幂等取二维码/LoginStatus idle-waiting-confirmed-failed);
login.go 重写 Connect 委托 StartLogin+等待,后台 runLogin 轮询,completeLogin/failLogin
(锁序 loginMu->a.mu 不嵌套反向无死锁); adapter.go 加登录会话字段
网关: admin_channels_weixin.go(2 端点 login-qr/login-status owner+审计, confirmed 合并写回
channels.json 保留 base_url/cdn/黑白名单 + Reload 热重载连接; qrImage best-effort Base64,
token 掩码) + server.go 路由
前端: WeixinLogin.tsx(token空→扫码按钮→二维码→1.5s轮询→confirmed提示已登录+显示bot_id),
AdapterDetailPage 渲染, api/types 补类型
必需偏离(最小化): 允许空token的weixin账号被构建/持久化(channels.go+runtimeconfig移出
tokenRequiringPlatforms),否则空token账号无法注册调用StartLogin; 空token保持断开(configured
仍要求token非空),确认后才持久化连接——守红线。
测试: login_admin/admin端点用例; 后端 build/vet/test 全绿 + 前端 build 101模块绿.
This commit is contained in:
1 parent
0a597cfa42
commit
e037fab7d0
13 files changed
+1155
-46
No files matched your search
@@ -160,6 +160,15 @@ type Adapter struct {
|
||||
contexts map[string]string
|
||||
lastMsgAt map[string]time.Time
|
||||
handler adapter.MessageHandler
|
||||
|
||||
// loginMu serializes the scan-login session lifecycle (StartLogin/Connect),
|
||||
// so only one QR bind runs at a time. loginSession / loginStatus / loginDetail
|
||||
// carry the panel-observable login state; loginStatus/loginDetail are guarded
|
||||
// by mu, loginSession by loginMu.
|
||||
loginMu sync.Mutex
|
||||
loginSession *loginSession
|
||||
loginStatus string
|
||||
loginDetail string
|
||||
}
|
||||
|
||||
// New builds an Adapter. client may be nil to use http.DefaultClient; log may be
|
||||
@@ -179,12 +188,13 @@ func New(cfg Config, client *http.Client, log *slog.Logger) (*Adapter, error) {
|
||||
log = logger.WithSource(log, source)
|
||||
|
||||
return &Adapter{
|
||||
cfg: cfg,
|
||||
httpClient: client,
|
||||
log: log,
|
||||
clock: time.Now,
|
||||
contexts: map[string]string{},
|
||||
lastMsgAt: map[string]time.Time{},
|
||||
cfg: cfg,
|
||||
httpClient: client,
|
||||
log: log,
|
||||
clock: time.Now,
|
||||
contexts: map[string]string{},
|
||||
lastMsgAt: map[string]time.Time{},
|
||||
loginStatus: LoginStatusIdle,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user