系统架构
本页面深入介绍 FeedbackPulse SaaS 的构建方式。理解系统架构有助于您排查问题、扩展平台功能,并做出合理的部署决策。
技术栈
| 层级 | 技术 | 用途 |
|---|---|---|
| 后端 | Laravel 12(PHP 8.4+) | 应用框架、路由、ORM、队列 |
| 数据库 | MySQL 8.0+ / MariaDB 10.6+ | 持久化数据存储 |
| 前端 | Blade + Alpine.js + Tailwind CSS | 服务端渲染 UI,含响应式组件 |
| 支付 | Stripe PHP SDK + PayPal REST API | 订阅计费 |
| AI | OpenAI GPT API | 情感分析、自动标签、回复建议 |
| 认证 | Laravel Socialite | Google 和 GitHub OAuth |
| 邮件 | Laravel Mail(SMTP) | 事务性邮件、摘要、报告 |
| 实时 | Server-Sent Events(SSE) | 实时提交流推送 |
| 定时任务 | Laravel Scheduler(cron) | 摘要推送、试用期到期、数据保留 |
多租户模型
FeedbackPulse 采用单数据库、共享结构的多租户模型,这意味着:
- 一个数据库为所有租户提供服务
- 每个租户范围内的表都有
tenant_id列 - 全局作用域(
TenantScope)自动将所有查询过滤为当前租户的数据 - Trait(
BelongsToTenant)在创建时自动填充tenant_id并应用作用域
租户解析方式
当请求到来时,ResolveTenant 中间件按以下优先级确定当前租户:
- 子域名 —
acme.yourdomain.com→ 查找子域名为"acme"的租户 - 自定义域名 —
feedback.acmecorp.com→ 在tenant_domains表中查找已验证的域名 - 已认证用户 — 回退到已登录用户的
tenant_id
对于公开页面(如 /wall/acme-corp),租户直接从控制器中的 URL slug 解析(绕过中间件)。
数据隔离
+------------------------------------------+
| 数据库 |
| |
| products (tenant_id = 1) -> Acme 数据 |
| products (tenant_id = 2) -> TechCorp |
| products (tenant_id = 3) -> 电商平台 |
| |
| TenantScope 确保 Acme 只能看到 |
| tenant_id = 1 的数据行 |
+------------------------------------------+
安全说明: 面向公众的控制器使用
withoutGlobalScopes()绕过租户作用域,再手动按租户 ID 过滤。这是有意为之的设计 — 公开页面需要在没有认证 Session 的情况下展示数据。
目录结构
feedbackpulse-saas/
+-- app/
| +-- Console/Commands/ # 7 个 artisan 命令(摘要、数据保留、警报)
| +-- Http/
| | +-- Controllers/
| | | +-- Admin/ # 超级管理员面板控制器
| | | +-- Auth/ # 登录、注册、2FA、OAuth、模拟登录
| | | +-- Customer/ # 客户门户
| | | +-- Public/ # 公开页面(反馈墙、表单、路线图、更新日志、产品中心)
| | | +-- Tenant/ # 租户仪表板控制器
| | | +-- Webhooks/ # Stripe 和 PayPal webhook 处理器
| | +-- Middleware/ # 15 个自定义中间件
| +-- Mail/ # 7 个邮件类
| +-- Models/ # 28 个 Eloquent 模型
| +-- Scopes/ # TenantScope(全局查询作用域)
| +-- Services/ # 业务逻辑(AI、支付、webhooks 等)
| +-- Traits/ # BelongsToTenant trait
| +-- Providers/ # 服务提供者
+-- config/ # 11 个 Laravel 配置文件
+-- database/
| +-- migrations/ # 35+ 个迁移文件
| +-- seeders/ # 演示数据填充器
+-- public/ # Web 根目录(index.php、资源、存储软链接)
+-- resources/views/ # 86 个 Blade 模板
| +-- admin/ # 超级管理员视图
| +-- auth/ # 认证视图(登录、注册、2FA)
| +-- tenant/ # 租户仪表板视图
| +-- public/ # 公开页面视图
| +-- emails/ # 邮件模板
| +-- layouts/ # 布局模板(管理员、租户、访客、安装)
| +-- partials/ # 共享组件(导航栏、元信息、命令面板)
| +-- install/ # Web 安装程序视图
| +-- legal/ # 隐私、条款、Cookie 页面
| +-- errors/ # 错误页面(403、404、419、429、500)
| +-- landing/ # 落地页部分
+-- routes/
| +-- web.php # 416 行 Web 路由
| +-- api.php # API v2 路由
+-- storage/ # 上传文件、缓存、Session、日志
+-- bootstrap/ # 框架启动文件
用户角色
FeedbackPulse 拥有四种用户角色,存储在 users.role 列中:
| 角色 | 访问权限 | 登录 URL |
|---|---|---|
superadmin | 完整平台控制(/admin/*) | /login |
tenant_admin | 完整租户控制(/dashboard、/settings/*) | /login |
tenant_staff | 有限租户访问(无计费、无删除权限) | /login |
customer | 仅限客户门户(/customer/dashboard) | /customer/login |
角色层级
superadmin
+-- 可模拟任意 tenant_admin
+-- tenant_admin
+-- 可邀请 tenant_staff
+-- 可管理计费、设置、团队
+-- tenant_staff
+-- 可管理提交记录、活动
+-- customer
+-- 可查看自己的反馈
请求生命周期
请求到达 FeedbackPulse 后的处理流程:
浏览器请求
|
v
public/index.php
|
v
Laravel Kernel(中间件栈)
|
+-- EnsureInstalled -> 未安装则重定向至 /install
+-- SecurityHeaders -> 添加 HSTS、CSP、X-Frame-Options
+-- VerifyCsrfToken -> 检查 CSRF token(Webhook 除外)
+-- ResolveTenant -> 确定当前租户
+-- Authenticate -> 检查用户是否已登录
+-- EnsureTenantAccess -> 验证用户是否属于该租户
+-- EnsureTwoFactorVerified -> 检查 2FA(若已启用)
+-- CheckPlanLimit -> 强制套餐功能限制
|
v
控制器(处理请求)
|
v
Blade 视图(渲染 HTML)
|
v
响应 -> 浏览器
数据库架构
核心数据表
| 数据表 | 归属 | 用途 |
|---|---|---|
tenants | 平台 | 多租户账户 |
users | 平台 | 所有用户账户(所有角色) |
plans | 平台 | 订阅套餐 |
platform_settings | 平台 | 全局键值配置 |
products | 租户 | 反馈产品 |
feedback_campaigns | 租户 | 反馈表单配置 |
feedback_submissions | 租户 | 单条反馈记录 |
feedback_tags | 租户 | 标签(与提交记录多对多) |
roadmap_items | 租户 | 路线图看板项目 |
roadmap_votes | 租户 | 路线图项目匿名投票 |
feature_requests | 租户 | 社区功能建议 |
changelog_entries | 租户 | 产品发布说明 |
team_members | 租户 | 团队成员记录 |
team_invitations | 租户 | 待接受邀请 |
api_keys | 租户 | API 访问密钥 |
audit_logs | 平台 | 操作审计日志 |
notifications | 平台 | 应用内通知 |
payment_events | 平台 | Stripe/PayPal webhook 事件 |
webhook_logs | 租户 | 出站 webhook 投递日志 |
data_deletion_requests | 租户 | GDPR 删除请求 |
landing_pages | 平台 | 落地页构建器数据 |
tenant_domains | 租户 | 自定义域名映射 |
referral_codes | 租户 | 推荐码 |
referral_conversions | 平台 | 推荐转化追踪 |
cron_logs | 平台 | 定时任务执行日志 |
关键索引
所有租户范围内的数据表均按 (tenant_id, created_at) 建立索引,以获得最佳查询性能。feedback_submissions 表还在 status、product_id、campaign_id 和 sentiment_label 字段上额外建立了索引。
安全架构
| 层级 | 保护措施 |
|---|---|
| 传输 | 强制 HTTPS、HSTS 响应头 |
| 认证 | Bcrypt(12 轮),可选 2FA(TOTP) |
| 授权 | 基于角色的中间件 + Policy 类 |
| CSRF | 所有表单使用 Laravel CSRF token |
| XSS | Blade 自动转义({{ }}) |
| SQL 注入 | Eloquent 参数化查询 |
| 频率限制 | 按路由限流(5-120 次/分钟) |
| API 安全 | SHA256 哈希 API 密钥,按租户限流 |
| Webhook 安全 | HMAC 签名验证(Stripe),SSRF 防护 |
| 数据 | 敏感设置静态加密存储 |
| Session | 加密、HTTP-only、安全 Cookie |
| 响应头 | CSP、X-Frame-Options、X-Content-Type-Options |