feat: add 新增验证码登录
This commit is contained in:
3
.env
3
.env
@@ -6,8 +6,9 @@ APIKEY=sk-85880595fc714d63bfd0b025e917bd26#千问apikey
|
|||||||
# 962516e4-60eb-4a26-a5a3-44e21adcf7bc #豆包
|
# 962516e4-60eb-4a26-a5a3-44e21adcf7bc #豆包
|
||||||
|
|
||||||
# 消息回调(ngrok 调通用,由 run-ngrok.sh 自动写入)
|
# 消息回调(ngrok 调通用,由 run-ngrok.sh 自动写入)
|
||||||
CALLBACK_BASE_URL=https://dissonant-destinee-nonsensibly.ngrok-free.dev
|
# CALLBACK_BASE_URL=https://dissonant-destinee-nonsensibly.ngrok-free.dev
|
||||||
|
|
||||||
|
CALLBACK_BASE_URL=http://demo.bimwe.com
|
||||||
|
|
||||||
# 固定隧道代理(socks5h):不填登录页代理时后端自动用此处,传给 7006
|
# 固定隧道代理(socks5h):不填登录页代理时后端自动用此处,传给 7006
|
||||||
# TUNNEL_PROXY=218.78.109.253:16816
|
# TUNNEL_PROXY=218.78.109.253:16816
|
||||||
|
|||||||
@@ -15140,3 +15140,45 @@ httpx.ConnectError: All connection attempts failed
|
|||||||
2026-03-15 17:31:04,477 [INFO] wechat-backend - SetCallback registered for key=***9BJZ, CallbackURL=https://dissonant-destinee-nonsensibly.ngrok-free.dev/api/callback/wechat-message
|
2026-03-15 17:31:04,477 [INFO] wechat-backend - SetCallback registered for key=***9BJZ, CallbackURL=https://dissonant-destinee-nonsensibly.ngrok-free.dev/api/callback/wechat-message
|
||||||
2026-03-15 17:31:04,478 [INFO] wechat-backend - 启动时已注册回调 key=***9BJZ
|
2026-03-15 17:31:04,478 [INFO] wechat-backend - 启动时已注册回调 key=***9BJZ
|
||||||
2026-03-15 17:31:04,478 [INFO] wechat-backend - 消息接收已切换为实时回调入口,不再启动 WS GetSyncMsg
|
2026-03-15 17:31:04,478 [INFO] wechat-backend - 消息接收已切换为实时回调入口,不再启动 WS GetSyncMsg
|
||||||
|
2026-03-24 13:53:30,527 [INFO] wechat-backend - proxy config: tunnel=True (TUNNEL_PROXY=14.103.95.78:16816), kdl=False (KDL_API=(empty))
|
||||||
|
2026-03-24 13:53:30,726 [INFO] httpx - HTTP Request: POST http://113.44.162.180:7006/message/SetCallback?key=HBpEnbtj9BJZ "HTTP/1.1 200 OK"
|
||||||
|
2026-03-24 13:53:30,727 [INFO] wechat-backend - SetCallback registered for key=***9BJZ, CallbackURL=https://dissonant-destinee-nonsensibly.ngrok-free.dev/api/callback/wechat-message
|
||||||
|
2026-03-24 13:53:30,727 [INFO] wechat-backend - 启动时已注册回调 key=***9BJZ
|
||||||
|
2026-03-24 13:53:30,728 [INFO] wechat-backend - 消息接收已切换为实时回调入口,不再启动 WS GetSyncMsg
|
||||||
|
2026-03-24 13:56:12,539 [INFO] wechat-backend - proxy config: tunnel=True (TUNNEL_PROXY=14.103.95.78:16816), kdl=False (KDL_API=(empty))
|
||||||
|
2026-03-24 13:56:12,718 [INFO] httpx - HTTP Request: POST http://113.44.162.180:7006/message/SetCallback?key=HBpEnbtj9BJZ "HTTP/1.1 200 OK"
|
||||||
|
2026-03-24 13:56:12,719 [INFO] wechat-backend - SetCallback registered for key=***9BJZ, CallbackURL=http://demo.bimwe.com/api/callback/wechat-message
|
||||||
|
2026-03-24 13:56:12,719 [INFO] wechat-backend - 启动时已注册回调 key=***9BJZ
|
||||||
|
2026-03-24 13:56:12,719 [INFO] wechat-backend - 消息接收已切换为实时回调入口,不再启动 WS GetSyncMsg
|
||||||
|
2026-03-24 13:56:47,859 [INFO] wechat-backend - HTTP GET /api/ws-status from 127.0.0.1
|
||||||
|
2026-03-24 13:56:47,865 [INFO] wechat-backend - HTTP GET /api/ws-status -> 200
|
||||||
|
2026-03-24 13:57:24,091 [INFO] wechat-backend - HTTP GET /auth/scan-status from 127.0.0.1
|
||||||
|
2026-03-24 13:57:24,092 [INFO] wechat-backend - CheckLoginStatus: key=HBQ0d1NFqpio, url=http://113.44.162.180:7006/login/CheckLoginStatus
|
||||||
|
2026-03-24 13:57:24,234 [INFO] httpx - HTTP Request: GET http://113.44.162.180:7006/login/CheckLoginStatus?key=HBQ0d1NFqpio "HTTP/1.1 200 OK"
|
||||||
|
2026-03-24 13:57:24,237 [INFO] wechat-backend - Upstream CheckLoginStatus response: status=200, body={"Code":200,"Data":{"uuid":"A60ypn3NgZtZmIxMPDS7","state":1,"head_img_url":"http://wx.qlogo.cn/mmhead/ver_1/MYpdk7UU5ibX2RljVicmpcDMBxxog9qvtUvvrXlBVv4twgQibIZcnhIpjR5Qe93KB8I8y0fopiaFYE9Yd6xAfcSm2VXoTibyABYpFHrs4oXpg7eCvN6UFBg3IWjmlf4iaXzUhl/0","push_login_url_expired_time":0,"nick_name":"🧶花漾十年🧶 1098","effective_time":158,"unknow":0,"ret":0,"othersInServerLogin":false,"tarGetServerIp":"","uuId":"","msg":"请提交验证码后登录","data62":"","ticket":""},"Text":"请提交验证码后登录","Success":false,"Data62":"","Ticket":""}
|
||||||
|
2026-03-24 13:57:24,239 [INFO] wechat-backend - HTTP GET /auth/scan-status -> 200
|
||||||
|
2026-03-24 13:57:24,265 [INFO] wechat-backend - HTTP GET /auth/slider-assets/N_jYM_2V.js from 127.0.0.1
|
||||||
|
2026-03-24 13:57:24,525 [INFO] httpx - HTTP Request: GET http://113.44.162.180:7765/assets/N_jYM_2V.js "HTTP/1.1 200 OK"
|
||||||
|
2026-03-24 13:57:24,619 [INFO] wechat-backend - HTTP GET /auth/slider-assets/N_jYM_2V.js -> 200
|
||||||
|
2026-03-24 14:06:48,603 [INFO] wechat-backend - HTTP GET /api/ws-status from 127.0.0.1
|
||||||
|
2026-03-24 14:06:48,614 [INFO] wechat-backend - HTTP GET /api/ws-status -> 200
|
||||||
|
2026-03-24 14:06:52,271 [INFO] wechat-backend - HTTP GET /auth/scan-status from 127.0.0.1
|
||||||
|
2026-03-24 14:06:52,273 [INFO] wechat-backend - CheckLoginStatus: key=HBQ0d1NFqpio, url=http://113.44.162.180:7006/login/CheckLoginStatus
|
||||||
|
2026-03-24 14:06:52,402 [INFO] httpx - HTTP Request: GET http://113.44.162.180:7006/login/CheckLoginStatus?key=HBQ0d1NFqpio "HTTP/1.1 200 OK"
|
||||||
|
2026-03-24 14:06:52,404 [INFO] wechat-backend - Upstream CheckLoginStatus response: status=200, body={"Code":200,"Data":{"uuid":"A60ypn3NgZtZmIxMPDS7","state":1,"head_img_url":"http://wx.qlogo.cn/mmhead/ver_1/MYpdk7UU5ibX2RljVicmpcDMBxxog9qvtUvvrXlBVv4twgQibIZcnhIpjR5Qe93KB8I8y0fopiaFYE9Yd6xAfcSm2VXoTibyABYpFHrs4oXpg7eCvN6UFBg3IWjmlf4iaXzUhl/0","push_login_url_expired_time":0,"nick_name":"🧶花漾十年🧶 1098","effective_time":159,"unknow":0,"ret":0,"othersInServerLogin":false,"tarGetServerIp":"","uuId":"","msg":"请提交验证码后登录","data62":"","ticket":""},"Text":"登录处理中,请稍候...","Success":false,"Data62":"","Ticket":""}
|
||||||
|
2026-03-24 14:06:52,405 [INFO] wechat-backend - HTTP GET /auth/scan-status -> 200
|
||||||
|
2026-03-24 14:06:52,421 [INFO] wechat-backend - HTTP GET /auth/slider-assets/N_jYM_2V.js from 127.0.0.1
|
||||||
|
2026-03-24 14:06:52,622 [INFO] httpx - HTTP Request: GET http://113.44.162.180:7765/assets/N_jYM_2V.js "HTTP/1.1 200 OK"
|
||||||
|
2026-03-24 14:06:52,802 [INFO] wechat-backend - HTTP GET /auth/slider-assets/N_jYM_2V.js -> 200
|
||||||
|
2026-03-24 14:07:32,960 [INFO] wechat-backend - proxy config: tunnel=True (TUNNEL_PROXY=14.103.95.78:16816), kdl=False (KDL_API=(empty))
|
||||||
|
2026-03-24 14:07:33,158 [INFO] httpx - HTTP Request: POST http://113.44.162.180:7006/message/SetCallback?key=HBpEnbtj9BJZ "HTTP/1.1 200 OK"
|
||||||
|
2026-03-24 14:07:33,159 [INFO] wechat-backend - SetCallback registered for key=***9BJZ, CallbackURL=http://demo.bimwe.com/api/callback/wechat-message
|
||||||
|
2026-03-24 14:07:33,159 [INFO] wechat-backend - 启动时已注册回调 key=***9BJZ
|
||||||
|
2026-03-24 14:07:33,159 [INFO] wechat-backend - 消息接收已切换为实时回调入口,不再启动 WS GetSyncMsg
|
||||||
|
2026-03-24 14:07:41,711 [INFO] wechat-backend - HTTP GET /api/ws-status from 127.0.0.1
|
||||||
|
2026-03-24 14:07:41,716 [INFO] wechat-backend - HTTP GET /api/ws-status -> 200
|
||||||
|
2026-03-24 14:07:43,482 [INFO] wechat-backend - HTTP GET /auth/scan-status from 127.0.0.1
|
||||||
|
2026-03-24 14:07:43,487 [INFO] wechat-backend - CheckLoginStatus: key=HBQ0d1NFqpio, url=http://113.44.162.180:7006/login/CheckLoginStatus
|
||||||
|
2026-03-24 14:07:43,602 [INFO] httpx - HTTP Request: GET http://113.44.162.180:7006/login/CheckLoginStatus?key=HBQ0d1NFqpio "HTTP/1.1 200 OK"
|
||||||
|
2026-03-24 14:07:43,607 [INFO] wechat-backend - Upstream CheckLoginStatus response: status=200, body={"Code":200,"Data":{"uuid":"47ValF_qGD7osGBMYEap","state":1,"head_img_url":"http://wx.qlogo.cn/mmhead/ver_1/MYpdk7UU5ibX2RljVicmpcDMBxxog9qvtUvvrXlBVv4twgQibIZcnhIpjR5Qe93KB8I8y0fopiaFYE9Yd6xAfcSm2VXoTibyABYpFHrs4oXpg7eCvN6UFBg3IWjmlf4iaXzUhl/0","push_login_url_expired_time":0,"nick_name":"🧶花漾十年🧶 1098","effective_time":239,"unknow":0,"ret":0,"othersInServerLogin":false,"tarGetServerIp":"","uuId":"","msg":"","data62":"","ticket":""},"Text":"","Success":false,"Data62":"","Ticket":""}
|
||||||
|
2026-03-24 14:07:43,608 [INFO] wechat-backend - HTTP GET /auth/scan-status -> 200
|
||||||
|
|||||||
@@ -5618,3 +5618,17 @@
|
|||||||
::1 - - [15/Mar/2026:09:15:28 +0000] "GET /api/ws-status HTTP/1.1" 200 19 "http://localhost:3000/manage.html?key=HBpEnbtj9BJZ" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"
|
::1 - - [15/Mar/2026:09:15:28 +0000] "GET /api/ws-status HTTP/1.1" 200 19 "http://localhost:3000/manage.html?key=HBpEnbtj9BJZ" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"
|
||||||
[2026-03-15T09:31:04.748Z] Static frontend server listening on port 3000; access log: /Users/dannier/Desktop/living/AICLW/wechatAiclaw/backend/data/logs/node-access.log
|
[2026-03-15T09:31:04.748Z] Static frontend server listening on port 3000; access log: /Users/dannier/Desktop/living/AICLW/wechatAiclaw/backend/data/logs/node-access.log
|
||||||
[2026-03-15T09:48:21.689Z] Static frontend server listening on port 3000; access log: /Users/dannier/Desktop/living/AICLW/wechatAiclaw/backend/data/logs/node-access.log
|
[2026-03-15T09:48:21.689Z] Static frontend server listening on port 3000; access log: /Users/dannier/Desktop/living/AICLW/wechatAiclaw/backend/data/logs/node-access.log
|
||||||
|
[2026-03-24T05:53:30.775Z] Static frontend server listening on port 3000; access log: /Users/dannier/Desktop/living/AICLW/wechatAiclaw/backend/data/logs/node-access.log
|
||||||
|
[2026-03-24T05:56:13.060Z] Static frontend server listening on port 3000; access log: /Users/dannier/Desktop/living/AICLW/wechatAiclaw/backend/data/logs/node-access.log
|
||||||
|
127.0.0.1 - - [24/Mar/2026:05:56:47 +0000] "GET / HTTP/1.1" 200 48534 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"
|
||||||
|
127.0.0.1 - - [24/Mar/2026:05:56:47 +0000] "GET /api/ws-status HTTP/1.1" 200 19 "http://localhost:3000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"
|
||||||
|
127.0.0.1 - - [24/Mar/2026:05:57:24 +0000] "GET /auth/scan-status?key=HBQ0d1NFqpio HTTP/1.1" 200 554 "http://localhost:3000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"
|
||||||
|
127.0.0.1 - - [24/Mar/2026:05:57:24 +0000] "GET /auth/slider-assets/N_jYM_2V.js HTTP/1.1" 200 64695 "http://localhost:3000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"
|
||||||
|
127.0.0.1 - - [24/Mar/2026:06:06:48 +0000] "GET / HTTP/1.1" 200 50250 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"
|
||||||
|
127.0.0.1 - - [24/Mar/2026:06:06:48 +0000] "GET /api/ws-status HTTP/1.1" 200 19 "http://localhost:3000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"
|
||||||
|
127.0.0.1 - - [24/Mar/2026:06:06:52 +0000] "GET /auth/scan-status?key=HBQ0d1NFqpio HTTP/1.1" 200 557 "http://localhost:3000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"
|
||||||
|
127.0.0.1 - - [24/Mar/2026:06:06:52 +0000] "GET /auth/slider-assets/N_jYM_2V.js HTTP/1.1" 200 64695 "http://localhost:3000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"
|
||||||
|
[2026-03-24T06:07:33.460Z] Static frontend server listening on port 3000; access log: /Users/dannier/Desktop/living/AICLW/wechatAiclaw/backend/data/logs/node-access.log
|
||||||
|
127.0.0.1 - - [24/Mar/2026:06:07:41 +0000] "GET / HTTP/1.1" 304 - "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"
|
||||||
|
127.0.0.1 - - [24/Mar/2026:06:07:41 +0000] "GET /api/ws-status HTTP/1.1" 200 19 "http://localhost:3000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"
|
||||||
|
127.0.0.1 - - [24/Mar/2026:06:07:43 +0000] "GET /auth/scan-status?key=HBQ0d1NFqpio HTTP/1.1" 200 500 "http://localhost:3000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"
|
||||||
|
|||||||
@@ -387,6 +387,14 @@ class WakeUpRequest(BaseModel):
|
|||||||
Proxy: Optional[str] = ""
|
Proxy: Optional[str] = ""
|
||||||
|
|
||||||
|
|
||||||
|
class VerifyCodeRequest(BaseModel):
|
||||||
|
"""手机验证码验证:默认只需要 key + code,data62/ticket 优先从缓存补全。"""
|
||||||
|
key: str
|
||||||
|
code: str
|
||||||
|
data62: Optional[str] = ""
|
||||||
|
ticket: Optional[str] = ""
|
||||||
|
|
||||||
|
|
||||||
@app.middleware("http")
|
@app.middleware("http")
|
||||||
async def log_requests(request: Request, call_next):
|
async def log_requests(request: Request, call_next):
|
||||||
logger.info("HTTP %s %s from %s", request.method, request.url.path, request.client.host if request.client else "-")
|
logger.info("HTTP %s %s from %s", request.method, request.url.path, request.client.host if request.client else "-")
|
||||||
@@ -942,6 +950,12 @@ async def check_scan_status(
|
|||||||
data62 = (stored.get("data62") or "").strip()
|
data62 = (stored.get("data62") or "").strip()
|
||||||
if not data62:
|
if not data62:
|
||||||
data62 = (data.get("Data62") or (data.get("Data") or {}).get("Data62") or (data.get("Data") or {}).get("data62") or "").strip()
|
data62 = (data.get("Data62") or (data.get("Data") or {}).get("Data62") or (data.get("Data") or {}).get("data62") or "").strip()
|
||||||
|
# 缓存 ticket 与 data62,供 /auth/verify-code 直接使用(前端只填验证码即可)
|
||||||
|
qrcode_store[key] = {
|
||||||
|
**stored,
|
||||||
|
"ticket": ticket,
|
||||||
|
"data62": data62,
|
||||||
|
}
|
||||||
params = {"key": SLIDER_VERIFY_KEY, "ticket": ticket}
|
params = {"key": SLIDER_VERIFY_KEY, "ticket": ticket}
|
||||||
if data62:
|
if data62:
|
||||||
params["data62"] = data62
|
params["data62"] = data62
|
||||||
@@ -955,6 +969,62 @@ async def check_scan_status(
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/auth/verify-code")
|
||||||
|
async def verify_login_code(body: VerifyCodeRequest):
|
||||||
|
"""
|
||||||
|
手机验证码验证(本地入口):
|
||||||
|
- 前端只传 key + code;
|
||||||
|
- data62/ticket 优先从缓存补全;
|
||||||
|
- 转发到 7006: POST /login/VerifyCode?key=...
|
||||||
|
"""
|
||||||
|
key = (body.key or "").strip()
|
||||||
|
code = (body.code or "").strip()
|
||||||
|
if not key:
|
||||||
|
raise HTTPException(status_code=400, detail="key is required")
|
||||||
|
if not code:
|
||||||
|
raise HTTPException(status_code=400, detail="code is required")
|
||||||
|
|
||||||
|
stored = qrcode_store.get(key) or {}
|
||||||
|
data62 = (body.data62 or "").strip() or (stored.get("data62") or "").strip()
|
||||||
|
ticket = (body.ticket or "").strip() or (stored.get("ticket") or "").strip()
|
||||||
|
if not data62 or not ticket:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=400,
|
||||||
|
detail="missing data62 or ticket; please get qrcode and check scan status first",
|
||||||
|
)
|
||||||
|
|
||||||
|
payload = {
|
||||||
|
"code": code,
|
||||||
|
"data62": data62,
|
||||||
|
"ticket": ticket,
|
||||||
|
}
|
||||||
|
url = f"{CHECK_STATUS_BASE_URL.rstrip('/')}/login/VerifyCode"
|
||||||
|
logger.info("VerifyCode: key=%s, url=%s, code_len=%s, data62_len=%s, ticket_len=%s",
|
||||||
|
key, url, len(code), len(data62), len(ticket))
|
||||||
|
try:
|
||||||
|
async with httpx.AsyncClient(trust_env=False, timeout=20.0) as client:
|
||||||
|
resp = await client.post(url, params={"key": key}, json=payload)
|
||||||
|
except Exception as exc:
|
||||||
|
logger.exception("Error calling upstream VerifyCode: %s", exc)
|
||||||
|
raise HTTPException(status_code=502, detail=f"upstream_error: {exc}") from exc
|
||||||
|
|
||||||
|
body_text = resp.text[:500]
|
||||||
|
logger.info("Upstream VerifyCode response: status=%s, body=%s", resp.status_code, body_text)
|
||||||
|
if resp.status_code >= 400:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=502,
|
||||||
|
detail={
|
||||||
|
"error": "upstream_bad_response",
|
||||||
|
"status_code": resp.status_code,
|
||||||
|
"body": body_text,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
return resp.json()
|
||||||
|
except Exception:
|
||||||
|
return {"ok": True, "text": body_text}
|
||||||
|
|
||||||
|
|
||||||
def _slider_form_html(key_val: str, data62_val: str, ticket_val: str) -> str:
|
def _slider_form_html(key_val: str, data62_val: str, ticket_val: str) -> str:
|
||||||
"""本地滑块验证页:与 7765 相同 DOM 结构(#app、keyInput、data62Input、originalTicketInput),加载 7765 的 module 脚本,不用 iframe。"""
|
"""本地滑块验证页:与 7765 相同 DOM 结构(#app、keyInput、data62Input、originalTicketInput),加载 7765 的 module 脚本,不用 iframe。"""
|
||||||
k = html.escape(key_val, quote=True)
|
k = html.escape(key_val, quote=True)
|
||||||
|
|||||||
@@ -560,6 +560,14 @@
|
|||||||
<option value="mac">Mac</option>
|
<option value="mac">Mac</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label for="verify-code">手机验证码(收到后填写)</label>
|
||||||
|
<input
|
||||||
|
id="verify-code"
|
||||||
|
placeholder="例如:123456"
|
||||||
|
autocomplete="off"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
@@ -578,6 +586,9 @@
|
|||||||
<button class="secondary" id="btn-online">
|
<button class="secondary" id="btn-online">
|
||||||
获取在线状态
|
获取在线状态
|
||||||
</button>
|
</button>
|
||||||
|
<button class="secondary" id="btn-verify-code">
|
||||||
|
验证验证码
|
||||||
|
</button>
|
||||||
<button class="danger" id="btn-logout">
|
<button class="danger" id="btn-logout">
|
||||||
退出当前账号
|
退出当前账号
|
||||||
</button>
|
</button>
|
||||||
@@ -760,6 +771,8 @@
|
|||||||
if (btnWake) btnWake.disabled = loading;
|
if (btnWake) btnWake.disabled = loading;
|
||||||
$('btn-check-scan').disabled = loading;
|
$('btn-check-scan').disabled = loading;
|
||||||
$('btn-online').disabled = loading;
|
$('btn-online').disabled = loading;
|
||||||
|
var btnVerifyCode = $('btn-verify-code');
|
||||||
|
if (btnVerifyCode) btnVerifyCode.disabled = loading;
|
||||||
$('btn-logout').disabled = loading;
|
$('btn-logout').disabled = loading;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1207,6 +1220,34 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function onVerifyCode() {
|
||||||
|
const payload = getCommonPayload();
|
||||||
|
if (!payload) return;
|
||||||
|
const code = (($('verify-code') && $('verify-code').value) || '').trim();
|
||||||
|
if (!code) {
|
||||||
|
alert('请先填写手机上的验证码');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
log('正在提交验证码验证...');
|
||||||
|
const data = await callApi('/auth/verify-code', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({
|
||||||
|
key: payload.key,
|
||||||
|
code,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
log('验证码验证结果: ' + JSON.stringify(data), 'ok');
|
||||||
|
updateLoginState('验证码已提交', 'pending', '请稍后点击「获取在线状态」确认是否已登录');
|
||||||
|
} catch (e) {
|
||||||
|
log('验证码验证失败: ' + (e.message || e), 'error');
|
||||||
|
updateLoginState('验证码验证失败', 'offline', e.message || '');
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function onLogout() {
|
async function onLogout() {
|
||||||
const payload = getCommonPayload();
|
const payload = getCommonPayload();
|
||||||
if (!payload) return;
|
if (!payload) return;
|
||||||
@@ -1262,6 +1303,10 @@
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
onGetOnlineStatus();
|
onGetOnlineStatus();
|
||||||
});
|
});
|
||||||
|
$('btn-verify-code') && $('btn-verify-code').addEventListener('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
onVerifyCode();
|
||||||
|
});
|
||||||
$('btn-logout').addEventListener('click', (e) => {
|
$('btn-logout').addEventListener('click', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
onLogout();
|
onLogout();
|
||||||
|
|||||||
17
方案.md
17
方案.md
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
| 版本 | 月费 | 一次性授权费 | 适用客户 | 核心价值 |
|
| 版本 | 月费 | 一次性授权费 | 适用客户 | 核心价值 |
|
||||||
|---|---:|---:|---|---|
|
|---|---:|---:|---|---|
|
||||||
| 初级版 | 300元/月 | 3000元 | 个人、微团队 | 基础收发与基础运营,适合低风险起步 |
|
| 初级版 | 300元/月 | 3000元 | 个人、微团队 | 基础收发与基础运营,适合项目起步 |
|
||||||
| 高级版 | 600元/月 | 5000元 | 工作室、代运营 | 关键增长能力(群发、朋友圈深度、支付) |
|
| 高级版 | 600元/月 | 5000元 | 工作室、代运营 | 关键增长能力(群发、朋友圈深度、支付) |
|
||||||
| 定制版 | 1200元/月 | 10000元 | 企业客户 | 企业协同与管理能力(企微、授权、小店) |
|
| 定制版 | 1200元/月 | 10000元 | 企业客户 | 企业协同与管理能力(企微、授权、小店) |
|
||||||
| 白标/OEM | 3000~20000元/月 | 50000元起 | 平台型客户 | 在定制版能力上增加商业授权条款 |
|
| 白标/OEM | 3000~20000元/月 | 50000元起 | 平台型客户 | 在定制版能力上增加商业授权条款 |
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
套餐额度:
|
套餐额度:
|
||||||
|
|
||||||
- 消息调用:5万次/月
|
- 消息调用:8万次/月
|
||||||
- 群发任务:0次/月(不含群发)
|
- 群发任务:0次/月(不含群发)
|
||||||
- 加好友动作:200次/月
|
- 加好友动作:200次/月
|
||||||
- 朋友圈动作:200次/月
|
- 朋友圈动作:200次/月
|
||||||
@@ -158,13 +158,12 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7) 联系方式(PPT可直接使用)
|
## 7) 联系方式
|
||||||
|
|
||||||
- 公司名称:XXX科技有限公司
|
- 公司名称:上海丙维数字科技有限公司
|
||||||
- 联系人:XXX(商务负责人)
|
- 联系人:Daniel(商务负责人)
|
||||||
- 联系电话:13XXXXXXXXX
|
- 联系电话:13585795811
|
||||||
- 微信号:XXXXX
|
- 邮箱:bimwe@bimwe.com
|
||||||
- 邮箱:business@xxxx.com
|
- 官网:www.bimwe.com
|
||||||
- 官网(可选):www.xxxx.com
|
|
||||||
|
|
||||||
---
|
---
|
||||||
Reference in New Issue
Block a user