跳到主要内容

系统架构

本页面深入介绍 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订阅计费
AIOpenAI GPT API情感分析、自动标签、回复建议
认证Laravel SocialiteGoogle 和 GitHub OAuth
邮件Laravel Mail(SMTP)事务性邮件、摘要、报告
实时Server-Sent Events(SSE)实时提交流推送
定时任务Laravel Scheduler(cron)摘要推送、试用期到期、数据保留

多租户模型

FeedbackPulse 采用单数据库、共享结构的多租户模型,这意味着:

  • 一个数据库为所有租户提供服务
  • 每个租户范围内的表都有 tenant_id
  • 全局作用域TenantScope)自动将所有查询过滤为当前租户的数据
  • TraitBelongsToTenant)在创建时自动填充 tenant_id 并应用作用域

租户解析方式

当请求到来时,ResolveTenant 中间件按以下优先级确定当前租户:

  1. 子域名acme.yourdomain.com → 查找子域名为"acme"的租户
  2. 自定义域名feedback.acmecorp.com → 在 tenant_domains 表中查找已验证的域名
  3. 已认证用户 — 回退到已登录用户的 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 表还在 statusproduct_idcampaign_idsentiment_label 字段上额外建立了索引。


安全架构

层级保护措施
传输强制 HTTPS、HSTS 响应头
认证Bcrypt(12 轮),可选 2FA(TOTP)
授权基于角色的中间件 + Policy 类
CSRF所有表单使用 Laravel CSRF token
XSSBlade 自动转义({{ }}
SQL 注入Eloquent 参数化查询
频率限制按路由限流(5-120 次/分钟)
API 安全SHA256 哈希 API 密钥,按租户限流
Webhook 安全HMAC 签名验证(Stripe),SSRF 防护
数据敏感设置静态加密存储
Session加密、HTTP-only、安全 Cookie
响应头CSP、X-Frame-Options、X-Content-Type-Options

下一步