🏆 基于阿里云百炼的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 的推理逻辑
- 实时显示 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 员工管理
功能定位: 员工档案管理中心,维护员工基础信息。
核心功能:
-
👤 员工档案管理:
- 基础信息:姓名、岗位、状态、联系方式
- 扩展字段:员工编号(
staff_id)、门店编号(store_code)、偏好设置 - 岗位类型:前台、销售、店助、保洁等(可自定义)
- 状态管理:
active(在职)、inactive(离职)
-
🔍 智能搜索筛选:
- 按姓名快速搜索(实时过滤)
- 按岗位分类筛选
- 按状态过滤显示(在职/离职)
- 支持组合筛选条件
-
📥 批量操作:
- 批量导入员工信息(通过 AI 解析 Excel/Word)
- 批量编辑员工状态
- 批量删除离职员工(带二次确认)
-
💾 数据持久化:
- 基于 LocalStorage 存储(键名:
employees) - 自动保存,刷新页面数据不丢失
- 支持数据导出备份(JSON 格式)
- 基于 LocalStorage 存储(键名:
数据结构:
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 实时数据统计(右侧面板)
功能定位: 全局数据看板,实时展示系统关键指标,嵌入在主界面右侧。
统计面板包含:
-
📊 今日概览:
- 今日排班数(实时统计当天的排班记录)
- 在职员工数(状态为
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 整体架构
架构分层:
┌─────────────────────────────────────────────────────────┐
│ 展示层 (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
├── 功能: 对话生成、文件解析
├── 特性: 流式输出、多轮对话
└── 文件支持: Excel、Word、PDF、图片
3.3 AI 模型工作流
四大核心流程:
- AI 问答 → LLM大模型 → 搜索引擎 → 多轮对话管理
- 文档识别 → 排班规则文件上传 → 文档识别 → 智能长期记忆 → 规则列表
- 智能排班 → 开始排班 → 信息收集工作流 → 知识库 → 大语言模型 → Python节点 → 值班表
- 通知提醒 → 事件通知 → 值班结果 → 报表识别 → 变动监测 → 华通提醒
四、前端核心技术实现
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;
}
};
技术亮点:
- ✅ 使用
fetchAPI +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 };
};
识别流程:
- AI 返回 Markdown 格式的排班表
- 前端正则匹配表格结构
- 解析表头和表体
- 提取日期、员工姓名、岗位、班次等信息
- 自动创建员工档案 + 排班记录
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 对话式交互
传统方式 ❌:
- 打开 Excel
- 手工填写日期、姓名、岗位
- 复制粘贴、反复调整
- 发送邮件/群消息
我们的方式 ✅:
- 对 AI 说一句话
- AI 自动生成表格
- 系统自动识别导入
- 完成! 🎉
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 智能排班系统 | 基于阿里云百炼大模型