You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Prisma ORM存储事件模板数据并在React前端实现过滤跳转?

解决方案:Prisma存储事件记录+React前端展示实现方案

一、数据库模型优化(Prisma)

基于现有模型扩展,兼顾过滤性能和模板数据灵活性,设计如下:

model Event {
  id            String   @id @default(cuid())
  action_type   String   // 操作类型:meeting/email/call/user_management等
  message_code  String   // 翻译模板编码,如email_to_contact
  created_at    DateTime @default(now())
  // 核心过滤字段:单独存储常用关联ID,方便加索引快速查询
  contact_id    String?  @db.VarChar(255) @index()
  employee_id   String?  @db.VarChar(255) @index()
  contract_id   String?  @db.VarChar(255) @index()
  quote_id      String?  @db.VarChar(255) @index()
  // 动态模板数据:存储所有模板需要的变量(如contact_name、email_subject等)
  metadata      Json
}

设计原因:

  • 单独的关联ID字段(如contact_id):支持快速过滤查询(比如筛选某联系人的所有事件),且可添加索引提升性能。
  • metadata字段:用JSON格式存储动态变量,适配不同事件模板的差异化需求,无需频繁修改数据库表结构。

二、前端模板渲染与跳转实现

1. 维护翻译模板JSON

创建event-templates.json文件,定义所有事件的模板:

{
  "email_to_contact": "已向{{contact_name}}发送主题为「{{email_subject}}」的邮件",
  "call_from_contact": "{{contact_name}}来电",
  "contract_updated": "员工{{employee_name}}更新了合同#{{contract_id}}",
  "quote_accepted": "{{contact_name}}接受了报价#{{quote_id}}"
}

2. React事件渲染组件

实现EventItem组件,完成模板变量填充和关联元素跳转:

import templates from './event-templates.json';
import DOMPurify from 'dompurify'; // 用于防XSS,需先安装npm i dompurify

const EventItem = ({ event }) => {
  const renderEventContent = () => {
    const template = templates[event.message_code] || '未知事件';
    // 替换模板变量并生成可点击链接
    const processedContent = template.replace(/{{(\w+)}}/g, (match, key) => {
      const value = event.metadata[key];
      if (!value) return match;

      // 根据变量类型匹配跳转路径
      let linkPath = null;
      switch (key) {
        case 'contact_name':
          linkPath = event.contact_id ? `/contacts/${event.contact_id}` : null;
          break;
        case 'contract_id':
          linkPath = `/contracts/${event.contract_id}`;
          break;
        case 'quote_id':
          linkPath = `/quotes/${event.quote_id}`;
          break;
        case 'employee_name':
          linkPath = event.employee_id ? `/employees/${event.employee_id}` : null;
          break;
        default:
          break;
      }

      if (linkPath) {
        return `<a href="${linkPath}" class="event-link">${value}</a>`;
      }
      return value;
    });
    // 净化HTML防止XSS攻击
    return DOMPurify.sanitize(processedContent);
  };

  return (
    <div className="event-item">
      <p dangerouslySetInnerHTML={{ __html: renderEventContent() }} />
      <span className="event-time">
        {new Date(event.created_at).toLocaleString('zh-CN')}
      </span>
    </div>
  );
};

export default EventItem;

关键逻辑说明:

  • 用正则匹配模板中的{{变量名}},替换为metadata中的实际值。
  • 根据变量类型和关联ID生成跳转链接,比如contact_name对应联系人详情页。
  • 使用DOMPurify净化生成的HTML,避免XSS风险。

三、事件过滤实现

1. 后端查询接口(示例:Next.js API)

通过Prisma根据前端传入的筛选条件查询事件:

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export default async function handler(req, res) {
  const { contactId, employeeId, actionType } = req.query;
  const whereClause = {};

  if (contactId) whereClause.contact_id = contactId;
  if (employeeId) whereClause.employee_id = employeeId;
  if (actionType) whereClause.action_type = actionType;

  const events = await prisma.event.findMany({
    where: whereClause,
    orderBy: { created_at: 'desc' }, // 按时间倒序展示
  });

  res.status(200).json(events);
}

2. 前端筛选交互

在前端页面添加筛选组件(比如下拉框、搜索框),用户选择筛选条件后,调用上述API获取过滤后的事件列表,再用EventItem渲染。

四、额外注意事项

  • 索引优化:给contact_id、employee_id等过滤字段添加索引,大幅提升查询速度。
  • 模板扩展:新增事件类型时,只需在event-templates.json添加模板,同时在metadata中存储对应变量即可,无需修改数据库结构。
  • 数据一致性:确保metadata中的变量(如contact_name)与关联ID(如contact_id)对应的数据一致,可通过业务逻辑层保证。

内容的提问来源于stack exchange,提问作者Thore

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 17:45:56