fix: wechat account scrape (form-data+dates) + frontend staff page

Backend (scrape_wechat_accounts):
- Send wxUser/list as form-urlencoded (not JSON) with the REQUIRED filters
  isOnJob / departmentId / startdate / enddate + empty userId/salesname/
  weChatNickName, matching the live request (empty fails with code -90000).
- scrape_wechat_accounts now takes department_id (the company-root dept id)
  plus optional start/end defaulting to a recent 7-day UTC window.
- paginate_by_page gains a form=True mode (data= + form content-type).
- Orchestrator sync_wechat_accounts resolves the root dept from the
  Department table (or accepts one) and skips with a warning when unknown.
- seed_accounts.py resolves the root via scrape_departments.

Frontend (yunkes):
- Add StaffList.vue (/staff) with is_on_job filter + pagination.
- Add /staff route and a 员工 nav item between 客户 and 群.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
浅念
2026-08-01 17:11:17 +08:00
parent 4dcfc66741
commit 0df53c6b1a
10 changed files with 638 additions and 30 deletions
@@ -5,8 +5,15 @@ data dictionary §2: ``wechatId, nickName, alias, phone, userId,
userName(员工真名), contactsNum, groupNum, sendNum/receiveNum, isOnJob,
dbSize, 在线状态, lastUpdate``; total=55).
The envelope differs from ``wxFriends/friend_list/es``: there is **no**
``basicResult`` wrapper. The pagination fields sit directly under ``data``::
The REQUEST is **form-urlencoded** (NOT JSON): the endpoint binds Spring
``@RequestParam`` from the form body and REQUIRES ``isOnJob`` /
``departmentId`` (the company-root dept id) / ``startdate`` / ``enddate`` or
it answers ``code -90000`` ("缺少..."). ``userId`` / ``salesname`` /
``weChatNickName`` are sent empty to mirror the real client.
The RESPONSE envelope differs from ``wxFriends/friend_list/es``: there is
**no** ``basicResult`` wrapper. The pagination fields sit directly under
``data``::
{"code":"10000","data":{"data":[...], "total":.., "pageNum":.., "pageSize":..}}