# 纺织行业采购计划管理系统

一款专为纺织行业设计的全流程协作管理平台，连接采购商（布行）、纺织厂、水洗厂三方，实现从计划制定到成品交付的数字化管理。

## 核心功能

### 多角色协作
- **采购商/布行**：创建生产计划、管理坯布库存、跟踪生产进度、处理结款
- **纺织厂**：接收生产计划、管理生产流程、坯布入库、纱线库存管理
- **水洗厂**：接收水洗订单、管理水洗流程

### 计划管理
- 自动生成唯一计划编号和坯布识别码
- 纱线配比配置与用量自动计算
- 生产流程节点跟踪（确认计划 → 采纱 → 染纱 → 上机 → 坯布入库）
- 实时进度可视化，支持97%完成度自动提醒

### 库存管理
- **产品信息**：按坯布码分组管理，入库记录追溯
  - 产品管理：支持按名称、克重、颜色多级分组展示
  - 出入库历史：查看每个产品的完整库存变动记录
  - 价格历史：追踪采购价格变动
  - 产品唯一性：产品码全局唯一，色号在"成品名称-克重-颜色"组合中唯一
- **原料纱仓库**：库存预警、最低库存提醒
- 实时库存数据同步，入库自动更新

### 结款管理
- 按完成米数自动计算结款金额
- 待结款汇总统计
- 一键确认结款，记录结款时间

### 分享与导入
- 加密分享链接，保护敏感信息
- 支持剪贴板自动识别导入
- 扫码或链接快速关联计划

## 技术特性

### 前端技术栈
- **React 18** + TypeScript - 类型安全的函数组件开发（strict模式）
- **Webpack 5** - 构建工具，开发服务器端口 3015，host: 0.0.0.0
- **TailwindCSS 3** + PostCSS - 原子化CSS，自定义CSS变量体系
- **Framer Motion** - 页面过渡、交互动画、性能降级
- **Lucide React** - 现代化图标库
- **Recharts** - 数据可视化图表
- **React Router v6** - HashRouter 模式，25条路由配置

### 多角色主题色系统
| 角色 | 主色调 | 渐变配色 | 应用场景 |
|------|--------|---------|---------|
| 采购商 | Amber | `from-amber-400 to-orange-500` | Dashboard、Layout、通知中心 |
| 纺织厂 | Emerald | `from-emerald-400 to-teal-400` | Dashboard、Layout、通知中心 |
| 水洗厂 | Violet | `from-violet-400 to-fuchsia-400` | Dashboard、通知中心 |
| 系统/公共 | Blue | `from-blue-500 to-blue-600` | 登录页、通用组件 |

### 前端配置架构

系统采用**双层配置架构**，将所有可配置项从散落的 hardcode 集中到统一配置中心：

```
src/config/app.ts    ← 配置源头（环境感知、数值型配置、主题色、存储键）
       ↓ 导入
src/utils/constants.ts ← 向后兼容层（状态枚举、UI映射、步骤配置 + 重新导出app.ts配置）
       ↓ 导入
各业务文件            ← 消费方（Hooks、页面、组件）
```

#### 配置模块清单 (`src/config/app.ts`)

| 配置模块 | 导出常量 | 说明 |
|----------|---------|------|
| 环境配置 | `APP_ENV`, `IS_DEV`, `IS_PROD` | 通过 webpack DefinePlugin 注入 `__APP_ENV__` |
| 应用信息 | `APP_CONFIG` | 名称、版本号、Demo密码、免密登录有效期 |
| 演示账号 | `DEMO_ACCOUNTS`, `SHOW_DEMO_ACCOUNTS` | 三个角色的演示账号配置 |
| 缓存配置 | `CACHE_CONFIG` | 计划数据(10s)、库存数据(5s)、Dashboard(10s) |
| 分页配置 | `PAGINATION_CONFIG` | 默认页大小(20)、入库记录上限(100)、价格历史上限(50) |
| 同步配置 | `SYNC_CONFIG` | 计划状态同步间隔(开发10s/生产5min)、Realtime重连延迟 |
| 动画配置 | `ANIMATION_CONFIG` | 标准/快速/慢速过渡、弹簧动画、页面过渡、交错延迟 |
| 进度阈值 | `PROGRESS_THRESHOLDS` | 完成(97%)、低警告(30%)、中提示(60%) |
| 角色主题色 | `ROLE_THEMES`, `getRoleTheme()` | purchaser/textile/washing/system 四套完整主题色 |
| 文件上传 | `UPLOAD_CONFIG` | 图片大小限制(5MB)、允许类型、存储桶名称 |
| 分享链接 | `SHARE_CONFIG` | 链接有效期(30min)、短码长度(8) |
| 存储键 | `STORAGE_KEYS` | 所有 localStorage key 集中管理（14个键） |

#### 状态枚举常量 (`src/utils/constants.ts`)

| 枚举常量 | 值 | 对应数据库枚举 |
|----------|-----|--------------|
| `PLAN_STATUS` | PENDING/PRODUCING/COMPLETED/REJECTED | plan_status |
| `STEP_STATUS` | PENDING/ACTIVE/COMPLETED/REJECTED | step_status |
| `FACTORY_TYPE` | TEXTILE/WASHING | factory_type |
| `WAREHOUSE_TYPE` | RAW_FABRIC/FABRIC/FINISHED/YARN | warehouse_type |
| `PAYMENT_STATUS` | PENDING/COMPLETED | payment_status |
| `SHARE_LINK_STATUS` | PENDING/CLICKED/CONFIRMED/REJECTED/EXPIRED/CANCELLED | share_links.status |
| `WASHING_PLAN_STATUS` | PENDING/IN_PROGRESS/COMPLETED | washing_plans.status |
| `INVENTORY_RECORD_TYPE` | IN/OUT | yarn_stock_records.record_type |
| `OUTBOUND_TYPE` | MANUAL/AUTO | product_outbound_records.outbound_type |

#### 使用规范

1. **新增配置项**：统一添加到 `src/config/app.ts`，不要在业务文件中硬编码
2. **状态字符串**：使用 `PLAN_STATUS.PENDING` 代替 `'pending'`，避免拼写错误
3. **localStorage**：使用 `STORAGE_KEYS.savedUsername` 代替 `'saved_username'`
4. **缓存时间**：使用 `CACHE_CONFIG.planDataDuration` 代替 `10000`
5. **向后兼容**：`constants.ts` 重新导出 `animationConfig`/`paginationConfig`/`progressThresholds`，旧代码无需修改

### 设计架构

#### CSS 变量体系 (`src/styles/index.css`)
- **色阶系统**: 完整的 50-900 色阶定义（Primary, Success, Warning, Error, Gray）
- **阴影层级**: 6级阴影系统 (`--shadow-sm` ~ `--shadow-2xl`)
- **自定义工具类**: `.glass`/`.glass-dark`(毛玻璃)、`.scrollbar-thin`/`.scrollbar-hide`(滚动条美化)、`.animate-fade-in`/`.animate-slide-in`(入场动画)、`.safe-area-top/bottom`(iOS安全区)

#### 动效规范 (Framer Motion + constants.ts)
- **页面过渡**: `opacity: 0→1`, `y: 20→0`, `scale: 0.98→1` (Duration: 0.35s)
- **列表交错**: `staggerChildren: 0.08`
- **交互反馈**: Spring 弹簧动画 (`stiffness: 200, damping: 25`)
- **性能降级**: `usePerformance` Hook 自动检测，低性能设备仅使用 opacity 过渡
- **硬件加速**: `will-change-transform` + `content-visibility-auto`

#### 响应式设计
- **断点**: `sm(640px)`, `md(768px)`, `lg(1024px)`, `xl(1280px)`
- **移动优先**: 默认样式为移动端，通过 `sm:/md:/lg:` 向上覆盖
- **触控优化**: 最小触控区域 44x44px (`@media (pointer: coarse)`)
- **布局切换**: 桌面端表格 ↔ 移动端卡片，根据屏幕宽度自动切换

### 布局架构
| 角色 | 布局组件 | 导航项数 | 路由嵌套 |
|------|---------|---------|---------|
| 采购商 | PurchaserLayout | 8项 | 嵌套 Outlet |
| 纺织厂 | TextileLayout | 5项 | 嵌套 Outlet |
| 水洗厂 | WashingLayout | 6项 | 嵌套 Outlet |

### 后端服务
- **Meoo Cloud (Supabase)** - 云数据库 + 认证 + 实时订阅 + 文件存储
- **PostgreSQL** - 31张业务表，支持复杂查询和事务
- **Row Level Security** - 行级安全策略，基于 company_id 的数据隔离
- **Realtime** - 实时数据同步，单例管理器 + 引用计数自动清理
- **Storage** - avatars + product_images 两个存储桶

### 数据安全
- **RLS 策略** - 所有表启用行级安全，严格的数据访问控制
- **公司隔离** - 基于 company_id + get_user_master_company_id() 的数据隔离
- **子账号支持** - 主账号/子账号权限继承，master_id 关联
- **分享加密** - HMAC-SHA256签名 + Base64编码，30分钟有效期
- **合作关系** - company_relationships 表实现首次合作确认机制

## 快速开始

### 环境要求
- Node.js 18+
- pnpm 8+

### 安装依赖
```bash
pnpm install
```

### 开发模式
```bash
pnpm run dev
```
服务启动在 http://localhost:3015

### 构建生产版本
```bash
pnpm run build
```

### 数据库迁移
```bash
# 查看云服务状态
meoo-cli cloud status

# 执行数据库迁移
meoo-cli cloud migrate --sql "..." --name "migration_name" --changes "变更说明"
```

## 项目结构（2026-06-04 更新）

```
src/
├── App.tsx                  # 根组件（25条HashRouter路由 + PageErrorBoundary）
├── components/              # 共享组件（35个）
│   ├── layout/                  # 布局组件（4个）
│   │   ├── Sidebar.tsx              # 可折叠侧边栏导航
│   │   ├── PurchaserLayout.tsx      # 采购商布局（8项导航 + amber主题）
│   │   ├── TextileLayout.tsx        # 纺织厂布局（5项导航 + emerald主题）
│   │   └── WashingLayout.tsx        # 水洗厂布局（6项导航 + violet主题）
│   ├── warehouse/               # 仓库管理组件（6个）
│   │   ├── WarehouseNav.tsx         # 仓库类型导航
│   │   ├── ProductForm.tsx          # 产品创建/编辑表单
│   │   ├── InboundForm.tsx          # 入库表单
│   │   ├── OutboundForm.tsx         # 出库表单
│   │   ├── ProductList.tsx          # 产品列表（桌面表格+移动卡片）
│   │   └── InboundRecords.tsx       # 入库记录列表
│   ├── plans/                   # 计划管理组件（3个）
│   │   ├── PlanGroup.tsx            # 工厂分组 + 计划卡片
│   │   ├── ShareModal.tsx           # 分享链接弹窗（短链+长链+隐藏敏感信息）
│   │   └── PlanEditModal.tsx        # 计划编辑弹窗
│   ├── PlanCard.tsx               # 计划卡片（进度条+状态+流程节点）
│   ├── ProcessFlow.tsx            # 生产流程节点（呼吸动画+弹窗确认）
│   ├── ProgressBar.tsx / StatusBadge.tsx  # 基础UI组件
│   ├── InventoryRecordsModal.tsx  # 入库记录弹窗
│   ├── YarnAllocationModal.tsx    # 纱线分配弹窗（自动/手动模式）
│   ├── NotificationCenter.tsx     # 通知中心（amber/emerald/violet主题）
│   ├── HelpCenter.tsx / UserManual.tsx / OnboardingGuide.tsx  # 帮助系统
│   ├── VersionUpdate.tsx / FeedbackModal.tsx / AboutModal     # 版本与反馈
│   ├── CrashReporter.tsx / ErrorBoundary.tsx                  # 错误处理
│   ├── DemoDisclaimerModal.tsx / DemoWatermark.tsx            # Demo标识
│   ├── PageTransition.tsx / VirtualList.tsx / Tooltip.tsx     # UI增强
│   └── NetworkStatusBar.tsx / ComingSoonModal.tsx             # 辅助组件
├── pages/                     # 页面组件（25个）
│   ├── LoginPage.tsx / RegisterPage.tsx / RoleSelectPage.tsx  # 认证页
│   ├── MemberManage.tsx       # 子账号管理 + 帮助系统入口
│   ├── ImportPlanPage.tsx     # 分享链接导入（解密+确认/拒绝）
│   ├── DemoDataSharing.tsx    # 数据共享演示
│   ├── purchaser/             # 采购商页面（8个，PurchaserLayout嵌套）
│   │   ├── Dashboard.tsx          # 首页（统计+最近计划+快捷操作）
│   │   ├── PlanOverview.tsx       # 纺织计划总览
│   │   ├── NewPlan.tsx / NewWashingPlan.tsx  # 新建计划
│   │   ├── WarehouseManage.tsx    # 产品信息管理
│   │   ├── FinishedWarehouse.tsx  # 成品仓库
│   │   ├── FactoryManage.tsx      # 工厂管理
│   │   └── AccountsPayable.tsx    # 应付账款
│   ├── textile/               # 纺织厂页面（5个，TextileLayout嵌套）
│   │   ├── Dashboard.tsx          # 生产概览
│   │   ├── PlanOverview.tsx       # 接单与生产进度
│   │   ├── YarnWarehouse.tsx      # 原料纱仓库（出入库记录）
│   │   ├── FabricWarehouse.tsx    # 已生产坯布（Realtime订阅）
│   │   └── PaymentPending.tsx     # 待结款
│   └── washing/               # 水洗厂页面（6个，WashingLayout嵌套）
│       ├── Dashboard.tsx          # 首页（violet主题）
│       ├── PlanOverview.tsx       # 水洗计划总览
│       ├── PendingFabric.tsx / CompletedFabric.tsx  # 待洗/已完成
│       ├── FinishedWarehouse.tsx  # 成品仓库
│       └── PaymentPending.tsx     # 待结款
├── hooks/                     # 自定义Hooks（10个）
│   ├── useInventoryData.ts        # 库存数据（5秒缓存+Realtime）
│   ├── usePlanData.ts             # 计划数据（10秒缓存+分页+Realtime）
│   ├── usePlanStatusSync.ts       # 计划状态自动同步（10秒测试间隔）
│   ├── useRealtime.ts             # Realtime单例管理器（引用计数）
│   ├── useResponsive.ts           # 响应式断点检测
│   ├── useTheme.ts                # 主题管理（暗黑模式class策略）
│   ├── usePerformance.ts          # 性能检测（三档动画降级）
│   ├── useNetworkStatus.ts        # 网络状态监听
│   ├── useVirtualScroll.ts        # 虚拟滚动
│   └── useErrorHandler.ts         # 统一错误处理Hook
├── config/app.ts              # 应用全局配置中心（环境/缓存/分页/动画/主题色/存储键等）
├── contexts/AuthContext.tsx   # 认证上下文（login/register/logout）
├── styles/index.css           # 全局样式（CSS变量+工具类+移动端适配）
├── supabase/                  # Supabase客户端（自动生成，禁止修改）
├── types/index.ts             # 统一类型定义中心（30+接口）
└── utils/                     # 工具函数
    ├── constants.ts               # 状态枚举、UI映射、步骤配置（从config/app导入并重新导出）
    ├── helpers.ts                 # 日期格式化、数字解析、分组计算
    └── shareCrypto.ts             # HMAC-SHA256签名加密
```

## 路由结构

| URL 路径 | 组件 | 布局 | 说明 |
|----------|------|------|------|
| `/login` | LoginPage | - | 登录页（演示账号+三角色主题色） |
| `/register` | RegisterPage | - | 企业注册 |
| `/role-select` | RoleSelectPage | - | 角色选择 |
| `/purchaser` | PurchaserDashboard | PurchaserLayout | 采购商首页 |
| `/purchaser/plans` | PlanOverview | PurchaserLayout | 纺织计划总览 |
| `/purchaser/plans/new` | NewPlan | PurchaserLayout | 新建纺织计划 |
| `/purchaser/washing-plans/new` | NewWashingPlan | PurchaserLayout | 新建水洗计划 |
| `/purchaser/warehouse` | WarehouseManage | PurchaserLayout | 产品信息管理 |
| `/purchaser/finished-warehouse` | FinishedWarehouse | PurchaserLayout | 成品仓库 |
| `/purchaser/factories` | FactoryManage | PurchaserLayout | 工厂管理 |
| `/purchaser/accounts-payable` | AccountsPayable | PurchaserLayout | 应付账款 |
| `/textile` | TextileDashboard | TextileLayout | 纺织厂首页 |
| `/textile/plans` | TextilePlanOverview | TextileLayout | 接单与生产进度 |
| `/textile/yarn-warehouse` | YarnWarehouse | TextileLayout | 原料纱仓库 |
| `/textile/fabric-warehouse` | FabricWarehouse | TextileLayout | 已生产坯布 |
| `/textile/payments` | PaymentPending | TextileLayout | 待结款 |
| `/washing` | WashingDashboard | WashingLayout | 水洗厂首页 |
| `/washing/plans` | WashingPlanOverview | WashingLayout | 水洗计划总览 |
| `/washing/pending` | PendingFabric | WashingLayout | 待水洗坯布 |
| `/washing/completed` | CompletedFabric | WashingLayout | 已完成水洗 |
| `/washing/finished-warehouse` | FinishedWarehouse | WashingLayout | 成品仓库 |
| `/washing/payments` | WashingPaymentPending | WashingLayout | 待结款 |
| `/members` | MemberManage | - | 子账号管理 |
| `/import` | ImportPlanPage | - | 分享链接导入 |
| `/demo/data-sharing` | DemoDataSharing | - | 数据共享演示 |

## 组件说明

### InventoryRecordsModal 入库记录弹窗
统一风格的入库记录详情弹窗，支持采购商和纺织厂页面复用。

**特性：**
- 统计摘要：显示总匹数和总米数
- 记录列表：按时间倒序显示所有入库记录
- 详细信息：日期时间、计划编号、工厂名称、批号、匹数、米数
- 动画效果：Framer Motion 平滑动画

**使用示例：**
```tsx
import { InventoryRecordsModal } from '../../components/InventoryRecordsModal';

<InventoryRecordsModal
  isOpen={recordsModalOpen}
  onClose={() => setRecordsModalOpen(false)}
  records={selectedRecords}
  title="产品名称 - 入库记录"
/>
```

### OnboardingGuide 新用户引导
首次进入系统时展示的功能引导动画，支持采购商和纺织厂角色。

**特性：**
- 分步骤功能介绍
- 支持跳转到对应功能区
- 进度条和步骤指示器
- 可跳过引导

### DemoDisclaimerModal Demo免责声明
访问网站时显示的Demo阶段免责声明弹窗。

### ComingSoonModal 功能开发中
点击未开发功能时显示的提示弹窗。

## 使用指南

### 采购商操作流程
1. 注册/登录账号，选择"采购商"角色
2. 创建新计划，填写产品信息、纱线配比
3. 通过分享链接将计划发送给纺织厂
4. 实时查看生产进度，管理坯布库存
5. 生产完成后确认结款

### 纺织厂操作流程
1. 注册/登录账号，选择"纺织厂"角色
2. 通过分享链接或剪贴板导入计划
3. 按流程节点确认生产进度
4. 坯布入库时填写入库数量和匹数
5. 查看待结款，确认收款

### 子账号管理
- 主账号可创建子账号，分配不同权限
- 子账号可独立操作，数据归属主账号公司
- **用户名全局唯一**：子账号用户名不可与其他主账号或子账号重复

## 数据安全

- 分享链接采用加密传输，不包含敏感信息
- 导入页面隐藏成品名称、颜色、色号等敏感字段
- RLS策略确保数据隔离，仅授权用户可访问
- 虚拟邮箱格式 `{username}@meoo.local` 保护隐私

## 浏览器支持

- Chrome 90+
- Safari 14+
- Firefox 88+
- Edge 90+

## 更新日志

### 2026-06-04 (v2.2.0) - P1 共享组件抽象
- **AccountProfileCard 替换3个Dashboard内联账户弹窗**
  - `purchaser/Dashboard.tsx`：~140行内联弹窗 → `<AccountProfileCard role="purchaser" />`
  - `textile/Dashboard.tsx`：~150行内联弹窗 → `<AccountProfileCard role="textile" />`
  - `washing/Dashboard.tsx`：~150行内联弹窗 → `<AccountProfileCard role="washing" />`
  - 共减少约440行重复代码，头像上传功能随组件一并收敛
  - 清理三个文件中不再使用的图标 import（X, BookOpen, MessageSquare, Info, Camera 等）
- **ImageUploader 任务合并完成**
  - 原计划独立抽象 ImageUploader 组件，实际头像上传已随 AccountProfileCard 替换一并移除
  - pages 目录中已无内联头像上传代码残留

### 2026-06-04 (v2.1.0) - 架构优化与代码治理
- **Phase 1: 路由守卫**
  - 新增 RoleGuard 组件 (`src/components/RoleGuard.tsx`)，基于 AuthContext 的角色权限校验
  - App.tsx 路由重构：采购商/纺织厂/水洗厂路由组均包裹 RoleGuard，防止越权访问
- **Phase 2: 数据层优化**
  - extractParamsFromLink 去重：统一至 `src/utils/helpers.ts`，移除 textile/washing PlanOverview 中的本地重复实现（共47行）
  - 新增 useErrorHandler Hook (`src/hooks/useErrorHandler.ts`)：统一错误处理模式，替代散落的 console.error + alert
- **Phase 3: 业务组件抽象**
  - 新增 WashingLayout 组件 (`src/components/layout/WashingLayout.tsx`)：解决水洗厂缺少独立 Layout 的架构债务
  - App.tsx 水洗厂路由重构：从扁平路由改为 WashingLayout 嵌套结构，三个角色布局架构完全统一
  - 实时订阅审计：确认 pages 目录无直接 supabase.channel 调用
- **Phase 4: 代码治理**
  - usePlanData 闭包陷阱修复：setState 从直接引用 state.plans 改为函数式更新
  - useInventoryData any 类型治理：18处 any 全部替换为 Supabase Tables<> 精确类型 + 局部接口
- **项目统计更新**：35组件/25页面/10 Hooks

### 2026-06-04 (v2.0.0) - 重大版本更新
- **系统审计与质量保障**
  - 完成四维度系统审计（文件关联/内存安全/路由配置/权限授权），全部通过
  - 新增 Bug 快速排查检查单（12大类90+检查项），覆盖页面白屏、数据读写、状态同步、内存性能、样式UI、认证权限、分享链接、构建部署等全部问题类型
  - 新增数据库诊断常用 SQL（7条）和高频 Bug 速查索引（14条）
  - 修复数据完整性问题：清理 share_links 孤儿记录、修复计划状态不一致、标记过期链接
- **文档体系完善**
  - 完善数据库31张表完整文档，按6大模块组织（用户权限/生产计划/库存管理/财务结算/分享协作/系统辅助）
  - 新增设计架构规范（CSS变量体系/动效规范/响应式设计/布局架构差异）
  - 新增多角色主题色系统完整文档
  - API 调用示例扩展（Realtime订阅/分享链接加密解密）
- **测试体系建设**
  - 新增 E2E 全流程测试文件 `e2e/full-workflow.spec.ts`
  - 完成采购商下单→分享链接→纺织厂确认→生产流程→分批次入库的端到端模拟测试
  - 验证数据一致性：completed_quantity = SUM(inventory_records.quantity)
- **代码质量**
  - usePlanStatusSync 测试间隔标注（10秒测试用，生产环境需改回5分钟）
  - 项目目录结构文档更新至最新状态（33组件/25页面/9 Hooks）

### 2025-06-02 (v1.0.36)
- **水洗厂功能完善**
  - 新增已完成坯布仓库页面，展示水洗完成的坯布库存
  - 新增待水洗坯布页面，展示待水洗的坯布列表
  - 新增水洗厂计划总览页面，统一管理水洗计划
  - 新增水洗厂结款页面，支持查看和确认水洗费用
- **采购商功能增强**
  - 新增成品仓库页面，管理已完成水洗的成品
  - 新增应付账款页面，查看各工厂的应付费用
- **组件优化**
  - 新增 YarnAllocationModal 组件，优化纱线分配流程
  - 新增 DemoWatermark 组件，Demo 模式显示水印
  - 新增 PageTransition 组件，统一页面过渡动画
  - 优化 VirtualList 组件，支持大数据列表虚拟滚动
- **布局优化**
  - 新增 Sidebar 侧边栏组件，统一导航结构
  - 新增 PurchaserLayout 采购商布局组件
  - 统一各角色工作台的布局风格

### 2025-06-01 (v1.0.35)
- **分享链接自动过期机制**
  - 创建 `check_share_links_expired()` 数据库函数，自动更新过期链接状态
  - 完善分享链接流程，符合业务流程图要求
  - 移除 `plan_factories` 表错误唯一约束 `unique_plan_factory_type`
- **系统逻辑闭环检查**
  - 全面检查采购商与纺织厂关联流程
  - 修复 NewPlan.tsx 子操作错误处理（纱线配比、流程节点、价格历史）
  - 验证系统符合计划分享流程图和计划确认流程图

### 2025-05-30 (v1.0.34)
- **计划创建流程修复**
  - 修复创建计划时自动关联工厂的问题
  - 创建计划时不再自动在 `plan_factories` 表中插入关联记录
  - 工厂关联改为通过分享链接或推送功能，由工厂确认后才建立
  - 删除 `auto_sync_plan_trigger` 触发器，避免自动关联历史工厂
- **Bug修复**
  - 修复 `factory_type` 枚举类型错误（`'textile' as FactoryType`）
  - 修复触发器函数 `auto_sync_plan_to_factory()` 中变量类型声明（`TEXT` → `factory_type`）

### 2025-05-30 (v1.0.33)
- **采购商移动端UI重构**
  - 移动端界面风格与纺织厂保持一致，采用卡片式布局
  - 统计卡片改为3列紧凑布局，与纺织厂一致
  - 最近计划支持左右滑动展示，带滑动按钮和指示器
  - 快捷操作区域显示6个功能按钮（3列布局）：新建纺织计划、新建水洗计划、产品信息、水洗仓库、工厂管理、应付账款
  - 背景使用渐变风格（amber-50/orange-50）
- **页面切换优化**
  - 添加数据缓存机制（dataLoaded状态），避免重复加载
  - 从其他页面返回时保持原有数据，不显示加载动画，页面瞬间呈现
  - 添加页面可见性监听（visibilitychange），后台返回前台时自动刷新数据
- **Bug修复**
  - 修复快捷操作路由路径错误（应付账款、水洗仓库）
  - 修复CreditCard图标未导入导致的运行时错误

### 2025-05-30 (v1.0.32)
- **分享链接流程重构**
  - 新增 `company_relationships` 表记录采购商与工厂的合作关系
  - 重构分享逻辑：已有合作关系直接推送，无合作关系生成30分钟有效期的分享链接
  - 新增链接状态追踪：pending → clicked → confirmed/rejected/expired/cancelled
  - 工厂可确认或拒绝计划，拒绝时可填写原因反馈给采购商
  - 确认后自动建立合作关系，后续计划可直接推送
  - 链接30分钟过期自动失效，可重新生成
- **数据库 RLS 策略修复**
  - 修复 `yarn_ratios` INSERT 策略缺失 WITH CHECK 条件导致 403 错误
  - 简化 `share_links` SELECT 策略，避免复杂查询导致 500 错误
  - 添加 `companies` DELETE 策略，支持删除工厂信息
- **Bug 修复**
  - 修复 `usePlanData` Hook 依赖项导致无限循环、页面卡加载问题
  - 修复删除工厂时未清理 `company_relationships` 关联导致外键约束错误
  - 修复 `ShareModal` 和 `ImportPlanPage` Date 构造类型错误
  - 修复计划总览 factories 查询逻辑，显示所有工厂而非仅有关联的
  - **计划状态同步修复**：创建 `usePlanStatusSync` Hook，每5分钟自动检查并修复计划状态不一致问题
  - **分享链接导入修复**：修复导入成功后未更新 `production_plans.status` 为 `producing` 的问题
  - **采购商界面优化**：计划卡片显示关联纺织厂公司名称，便于二次确认
  - **水洗计划数据加载修复**：修复 RLS 策略冲突导致产品库存数据无法加载的问题
  - **入库记录产品信息显示修复**：修复 `useInventoryData` 返回数据缺少产品信息导致"未知产品"显示问题
- **UI 优化**
  - 采购商 Dashboard "新建水洗"更名为"新建水洗计划"
  - 工厂管理添加删除功能，支持删除无关联计划的工厂

### 2025-05-28 (v1.0.31)
- **动画性能优化**
  - 创建 `usePerformance` Hook，自动检测设备性能级别
  - 支持三种性能模式：高性能/中等性能/低性能
  - 自动检测系统减少动画偏好设置
  - 简化页面过渡动画，仅使用 opacity 变化
  - 优化 Dashboard 页面，使用 CSS transition 替代复杂动画
  - 添加 CSS 硬件加速优化（GPU加速、内容可见性）
  - 支持低配置电脑流畅运行
- **分享链接安全修复**
  - 统一加密/解密为带 HMAC-SHA256 签名的异步版本，消除同步版本无签名验证的安全隐患
  - `decryptShareParams` 返回类型扩展，补回之前丢失的 `hideSensitive` 字段
  - `ShareModal` 长链接 token 改为异步生成，确保签名完整性
  - `ImportPlanPage` 长链接解析改为异步解密，启用签名验证
- **短链 hideSensitive 同步修复**
  - 用户切换"隐藏成品信息"开关后，短链对应的 `hide_sensitive` 值实时同步到数据库
  - 纺织厂通过短链导入时，敏感信息显示状态与采购商当前设置一致
- **已知未修复问题**
  - `production_plans` SELECT RLS 策略过于宽松：任何登录用户可通过 `plan_factories` 存在关联这一条件查看计划详情，存在数据泄露风险
- **导入流程修复**
  - 导入成功后跳转到计划总览而非 Dashboard，确保用户能立即看到导入的计划
  - 纺织厂计划总览添加 `plan_factories` Realtime 订阅，导入新计划后自动刷新
- **分享链接失效机制**
  - `share_links` 表新增 `used_at` 字段，导入成功后标记短链为已使用
  - 解析短链时检查 `used_at`，已使用的链接显示"链接已失效"提示
  - 防止同一分享链接被重复导入

### 2025-05-28 (v1.0.3)
- **原料纱仓库出入库记录功能**
  - 创建 `yarn_stock_records` 表，记录原料纱出入库历史
  - 采纱环节自动记录出库，关联到对应生产计划
  - 原料纱入库时自动记录入库
  - 原料纱仓库页面新增"出入库记录"标签页
  - 显示出入库类型、数量、关联计划、时间等信息
- **采纱环节优化**
  - 添加自动/手动分配模式切换
  - 自动匹配失败时提示切换到手动分配
  - 手动模式支持输入实际使用纱线名称和重量
  - 确认时显示实际消耗统计（各纱线用量+总计）
  - 库存不足时强制阻止确认，必须先补充库存
- **Bug 修复**
  - 修复纱线占比显示为10000%的问题

### 2025-05-27 (v1.0.2)
- **账号管理页面帮助系统集成**
  - 新增"帮助与支持"卡片区域，集成用户手册、用户反馈、关于窗口
  - 用户手册：详细使用指南，支持搜索功能
  - 用户反馈：支持提交问题或建议到数据库
  - 关于窗口：显示版本号 v1.0.2、版权信息、技术支持联系方式
- **帮助系统组件完善**
  - 内置帮助中心（F1快捷键）：功能介绍、常见操作步骤、快捷键列表
  - 新手指引：首次登录自动弹窗，引导完成关键设置
  - 工具提示：所有按钮悬停显示功能说明
  - 版本更新检查：自动检测新版本，仅弹窗一次
  - 崩溃报告系统：全局错误监听，自动收集错误日志
- **通知中心主题色适配**
  - 采购商工作台：琥珀色主题（bg-amber-100/text-amber-700）
  - 纺织厂工作台：翠绿色主题（bg-emerald-100/text-emerald-700）
  - 水洗厂工作台：紫色主题（bg-purple-100/text-purple-700）
- **计划拒绝功能优化**
  - 使用 localStorage 持久化拒绝状态，跨页面保持同步
  - 被拒绝的计划显示灰色卡片和"已拒绝"标签
  - 被拒绝的计划自动从 Dashboard "最近计划"中移除
  - 每个被拒绝的计划弹窗仅显示一次

### 2025-05-26
- **计划详情字段完善**
  - 采购商和纺织厂计划总览页面统一显示所有技术字段
  - 新增显示字段：克重、经线克重、纬线克重、总克重、生产采购价、产品图片、纱线配比、每米纱用量
  - 新增时间字段：创建时间、计划开始时间
  - 新增备注字段显示
  - 纺织厂页面隐藏敏感信息（成品名称、颜色、色号）以保护采购商数据
- **移动端 UI 优化**
  - 计划卡片移动端适配：缩小图片尺寸（64x64）、字体调整为 text-xs
  - 字段标签简化（如"计划编号:"→"编号:"）
  - 网格布局优化，避免内容溢出
  - 所有工作台退出按钮在移动端变为图标形式（LogOut图标）
- **拒绝计划功能增强**
  - 纺织厂拒绝计划后立即显示灰色卡片和"已拒绝"标签
  - 被拒绝的计划自动折叠
  - 被拒绝的计划从 Dashboard "最近计划"中消失
  - 使用 localStorage 持久化拒绝状态，跨页面保持同步

### 2025-05-25
- **产品图片上传功能**
  - 为采购商产品信息管理添加图片上传功能
  - 支持在产品创建和编辑时上传产品图片（JPG、PNG格式，最大5MB）
  - 产品列表展示40x40px缩略图，无图片时显示默认占位图标
  - 产品表单支持图片预览、重新上传和删除功能
  - 使用 Supabase Storage `product_images` 存储桶存储图片
  - 数据库 `products` 表新增 `image_url` 字段
- **UI 优化**
  - 纺织厂工作台"原坯布仓库"更名为"已生产坯布"（页面标题和首页快捷操作）

### 2025-05-24
- **新增出入库历史功能**
  - 采购商产品信息列表新增"出入库历史"按钮
  - 支持查看每个产品的完整库存变动记录（批号、匹数、米数、时间）
  - 桌面端和移动端均支持
- **类型系统优化**
  - 修复 `ProductInRecord` 类型定义，与数据库表结构保持一致
  - 区分数据库必需字段和前端展示扩展字段
- **新增组件**
  - `OutboundForm.tsx` - 出库表单组件
  - `PlanEditModal.tsx` - 计划编辑弹窗
  - `NotificationCenter.tsx` - 通知中心
  - `NetworkStatusBar.tsx` - 网络状态栏
  - `VirtualList.tsx` - 虚拟列表组件
  - `ErrorBoundary.tsx` - 错误边界组件

### 2025-05-23
- 优化纺织厂工作台UI动画流畅度
- 全面适配移动端，优化触控体验
- 添加实时数据订阅，入库记录自动更新
- 优化坯布入库输入框布局
- 修复采购商仓库管理数据同步问题
- 创建统一的入库记录弹窗组件 `InventoryRecordsModal`

### 2025-05-22
- 项目初始化
- 完成基础架构搭建
- 实现用户认证系统
- 完成数据库设计和迁移

## 测试

### 类型检查
```bash
pnpm run typecheck
```

### 代码规范
```bash
pnpm run lint
```

### 构建验证
```bash
pnpm run build
```

## CI/CD 配置

项目使用 GitHub Actions 进行持续集成和部署：

### 工作流配置
```yaml
# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: pnpm/action-setup@v2
        with:
          version: 8
      - uses: actions/setup-node@v3
        with:
          node-version: 18
          cache: 'pnpm'
      - run: pnpm install
      - run: pnpm run typecheck
      - run: pnpm run lint
      - run: pnpm run build
```

## 环境变量配置

项目使用以下环境变量：

### 开发环境 (.env.local)
```env
# Supabase 配置
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key

# 应用配置
VITE_APP_NAME=昱森（Demo版）
VITE_APP_VERSION=2.1.0
```

### 生产环境
生产环境变量通过 CI/CD 流水线注入，请勿在代码中硬编码敏感信息。

## 数据架构（2026-06-04 更新）

### 数据库概览

共 **31张业务表**，按功能分为6大模块：

| 模块 | 表数量 | 核心表 |
|------|--------|--------|
| 用户与权限 | 4 | companies, profiles, company_members, company_relationships |
| 生产计划 | 5 | production_plans, plan_factories, yarn_ratios, plan_process_steps, washing_plans |
| 库存管理 | 8 | products, warehouses, inventory_records, product_inventory_records, yarn_stock, yarn_stock_records, finished_products, finished_product_inventory_records |
| 财务结算 | 5 | payments, accounts_payable, accounts_payable_items, production_price_history, product_price_history |
| 分享与协作 | 2 | share_links, notifications |
| 系统辅助 | 7 | audit_logs, user_feedback, crash_reports, product_yarn_ratios, product_outbound_records, washing_plan_completions, washing_process_steps |

### ER 关系图

```
auth.users (Supabase内置)
    │
    ├── 1:1 ── profiles (用户配置, master_id支持子账号)
    │              │
    │              ├── N:1 ── companies (公司, role:purchaser/textile/washing)
    │              │              │
    │              │              ├── 1:N ── company_members (公司成员)
    │              │              │
    │              │              ├── 1:N ── warehouses (仓库)
    │              │              │              └── 1:N ── inventory_records / yarn_stock
    │              │              │
    │              │              ├── 1:N ── products (产品信息)
    │              │              │              ├── 1:N ── product_inventory_records
    │              │              │              ├── 1:N ── product_yarn_ratios
    │              │              │              └── 1:N ── product_price_history
    │              │              │
    │              │              └── N:M ── company_relationships (合作关系)
    │              │
    │              ├── 1:N ── production_plans (生产计划)
    │              │              ├── 1:N ── plan_factories (关联工厂)
    │              │              ├── 1:N ── yarn_ratios (纱线配比)
    │              │              ├── 1:N ── plan_process_steps (流程节点)
    │              │              ├── 1:N ── inventory_records (入库记录)
    │              │              ├── 1:N ── payments (结款)
    │              │              └── 1:N ── production_price_history
    │              │
    │              └── 1:N ── washing_plans (水洗计划)
    │                             ├── 1:N ── washing_process_steps
    │                             ├── 1:N ── washing_plan_completions
    │                             └── 1:N ── finished_products
```

### 表结构详细设计（31张表）

#### 一、用户与权限模块

**companies** - 公司表 (12条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| name | TEXT NOT NULL | 公司名称 |
| role | app_role NOT NULL | purchaser/textile/washing |
| address | TEXT | 公司地址 |
| contact_phone | TEXT | 联系电话 |
| created_at | TIMESTAMPTZ | now() |

**profiles** - 用户配置表 (8条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | 关联 auth.users.id |
| username | TEXT NOT NULL UNIQUE | 用户名 |
| phone | TEXT | 手机号 |
| company_id | UUID FK | 所属公司 |
| is_master | BOOLEAN NOT NULL | 是否主账号，默认true |
| master_id | UUID FK | 主账号ID（子账号使用） |
| display_name | TEXT | 显示名称 |
| image_url | TEXT | 头像URL |
| created_at | TIMESTAMPTZ | now() |

**company_members** - 公司成员表 (3条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| company_id | UUID FK NOT NULL | 公司ID |
| user_id | UUID FK NOT NULL | 用户ID |
| role | TEXT NOT NULL | 成员角色，默认'member' |
| created_at | TIMESTAMPTZ | now() |

**company_relationships** - 公司合作关系表 (2条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| purchaser_company_id | UUID FK NOT NULL | 采购商公司ID |
| factory_company_id | UUID FK NOT NULL | 工厂公司ID |
| factory_type | factory_type NOT NULL | textile/washing |
| status | TEXT NOT NULL | active/inactive，默认'active' |
| created_at / updated_at | TIMESTAMPTZ | 时间戳 |

#### 二、生产计划模块

**production_plans** - 生产计划表 (3条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| plan_code | TEXT NOT NULL UNIQUE | 计划编号 |
| product_name | TEXT NOT NULL | 成品名称 |
| color | TEXT NOT NULL | 颜色 |
| fabric_code | TEXT NOT NULL | 坯布识别码 |
| color_code | TEXT NOT NULL | 色号，默认'01' |
| remark | TEXT | 备注 |
| purchaser_id | UUID FK NOT NULL | 采购商公司ID |
| target_quantity | INTEGER NOT NULL | 计划产量(米)，默认0 |
| completed_quantity | INTEGER NOT NULL | 已完成产量(米)，默认0 |
| yarn_usage_per_meter | NUMERIC | 每米纱用量(g/m)，默认0 |
| production_price | NUMERIC | 生产采购价(元/米)，默认0 |
| status | plan_status NOT NULL | pending/producing/completed |
| start_time | TIMESTAMPTZ | 计划开始时间 |
| created_by | UUID FK | 创建人 |
| created_at / updated_at | TIMESTAMPTZ | now() |

**plan_factories** - 计划工厂关联表 (3条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| plan_id | UUID FK NOT NULL | 计划ID |
| factory_id | UUID FK NOT NULL | 工厂公司ID |
| factory_type | factory_type NOT NULL | textile/washing |
| created_at | TIMESTAMPTZ | now() |

**yarn_ratios** - 纱线配比表 (2条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| plan_id | UUID FK NOT NULL | 计划ID |
| yarn_name | TEXT NOT NULL | 纱线名称 |
| ratio | NUMERIC NOT NULL | 配比比例，默认1 |
| amount_per_meter | NUMERIC NOT NULL | 每米用量(g/m) |
| total_amount | NUMERIC NOT NULL | 总用纱量 |
| company_id | UUID FK | 公司ID |
| yarn_type | TEXT | 纱线类型，默认'all' |
| created_at | TIMESTAMPTZ | now() |

**plan_process_steps** - 计划流程节点表 (15条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| plan_id | UUID FK NOT NULL | 计划ID |
| step_type | step_type NOT NULL | confirm/yarn_purchase/dyeing/machine_start/fabric_warehouse |
| status | step_status NOT NULL | pending/active/completed/rejected |
| timestamp | TIMESTAMPTZ | 确认时间戳 |
| operator_id | UUID FK | 操作人 |
| notes | TEXT | 备注 |
| company_id | UUID FK | 公司ID |
| created_at | TIMESTAMPTZ | now() |

**washing_plans** - 水洗计划表 (1条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| plan_code | TEXT NOT NULL | 水洗计划编号 |
| company_id | UUID FK NOT NULL | 采购商公司ID |
| product_id | UUID FK NOT NULL | 产品ID |
| washing_factory_id | UUID FK | 水洗厂公司ID |
| planned_meters | NUMERIC NOT NULL | 计划水洗米数 |
| washing_price | NUMERIC NOT NULL | 水洗单价(元/米) |
| estimated_shrinkage_rate | NUMERIC NOT NULL | 预估缩水率(%) |
| estimated_washed_meters | NUMERIC | 预估洗后米数(自动计算) |
| estimated_total_cost | NUMERIC | 预估总费用(自动计算) |
| actual_shrinkage_rate | NUMERIC | 实际缩水率(%) |
| actual_washed_meters | NUMERIC | 实际洗后米数 |
| actual_total_cost | NUMERIC | 实际总费用 |
| washing_date | DATE | 水洗日期 |
| status | TEXT NOT NULL | pending/in_progress/completed |
| notes | TEXT | 备注 |
| created_by | UUID FK | 创建人 |
| created_at / updated_at | TIMESTAMPTZ | now() |

#### 三、库存管理模块

**products** - 产品信息表 (9条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| company_id | UUID FK NOT NULL | 所属公司 |
| product_name | TEXT NOT NULL | 产品名称 |
| weight | NUMERIC NOT NULL | 克重(g) |
| color | TEXT NOT NULL | 颜色 |
| fabric_code | TEXT NOT NULL | 坯布码 |
| color_code | TEXT NOT NULL | 色号，默认'01' |
| yarn_usage_per_meter | NUMERIC NOT NULL | 每米纱用量 |
| yarn_types | TEXT[] | 纱线类型数组 |
| yarn_ratios | NUMERIC[] | 纱线配比数组 |
| raw_fabric_rolls | INTEGER NOT NULL | 坯布匹数 |
| raw_fabric_meters | NUMERIC NOT NULL | 坯布米数 |
| total_stock | NUMERIC NOT NULL | 总库存 |
| production_price | NUMERIC | 生产价格 |
| image_url | TEXT | 产品图片URL |
| warp_weight | NUMERIC | 经线克重 |
| weft_weight | NUMERIC | 纬线克重 |
| total_weight | NUMERIC | 总克重 |
| created_at / updated_at | TIMESTAMPTZ | now() |

**warehouses** - 仓库表 (5条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| company_id | UUID FK NOT NULL | 所属公司 |
| name | TEXT NOT NULL | 仓库名称 |
| type | warehouse_type NOT NULL | raw_fabric/fabric/finished/yarn |
| location | TEXT | 仓库位置 |
| created_at | TIMESTAMPTZ | now() |

**inventory_records** - 入库记录表 (0条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| plan_id | UUID FK NOT NULL | 关联计划ID |
| warehouse_id | UUID FK NOT NULL | 仓库ID |
| quantity | NUMERIC NOT NULL | 入库米数 |
| rolls | INTEGER | 入库匹数 |
| warehouse_location | TEXT | 库位 |
| operator_id | UUID FK | 操作人 |
| company_id | UUID FK | 公司ID |
| price_per_meter | NUMERIC | 单价 |
| price_note | TEXT | 价格备注 |
| created_at | TIMESTAMPTZ | now() |

**product_inventory_records** - 产品出入库记录表 (4条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| product_id | UUID FK NOT NULL | 产品ID |
| warehouse_id | UUID FK | 仓库ID |
| batch_no | TEXT NOT NULL | 批号 |
| rolls | INTEGER NOT NULL | 匹数 |
| meters | NUMERIC NOT NULL | 米数 |
| operator_id | UUID FK | 操作人 |
| notes | TEXT | 备注 |
| company_id | UUID FK | 公司ID |
| created_at | TIMESTAMPTZ | now() |

**yarn_stock** - 纱线库存表 (4条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| company_id | UUID FK NOT NULL | 所属公司 |
| warehouse_id | UUID FK | 仓库ID |
| name | TEXT NOT NULL | 纱线名称 |
| spec | TEXT | 规格 |
| quantity | NUMERIC NOT NULL | 库存数量(kg) |
| min_stock | NUMERIC NOT NULL | 最低库存预警(kg) |
| unit | TEXT NOT NULL | 单位，默认'kg' |
| updated_at | TIMESTAMPTZ | now() |

**yarn_stock_records** - 纱线出入库记录表 (0条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| company_id | UUID FK NOT NULL | 公司ID |
| yarn_stock_id | UUID FK | 纱线库存ID |
| plan_id | UUID FK | 关联计划ID |
| record_type | TEXT NOT NULL | in/out |
| quantity | NUMERIC NOT NULL | 数量(kg) |
| unit | TEXT NOT NULL | 单位，默认'kg' |
| batch_no | TEXT | 批号 |
| notes | TEXT | 备注 |
| operator_id | UUID FK | 操作人 |
| created_at | TIMESTAMPTZ | now() |

**finished_products** - 成品表 (0条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| company_id | UUID FK NOT NULL | 所属公司 |
| washing_plan_id | UUID FK | 水洗计划ID |
| product_id | UUID FK | 产品ID |
| product_name / color / fabric_code / color_code | TEXT | 产品信息 |
| weight | NUMERIC | 克重 |
| washed_meters | NUMERIC NOT NULL | 洗后米数 |
| shrinkage_rate | NUMERIC NOT NULL | 缩水率 |
| rolls | INTEGER | 匹数 |
| stock_meters / stock_rolls | NUMERIC/INTEGER | 库存 |
| warehouse_id / warehouse_location | UUID/TEXT | 仓库信息 |
| washing_cost / unit_cost | NUMERIC | 成本 |
| status | TEXT NOT NULL | in_stock/out_of_stock |
| created_at / updated_at | TIMESTAMPTZ | now() |

**finished_product_inventory_records** - 成品出入库记录表 (0条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| company_id | UUID FK NOT NULL | 公司ID |
| finished_product_id | UUID FK NOT NULL | 成品ID |
| record_type | TEXT NOT NULL | in/out |
| rolls / meters | INTEGER/NUMERIC | 数量 |
| washing_completion_id | UUID FK | 水洗完成记录ID |
| related_order_id / related_order_type | UUID/TEXT | 关联订单 |
| warehouse_id / warehouse_location | UUID/TEXT | 仓库信息 |
| batch_no / notes | TEXT | 批号/备注 |
| operator_id | UUID FK | 操作人 |
| created_at | TIMESTAMPTZ | now() |

#### 四、财务结算模块

**payments** - 结款记录表 (0条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| plan_id | UUID FK NOT NULL | 关联计划ID |
| from_company_id | UUID FK NOT NULL | 付款方 |
| to_company_id | UUID FK NOT NULL | 收款方 |
| amount | NUMERIC NOT NULL | 结款金额 |
| quantity | NUMERIC NOT NULL | 结款数量(米) |
| price_per_meter | NUMERIC NOT NULL | 单价 |
| status | payment_status NOT NULL | pending/completed |
| paid_at | TIMESTAMPTZ | 结款时间 |
| created_at | TIMESTAMPTZ | now() |

**accounts_payable** - 应付账款表 (0条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| plan_id | UUID FK NOT NULL | 计划ID |
| purchaser_id | UUID FK NOT NULL | 采购商ID |
| textile_factory_id | UUID FK NOT NULL | 纺织厂ID |
| total_amount / paid_amount / unpaid_amount | NUMERIC | 金额统计 |
| total_quantity / paid_quantity / unpaid_quantity | NUMERIC | 数量统计 |
| price_per_meter | NUMERIC NOT NULL | 单价 |
| status | TEXT NOT NULL | unpaid/partial/paid |
| created_at / updated_at | TIMESTAMPTZ | now() |

**accounts_payable_items** - 应付账款明细表 (0条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| accounts_payable_id | UUID FK NOT NULL | 应付账款ID |
| inventory_record_id | UUID FK | 入库记录ID |
| quantity / rolls / price_per_meter / amount | NUMERIC/INTEGER | 明细数据 |
| status | TEXT NOT NULL | unpaid/paid |
| payment_id | UUID FK | 关联结款ID |
| created_at / paid_at | TIMESTAMPTZ | 时间戳 |

**production_price_history** - 生产价格变更历史 (3条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| plan_id | UUID FK NOT NULL | 计划ID |
| old_price / new_price / change_amount | NUMERIC NOT NULL | 价格变更 |
| operator_id / operator_name | UUID/TEXT | 操作人 |
| change_reason | TEXT | 变更原因 |
| created_at | TIMESTAMPTZ | now() |

**product_price_history** - 产品价格变更历史 (3条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| product_id | UUID FK NOT NULL | 产品ID |
| company_id | UUID FK NOT NULL | 公司ID |
| old_price / new_price / change_amount | NUMERIC NOT NULL | 价格变更 |
| operator_id / operator_name | UUID/TEXT | 操作人 |
| change_reason | TEXT | 变更原因 |
| created_at | TIMESTAMPTZ | now() |

#### 五、分享与协作模块

**share_links** - 分享链接表 (2条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| short_code | TEXT NOT NULL | 短码 |
| plan_id | UUID FK NOT NULL | 计划ID |
| factory_type | TEXT NOT NULL | textile/washing |
| created_by | UUID FK NOT NULL | 创建人 |
| expires_at | TIMESTAMPTZ | 过期时间 |
| click_count | INTEGER | 点击次数，默认0 |
| hide_sensitive | BOOLEAN | 隐藏敏感信息，默认false |
| used_at | TIMESTAMPTZ | 使用时间 |
| status | TEXT NOT NULL | pending/clicked/confirmed/rejected/expired/cancelled |
| clicked_at / responded_at | TIMESTAMPTZ | 时间戳 |
| response_result | TEXT | confirmed/rejected |
| reject_reason | TEXT | 拒绝原因 |
| created_at | TIMESTAMPTZ | now() |

**notifications** - 通知表 (4条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| recipient_id | UUID FK NOT NULL | 接收人 |
| sender_id / sender_company_id | UUID FK | 发送人/公司 |
| plan_id | UUID FK | 关联计划 |
| type | TEXT NOT NULL | 通知类型 |
| title / content | TEXT NOT NULL | 标题/内容 |
| is_read | BOOLEAN | 已读标记，默认false |
| created_at / read_at | TIMESTAMPTZ | 时间戳 |

#### 六、系统辅助模块

**audit_logs** - 审计日志表 (0条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| user_id / company_id | UUID FK | 用户/公司 |
| action | TEXT NOT NULL | 操作类型 |
| resource_type / resource_id | TEXT/UUID | 资源类型/ID |
| details | JSONB | 详细信息 |
| ip_address / user_agent | TEXT | 请求信息 |
| created_at | TIMESTAMPTZ | now() |

**user_feedback** - 用户反馈表 (0条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| type | TEXT NOT NULL | 反馈类型 |
| content | TEXT NOT NULL | 反馈内容 |
| contact | TEXT | 联系方式 |
| user_id | UUID FK | 用户ID |
| status | TEXT NOT NULL | pending/resolved |
| created_at / updated_at | TIMESTAMPTZ | now() |

**crash_reports** - 崩溃报告表 (0条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| error_message | TEXT NOT NULL | 错误信息 |
| error_stack / component_stack | TEXT | 堆栈信息 |
| user_description | TEXT | 用户描述 |
| user_agent / url | TEXT | 环境信息 |
| user_id | UUID FK | 用户ID |
| status | TEXT NOT NULL | pending/resolved |
| created_at / updated_at | TIMESTAMPTZ | now() |

**product_yarn_ratios** - 产品纱线配比表 (13条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| product_id | UUID FK NOT NULL | 产品ID |
| yarn_name | TEXT NOT NULL | 纱线名称 |
| ratio | NUMERIC NOT NULL | 配比 |
| yarn_type | TEXT | 纱线类型，默认'all' |
| created_at | TIMESTAMPTZ | now() |

**product_outbound_records** - 产品出库记录表 (1条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| product_id | UUID FK NOT NULL | 产品ID |
| company_id | UUID FK | 公司ID |
| batch_no | TEXT NOT NULL | 批号 |
| rolls / meters | INTEGER/NUMERIC | 数量 |
| washing_plan_id | UUID FK | 水洗计划ID |
| outbound_type | TEXT NOT NULL | manual/auto |
| source_batch_id | UUID FK | 源批次ID |
| recipient_company_id / recipient_company_name | UUID/TEXT | 接收方 |
| notes / operator_id | TEXT/UUID | 备注/操作人 |
| created_at | TIMESTAMPTZ | now() |

**washing_plan_completions** - 水洗完成记录表 (0条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| company_id | UUID FK NOT NULL | 公司ID |
| washing_plan_id | UUID FK NOT NULL | 水洗计划ID |
| actual_washed_meters / actual_shrinkage_rate | NUMERIC NOT NULL | 实际数据 |
| rolls | INTEGER NOT NULL | 匹数 |
| washing_date | DATE NOT NULL | 水洗日期 |
| actual_washing_cost / unit_cost | NUMERIC | 成本 |
| warehouse_id / warehouse_location | UUID/TEXT | 仓库 |
| auto_imported | BOOLEAN | 自动导入标记 |
| finished_product_id | UUID FK | 成品ID |
| completed_by / completed_at | UUID/TIMESTAMPTZ | 完成人/时间 |
| created_at | TIMESTAMPTZ | now() |

**washing_process_steps** - 水洗流程节点表 (0条)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | UUID PK | gen_random_uuid() |
| washing_plan_id | UUID FK NOT NULL | 水洗计划ID |
| company_id | UUID FK NOT NULL | 公司ID |
| step_type | TEXT NOT NULL | 步骤类型 |
| status | TEXT NOT NULL | pending/completed |
| timestamp | TIMESTAMPTZ | 确认时间 |
| operator_id | UUID FK | 操作人 |
| notes | TEXT | 备注 |
| created_at / updated_at | TIMESTAMPTZ | now() |

### 自定义枚举类型

```sql
-- 应用角色（公司类型）
CREATE TYPE app_role AS ENUM ('purchaser', 'textile', 'washing');

-- 工厂类型
CREATE TYPE factory_type AS ENUM ('textile', 'washing');

-- 计划状态
CREATE TYPE plan_status AS ENUM ('pending', 'producing', 'completed');

-- 流程节点类型
CREATE TYPE step_type AS ENUM ('confirm', 'yarn_purchase', 'dyeing', 'machine_start', 'fabric_warehouse');

-- 流程节点状态
CREATE TYPE step_status AS ENUM ('pending', 'active', 'completed', 'rejected');

-- 仓库类型
CREATE TYPE warehouse_type AS ENUM ('raw_fabric', 'fabric', 'finished', 'yarn');

-- 结款状态
CREATE TYPE payment_status AS ENUM ('pending', 'completed');
```

### RLS 策略

所有表启用 Row Level Security，基于 `company_id` + `get_user_master_company_id()` 进行数据隔离：

```sql
-- 示例：production_plans 表 RLS 策略
CREATE POLICY company_select_plans ON production_plans
  FOR SELECT USING (purchaser_id = get_user_master_company_id());

CREATE POLICY company_insert_plans ON production_plans
  FOR INSERT WITH CHECK (purchaser_id = get_user_master_company_id());
```

### API 调用示例

**查询计划列表**
```typescript
const { data } = await supabase
  .from('production_plans')
  .select('*')
  .eq('purchaser_id', companyId)
  .order('created_at', { ascending: false });
```

**创建入库记录**
```typescript
await supabase.from('inventory_records').insert({
  plan_id: planId,
  warehouse_id: warehouseId,
  quantity: quantity,
  rolls: rolls,
  company_id: companyId,
  operator_id: userId
});
```

**实时订阅库存更新**
```typescript
// 使用单例管理器（推荐）
import { useInventoryRealtime } from '../hooks/useRealtime';
useInventoryRealtime(companyId, onDataChange);

// 或直接订阅
supabase
  .channel('inventory_changes')
  .on('postgres_changes', {
    event: '*', schema: 'public', table: 'inventory_records'
  }, callback)
  .subscribe();
```

**分享链接加密**
```typescript
import { encryptShareParams, decryptShareParams } from '../utils/shareCrypto';

// 生成加密链接（HMAC-SHA256签名）
const token = await encryptShareParams(planId, factoryType, hideSensitive);

// 解密验证
const result = await decryptShareParams(token);
// result: { planId, factoryType, hideSensitive } | null
```

## 许可证

MIT License

## 技术支持

如有问题或建议，请联系开发团队。

---

## 常见问题与解决方案

### Q1: 页面白屏/无法加载
**可能原因**：
- Webpack 热更新失败
- 类型检查错误阻止构建
- 环境变量配置错误

**解决方案**：
```bash
# 1. 清除缓存重新构建
rm -rf node_modules dist
pnpm install
pnpm run dev

# 2. 检查类型错误
pnpm run typecheck

# 3. 检查环境变量
cat .env.local
```

### Q2: 数据无法保存/读取
**可能原因**：
- RLS 策略限制
- 网络连接问题
- 权限不足

**解决方案**：
```bash
# 1. 检查云服务状态
meoo-cli cloud status

# 2. 检查 RLS 策略
meoo-cli cloud query --sql "\dt"
meoo-cli cloud query --sql "SELECT * FROM pg_policies WHERE tablename = 'your_table'"

# 3. 检查用户权限
meoo-cli cloud query --sql "SELECT * FROM profiles WHERE id = 'your-user-id'"
```

### Q3: 移动端样式错乱
**可能原因**：
- Tailwind 配置问题
- 响应式断点使用错误
- CSS 未正确加载

**解决方案**：
```bash
# 1. 检查 Tailwind 配置
cat tailwind.config.js

# 2. 检查 PostCSS 配置
cat postcss.config.js

# 3. 重新构建样式
pnpm run build
```

### Q4: 实时数据不更新
**可能原因**：
- Realtime 未启用
- 订阅配置错误
- 网络问题

**解决方案**：
```typescript
// 检查订阅是否正确设置
const channel = supabase
  .channel('table_changes')
  .on('postgres_changes', {
    event: '*',
    schema: 'public',
    table: 'your_table'
  }, (payload) => {
    console.log('Change received:', payload);
  })
  .subscribe((status) => {
    console.log('Subscription status:', status);
  });
```

### Q5: 开发服务器预览加载失败（沙箱环境）
**现象**：
- `pnpm run dev` 启动正常，端口 3015 在监听
- 但浏览器预览无法加载，curl 请求超时

**根本原因**：
- 沙箱环境网络限制：`net.ipv4.conf.all.forwarding = 0`
- Webpack devServer 配置不当：`host: '127.0.0.1'` 无法在沙箱访问

**解决方案**：
```javascript
// webpack.config.js - 正确配置
devServer: {
  port: 3015,
  host: '0.0.0.0',  // 必须使用 0.0.0.0
  allowedHosts: 'all',
  hot: true,
  historyApiFallback: true,
  // 不要配置 static 和 devMiddleware
}
```

**验证方法**：
```bash
# 1. 类型检查
pnpm run typecheck

# 2. 构建验证（关键）
pnpm run build

# 3. 检查产物
ls -la dist/

# 4. 启动服务器（沙箱中预览可能受限，但构建成功即可部署）
pnpm run dev
```

**注意**：沙箱环境中 curl 可能仍超时，这不影响实际部署。只要 `pnpm run build` 成功，应用即可正常发布。

---

## 性能优化建议

### 1. 图片优化
- 使用 WebP 格式
- 实现懒加载
- 使用 CDN 加速

### 2. 代码分割
```typescript
// 使用 React.lazy 进行代码分割
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));

function App() {
  return (
    <Suspense fallback={<Loading />}>
      <HeavyComponent />
    </Suspense>
  );
}
```

### 3. 数据缓存
```typescript
// 使用 SWR 或 React Query 进行数据缓存
import useSWR from 'swr';

const { data, error } = useSWR('/api/data', fetcher, {
  revalidateOnFocus: false,
  dedupingInterval: 5000
});
```

### 4. 虚拟列表
对于大数据列表，使用虚拟列表组件避免渲染过多 DOM 节点。

---

## 安全最佳实践

### 1. 输入验证
```typescript
// 始终验证用户输入
const validateInput = (input: string): boolean => {
  // 防止 XSS
  const xssPattern = /<script|javascript:|onerror=/i;
  if (xssPattern.test(input)) return false;

  // 防止 SQL 注入（虽然 Supabase 已防护）
  const sqlPattern = /(\b(SELECT|INSERT|UPDATE|DELETE|DROP|CREATE)\b)/i;
  if (sqlPattern.test(input)) return false;

  return true;
};
```

### 2. 敏感数据处理
```typescript
// 不要在客户端暴露敏感信息
// ❌ 错误
const apiKey = 'sk-live-xxx';

// ✅ 正确 - 使用环境变量
const apiKey = process.env.VITE_API_KEY;
```

### 3. 认证检查
```typescript
// 每个需要认证的页面都添加检查
useEffect(() => {
  const checkAuth = async () => {
    const { data: { user } } = await supabase.auth.getUser();
    if (!user) {
      navigate('/login');
    }
  };
  checkAuth();
}, []);
```

---

## 贡献指南

### 提交代码
1. Fork 项目
2. 创建功能分支 (`git checkout -b feature/xxx`)
3. 提交更改 (`git commit -m 'Add xxx'`)
4. 推送到分支 (`git push origin feature/xxx`)
5. 创建 Pull Request

### 代码规范
- 使用 TypeScript 严格模式
- 遵循 ESLint 规则
- 编写单元测试
- 更新相关文档

### 提交信息规范
```
feat: 新增功能
fix: 修复 bug
docs: 文档更新
style: 代码格式调整
refactor: 重构代码
test: 测试相关
chore: 构建/工具相关
```
