水果供应链业财一体系统的技术架构说明。业务约束见 00-业务规则.md;库存确认见 14-库存确认契约.md;表结构见各功能文档。
| 层 | 选型 | 说明 |
|---|---|---|
| 运行时 | PHP 8.3 | |
| 框架 | Laravel 13 | Web、队列、调度、Auth |
| 管理端 | Filament 5 | PC 后台录入、审批、主数据、报表入口 |
| 企业 H5 | Blade + Vite + Tailwind + Alpine | 企微内打开,路径 /app,OAuth 登录 |
| 数据库 | MySQL | 业务库;会话/队列/缓存当前可为 database 驱动,生产可换 Redis |
| 权限 | spatie/laravel-permission + filament-shield | 角色 name(key)+ label(中文);数据范围按 product_user |
| 队列 | Laravel Queue | 采单解析、消息投递、夜间分析 |
| 调度 | Laravel Scheduler | 日终库存快照、每日分析 |
| 文件 | Spatie Media Library + 七牛 | MEDIA_DISK;未配齐七牛回退 public;H5 直传 |
| 企微 | 官方 API | 群机器人收单、通讯录同步、应用消息、H5 OAuth / JS-SDK |
| 企微语音 | JS-SDK translateVoice |
企业 H5 按住说话转写 |
| 微信 | 服务消息等 | 出站推送通道之一 |
| AI | OCR + 火山方舟 | 单据识别、字段抽取、语音草稿、H5 对话问数 |
┌─────────────────────────────────────────────────────────┐
│ 接入层 │
│ Filament PC 后台 │ 企业 H5(/app)│ 企微群机器人 │ 网页兜底 │
└────────────┬────────────────┬───────────────┬───────────┘
│ │ │
┌────────────▼────────────────▼───────────────▼───────────┐
│ 应用服务层 │
│ 部门员工 │ 产品SKU │ 仓库 │ 采购 │ 订单 │ 加工 │ 财务 │
│ 消息(出站)│ AI 应用(采单/OCR)│ 数据分析 │
└────────────┬────────────────────────────┬───────────────┘
│ │
┌────────────▼──────────────┐ ┌──────────▼────────────────┐
│ 领域持久化(MySQL) │ │ 异步 / 外部 │
│ 主数据 + 单据 + 库存流水 │ │ Queue │ Scheduler │
│ 站内消息 + 投递记录 │ │ 企微/微信 API │ AI API │
│ 原始文件元数据 │ │ 对象存储 │
└───────────────────────────┘ └───────────────────────────┘
不另起前端仓库,挂在本 Laravel 应用内,企微工作台打开。
| 项 | 约定 |
|---|---|
| 入口 | /app(企微 OAuth);根路径 / 进后台,若带 OAuth code/state 则转发 H5 回调 |
| 技术 | Blade 视图 + Vite 8 + Tailwind + Alpine.js(按需 Chart 等) |
| 布局 | resources/views/layouts/*-app.blade.php + 独立 css/js entry(如 h5-app) |
| 页面 | resources/views/h5/(或业务子目录);Controller 如 App\Http\Controllers\H5\* / WeCom\* |
| 鉴权 | 企微 OAuth → 绑定 users.wecom_userid → Session;回调时更新 mobile、avatar;中间件可关 H5(维护页) |
| JS-SDK | /app/wecom/js-sdk-config;拍照、选图、语音识别(translateVoice) |
| 权限 | 同一套 laravel-permission + 产品数据范围;H5 只暴露业务员能力子集 |
| 上传 | 七牛直传(token 接口);后台走 Spatie Media Library |
| 语音录单 | 所有 H5 业务表单可语音 → 方舟草稿 → 人工确认后提交 |
| 对话 | /app/chat;自然语言查权限内业务数据(只读) |
典型路由
| 路由 | 用途 |
|---|---|
/app |
企微入口 / OAuth |
/app/wecom/callback |
OAuth 回调 |
/app/home |
首页(待办、入口) |
/app/chat |
对话问数(自然语言查本人相关数据) |
/app/... |
单据查看、简易录入、站内消息、审批待办等 |
/app/wecom/js-sdk-config |
JS-SDK 签名 |
后台仍用 Filament(/admin);H5 不做完整主数据治理,复杂配置回 PC。
边界
product_user 数据范围,不扩权;只读。messages。| 模块 | 文档 | 阶段 | 职责 |
|---|---|---|---|
| 部门与员工 | 01 | P0 | 企微入站同步;产品成员;权限 |
| 产品 SKU | 03 | P0 | 产品、SKU、单位 |
| 仓库 | 04 | P0 | 结存流水;调拨降级盘点;期初/报损/拆合 |
| 采购 | 05 | P0 | 确认归档;采销关联;财务看板 |
| 订单 | 06 | P0 | 确认归档;财务驳回 |
| 生产加工 | 07 | P0 | 工单确认出入库 |
| 财务 | 08 | P0 | 费用单多态;开票资料多态;发票;请款;报销 |
| 消息 | 09 | P1 | 出站消息 |
| 数据分析 | 10 | P1 | 单据金额+费用单盈亏、预警、对账导出 |
| AI 应用 | 11 | P2 | 采单 OCR、语音、对话 |
| 库存确认契约 | 14 | P0 | 确认与财务驳回→流水 |
边界
stock_documents 仅期初/报损/拆合。related_purchase_id;仓间实物走调拨。purchases / orders / process_orders / stock_* / stock_documents
→ 确认服务(按 14 矩阵)
→ stock_ledgers(source_* 必填)
→ stocks
企微 @ / 网页 / H5 语音
→ inbound_messages → OCR + 方舟 → 草稿
→ 人工确认写入业务单
→ 再经业务确认走 14(禁止解析直接写 stocks)
语音 / 对话问数见 AI 文档;属 P2。
业务事件 / 分析任务 / 审批
→ messages(站内必留)
→ message_deliveries(inbox / wecom / wechat …)
→ 按 message_subscriptions 发送或 skipped
Scheduler(夜间)
→ stock_snapshots
→ analysis_runs → profit_daily / alerts / replenish / statements
→ 摘要写入 messages → 多平台投递
wecom_userid)。二者同一 users 表。OAuth 成功时刷新 mobile、avatar。users.status === active。不强制 panel_user,避免企微同步员工进不了后台。roles.name 是代码 key(如 super_admin),roles.label 是界面中文名。后台「角色」勾资源/页面/自定义权限;员工表单赋角色。product_user 所属产品;data.view-all 看全量。employment_type 影响报销制度与默认可授角色,不是独立权限包。细节见 01-部门与员工.md。
| 集成 | 用途 | 注意 |
|---|---|---|
| 企微通讯录 | 部门、员工入站同步(回写属 P2) | 关联键 wecom_dept_id / wecom_userid;编制与权限不同步 |
| 企微 OAuth | H5/后台登录 | 回调 upsert 员工,并更新手机号、头像 |
| 企微群机器人 | 采单 | 必须 @;分业务域 bot;官方 API only |
| 企微 JS-SDK 语音 | H5 语音转写 | translateVoice;需可信域名与签名 |
| 火山方舟 | LLM 抽字段 / 整理草稿 / 对话问数 | VOLCENGINE_ARK_*;写单未确认不入账;对话只读 |
| 微信服务消息等 | 出站 | 经 message_deliveries,失败可重试 |
| AI OCR | 图片/PDF 识字 | 与方舟串联:OCR 文本 → 方舟结构化 |
| 文件(七牛 / 本地) | 单据原件、报销凭证、导出附件 | 见下节「文件管理」 |
业务附件统一用 Spatie Media Library 做元数据与多态挂载;物理文件优先 七牛,本地开发可回退 public。
| 层 | 做法 | 说明 |
|---|---|---|
| 元数据 | media 表;Model InteractsWithMedia;自定义 App\Models\Media |
预览/下载鉴权 URL |
| 默认盘 | MEDIA_DISK(qiniu / public);七牛未配齐 AK/SK/Bucket/Domain 时回退 public |
MediaDisk::name() |
| 后台上传 | Filament SpatieMediaLibraryFileUpload;预览/下载走应用内鉴权路由,不裸奔私有链 |
全局配置上传组件 |
| H5 上传 | 浏览器向应用要 uploadToken + key,再直传七牛;服务端只校验 key 前缀与扩展名后挂到业务单 | QiniuUpload + UploadController |
| CDN 图 | 列表缩略用七牛 imageView2 / imageslim 拼查询参数 |
listThumbUrl |
H5/前端
→ GET/POST /app/.../upload-token?ext=&kind=
→ 七牛 upload_url + token + 预定 key
→ 直传成功
→ 业务提交时带 key / url,服务端校验后 addMedia 或写附件字段
{业务前缀}/{Ymd}/{random}.{ext}(如 docs/20260331/xxxx.jpg),拒绝非托管 key。image / video / audio / file,限制扩展名与大小。QINIU_ACCESS_KEY、QINIU_SECRET_KEY、QINIU_BUCKET、QINIU_DOMAIN、QINIU_UPLOAD_URL;MEDIA_DISK=qiniu(生产)。media.preview / media.download(校验当前用户对父模型的查看权)。| 场景 | 挂载方式 |
|---|---|
| 采购/订单/加工附件、出入库凭证图 | 单据 Model Media Collection(如 attachments) |
| 报销发票/支付截图 | expense_claims collection |
| AI 采单原图/PDF | inbound_messages.attachment_paths 或 Media 挂采单记录 |
| 对账单/导出 Excel PDF | 生成后可落存储,路径写入结果表 |
不做:自建文件中台第二套库表替代 Spatie;H5 大文件不经 Laravel 中转上传(避免撑爆 PHP)。
依赖建议:spatie/laravel-medialibrary、filament/spatie-laravel-media-library-plugin、overtrue/laravel-filesystem-qiniu。
| 组件 | 建议 |
|---|---|
| Web | PHP-FPM / Octane(按量)+ Nginx |
| Worker | queue:work(解析、投递、分析) |
| Scheduler | schedule:run 每分钟(宿主机 cron) |
| DB | MySQL 8+;生产独立备份 |
| 缓存/队列 | 初期 database;并发上来后 Redis |
| 环境 | .env:DB、队列、企微、VOLCENGINE_ARK_*、MEDIA_DISK / QINIU_* |
本地:composer setup / php artisan dev(见项目脚本)。
app/
Models/Media.php # 扩展 Spatie Media(预览/下载 URL)
Support/
MediaDisk.php # MEDIA_DISK 解析与七牛回退
QiniuUpload.php # 直传 token、key、缩略图
Http/Controllers/
WeCom/
H5/
Media/ # preview / download
H5/QiniuUploadController.php
Filament/
resources/
views/h5/
css|js/ # 含七牛直传、企微语音等
docs/
不强制 DDD 分层。H5 / 文件 / 企微按上文约定实现(/app、MediaDisk、QiniuUpload、h5-app 布局)。
MEDIA_DISK=qiniu;存货成本层。