# 纺织行业采购计划管理系统 一款专为纺织行业设计的全流程协作管理平台,连接采购商(布行)、纺织厂、水洗厂三方,实现从计划制定到成品交付的数字化管理。 ## 核心功能 ### 多角色协作 - **采购商/布行**:创建生产计划、管理坯布库存、跟踪生产进度、处理结款 - **纺织厂**:接收生产计划、管理生产流程、坯布入库、纱线库存管理 - **水洗厂**:接收水洗订单、管理水洗流程 ### 计划管理 - 自动生成唯一计划编号和坯布识别码 - 纱线配比配置与用量自动计算 - 生产流程节点跟踪(确认计划 → 采纱 → 染纱 → 上机 → 坯布入库) - 实时进度可视化,支持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'; 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行内联弹窗 → `` - `textile/Dashboard.tsx`:~150行内联弹窗 → `` - `washing/Dashboard.tsx`:~150行内联弹窗 → `` - 共减少约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 ( }> ); } ``` ### 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 = / { 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: 构建/工具相关 ```