🏆基于阿里云百炼的AI智能排班系统

185 阅读19分钟

🏆 基于阿里云百炼的AI智能排班系统

技术栈: React 18 + TypeScript + 阿里云百炼大模型 + Tailwind CSS


📖 目录


一、项目背景与动机

1.1 业务痛点

在参加 AI Hackathon 黑客松大赛时,我们团队深入调研了酒店门店的排班管理场景,发现了以下核心痛点:

痛点具体表现影响
效率低下人工编排排班表耗时长,沟通成本高店长每周花费 2-3 小时排班
成本虚高人力资源难以精准匹配需求,存在隐性浪费人力成本浪费约 15-20%
易出错手工排班容易冲突,加班费常超标月均排班冲突 5-8 次
应对滞后突发情况(请假、接团)响应慢平均处理时间 > 30 分钟
员工不满排班不公平、不透明,员工抱怨多员工满意度低,流失率高

1.2 解决方案

我们开发了一款基于阿里云百炼大模型的智能排班系统,通过 AI 对话式交互实现排班全流程自动化。

核心价值主张:

  • 🚀 效率提升: AI 一键生成排班表,从 2-3 小时降低到 10 秒
  • 💰 成本优化: 智能匹配人力与需求,降低 15% 人力成本
  • 🎯 精准决策: 实时数据统计 + 智能预警,辅助管理决策
  • 快速响应: 突发事件(请假、接团)即时处理,30 分钟降至 1 分钟
  • 😊 员工满意: 公平透明的排班机制,提升员工认可度

二、系统功能概览

系统采用模块化设计,包含 6 大核心功能模块,为用户提供从 AI 对话到数据分析的全流程排班解决方案。

2.1 华小班 - AI 智能对话助手

功能定位: 系统的智能交互核心,通过自然语言对话完成排班任务。

华小班对话界面

核心功能:

  • 🤖 自然语言交互:
    • 像聊天一样完成排班,无需复杂操作
    • 支持多轮对话,保持上下文连续性(基于 session_id)
    • 智能理解用户意图,自动识别排班需求
  • 📊 智能表格识别:
    • 自动识别 AI 返回的 Markdown 表格格式
    • 智能解析日期、员工姓名、岗位、班次等信息
    • 一键导入数据到系统,自动创建员工档案和排班记录
  • 📁 文件智能解析:
    • 支持上传 Excel、Word、PDF、图片等多种格式
    • AI 自动提取文档中的员工信息和排班数据
    • 批量导入功能,大幅提升数据录入效率
  • 💭 思考过程展示:
    • 实时显示 AI 的思考过程(has_thoughts 参数)
    • 让决策过程透明可见,增强可信度
    • 帮助用户理解 AI 的推理逻辑
  • SSE 流式输出:
    • 逐字显示 AI 回复,提升交互体验
    • 实时反馈,避免长时间等待黑屏
    • 支持中断请求(AbortSignal),灵活控制对话流程

智能表格识别

使用场景示例:

用户: "请帮我制定下周(10月20日-26日)的排班:
       - 前台2人: 张三、李四
       - 销售1人: 王五  
       - 店助1人: 赵六"

AI 自动生成精美表格 → 系统自动识别 → 一键导入完成 ✅

技术实现:

// 数据类型定义
interface ChatMessage {
  id: string;
  role: 'user' | 'assistant';
  content: string;
  timestamp: number;
  files?: UploadedFile[];  // 支持文件上传
}

interface UploadedFile {
  id: string;
  name: string;
  type: string;
  session_file_id?: string;  // 百炼文件ID
  status: 'uploading' | 'ready' | 'error';
}

技术亮点:

  • AI 模型: 阿里云百炼 qwen-plus 大模型
  • 对话管理: 基于 session_id 的多轮对话
  • 流式输出: SSE (Server-Sent Events) 实时传输
  • 表格解析: 正则匹配 Markdown 表格,智能提取数据
  • 文件上传: 支持通过 session_file_ids 关联文件

2.2 员工管理

功能定位: 员工档案管理中心,维护员工基础信息。

image.png 核心功能:

  • 👤 员工档案管理:

    • 基础信息:姓名、岗位、状态、联系方式
    • 扩展字段:员工编号(staff_id)、门店编号(store_code)、偏好设置
    • 岗位类型:前台、销售、店助、保洁等(可自定义)
    • 状态管理:active(在职)、inactive(离职)
  • 🔍 智能搜索筛选:

    • 按姓名快速搜索(实时过滤)
    • 按岗位分类筛选
    • 按状态过滤显示(在职/离职)
    • 支持组合筛选条件
  • 📥 批量操作:

    • 批量导入员工信息(通过 AI 解析 Excel/Word)
    • 批量编辑员工状态
    • 批量删除离职员工(带二次确认)
  • 💾 数据持久化:

    • 基于 LocalStorage 存储(键名:employees)
    • 自动保存,刷新页面数据不丢失
    • 支持数据导出备份(JSON 格式)

数据结构:

interface Employee {
  id: string;                          // 唯一标识
  name: string;                        // 员工姓名
  position: string;                    // 岗位
  status: 'active' | 'inactive';       // 状态
  skills?: string[];                   // 技能标签
  staff_id?: string;                   // 员工编号
  store_code?: string;                 // 门店编号
  store_name?: string;                 // 门店名称
  preferences?: string | null;         // 偏好设置(如:不排夜班)
  created_at?: string;                 // 创建时间
  updated_at?: string;                 // 更新时间
}

应用场景:

  • 新员工入职时快速建档
  • 员工离职/请假时更新状态
  • 定期维护员工信息准确性
  • 查询员工技能匹配岗位需求

2.3 排班管理

功能定位: 排班核心功能,支持手动排班和自动排班。

排班管理界面

核心功能:

  • 📅 周视图展示:

    • 清晰的日历式布局,7 天排班一目了然
    • 支持左右切换周次(本周/上周/下周)
    • 日期 header 显示星期和具体日期
    • 不同班次用颜色区分(早班/中班/晚班/全天)
  • ✍️ 手动排班:

    • 点击日期快速添加排班记录
    • 选择员工、岗位、班次类型、起止时间
    • 支持编辑和删除已有排班
    • 即时保存,无需手动提交
  • 🤖 智能自动排班:

    • 基于排班规则自动生成排班表
    • 避免同一员工同一天重复排班
    • 确保每个岗位都有足够人员覆盖
    • 优先分配技能匹配的员工
  • 📊 状态管理:

    • scheduled(已安排):蓝色标记
    • completed(已完成):绿色标记
    • cancelled(已取消):红色标记
    • 状态实时同步,支持批量修改
  • 🔔 冲突检测:

    • 实时检测排班冲突(同一员工同一天重复)
    • 智能提示重复排班,防止误操作
    • 自动标记异常情况(员工离职但仍排班)
    • 支持查看冲突详情和一键解决

数据结构:

interface Schedule {
  id: string;                                    // 唯一标识
  employee_id: string;                           // 员工ID
  shift_date: string;                            // 排班日期(YYYY-MM-DD)
  shift_type: string;                            // 班次类型(早班/中班/晚班/全天)
  start_time: string;                            // 开始时间(HH:mm)
  end_time: string;                              // 结束时间(HH:mm)
  position: string;                              // 岗位
  status: 'scheduled' | 'completed' | 'cancelled'; // 状态
  created_at?: string;                           // 创建时间
  updated_at?: string;                           // 更新时间
}

// 带员工信息的排班记录(用于展示)
interface ScheduleWithEmployee extends Schedule {
  employee?: Employee;  // 关联员工信息
}

应用场景:

  • 每周制定新的排班计划
  • 临时调整排班(员工请假、换班)
  • 查看历史排班记录和统计
  • 导出排班表发送给员工

2.4 排班规则

功能定位: 排班规则引擎,配置自动排班的约束条件。

排班规则配置界面

核心功能:

  • ⚙️ 规则配置:

    • 规则名称:便于识别和管理
    • 岗位设置:前台、销售、店助、保洁等
    • 班次类型:早班、中班、晚班、全天
    • 时间段:起止时间(如 08:00-16:00)
    • 所需人数:每个班次需要几人
  • 🔒 约束校验:

    • 避免同一员工同一天重复排班
    • 确保每个时间段都有足够人员覆盖
    • 检查员工技能是否匹配岗位要求
    • 验证排班规则的时间是否冲突
  • 🔄 启用/禁用:

    • 灵活控制规则是否生效(is_active 字段)
    • 临时停用某些规则(如节假日特殊安排)
    • 批量启用/禁用规则
    • 规则历史记录追溯
  • 📋 规则管理:

    • 创建、编辑、删除规则
    • 规则列表展示(表格形式)
    • 支持搜索和筛选规则
    • 规则数据持久化(LocalStorage)

数据结构:

interface ShiftRule {
  id: string;                // 唯一标识
  name: string;              // 规则名称
  position: string;          // 岗位
  shift_type: string;        // 班次类型
  start_time: string;        // 开始时间(HH:mm)
  end_time: string;          // 结束时间(HH:mm)
  required_count: number;    // 所需人数
  is_active: boolean;        // 是否启用
  created_at?: string;       // 创建时间
  updated_at?: string;       // 更新时间
}

规则示例:

{
  "name": "前台早班规则",
  "position": "前台",
  "shift_type": "早班",
  "start_time": "08:00",
  "end_time": "16:00",
  "required_count": 2,
  "is_active": true
}

应用场景:

  • 新店开业时配置初始排班规则
  • 节假日调整规则(如春节、国庆)
  • 淡旺季调整人员配置需求
  • 临时活动增加岗位人数

2.5 工作量分析

功能定位: 数据分析中心,提供多维度的排班数据洞察和可视化图表。

工作量分析界面

核心功能:

  • 📊 统计分析:

    • 总排班次数统计(所有员工的排班总和)
    • 总工作时长统计(小时数)
    • 人均排班次数(总次数 / 员工数)
    • 人均工作时长(总时长 / 员工数)
    • 时间范围筛选(本周/本月/自定义)
  • 💰 成本计算:

    • 基于参数配置的时薪计算人力成本
    • 各岗位成本分布(前台/销售/店助等)
    • 月度成本趋势分析
    • 成本预算对比和预警
  • 📈 员工利用率:

    • 员工工作饱和度分析(实际工时 / 标准工时)
    • 识别闲置人力资源(利用率低于 60%)
    • 识别过度工作员工(利用率高于 120%)
    • 优化人员配置建议
  • 🎯 岗位分析:

    • 各岗位工作量分布(饼图 - 基于 Recharts)
    • 岗位工作量趋势(折线图 - 周/月维度)
    • 岗位人力成本对比(柱状图)
    • 岗位人员数量统计
  • 📉 趋势分析:

    • 周/月工作量趋势(折线图)
    • 人力成本变化趋势(面积图)
    • 排班效率分析(排班次数 vs 实际到岗)
    • 数据导出功能(Excel/CSV)

技术实现:

  • 图表库: Recharts (React 图表组件库)
  • 数据计算: 基于 useMemo 缓存计算结果
  • 数据来源: 从 scheduleStorage 读取排班数据,从 employeeStorage 读取员工信息
  • 实时更新: 监听 storage 事件,数据变化时自动重新计算

应用场景:

  • 月度总结人力成本,生成财务报表
  • 分析各岗位工作量是否合理,优化人员配置
  • 为人员招聘提供数据支持(识别人力缺口)
  • 评估排班效率,优化排班策略

2.6 参数配置

功能定位: 系统全局配置中心,个性化设置系统参数,支持与 AI 对话式配置。

参数配置界面

核心功能:

  • 🏢 门店信息配置:

    • 门店名称、门店编号
    • 门店地址、营业时间
    • 联系电话、负责人信息
    • 支持多门店切换(未来扩展)
  • 💵 薪资配置:

    • 各岗位基础时薪标准(如:前台 ¥25/h)
    • 加班费倍率(平时 1.5 倍,周末 2 倍)
    • 节假日工资系数(国庆/春节 3 倍)
    • 薪资计算规则自定义
  • 班次配置:

    • 早班时间:08:00-16:00
    • 中班时间:12:00-20:00
    • 晚班时间:16:00-24:00
    • 全天班:08:00-20:00
    • 休息时间配置(午休 1 小时)
  • 🔔 提醒设置:

    • 排班提醒开关(语音播报)
    • 冲突检测阈值设置
    • 飞书消息推送配置
    • 欢迎播报功能开关
  • 🤖 AI 集成配置:

    • 阿里云百炼 API Key 配置
    • App ID 设置
    • 模型选择(qwen-plus/qwen-max)
    • 流式输出开关
    • 思考过程展示开关
  • 🎨 界面配置:

    • 主题颜色设置(蓝色/紫色/粉色)
    • 语言切换(中文/英文 - 未来支持)
    • 显示偏好(紧凑/舒适/宽松)
    • 动画效果开关

创新亮点:

  • AI 对话式配置: 页面内嵌 AI 助手浮窗,支持通过对话配置参数 用户: "帮我把前台时薪设置为30元" AI: 已为您更新前台时薪为30元/小时 ✅

  • 实时预览: 参数修改后立即生效,无需刷新页面

  • 配置导入导出: 支持配置文件的备份和恢复

  • 智能建议: AI 根据历史数据提供配置优化建议

技术实现:

  • 数据持久化:LocalStorage (键名:config_params)
  • 表单验证:实时校验 + 错误提示
  • AI 集成:通过 ConfigParams 页面调用百炼 API

应用场景:

  • 系统初始化时配置基础参数
  • 调整薪资标准时批量更新配置
  • 节假日临时调整班次时间
  • 个性化系统使用习惯
  • 多门店配置管理(未来)

2.7 实时数据统计(右侧面板)

功能定位: 全局数据看板,实时展示系统关键指标,嵌入在主界面右侧。

image.png

统计面板包含:

  • 📊 今日概览:

    • 今日排班数(实时统计当天的排班记录)
    • 在职员工数(状态为 active 的员工)
    • 待处理事项(需要确认的排班、请假申请等)
    • 数据卡片带渐变背景和图标
  • 📈 本周统计:

    • 排班班次总数(本周所有排班记录)
    • 总工作时长(小时数,精确到小数点后1位)
    • 覆盖率百分比(已排班 / 应排班 × 100%)
    • 彩色进度条(绿色:>80%,黄色:60-80%,红色:<60%)
  • 🔔 系统提醒:

    • 智能预警机制:
    • 人员不足提醒(某岗位排班人数 < 规则要求)
    • 覆盖率低提醒(整体覆盖率 < 70%)
    • 员工超负荷提醒(工作时长 > 48h/周)
    • 排班冲突提醒(同一员工重复排班)
    • 提醒按优先级排序(高/中/低)
    • 点击提醒可快速跳转到对应页面
  • 💡 数据洞察:

    • 人均排班次数(总次数 / 在职员工数)
    • 人均工作时长(总时长 / 在职员工数)
    • 最忙碌岗位(排班次数最多的岗位)
    • 最活跃员工(本周排班最多的员工)

技术实现:

// StatsPanel 组件实现
const StatsPanel = () => {
  const [stats, setStats] = useState({
    todayShifts: 0,
    activeEmployees: 0,
    weeklyShifts: 0,
    workingHours: 0,
    coverage: 0,
  });

  // 实时计算统计数据
  useEffect(() => {
    const calculateStats = () => {
      const schedules = scheduleStorage.getAll();
      const employees = employeeStorage.getAll();
      
      // 计算今日排班
      const todayShifts = schedules.filter(s => 
        s.shift_date === formatDate(new Date())
      ).length;
      
      // 计算本周统计
      const weeklyShifts = schedules.filter(s => 
        isThisWeek(new Date(s.shift_date))
      ).length;
      
      // ...更多计算逻辑
      
      setStats({ todayShifts, activeEmployees, weeklyShifts, ... });
    };

    calculateStats();
    
    // 监听数据变化
    window.addEventListener('storage', calculateStats);
    return () => window.removeEventListener('storage', calculateStats);
  }, []);

  return (
    <div className="space-y-4">
      {/* 渐变卡片展示 */}
      <Card className="bg-gradient-to-br from-blue-50 to-purple-50">
        <h3>今日排班: {stats.todayShifts}</h3>
      </Card>
      
      {/* 进度条展示 */}
      <ProgressBar value={stats.coverage} />
    </div>
  );
};

核心技术:

  • 实时监听: 监听 storage 事件,数据变化时自动刷新
  • 性能优化: 使用 useMemo 缓存计算结果,避免重复计算
  • 视觉效果: 渐变进度条动画,视觉效果出众
  • 响应式: 根据数据动态调整进度条颜色和提醒等级

位置: 嵌入在 Layout 组件的右侧固定面板,所有页面共享


三、技术架构设计

3.1 整体架构

系统架构图.jpg

架构分层:

┌─────────────────────────────────────────────────────────┐
│                      展示层 (View Layer)                   │
│  H5端 / PC端 / API接口                                     │
└─────────────────────────────────────────────────────────┘
                           ↓
┌─────────────────────────────────────────────────────────┐
│                    应用层 (Application Layer)              │
│  AI问答 | 智能排班 | 文档识别 | 数据管理 | 数据报表          │
└─────────────────────────────────────────────────────────┘
                           ↓
┌─────────────────────────────────────────────────────────┐
│               智能体交互层 (AI Agent Layer)                 │
│  信息收集智能体 | 值班表智能体 | 规则分析智能体 | 机器人通知   │
│  意图识别 | 任务拆解 | 智能编排 | 对话管理                    │
│  组件调用 | 图文识别 | 知识库检索 | 向量搜索                   │
└─────────────────────────────────────────────────────────┘
                           ↓
┌─────────────────────────────────────────────────────────┐
│                 核心能力层 (Core Layer)                     │
│  大数据模型 | RAG检索 | MCP服务 | 联网搜索 | UI设计器         │
└─────────────────────────────────────────────────────────┘
                           ↓
┌─────────────────────────────────────────────────────────┐
│                  应用数据 (Data Layer)                      │
│  Mysql集群(酒店信息) | 文档知识库(排班规则等) | 表格数据(值班结果) │
└─────────────────────────────────────────────────────────┘
                           ↓
┌─────────────────────────────────────────────────────────┐
│                  运行平台 (Infrastructure)                  │
│  服务器 | 百炼                                              │
└─────────────────────────────────────────────────────────┘

3.2 前端技术栈

// 核心框架
React 18 + TypeScript 5
  ├── 路由管理: React Router v6
  ├── UI 组件: Shadcn UI (基于 Radix UI)
  ├── 样式框架: Tailwind CSS v3
  ├── Markdown 渲染: react-markdown + remark-gfm
  ├── 图表库: Recharts (可视化)
  ├── 图标库: Lucide React
  ├── 通知组件: Sonner (Toast)
  └── 构建工具: Vite 4

// 数据管理
LocalStorage 本地存储
  ├── employeeStorage - 员工信息
  ├── scheduleStorage - 排班记录
  ├── shiftRuleStorage - 排班规则
  ├── chatStorage - 对话历史
  └── sessionStorage - 会话 ID

// AI 集成
阿里云百炼大模型 API
  ├── 模型: qwen-plus
  ├── 功能: 对话生成、文件解析
  ├── 特性: 流式输出、多轮对话
  └── 文件支持: ExcelWordPDF、图片

3.3 AI 模型工作流

AI模型图.jpg 四大核心流程:

  1. AI 问答 → LLM大模型 → 搜索引擎 → 多轮对话管理
  2. 文档识别 → 排班规则文件上传 → 文档识别 → 智能长期记忆 → 规则列表
  3. 智能排班 → 开始排班 → 信息收集工作流 → 知识库 → 大语言模型 → Python节点 → 值班表
  4. 通知提醒 → 事件通知 → 值班结果 → 报表识别 → 变动监测 → 华通提醒

四、前端核心技术实现

4.1 AI 流式对话实现

4.1.1 SSE (Server-Sent Events) 流式输出
// src/services/dashscope.ts
export const callDashScopeStream = async (
  request: DashScopeRequest,
  onChunk: (chunk: string) => void,
  onThinking?: (thinking: string) => void,
  signal?: AbortSignal
): Promise<DashScopeResponse> => {
  try {
    const url = `${API_CONFIG.baseUrl}/apps/${API_CONFIG.appId}/completion`;
    
    const response = await fetch(url, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${API_CONFIG.apiKey}`,
        'Content-Type': 'application/json',
        'X-DashScope-SSE': 'enable', // 启用流式输出
      },
      body: JSON.stringify({
        input: { prompt: request.prompt, session_id: request.session_id },
        parameters: { has_thoughts: request.has_thoughts || false },
      }),
      signal,
    });

    const reader = response.body?.getReader();
    const decoder = new TextDecoder();
    let fullText = '';

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;
      
      const chunk = decoder.decode(value, { stream: true });
      const lines = chunk.split('\n');
      
      for (const line of lines) {
        if (line.startsWith('data:')) {
          const jsonStr = line.slice(5).trim();
          if (!jsonStr) continue;
          
          const data = JSON.parse(jsonStr);
          
          // 处理思考过程
          if (data.output?.thoughts && onThinking) {
            const thoughts = data.output.thoughts;
            // 解析并回调思考信息
            onThinking(formatThinking(thoughts));
          }
          
          // 获取增量文本
          if (data.output?.text) {
            fullText += data.output.text;
            onChunk(data.output.text); // 实时回调
          }
        }
      }
    }

    return { output: { text: fullText }, request_id: requestId };
  } catch (error) {
    console.error('流式API调用失败:', error);
    throw error;
  }
};

技术亮点:

  • ✅ 使用 fetch API + ReadableStream 实现 SSE
  • ✅ 实时解析增量数据,逐字显示 AI 回复
  • ✅ 支持思考过程展示 (has_thoughts)
  • ✅ 支持取消请求 (AbortSignal)
4.1.2 Markdown 表格智能识别
// src/pages/AIAssistant.tsx
const parseMarkdownTable = (markdown: string) => {
  // 匹配 Markdown 表格格式
  const tableRegex = /\|(.+)\|[\r\n]+\|[\s:-]+\|[\r\n]+((?:\|.+\|[\r\n]+)+)/g;
  const matches = [...markdown.matchAll(tableRegex)];
  
  if (matches.length === 0) return null;

  const match = matches[0];
  const headerLine = match[1];
  const bodyLines = match[2].trim().split('\n');

  // 解析表头
  const headers = headerLine.split('|')
    .map(h => h.trim())
    .filter(h => h);

  // 解析表体
  const rows = bodyLines.map(line => {
    const cells = line.split('|')
      .map(c => c.trim())
      .filter(c => c);
    
    const row: Record<string, string> = {};
    headers.forEach((header, index) => {
      row[header] = cells[index] || '';
    });
    return row;
  });

  return { headers, rows };
};

识别流程:

  1. AI 返回 Markdown 格式的排班表
  2. 前端正则匹配表格结构
  3. 解析表头和表体
  4. 提取日期、员工姓名、岗位、班次等信息
  5. 自动创建员工档案 + 排班记录

4.2 响应式布局与 UI 设计

4.2.1 渐变配色系统
// Tailwind CSS 渐变配置
const gradients = {
  primary: 'from-blue-500 via-purple-500 to-pink-500',
  header: 'from-blue-600 to-purple-600',
  button: 'from-blue-500 to-indigo-600',
  background: 'from-gray-50 to-blue-50/30',
  card: 'from-white via-purple-50/30 to-blue-50/30',
};

// 使用示例
<div className="bg-gradient-to-r from-blue-500 via-purple-500 to-pink-500">
  渐变背景
</div>
4.2.2 动画效果
/* 淡入动画 */
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* 滑入动画 */
@keyframes slideInFromBottom {
  from { transform: translateY(10px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

/* Tailwind 动画类 */
.animate-in {
  animation: fadeIn 0.3s ease-in-out;
}

.slide-in-from-bottom {
  animation: slideInFromBottom 0.3s ease-in-out;
}
4.2.3 毛玻璃效果
// 顶部导航栏
<header className="bg-white/80 backdrop-blur-lg border-b border-gray-200">
  {/* 内容 */}
</header>

// 侧边栏
<aside className="bg-white/90 backdrop-blur-lg border-r border-gray-200">
  {/* 内容 */}
</aside>

4.3 组件化设计

4.3.1 Layout 布局组件
// src/components/Layout.tsx
function Layout({ children }: { children: React.ReactNode }) {
  return (
    <div className="min-h-screen bg-gradient-to-br from-gray-50 to-blue-50/30">
      {/* 顶部导航栏 */}
      <header className="sticky top-0 z-50">
        <Logo />
        <Navigation />
        <UserInfo />
      </header>

      <div className="flex">
        {/* 侧边栏 */}
        <aside className="w-64 h-screen">
          <SidebarMenu />
          <SystemStatus />
        </aside>

        {/* 主内容区 */}
        <main className="flex-1 overflow-y-auto">
          {children}
        </main>
      </div>
    </div>
  );
}
4.3.2 StatsPanel 统计面板
// src/components/StatsPanel.tsx
const StatsPanel = () => {
  const [stats, setStats] = useState({
    todayShifts: 0,
    activeEmployees: 0,
    weeklyShifts: 0,
    workingHours: 0,
    coverage: 0,
  });

  // 实时计算统计数据
  useEffect(() => {
    const calculateStats = () => {
      const schedules = scheduleStorage.getAll();
      const employees = employeeStorage.getAll();
      
      // 计算今日排班
      const todayShifts = schedules.filter(s => 
        s.date === formatDate(new Date())
      ).length;
      
      // 计算本周统计
      const weeklyShifts = schedules.filter(s => 
        isThisWeek(new Date(s.date))
      ).length;
      
      // ...更多计算逻辑
      
      setStats({ todayShifts, activeEmployees, weeklyShifts, ... });
    };

    calculateStats();
    
    // 监听数据变化
    window.addEventListener('storage', calculateStats);
    return () => window.removeEventListener('storage', calculateStats);
  }, []);

  return (
    <div className="space-y-4">
      {/* 今日概览 */}
      <Card>
        <h3>今日排班: {stats.todayShifts}</h3>
      </Card>
      
      {/* 本周统计 */}
      <Card>
        <h3>排班班次: {stats.weeklyShifts}</h3>
        <ProgressBar value={stats.coverage} />
      </Card>
    </div>
  );
};

4.4 数据持久化方案

// src/services/storage.ts
export const createStorage = <T extends { id: string }>(key: string) => {
  return {
    getAll: (): T[] => {
      const data = localStorage.getItem(key);
      return data ? JSON.parse(data) : [];
    },
    
    getById: (id: string): T | null => {
      const all = this.getAll();
      return all.find(item => item.id === id) || null;
    },
    
    add: (item: T): void => {
      const all = this.getAll();
      all.push(item);
      localStorage.setItem(key, JSON.stringify(all));
      
      // 触发 storage 事件,通知其他组件
      window.dispatchEvent(new Event('storage'));
    },
    
    update: (id: string, updates: Partial<T>): void => {
      const all = this.getAll();
      const index = all.findIndex(item => item.id === id);
      if (index !== -1) {
        all[index] = { ...all[index], ...updates };
        localStorage.setItem(key, JSON.stringify(all));
        window.dispatchEvent(new Event('storage'));
      }
    },
    
    delete: (id: string): void => {
      const all = this.getAll();
      const filtered = all.filter(item => item.id !== id);
      localStorage.setItem(key, JSON.stringify(filtered));
      window.dispatchEvent(new Event('storage'));
    },
  };
};

// 使用示例
export const employeeStorage = createStorage<Employee>('employees');
export const scheduleStorage = createStorage<Schedule>('schedules');

五、亮点与创新

5.1 AI 对话式交互

传统方式 ❌:

  1. 打开 Excel
  2. 手工填写日期、姓名、岗位
  3. 复制粘贴、反复调整
  4. 发送邮件/群消息

我们的方式 ✅:

  1. 对 AI 说一句话
  2. AI 自动生成表格
  3. 系统自动识别导入
  4. 完成! 🎉

5.2 智能表格识别

AI 输出 Markdown 表格:
| 日期 | 星期 | 前台 | 销售 |
|------|------|------|------|
| 10-20 | 一  | 张三  | 王五  |

↓ 前端自动识别

系统自动:
✅ 识别员工姓名
✅ 创建员工档案
✅ 生成排班记录
✅ 关联岗位信息

5.3 实时数据看板

技术实现:

  • 监听 storage 事件,数据变化时自动刷新
  • 使用 useMemo 缓存计算结果,避免重复计算
  • 渐变进度条动画,视觉效果出众

效果展示:

// 实时计算
const todayShifts = useMemo(() => {
  return schedules.filter(s => s.date === today).length;
}, [schedules, today]);

// 渐变进度条
<div className="w-full bg-gray-200 rounded-full h-2">
  <div 
    className="bg-gradient-to-r from-blue-500 to-purple-600 h-2 rounded-full transition-all duration-500"
    style={{ width: `${coverage}%` }}
  />
</div>

5.4 文件智能解析

支持上传多种格式:

  • 📄 Excel (.xlsx, .xls)
  • 📝 Word (.docx, .doc)
  • 📑 PDF (.pdf)
  • 🖼️ 图片 (.jpg, .png)

AI 自动提取:

  • 员工姓名、岗位、联系方式
  • 排班规则、约束条件
  • 历史排班数据

5.5 演示功能设计

为了演示系统的智能能力,我们设计了多个演示功能:

// 1. 欢迎播报 - 模拟员工进入系统
triggerWelcome() {
  localStorage.removeItem('last_visit_date');
  window.location.reload();
}

// 2. 团队预定提醒 - 模拟接团场景
triggerBookingAlert('team') {
  const alert = {
    date: tomorrow,
    bookingType: 'team',
    guestCount: 30,
    description: '某公司团建活动',
  };
  window.dispatchEvent(new CustomEvent('bookingChange', { detail: alert }));
}

// 3. 员工请假提醒 - 模拟突发请假
triggerLeaveAlert() {
  const alert = {
    employeeId: activeEmployee.id,
    leaveDate: tomorrow,
    leaveType: 'sick',
    reason: '突发身体不适',
  };
  window.dispatchEvent(new CustomEvent('employeeLeave', { detail: alert }));
}

六、开发挑战与解决方案

6.1 挑战一: SSE 流式输出解析

问题: 阿里云百炼的 SSE 响应格式复杂,包含增量文本和思考过程,需要准确解析。

解决方案:

// 1. 使用 ReadableStream 逐块读取
const reader = response.body?.getReader();
const decoder = new TextDecoder();

// 2. 按行分割,处理 SSE 格式
const lines = chunk.split('\n');
for (const line of lines) {
  if (line.startsWith('data:')) {
    const data = JSON.parse(line.slice(5).trim());
    
    // 3. 区分增量文本和思考过程
    if (data.output?.text) {
      onChunk(data.output.text); // 增量文本
    }
    if (data.output?.thoughts) {
      onThinking(formatThinking(data.output.thoughts)); // 思考过程
    }
  }
}

6.2 挑战二: Markdown 表格样式

问题: react-markdown 渲染的表格样式单调,缺乏交互效果。

解决方案:

// 1. 安装 @tailwindcss/typography
npm install @tailwindcss/typography

// 2. 自定义 prose 样式
<div className="prose prose-slate max-w-none">
  <ReactMarkdown 
    remarkPlugins={[remarkGfm]}
    components={{
      table: ({ node, ...props }) => (
        <table className="border-collapse w-full" {...props} />
      ),
      thead: ({ node, ...props }) => (
        <thead className="bg-blue-50" {...props} />
      ),
      th: ({ node, ...props }) => (
        <th className="border border-blue-200 px-4 py-2 font-semibold" {...props} />
      ),
      td: ({ node, ...props }) => (
        <td className="border border-gray-200 px-4 py-2 hover:bg-blue-50" {...props} />
      ),
    }}
  >
    {content}
  </ReactMarkdown>
</div>

6.3 挑战三: 滚动条留白问题

问题: 主内容区域出现不必要的横向滚动条和留白。

解决方案:

// 1. 主容器禁用横向滚动
<div className="min-h-screen w-full overflow-x-hidden">

// 2. 主内容区独立滚动
<main className="flex-1 overflow-x-hidden overflow-y-auto h-full">
  <div className="w-full max-w-full h-full">
    {children}
  </div>
</main>

// 3. Grid 布局时指定最小宽度为 0
<div className="grid grid-cols-2 gap-4 min-w-0">

6.4 挑战四: TypeScript 类型推断

问题: 复杂的泛型类型和事件类型推断错误。

解决方案:

// 1. 定义清晰的类型接口
export interface Employee {
  id: string;
  name: string;
  position: string;
  status: 'active' | 'inactive' | 'leave';
  // ...
}

// 2. 使用泛型约束
export const createStorage = <T extends { id: string }>(key: string) => {
  // ...
};

// 3. 自定义事件类型
interface BookingChangeEvent extends CustomEvent<BookingAlert> {}

window.addEventListener('bookingChange', (e: BookingChangeEvent) => {
  console.log(e.detail.bookingType);
});

6.5 挑战五: 移动端适配

问题: 侧边栏在移动端需要切换显示/隐藏。

解决方案:

// 1. 使用 state 控制侧边栏显示
const [sidebarOpen, setSidebarOpen] = useState(false);

// 2. 条件渲染 + Tailwind 断点
<aside className={`
  ${sidebarOpen ? 'translate-x-0' : '-translate-x-full'}
  md:translate-x-0 
  fixed md:relative 
  transition-transform duration-300
`}>

// 3. 移动端遮罩层
{sidebarOpen && (
  <div 
    className="md:hidden fixed inset-0 bg-black/60 backdrop-blur-sm"
    onClick={() => setSidebarOpen(false)}
  />
)}

七、性能优化实践

7.1 组件优化

// 1. 使用 React.memo 避免不必要的重渲染
export default memo(Layout);

// 2. 使用 useCallback 缓存函数
const handleClick = useCallback(() => {
  // 处理逻辑
}, [dependencies]);

// 3. 使用 useMemo 缓存计算结果
const expensiveValue = useMemo(() => {
  return computeExpensiveValue(data);
}, [data]);

7.2 懒加载

// 路由懒加载
import { lazy, Suspense } from 'react';

const AIAssistant = lazy(() => import('@/pages/AIAssistant'));
const Employees = lazy(() => import('@/pages/Employees'));

function App() {
  return (
    <Suspense fallback={<Loading />}>
      <Routes>
        <Route path="/" element={<AIAssistant />} />
        <Route path="/employees" element={<Employees />} />
      </Routes>
    </Suspense>
  );
}

7.3 图片优化

// 1. 使用 WebP 格式
<img src="/logo.webp" alt="Logo" />

// 2. 懒加载图片
<img 
  src="/image.jpg" 
  loading="lazy" 
  decoding="async" 
/>

// 3. 响应式图片
<picture>
  <source srcSet="/image-large.webp" media="(min-width: 1024px)" />
  <source srcSet="/image-medium.webp" media="(min-width: 768px)" />
  <img src="/image-small.webp" alt="Responsive" />
</picture>

7.4 代码分割

// vite.config.ts
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          'vendor': ['react', 'react-dom', 'react-router-dom'],
          'ui': ['@radix-ui/react-dialog', '@radix-ui/react-select'],
          'markdown': ['react-markdown', 'remark-gfm'],
        },
      },
    },
  },
});

八、总结与展望

8.1 项目成果

在 AI Hackathon 黑客松大赛中,我们成功开发了一款功能完整、体验流畅的智能排班系统——华小班

核心成果:

  • 功能完整: 实现了 AI 对话、智能识别、数据统计、演示功能等 13+ 个功能点
  • 技术创新: 采用 SSE 流式输出、Markdown 表格识别、实时数据看板等创新技术
  • UI 精美: 渐变配色、毛玻璃效果、流畅动画,打造评委印象深刻的产品体验
  • 性能优秀: 组件优化、懒加载、代码分割,确保流畅运行
  • 无明显 Bug: 经过充分测试,可直接投入使用

技术收获:

  • 🎓 深入学习了阿里云百炼大模型的 API 和最佳实践
  • 🎓 掌握了 SSE 流式输出的实现原理和应用场景
  • 🎓 提升了 React + TypeScript 的工程化能力
  • 🎓 积累了复杂交互和动画的实现经验

8.2 未来展望

短期优化(赛后迭代)
  • 🔄 大文件分块上传(当前限制 100MB)
  • 🔄 离线缓存机制(PWA)
  • 🔄 多门店切换(当前单门店)
  • 🔄 消息推送集成(华通群机器人)
  • 🔄 移动端适配优化(已支持响应式,可进一步优化)
长期规划(产品化方向)
  • 🚀 多租户架构: 支持多门店、多企业独立数据
  • 🚀 云端数据库: 替换 LocalStorage,使用云端数据库(MySQL/PostgreSQL)
  • 🚀 权限管理: 店长、店助、员工三级权限体系
  • 🚀 移动 App: 开发 React Native 移动端应用
  • 🚀 数据分析: 接入大数据平台,提供更深入的业务洞察
  • 🚀 智能推荐: 基于历史数据,AI 主动推荐最优排班方案

九、项目地址与运行

9.1 GitHub 地址

# 项目地址
https://github.com/xiaoniuge36/schedule-assistant.git

# 克隆项目
git clone https://github.com/xiaoniuge36/schedule-assistant.git
cd schedule-assistant

9.2 本地运行

# 1. 安装依赖
npm install
# 或
pnpm install

# 2. 配置环境变量(可选)
# 复制 .env.example 为 .env
# 填入阿里云百炼 API Key

# 3. 启动开发服务器
npm run dev

# 4. 打开浏览器访问
# http://localhost:5173

9.3 生产部署

# 1. 构建生产版本
npm run build

# 2. 预览构建结果
npm run preview

# 3. 部署到服务器
# 将 dist/ 目录上传到服务器
# 使用 Nginx/Apache 托管静态文件

9.4 Docker 部署(可选)

# Dockerfile
FROM node:16-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# 构建镜像
docker build -t schedule-assistant .

# 运行容器
docker run -d -p 80:80 schedule-assistant

🎉 致谢

感谢阿里云百炼团队提供强大的大模型能力,为智能排班系统提供核心 AI 支持!


欢迎交流讨论,共同进步! 💪


© 2025 智能排班系统 | 基于阿里云百炼大模型