Files
daiyongkang 76f266645d Initial commit: 风影 OA 全栈源码(API/Web/Flutter/IM)
含 Phase 1.1 IM seq 排序、断线重连、多端已读同步与微信式语音转文字 UI。
排除 node_modules、构建产物、安装包与 .env 密钥。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 10:04:03 +00:00

30 KiB
Raw Permalink Blame History

风影智慧办公 · 全系统转交文档

更新日期:2026-09-01
当前手机包:3.1.8+318com.fengying.oa.mobile
本次生产修复与当前真实状态:先读 /opt/HANDOFF.md,再读本文件第 0、2、3、14 节和 .cursor/rules/

本文件覆盖 Web + API + 手机 + IM + 库表 + 密钥 + 发版。不是只写手机端。
含生产密钥,不要推到公开 git。


0. 你接手后立刻要知道的事

  1. 这是一家约四十人的工程/软件公司内部 OA,从旧 Java OA(生产 MySQL 库 oa)迁到本仓库。
  2. 用户同时用 网页 https://oa.fysxkj.com安卓包。IM 是自研 TCP,不是环信。
  3. 办公模块有固定产品规则(第 3 节)。乱改列表筛选或审批不写下游,会被用户打回。
  4. 2026-09-01 的 API 数据修复、旧终止投标恢复兼容和项目类型修复已经发到生产;精确结果与备份位置见 /opt/HANDOFF.md。后续不要依据本文件旧版本描述判断是否已部署。
  5. 回复用户用简体中文。不要主动 git commit / push,除非用户说。
  6. 改菜单后必须跑 apps/api/prisma/sync-menus.ts,侧栏才更新。
  7. 手机登录/刷新必须带 clientKind: 'mobile'

1. 产品与架构

一套 API,三端消费:

路径 技术 入口
API apps/api NestJS 11 + Prisma 6 + PostgreSQL /api/v1Swagger /api/v1/docs
Web apps/web React 18 + Vite 5 + Ant Design 5 + React Query + Zustand 路由 apps/web/src/App.tsx
手机 apps/native Flutter,包名 必须 com.fengying.oa.mobile 底栏:消息 / 工作台 / 通讯录 / 我
IM apps/im-server/server.js Node TCP 8901 + 本机 HTTP 8902 MobileIMSDK 协议

生产:

  • 站点:https://oa.fysxkj.com
  • RESThttps://oa.fysxkj.com/api/v1
  • IM TCP47.96.23.244:8901
  • APKhttps://oa.fysxkj.com/fengying-oa.apk
  • 远端代码:/data/fengying-oa/
  • systemdfengying-api.servicefengying-im.service(模板在 infra/fengying-cloud/
  • 生产 API 端口 3010nginx 反代);本机 nest 常在 3000

本机构建机 hostname fykj,公网不是 47.96.23.244

租户字段 tenantId 目前固定 '1',没有做多租户产品化。


2. 仓库地图

/opt
├── DELIVERY.md                 ← 本文件
├── .cursor/rules/office-process.mdc
├── apps/api                    Nest 后端
│   ├── prisma/schema.prisma    库表
│   ├── prisma/menus.ts         侧栏菜单源
│   ├── prisma/seed.ts          演示数据
│   ├── prisma/sync-menus.ts    菜单写入 Permission
│   ├── src/*.controller.ts     业务入口
│   ├── data/app-release.json   手机 OTA
│   └── .env                    本机密钥
├── apps/web/src
│   ├── App.tsx                 全部路由
│   ├── pages/                  业务页
│   ├── store/auth.ts           登录态
│   ├── api/client.ts           axios + sessionStorage
│   └── labels.ts               枚举中文
├── apps/native                 Flutter
├── apps/im-server/server.js
└── infra/fengying-cloud        nginx / systemd / compose 模板

本机常用:

cd /opt/apps/api && npx nest start          # http://localhost:3000/api/v1
cd /opt/apps/web && pnpm dev                # http://localhost:5173
cd /opt/apps/im-server && node server.js    # TCP 8901
cd /opt/apps/native && flutter build apk --release && bash scripts/publish-apk.sh

改 Prismacd /opt/apps/api && npx prisma migrate dev
改菜单:改 prisma/menus.tsnpx ts-node --transpile-only prisma/sync-menus.ts


3. 硬约束(违反就是返工)

3.1 个人办公怎么长

规则文件:.cursor/rules/office-process.mdc

  • 列表筛选用 ApplyBucketBarSegmented + ?bucket=),有选中态。
  • 标准桶:全部 / 待审批 / 已通过 / 已驳回。领域附加桶可以加,不能替代标准桶。
  • 禁止页头三个无选中态的 Link(「全部」「待审批」「外带未还」这种)。
  • 「我的申请」=/office/flow跟踪;人事/用章/办公申请是发起;「待我审批」是审批。不要做成三套互不相通的列表。
  • 申请人页只看自己的单;台账在业务模块(用章登记、资产管理、采购申请)。

审批通过必须写下游:

申请 落到
资产购置 ASSET_BUY 采购单 + 待入库台账 + 付款待办
资产领用 / 用车 占用记录(挂台账 id),交回不改保管人
出差(人事) 差旅报销草稿
用章外带 归还待办

保管人 = 台账责任人。占用 = 谁正在用。占用时不要把保管人改成持有人。

实现:apps/api/src/office/office-apply.ts

3.2 登录会话

apps/api/src/auth/auth.service.ts + Web apps/web/src/api/client.ts

  • Web 和手机可以同时在线
  • 同一账号不能开两个 Web(后登挤掉先登)。JWT 含 sid
  • 手机 clientKind: 'mobile'refresh 不轮换access 7 天,refresh 3650 天,除非退出一直在线。
  • Web token 用 sessionStorage + BroadcastChannel(同浏览器多标签共享)。关浏览器再开要重登。
  • 桌面端只能扫码,不能账密clientKind: 'desktop' 账密会被拒绝。页 /login/desktop;手机「我 → 确认电脑登录」;Deep Link fengyingoa://qr
  • 登出不带 refresh 时只撤 web/desktop,不踢手机。

3.3 安卓

  • applicationIdcom.fengying.oa.mobilenamespace 仍是 com.fysxkj.fengying_oa,不要改混。
  • 当前 release 用 debug 签名。华为控制台正式 SHA256 对不上 debugHMS token 可能拿不到。
  • 不要com.huawei.agconnect Gradle 插件(AGP 8.6 会炸)。HMS 依赖 + agconnect-services.json + Manifest appid 留着即可。

3.4 数据范围

AuthUser.dataScopeALL / DEPT / SELF。列表过滤在 apps/api/src/common/data-scope.ts。改列表不要只改前端。


4. 角色、权限、菜单

菜单源:apps/api/prisma/menus.ts,写入 PermissionpermType=MENU)。
admin / owner 前端 canSee 直接放行全部。其他人比 permissions 前缀。

种子角色(prisma/seed.ts,生产还会有导入岗位):

code 名称 dataScope 大致权限
admin 系统管理员 ALL *
owner 企业负责人 ALL *
biz_director 商务总监 DEPT office/party/seal/bid/contract/finance/report
biz_staff 商务专员 SELF office/party/seal/bid/contract
tech_director 技术总监 DEPT office/bid/project/report
rd_director / 3d_director / video_director / material_director 各技术条线总监 DEPT role-groups.ts
finance 财务 ALL office/finance/contract/report
hr 人事 ALL office/hr + 人事设置
employee / pm / 各 *_staff 员工/项目经理 SELF office + 工时等
seal / asset / cashier … 导入岗位 视脚本 fix-oa-posts.ts

总监集合:DIRECTOR_ROLES。可发短信:SMS_SEND_ROLES。可派工作:WORK_ASSIGN_ROLES
bid-workflow.ts 仍保留旧的 SPECIAL_COORDINATORS 常量用于兼容,但当前特殊筛选/特殊制标的办理人加载逻辑是全体在职人员,禁止再改回写死两人。

首次登录非 admin:改密 + 完善档案(/office/onboard)。mustChangePassword / profileCompletedAt

Web 侧栏:AppLayout/auth/me 带回的 menus
发公告:hr 与各总监(NOTICE_PUBLISH_ROLES in App.tsx)。


5. Web 功能全表(按侧栏)

路由全部在 apps/web/src/App.tsx。没有单独的移动端 Web。

5.1 工作台 /workbench

OverviewPage:待办/待审批数字、天气问候、快捷入口。API:GET /office/overviewGET /office/weather

5.2 个人办公

菜单 路径 页面 API 要点 说明
待办事项 /office/todos OfficeTodosPage GET /office/todos PATCH /office/todos/:id 待办可标已办
待我审批 /office/approvals OfficeApprovalsPage GET /office/approvals POST .../decide 统一审批入口
我的申请 /office/flow MyFlowPage GET /office/flow 只跟踪自己的单
我的日程 /office/calendar CalendarPage GET /office/calendar 含证照/印章逾期、开标等
工作汇报 /office/reports WorkReportPage /office/reports* 可从工时草稿带入
我的费用 /office/expenses MyExpensesPage + Expense/Loan 详情 /office/my-expenses /expenses /loans 员工发起报销/借款
人事申请 /office/hr-apply HrApplyPage / HrLeaveDetailPage /leave-requests 请假加班出差外出离职晋升
用章申请 /office/seal-apply SealRequestListPage mode=apply /seal-requests 发起;台账在证照用章
办公申请 /office/apply OfficeApplyPage /office/applies 购置/领用/用车
公司公告 /office/notices NoticePage / NoticeDetailPage /office/notices 员工阅读
发送短信 /office/sms OfficeSmsPage /sms/* 总监/人事/admin
工作安排 /office/assign WorkAssignPage /office/work-assignments 总监派任务
消息 /office/im ImPage /im/* Web IM + 通话弹层
员工通讯 /office/directory DirectoryPage /staff /directors 点人可开聊

出差通过后应落差旅报销草稿(人事申请下游)。

5.3 往来单位

菜单 路径 页面 API
招标单位 /party/tenders TenderPartyPage /parties
参与主体 /party/entities LegalEntityPage /legal-entities
联系名录 /party/contacts ContactDirectoryPage /contacts

本机已洗过 5 家主体:随行科技(默认,历史投标多挂这里)、风影软件、风影工程、山东鲁兵、隆创。脚本 prisma/wash-legal-entities.ts。OA dump 几乎没有「软件/工程」历史投标,不会自动拆单。

5.4 证照用章

菜单 路径 页面 API
资质台账 /seal/qualifications QualificationListPage /qualifications
证照借用 /seal/borrows BorrowListPage /credential-borrows
用章登记 /seal/requests SealRequestListPage mode=register /seal-requests
印章台账 /seal/registry SealRegistryPage /seals

印章状态:IN_STOCK 在库,OUT 外带(Web 台账有特判)。外带审批通过写归还待办。

5.5 投标管理(核心)

状态机:apps/api/src/bidding/bid-workflow.ts
列表桶:BidListPage + ?bucket=

普通 FLOW
  项目筛选 TECH_INITIAL → FETCH → TECH_FINAL
  → 标书制作 DRAFTING → REVIEW1 → REVIEW2 → PRINT
  → 投标执行 LIST → PENDING
  → 开标结果 WON / LOST / FAILED
  随时可 TERMINATED(权限内)

特殊 SPECIAL:特殊筛选 / 特殊制标的办理人从**全公司在职人员**中选择,不再写死刘运泽、陈铖。
菜单 路径 bucket
项目筛选 /bid/screening screening(可新建)
特殊筛选 /bid/special-screening 特殊
标书制作 /bid/drafting drafting
特殊制标 /bid/special-drafting drafting+special
投标执行 /bid/execution execution
开标结果 /bid/result result
终止投标 /bid/terminated terminated

详情 /bid/cases/:idBidDetailPage。新建:BidCreatePage
中标:ensureWonLedger 立刻落 合同草稿 + 项目台账(幂等)。
未中/终止:可「编辑」登记对方中标单位/金额 → 报表「落标对照」。
API/bid-casesPATCH /bid-cases/:id/competitor

5.6 合同管理

中标自动生成 kind=TENDER 草稿。直签/其他在本页新建,不互相重复。

菜单 路径 说明
投标合同 /contract/tender 中标来的
直签合同 /contract/direct 不经投标
其他合同 /contract/incremental 其余
人事合同 /contract/hr LaborContractPage /labor-contracts

详情 /contract/:id。API /contracts

5.7 资产管理

数字资产 /asset/digital、固定资产 /asset/fixedAssetRegistryPage/registered-assets
状态含 IN_STOCK / PENDING_IN / 占用。入库:POST /registered-assets/:id/inbound
领用占用走办公申请,不在本页把保管人改掉。

5.8 项目管理

中标自动写入台账。直签可在台账补登。

菜单 路径 API
项目台账 /project/list /projects
任务分解 /project/tasks /project-tasks
工时填报 /project/timesheets /timesheets
资源看板 /project/resources OpsPages ResourceBoardPage
项目验收 /project/acceptance 同一 ProjectListPage mode=acceptance
采购申请 /project/purchases PurchasePage(购置审批下游)
器材占用 /project/assets AssetPage 占用记录

详情 /project/:id。预算/报销:商务差旅进商务,技术部门差旅/工时/采购进技术(页面 description 已写)。

5.9 财务收支

员工在「我的费用」发起;财务在本模块确认、付款、开票。草稿财务看不到(canSeeSubmittedFinance)。

菜单 路径 API
费用报销 /finance/expenses /expenses
借支记录 /finance/loans /loans
投标/履约/质保金 /finance/bonds/* /bonds type=TENDER/PERFORMANCE/WARRANTY
开票收款 /finance/invoices /invoices
付款执行 /finance/payments /payments

报销必须挂费用对象:投标 / 正式项目 / 部门 / 行政,规则 assertCostObject。中标前挂投标,中标后挂项目,不要同时挂。

5.10 组织人事

菜单 路径 说明
在职员工 /hr/employees 档案、证件、银行卡
组织管理 /hr/org 部门树
入转调离 /hr/lifecycle EmploymentEvent
假勤结果 /hr/attendance 月导入 + 打卡
薪酬核算 /hr/payroll 核算批次
绩效发放 /hr/performance
发布公告 /hr/notices 人事发
规章制度 /hr/policies 同类 Noticekind 不同

5.11 经营报表

菜单 路径 API
投标转化 /report/conversion /reports/bid-conversion
落标对照 /report/lost /reports/competitor-wins
项目利润 /report/profit /reports/profit
部门人效 /report/efficiency /reports/efficiency
资金占用 /report/cash /reports/cash

页面在 OpsPages.tsx

5.12 系统设置

菜单 路径 说明
员工账号 /system/acl 用户/角色
人事参数 /system/hr-params
考勤设置 /system/attendance-rules
数据字典 /system/dicts
权限设置 /system/perms 菜单授权
编号规则 /system/numbers nextBizNo
短信服务 /system/sms 签名/模板/绑定事件
消息通道 /system/messages 占位页,文案可能过时(IM 已做)
手机端升级 /system/app-release app-release.json
操作日志 /system/logs

公开:GET /system/app-release(手机 OTA)。


6. 核心流程(改业务先对这条链)

投标 → 合同/项目

筛选 → 取标 → 终审 → 制标 → 一审二审 → 印封 → 执行 → 开标。
WON → 合同草稿 + 项目台账。售前报销仍挂投标;正式花费挂项目。

报销 / 借款

员工草稿 → 提交 PENDING → 财务/总监审批 APPROVED → 付款执行。借款还有 OPEN / OFFSET 冲账。

办公申请

发起 PENDING → 审批(admin/owner/hr/biz_director)→ 按 kind 写采购/占用/待入库。

用章

申请 → 审批 → 外带则归还待办;台账 status 在库/外带。

人事假勤

LeaveRequest.kindLEAVE / OVERTIME / TRIP / OUT / RESIGN / PROMOTE。出差通过 → 报销草稿。

统一待办 TodoTask、统一审批 ApprovalTaskbizType 区分投标/合同/报销/用章/人事/办公)。
待我审批一页消化,不要为每个 biz 再做孤立审批页。


7. API 地图

前缀均 /api/v1。鉴权 JWT,除标注 Public。

模块 文件 主要路径
登录 auth/ /auth/login /auth/refresh /auth/me /auth/logout /auth/profile /auth/password /auth/qr/*
办公 office/ /office/* 待办审批日程公告申请汇报工作安排天气地理
投标 bidding/ /bid-cases
合同 contract/ /contracts
项目 project/ /projects /project-tasks /timesheets
用章 seal/ /seal-requests /seals /qualifications /credential-borrows
财务 finance/ /expenses /loans /bonds /invoices /payments
人事 hr/ /employees /leave-requests /payroll /attendance /labor-contracts /org
主数据 master/ /parties /legal-entities /contacts /registered-assets
系统 system/ /system/menus /system/acl /system/dicts /system/numbers /system/app-release /system/logs
报表 report/ /reports/*
文件 files/ POST /files GET /files/:id
IM im/ /im/conversations /im/messages PATCH /im/messages/:id /im/calls* /im/read
推送 push/ 设备 token 注册与下发
短信 sms/ 签名模板发送 OTP
通讯录 business/ /staff /directors
健康 health/ /health
协议 legal/ 用户协议页

响应外包一层 { data }Web 用 unwrapList / body.data。手机 oa_client.dart 同样解包。
错误:HttpErrorFilter。请求号:X-Request-Id

地理:/office/geo/* 走腾讯位置服务,TENCENT_MAP_KEY


8. 数据模型(Prisma

完整定义:apps/api/prisma/schema.prisma

账号User、RefreshTokenclientKind)、AuthQrTicket、Role、Permission、UserRole、PushDevice
组织人事Department、Employee、LaborContract、EmploymentEvent、AttendanceMonth、AttendancePunch、LeaveRequest、HrSetting、AttendanceRule、PayrollRun、PayrollItem
主数据LegalEntity、BusinessParty、PartyContact、DictItem、NumberRule、Qualification、SealItem、RegisteredAsset
投标BidCase(含 winnerName/Amount/Note)、BidReviewer、BidAssignee、BidDocVersion、BidActionLog
合同项目Contract、ContractReviewer、PaymentMilestone、Project、ProjectBudget、ProjectTask、Timesheet、ProjectAcceptance、ProjectAcceptMaterial、ProjectChange
财务ExpenseClaim、ExpenseLine、LoanRecord、BondRecord、InvoiceRecord、PaymentRecord、PurchaseRequest
办公TodoTask、ApprovalTask、WorkReport、WorkAssignment、OfficeApply、Notice、AssetOccupancy、CredentialBorrow、SealRequest
IMImConversation、ImConversationMember、ImMessagefingerprint 唯一)、ImReadCursor、ImMessageReceipt、ImCall、ImCallMember、ImCallSignal
其它FileAsset、SmsSendLog、SmsEventBind、SmsOtp、OperationLog

编号:NumberRule + src/system/numbering.ts。注意:项目筛选、特殊筛选的招标编号和合同编号必须手填,系统不得另生成隐藏编号;报销等内部单据仍可使用系统编号。


9. 手机端

Flutter。版本:apps/native/lib/app_config.dart + pubspec.yaml + test/widget_test.dart + apps/api/data/app-release.json,四者一起改。

默认连生产 API / IM。底栏四页:messages_pageworkbench_pagedirectory_pagemine_page

工作台宫格来自登录菜单。open_module.dart / module_list_page.dart 把菜单码映射到 REST 列表(投标→/bid-cases 等)。系统设置、发短信、工作台里的「消息」入口故意不打开(消息在底栏)。详情 record_detail_page.dart + biz_route.dart 反查详情 API。中文:labels.dart

聊天/通话的关键文件:聊天 chat_page.dart,来电 home_shell.dart + call_page.dart。当前版本为 3.1.8+318;音视频、截屏提醒、撤回再编辑、会话已读后保留等需求必须按 /opt/HANDOFF.md 的“未完成/需真机回归”继续验证,不能仅凭旧交接宣称已修。

打包:

cd /opt/apps/native && flutter build apk --release && bash scripts/publish-apk.sh

产物:/opt/apps/native/dist/fengying-oa.apk。本机 root 跑 Flutter 会警告,仍能编过。下一版必须在 3.1.8+318 基础上递增。

OTA:比较 build。后台「手机端升级」。


10. IM

协议:4 字节大端长度 + UTF-8 JSON Protocal。登录用 OA accessToken 调 GET /auth/me

server.jsMap<userId, Set<socket>>,同一账号多端/重连 不再 kick。旧版会踢旧连接,客户端若把 _want=false 会永久断线。
生产必须换新 server.js 长连接才稳。新 APK 即使对旧 IM 也不会再「被踢后永不再连」。

HTTP 消息仍落 Postgres。TCP 负责推送。通话信令走 /im/calls/:id/signalHTTP 轮询),WebRTC + 国内 STUN。

PATCH /im/messages/:id2 分钟内改自己的文本。


11. 文件、短信、推送、地图

  • 文件:FilesService 存 MinIO(本机 docker)或本地 uploads/。下载带鉴权。手机 AuthImage / fileBytes 有内存缓存。
  • 短信:阿里云 Dysmsapi。系统设置申请签名/模板,事件绑定在 SmsEventBind。投标节点会 emitSms
  • 推送:vivo / OPPO / 魅族 / 华为。设备 PushDevice。华为 App ID 118301849
  • 地图:腾讯。选点 location_pick_page.dart + tencent-lbs;POI 用真实距离,不要写死「100m内」。

12. 前端约定

Web

  • 新列表:Ant Design Table + 中文 zh() / StatusTag,不要直接渲染枚举码。
  • 申请类列表:ApplyBucketBar + URL bucket
  • 抽屉表单:FormDrawer.tsx。附件:FileAttachments.tsx
  • 枚举中文:apps/web/src/labels.ts,与手机 labels.dart 对齐。
  • token 只放 sessionStorage。

手机

  • 企业微信风:theme.dartwidgets/wecom.dart
  • 英文字段:补 fieldZh / zhMap,不要在单个页写死。OUT 人事=外出、印章=外带,有冲突时按字段上下文。

13. 脚本与历史数据

apps/api/prisma/ 里常见脚本(跑前看文件头,生产库只读):

脚本 用途
seed.ts 空库演示
sync-menus.ts 菜单/权限
import-hr.ts / import-prod.ts 从旧 OA 导人事/业务
wash-legal-entities.ts 参与主体清洗
wash-oa-ledger.ts / wash-oa-flow-finance.ts 台账/财务清洗
sync-oa-attachments.ts 附件
grant-admin-equivalents.ts / ensure-prod-admin.ts 管理员
fix-oa-posts.ts / fix-expense-applicants.ts 岗位与报销申请人

旧 OA 在生产 MySQL oa(只读扒数,用户禁止改生产旧库、禁止整用户过来)。dump 曾放 /opt/import/prod/


14. 密钥与账号(Codex 直接用,不必再问)

生产 SSH

主机:47.96.23.244
用户:root
密码:VYTnNdfFfrX7xTP
代码目录:/data/fengying-oa/
export SSHPASS='VYTnNdfFfrX7xTP'
RSH='ssh -o StrictHostKeyChecking=no'
DEST=root@47.96.23.244
sshpass -e ssh -o StrictHostKeyChecking=no "$DEST" 'hostname; systemctl is-active fengying-api fengying-im'

发版:

export SSHPASS='VYTnNdfFfrX7xTP'
RSH='ssh -o StrictHostKeyChecking=no'
DEST=root@47.96.23.244
# 先 nest build、确认 APK 已 publish
sshpass -e rsync -az -e "$RSH" /opt/apps/api/dist/ $DEST:/data/fengying-oa/apps/api/dist/
sshpass -e rsync -az -e "$RSH" /opt/apps/api/data/app-release.json $DEST:/data/fengying-oa/apps/api/data/app-release.json
sshpass -e rsync -az -e "$RSH" /opt/apps/web/dist/ $DEST:/data/fengying-oa/apps/web/dist/   # 若本机有最新 web 构建
sshpass -e rsync -az -e "$RSH" /opt/apps/im-server/server.js $DEST:/data/fengying-oa/apps/im-server/server.js
sshpass -e rsync -az -e "$RSH" /opt/apps/native/dist/fengying-oa.apk $DEST:/data/fengying-oa/apps/web/dist/fengying-oa.apk
sshpass -e ssh -o StrictHostKeyChecking=no "$DEST" 'systemctl restart fengying-api fengying-im; sleep 2; systemctl is-active fengying-api fengying-im'

生产 API .env 在远端 /data/fengying-oa/apps/api/.env。上去先 cat不要用本机 development 的 JWT/Postgres 覆盖生产。发 IM/API 后确认 Prisma 已有 RefreshToken.clientKindAuthQrTicketBidCase.winner*

旧 OA MySQL(只读)

用户:root
密码:BtH9ywG8gFTXG9w!
库:oa

本机 API apps/api/.env

NODE_ENV=development
APP_PORT=3000
DATABASE_URL=postgresql://ops:ops_dev_only@localhost:5432/enterprise_ops
REDIS_URL=redis://localhost:6379
MINIO_ACCESS_KEY=opsadmin
MINIO_SECRET_KEY=opsadmin_dev_only
JWT_ACCESS_SECRET=change-me-access-secret-dev-only
JWT_REFRESH_SECRET=change-me-refresh-secret-dev-only
POSTGRES_USER=ops
POSTGRES_PASSWORD=ops_dev_only
POSTGRES_DB=enterprise_ops

ALIYUN_SMS_ACCESS_KEY_ID=LTAI5t9DdPycJp7sabQyEWRc
ALIYUN_SMS_ACCESS_KEY_SECRET=RPFVqKDUpEvxo3IsqlxLB5qIywfheM
ALIYUN_SMS_ENDPOINT=dysmsapi.aliyuncs.com
ALIYUN_SMS_REGION=cn-hangzhou
ALIYUN_SMS_DEFAULT_SIGN=江苏风影随行科技
ALIYUN_RAM_LOGIN=yongkangdai10@1801267455383083.onaliyun.com

TENCENT_MAP_KEY=L6NBZ-47KLI-OL7G2-UMROZ-XPI3T-SLFC7

IM_TCP_PORT=8901
IM_HTTP_PORT=8902
IM_INTERNAL_TOKEN=fengying-im-internal

VIVO_PUSH_APP_ID=106114371
VIVO_PUSH_APP_KEY=b521c805229a00e85a53d4b535a0cafe
VIVO_PUSH_APP_SECRET=2e1536ed-ed2f-4cd6-88d1-67aa9a93eeba

OPPO_PUSH_APP_ID=37438377
OPPO_PUSH_APP_KEY=e23832b52fbb46e18de6eef5affda2e9
OPPO_PUSH_APP_SECRET=e9cf0bf35052484ebcaf15d56576468b
OPPO_PUSH_MASTER_SECRET=e9cf0bf35052484ebcaf15d56576468b

MEIZU_PUSH_APP_ID=157643
MEIZU_PUSH_APP_KEY=4263a8d18de442b6a17203866ce1546d
MEIZU_PUSH_APP_SECRET=2a0bafc2d47a470f8b2aad3f182d2377

HUAWEI_PUSH_APP_ID=118301849
HUAWEI_PUSH_CLIENT_ID=118301849
HUAWEI_PUSH_CLIENT_SECRET=85c01c5c853d571e2d83fd8629efb21e9b2cad0bdfadd6f32c2c5b42e38d7888

本机 IM .env 写的是 OA_API_URL=http://127.0.0.1:3010/api/v1,本机 nest 常在 3000,连本机 IM 请改 3000。生产 systemdOA_API_URL=http://127.0.0.1:3010/api/v1

华为 AGC

  • 包名 com.fengying.oa.mobileApp ID 118301849
  • 服务端 Client Secret85c01c5c853d571e2d83fd8629efb21e9b2cad0bdfadd6f32c2c5b42e38d7888
  • JSONapps/native/android/app/agconnect-services.json
  • JSON client.client_id1993069421077225280
  • JSON client.client_secret93585E101B911EFF0F99F215050CD3E4297F67CB004E0D8E070AAB1EEDD7E725
  • JSON client.api_keyDgEDAFLpMeUxEsIEiKams+kYWThvAg0ioMuL1rW9BEP4i71BuChEPD7Udg1AbDKbg+ljwD+pBACxktLqHwmUlSxOCwsLHiRAKQDBFw==
  • cp_id10086000847744494product_id101653523864520415

OPPO Maven

https://maven.columbus.heytapmobi.com/repository/releases/
username: nexus
password: c0b08da17e3ec36c3870fed674a0bcb36abc2e23

腾讯地图 / vivo Manifest

  • TENCENT_MAP_KEY=L6NBZ-47KLI-OL7G2-UMROZ-XPI3T-SLFC7
  • Manifest vivoapi_key=b521c805229a00e85a53d4b535a0cafeapp_id=106114371

本机演示账号

admin / Admin@123456。种子其他人常见 Demo@123456 或导入后 123456。不要拿去撞生产。


15. 发生产清单

  1. npx nest build,同步 apps/api/dist/
  2. 若改了 Webpnpm --filter web build,同步 apps/web/dist/
  3. 同步 server.js、APK、app-release.json
  4. systemctl restart fengying-api fengying-im
  5. 后台确认手机端升级为当前最新 build(现为 318)
  6. 真机覆盖安装当前最新版(现为 3.1.8)

**APK 保留规则:**云主机只保留当前 OTA 指向的最新安装包(对外统一为 apps/web/dist/fengying-oa.apk)。每次发版先精确列出 /data/fengying-oa 下的 .apk / .aab,确认新包可下载后删除其他旧包,不要在 apps/native/dist 等目录留历史副本。

API/IM/APK 是否为同一版必须分别核对,不能只看网页或 OTA JSON。


16. 已知坑 / 未完成

  1. 生产 API 已同步 2026-09-01 的数据修复代码;Web、IM、APK 后续每次仍要分别核对版本和构建时间。
  2. 华为正式推送:缺正式签名 + AGConnect 插件未进构建。
  3. OUT 中文:人事外出 vs 印章外带。
  4. 系统设置「消息通道」文案还写「本期不做原生 IM」,已过时。
  5. Web IM 与手机 IM 都可用,但通话依赖双方打开页 + STUN,失败别先改来电弹层。
  6. 手机工作台对报表/部分系统页映射为 null,点了可能没页。
  7. 打开 docx 依赖手机已装 WPS/Office。
  8. 历史投标主体不会自动拆到软件/工程公司。
  9. apps/native/README.md、部分 api README 版本号过时,以 app_config.dart 和本文件为准。
  10. 薪酬/绩效/资源看板有页面,深度以现网数据为准,缺的是补流程不是再铺空壳。
  11. 问题视频:/opt/问题视频/。来电测试对象常为「戴永康」。

17. 建议接着做的顺序

  1. 用第 14 节发生产(API + Web + IM + APK + OTA),不要再问密码。
  2. 真机覆盖 2.3.2:来电能关、消息上屏、图片/地图能点、印章「在库」。
  3. 网页重新登录:确认扫码登电脑、Web 互踢、侧栏「落标对照」。
  4. 再改业务:遵守第 3 节办公规则;改投标走 bid-workflow.ts,不要只改一个列表页。
  5. 英文残留:补 labels.ts / labels.dart
  6. 华为推送真机(正式签名)。
  7. 用户新需求再开功能,不要平行重构目录。

改完菜单同步 sync-menus.ts。改完枚举两边 labels 一起改。改完版本四个文件一起改。