Skip to content

Pxcharts Ultra 技术文档

体验地址:ultra版多维表格编辑器

🎯 项目概述

Pxcharts Ultra 是一个基于 React 18+ 构建的现代化多表格编辑器,集成了 AI 助手、协作编辑(ui层)、甘特图、看板视图等多种功能。项目采用 TypeScript + React + Tailwind CSS 技术栈,提供了完整的表格数据管理解决方案。

TIP

注意:ultra是在plus版本基础上构建的更复杂的多维表格编辑器,所以部分实现文档可以参考plus版本。

项目特色

  • 企业级架构: 采用现代化的前端架构设计,支持大规模应用
  • AI 驱动: 集成多种 AI 交互层,可以轻松接入AI模型,提供智能数据分析和处理
  • 性能优化: 虚拟化渲染、懒加载等性能优化技术
  • 高度可定制: 模块化设计,易于扩展和定制

✨ 功能特点

🗄️ 核心功能

  • 多表格管理: 支持创建、编辑、删除多个数据表格
  • 多种视图模式: 表格视图、看板视图、甘特图、图表仪表板
  • 智能表单生成器: 可视化拖拽式表单设计,支持多种字段类型
  • AI 智能助手: 集成多种 AI 模型交互UI,支持数据分析、数据生成等
  • 实时协作UI控件: 多用户实时编辑、评论、在线状态显示的UI层界面
  • 数据导入导出: 支持 Excel、CSV 格式的导入导出

🚀 高级特性

  • 性能优化: 虚拟化渲染、懒加载、性能测试工具
  • 甘特图管理: 项目任务时间线管理、依赖关系、进度跟踪
  • 图表分析: 多种图表类型、自定义仪表板布局
  • 模板系统: 丰富的预设模板,快速创建常用表格
  • 主题定制: 支持明暗主题切换

📁 目录结构介绍

multi-table-ultra/
├── app/                          # Next.js 应用主目录
│   ├── globals.css              # 全局样式文件
│   ├── layout.tsx               # 应用布局组件
│   └── page.tsx                 # 主页面组件
├── components/                   # 组件目录
│   ├── ui/                      # 基础 UI 组件库
│   │   ├── button.tsx           # 按钮组件
│   │   ├── dialog.tsx           # 对话框组件
│   │   ├── form.tsx             # 表单组件
│   │   ├── sidebar.tsx          # 侧边栏组件
│   │   └── ...                  # 其他 UI 组件
│   ├── table-editor.tsx         # 主表格编辑器
│   ├── form-generator.tsx       # 表单生成器
│   ├── ai-assistant.tsx         # AI 助手组件
│   ├── gantt-view.tsx           # 甘特图视图
│   ├── kanban-view.tsx          # 看板视图
│   ├── collaboration-panel.tsx  # 协作面板
│   ├── chart-dashboard.tsx      # 图表仪表板
│   └── ...                      # 其他功能组件
├── lib/                         # 核心库文件
│   ├── store.ts                 # Zustand 状态管理
│   ├── types.ts                 # TypeScript 类型定义
│   ├── ai-service.ts            # AI 服务接口
│   ├── collaboration-service.ts # 协作服务
│   ├── gantt-utils.ts           # 甘特图工具函数
│   └── ...                      # 其他工具库
├── hooks/                       # 自定义 React Hooks
├── styles/                      # 样式文件
├── public/                      # 静态资源
├── package.json                 # 项目依赖配置
├── next.config.mjs             # Next.js 配置
├── tailwind.config.ts          # Tailwind CSS 配置
└── tsconfig.json               # TypeScript 配置

目录说明

app/ 目录

  • globals.css: 全局样式定义,包含 CSS 变量和基础样式
  • layout.tsx: 应用根布局,包含主题提供者和全局配置
  • page.tsx: 主页面入口,渲染 TableEditor 组件

components/ 目录

  • ui/: 基础 UI 组件库,基于 Radix UI 构建
  • table-editor.tsx: 主表格编辑器,整合所有功能模块
  • form-generator.tsx: 智能表单生成器,支持拖拽式设计
  • ai-assistant.tsx: AI 助手组件,集成多种 AI 模型
  • gantt-view.tsx: 甘特图视图,支持项目管理功能
  • kanban-view.tsx: 看板视图,支持任务流程管理
  • collaboration-panel.tsx: 协作面板,实时协作功能

lib/ 目录

  • store.ts: Zustand 状态管理,包含所有业务逻辑
  • types.ts: TypeScript 类型定义,确保类型安全
  • ai-service.ts: AI 服务接口,支持多种 AI 模型
  • collaboration-service.ts: 协作服务,实时数据同步
  • gantt-utils.ts: 甘特图工具函数,时间计算和布局

🛠️ 技术栈详解

🎨 前端框架

Next.js 14

  • App Router: 使用最新的 App Router 架构
  • Server Components: 支持服务端组件渲染
  • Streaming: 流式渲染提升用户体验
  • Turbopack: 快速的开发服务器

React 18

  • Concurrent Features: 并发特性支持
  • Automatic Batching: 自动批处理优化
  • Suspense: 异步组件加载
  • Strict Mode: 严格模式开发

🎯 状态管理

Zustand

typescript
// 轻量级状态管理
import { create } from 'zustand'

const useStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
}))

优势:

  • 体积小,bundle size 仅 1.5KB
  • API 简洁,学习成本低
  • 支持 TypeScript
  • 内置持久化中间件

React Hook Form

typescript
// 高性能表单处理
import { useForm } from 'react-hook-form'

const { register, handleSubmit, formState: { errors } } = useForm()

const onSubmit = (data) => {
  console.log(data)
}

特性:

  • 零依赖重渲染
  • 内置验证
  • 支持复杂表单
  • 性能优化

🎨 UI 组件库

Radix UI

  • 无样式: 只提供功能,样式完全自定义
  • 可访问性: 符合 WCAG 标准
  • 键盘导航: 完整的键盘操作支持
  • 状态管理: 内置状态管理逻辑

Tailwind CSS

typescript
// 原子化 CSS 类
<div className="
  flex items-center justify-between
  p-4 bg-white rounded-lg shadow-md
  hover:shadow-lg transition-shadow
">
  {/* 内容 */}
</div>

优势:

  • 快速开发
  • 响应式设计
  • 自定义主题
  • 生产环境优化

📊 数据可视化

Recharts

typescript
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip } from 'recharts'

<LineChart width={600} height={300} data={data}>
  <CartesianGrid strokeDasharray="3 3" />
  <XAxis dataKey="name" />
  <YAxis />
  <Tooltip />
  <Line type="monotone" dataKey="value" stroke="#8884d8" />
</LineChart>

React Grid Layout

typescript
import GridLayout from 'react-grid-layout'

<GridLayout
  className="layout"
  layout={layout}
  cols={12}
  rowHeight={30}
  width={1200}
>
  {items.map(item => (
    <div key={item.i}>{item.content}</div>
  ))}
</GridLayout>

🤖 AI 集成

多模型支持

  • OpenAI: GPT-3.5/4 系列模型
  • DeepSeek: 深度求索模型
  • 通义千问: 阿里云 AI 模型
  • Claude: Anthropic AI 模型
  • Gemini: Google AI 模型

智能功能

  • 数据分析: 自动数据洞察
  • 报表生成: 智能报表创建
  • 自然语言查询: 用自然语言操作数据
  • 异常检测: 自动发现数据异常

🏗️ 核心架构设计

状态管理架构

主要状态结构

typescript
interface TableStore {
  tables: Table[]                    // 表格列表
  currentTableId: string | null      // 当前表格ID
  currentView: ViewType              // 当前视图类型
  searchTerm: string                 // 搜索关键词
  filters: Filter[]                  // 过滤器
  selectedRecords: Set<string>       // 选中的记录
  dashboardLayouts: DashboardLayout[] // 仪表板布局
  templates: Template[]              // 模板列表
  ganttSettings: GanttViewSettings[] // 甘特图设置
}

状态更新流程

typescript
// 状态更新示例
const updateRecord = (id: string, data: any) => {
  set((state) => ({
    tables: state.tables.map(table => ({
      ...table,
      records: table.records?.map(record =>
        record.id === id 
          ? { ...record, data: { ...record.data, ...data } }
          : record
      )
    }))
  }))
}

组件架构

分层设计

  1. 容器组件: 负责状态管理和业务逻辑
  2. 展示组件: 纯 UI 组件,通过 props 接收数据
  3. 复合组件: 组合多个基础组件的复杂功能组件

组件通信

typescript
// 父子组件通信
interface ParentProps {
  onDataChange: (data: any) => void
}

// 兄弟组件通信
const useSharedState = create((set) => ({
  sharedData: null,
  setSharedData: (data: any) => set({ sharedData: data })
}))

数据流架构

用户操作 → 组件事件 → Store Action → 状态更新 → 组件重渲染

AI 服务 → 数据处理 → 结果展示

协作服务 → 实时同步 → 多用户状态

数据流示例

typescript
// 1. 用户操作
const handleEdit = (recordId: string, newData: any) => {
  // 2. 调用 Store Action
  updateRecord(recordId, newData)
  
  // 3. 同步到协作服务
  collaborationService.syncUpdate(recordId, newData)
  
  // 4. 触发 AI 分析
  aiService.analyzeChange(recordId, newData)
}

🔧 二次开发指南

1. 安装依赖

bash
pnpm install
# 或
npm install

2. 启动开发服务器

bash
pnpm dev
# 或
npm run dev

3. 环境变量配置(可选)

bash
# .env.local
NEXT_PUBLIC_AI_API_KEY=your_api_key
NEXT_PUBLIC_COLLABORATION_WS_URL=ws://your-websocket-server
NEXT_PUBLIC_APP_ENV=development

🔧 添加新功能

1. 创建新的视图类型

步骤 1: 在 types.ts 中添加新视图类型

typescript
export type ViewType = "table" | "kanban" | "gantt" | "your-view"

export interface YourViewSettings {
  id: string
  tableId: string
  config: YourViewConfig
  updatedAt: string
}

步骤 2: 在 store.ts 中添加相关状态和方法

typescript
interface TableStore {
  // ... 现有代码
  yourViewSettings: YourViewSettings[]
  
  // 添加新方法
  updateYourViewSettings: (tableId: string, settings: YourViewSettings) => void
  getYourViewSettings: (tableId: string) => YourViewSettings | undefined
}

// 实现方法
updateYourViewSettings: (tableId: string, settings: YourViewSettings) => {
  set((state) => ({
    yourViewSettings: state.yourViewSettings.map(s => 
      s.tableId === tableId ? settings : s
    )
  }))
}

步骤 3: 创建视图组件

typescript
// components/your-view.tsx
import React from 'react'
import { useTableStore } from '@/lib/store'
import type { Table } from '@/lib/types'

interface YourViewProps {
  table: Table
}

export function YourView({ table }: YourViewProps) {
  const { yourViewSettings, updateYourViewSettings } = useTableStore()
  
  // 实现视图逻辑
  return (
    <div className="your-view">
      {/* 你的视图内容 */}
    </div>
  )
}

步骤 4: 在主编辑器中集成

typescript
// components/table-editor.tsx
import { YourView } from './your-view'

// 在视图切换逻辑中添加
const renderCurrentView = () => {
  switch (currentView) {
    case 'your-view':
      return <YourView table={currentTable} />
    // ... 其他视图
  }
}

2. 扩展字段类型

步骤 1: 在 types.ts 中添加新字段类型

typescript
export type FieldType = "text" | "textarea" | "number" | "your-field-type"

export interface YourFieldConfig {
  customOption1?: string
  customOption2?: number
}

步骤 2: 在 form-generator.tsx 中添加字段配置

typescript
const FIELD_TYPES = [
  // ... 现有字段类型
  { 
    type: "your-field-type", 
    label: "你的字段", 
    icon: YourIcon, 
    category: "自定义类型",
    component: YourFieldComponent
  }
]

步骤 3: 创建字段组件

typescript
// components/fields/your-field.tsx
interface YourFieldProps {
  value: any
  onChange: (value: any) => void
  config: YourFieldConfig
}

export function YourField({ value, onChange, config }: YourFieldProps) {
  return (
    <div className="your-field">
      {/* 字段渲染逻辑 */}
    </div>
  )
}

3. 集成新的 AI 服务

步骤 1: 在 ai-service.ts 中添加新服务

typescript
export const aiService = {
  // ... 现有服务
  yourService: async (prompt: string, config: any) => {
    try {
      const response = await fetch('/api/your-ai-service', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ prompt, config })
      })
      
      if (!response.ok) {
        throw new Error('AI service request failed')
      }
      
      return await response.json()
    } catch (error) {
      console.error('Your AI service error:', error)
      throw error
    }
  }
}

步骤 2: 创建 API 路由

typescript
// app/api/your-ai-service/route.ts
import { NextRequest, NextResponse } from 'next/server'

export async function POST(request: NextRequest) {
  try {
    const { prompt, config } = await request.json()
    
    // 调用你的 AI 服务
    const result = await callYourAIService(prompt, config)
    
    return NextResponse.json(result)
  } catch (error) {
    return NextResponse.json(
      { error: 'AI service error' },
      { status: 500 }
    )
  }
}

🎨 自定义主题

1. 修改 Tailwind 配置

typescript
// tailwind.config.ts
export default {
  theme: {
    extend: {
      colors: {
        // 添加自定义颜色
        'custom-primary': '#your-color',
        'custom-secondary': '#your-secondary-color',
      },
      spacing: {
        '18': '4.5rem',
        '88': '22rem',
      },
      animation: {
        'bounce-slow': 'bounce 2s infinite',
      }
    }
  }
}

2. 创建主题组件

typescript
// components/theme-provider.tsx
'use client'

import { createContext, useContext, useEffect, useState } from 'react'

type Theme = 'light' | 'dark' | 'system'

interface ThemeContextType {
  theme: Theme
  setTheme: (theme: Theme) => void
}

const ThemeContext = createContext<ThemeContextType | undefined>(undefined)

export function ThemeProvider({ children }: { children: React.ReactNode }) {
  const [theme, setTheme] = useState<Theme>('system')

  useEffect(() => {
    const root = window.document.documentElement
    root.classList.remove('light', 'dark')

    if (theme === 'system') {
      const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
        ? 'dark'
        : 'light'
      root.classList.add(systemTheme)
    } else {
      root.classList.add(theme)
    }
  }, [theme])

  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {children}
    </ThemeContext.Provider>
  )
}

export const useTheme = () => {
  const context = useContext(ThemeContext)
  if (context === undefined) {
    throw new Error('useTheme must be used within a ThemeProvider')
  }
  return context
}

📱 响应式适配

1. 使用移动端 Hook

typescript
// hooks/use-mobile.tsx
import { useState, useEffect } from 'react'

export function useMobile() {
  const [isMobile, setIsMobile] = useState(false)

  useEffect(() => {
    const checkMobile = () => {
      setIsMobile(window.innerWidth < 768)
    }

    checkMobile()
    window.addEventListener('resize', checkMobile)
    
    return () => window.removeEventListener('resize', checkMobile)
  }, [])

  return isMobile
}

2. 响应式组件示例

typescript
import { useMobile } from '@/hooks/use-mobile'

export function ResponsiveComponent() {
  const isMobile = useMobile()
  
  return (
    <div className={`
      ${isMobile ? 'mobile-layout' : 'desktop-layout'}
      p-4 md:p-6 lg:p-8
      grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3
    `}>
      {/* 响应式内容 */}
    </div>
  )
}

🔌 插件系统

1. 创建插件接口

typescript
// lib/plugin-types.ts
export interface Plugin {
  id: string
  name: string
  version: string
  description: string
  author: string
  initialize: () => void | Promise<void>
  destroy: () => void
  onTableCreate?: (table: Table) => void
  onRecordUpdate?: (record: Record) => void
}

export interface PluginContext {
  store: any
  api: any
  utils: any
}

2. 插件管理器

typescript
// lib/plugin-manager.ts
export class PluginManager {
  private plugins: Map<string, Plugin> = new Map()
  private context: PluginContext

  constructor(context: PluginContext) {
    this.context = context
  }
  
  async register(plugin: Plugin) {
    try {
      await plugin.initialize()
      this.plugins.set(plugin.id, plugin)
      console.log(`Plugin ${plugin.name} registered successfully`)
    } catch (error) {
      console.error(`Failed to register plugin ${plugin.name}:`, error)
    }
  }
  
  unregister(pluginId: string) {
    const plugin = this.plugins.get(pluginId)
    if (plugin) {
      plugin.destroy()
      this.plugins.delete(pluginId)
      console.log(`Plugin ${plugin.name} unregistered`)
    }
  }
  
  getPlugin(pluginId: string): Plugin | undefined {
    return this.plugins.get(pluginId)
  }
  
  getAllPlugins(): Plugin[] {
    return Array.from(this.plugins.values())
  }
  
  // 触发插件事件
  triggerEvent(eventName: string, data: any) {
    this.plugins.forEach(plugin => {
      if (plugin[eventName as keyof Plugin]) {
        try {
          (plugin as any)[eventName](data)
        } catch (error) {
          console.error(`Plugin ${plugin.name} event error:`, error)
        }
      }
    })
  }
}

3. 使用插件系统(仅供扩展参考)

typescript
// 在主应用中初始化插件管理器
import { PluginManager } from '@/lib/plugin-manager'

const pluginManager = new PluginManager({
  store: useTableStore,
  api: apiService,
  utils: utilityFunctions
})

// 注册插件
await pluginManager.register({
  id: 'my-plugin',
  name: 'My Plugin',
  version: '1.0.0',
  description: 'A custom plugin',
  author: 'Your Name',
  initialize: () => {
    console.log('My plugin initialized')
  },
  destroy: () => {
    console.log('My plugin destroyed')
  }
})

🔍 实现原理详解

🗄️ 数据存储机制

1. 本地存储

typescript
// 使用 Zustand 的 persist 中间件
export const useTableStore = create<TableStore>()(
  persist(
    (set, get) => ({
      // ... store 实现
    }),
    {
      name: 'table-storage', // localStorage 键名
      version: 1, // 版本号,用于数据迁移
      migrate: (persistedState: any, version: number) => {
        // 数据迁移逻辑
        if (version === 0) {
          return migrateFromV0ToV1(persistedState)
        }
        return persistedState
      }
    }
  )
)

2. 状态同步

typescript
// 状态更新流程
const updateRecord = (id: string, data: any) => {
  set((state) => {
    // 创建新状态
    const newState = {
      ...state,
      tables: state.tables.map(table => ({
        ...table,
        records: table.records?.map(record =>
          record.id === id 
            ? { 
                ...record, 
                data: { ...record.data, ...data },
                updatedAt: new Date().toISOString()
              }
            : record
        )
      }))
    }
    
    // 触发插件事件
    pluginManager.triggerEvent('onRecordUpdate', { id, data })
    
    return newState
  })

让技术更平权,致力于高性价办公协同解决方案