The file /home/project/AGENTS.md has been updated. Made 1 replacement. Here's the result of running `cat -n` on a snippet of the edited file: 466→- **UI 优化** 467→ - 纺织厂工作台"原坯布仓库"更名为"已生产坯布" 468→ - 更新首页快捷操作按钮标签 469→ 470→## Bug 修复记录 471→ 472→### 2025-05-26 计划字段显示不一致问题 473→ 474→#### 问题描述 475→采购商和纺织厂的计划总览页面显示字段不一致,纺织厂缺少克重、纱线配比、生产采购价等关键字段。 476→ 477→#### 根本原因 478→- `usePlanData.ts` Hook 未查询 `products` 表关联数据 479→- `PlanGroup.tsx` 组件未展示 weight、yarn_ratios、production_price 等字段 480→- 纺织厂 `PlanOverview.tsx` 缺少展开详情视图 481→ 482→#### 修复方案 483→1. **数据层**:在 `usePlanData.ts` 中添加 products 表查询,获取 weight、image_url 等字段 484→2. **组件层**:在 `PlanGroup.tsx` 中添加完整字段展示,包括: 485→ - 克重信息(经线/纬线/总克重) 486→ - 纱线配比列表 487→ - 生产采购价 488→ - 产品图片 489→ - 创建时间、计划开始时间、备注 490→3. **页面层**:纺织厂 `PlanOverview.tsx` 添加展开详情功能,与采购商保持一致 491→ 492→#### 代码变更 493→- `src/hooks/usePlanData.ts` - 添加 products 表关联查询 494→- `src/components/plans/PlanGroup.tsx` - 扩展字段展示 495→- `src/pages/textile/PlanOverview.tsx` - 添加展开详情视图 496→- `src/pages/purchaser/PlanOverview.tsx` - 同步优化字段展示 497→ 498→#### 经验教训 499→- **数据一致性**:同一业务对象在不同页面的展示应保持一致,仅根据角色权限控制敏感字段 500→- **Hook 复用**:通过统一的数据获取 Hook 确保各页面数据一致性 501→- **类型安全**:扩展类型定义时注意与数据库生成的类型保持兼容 502→ 503→--- 504→ 505→### 2025-05-26 移动端退出按钮适配问题 506→ 507→#### 问题描述 508→工作台右上角退出按钮在移动端显示为"退出登录"文字,占用过多空间,与整体移动端设计不协调。 509→ 510→#### 根本原因 511→- 退出按钮未做响应式适配 512→- 移动端空间宝贵,文字按钮过于拥挤 513→ 514→#### 修复方案 515→使用响应式设计,桌面端显示"退出登录"文字,移动端仅显示 LogOut 图标: 516→```tsx 517→ 521→``` 522→ 523→#### 代码变更 524→- `src/pages/purchaser/Dashboard.tsx` - 退出按钮响应式优化 525→- `src/pages/textile/Dashboard.tsx` - 退出按钮响应式优化 526→- `src/pages/washing/Dashboard.tsx` - 退出按钮响应式优化 527→ 528→--- 529→ 530→### 2025-05-26 拒绝计划状态同步问题 531→ 532→#### 问题描述 533→纺织厂拒绝计划后,计划卡片未立即更新视觉状态,且仍显示在 Dashboard "最近计划"中。 534→ 535→#### 根本原因 536→- 拒绝操作仅更新数据库,未更新本地状态 537→- Dashboard 和 PlanOverview 之间没有共享拒绝状态 538→- 页面刷新后拒绝状态丢失 539→ 540→#### 修复方案 541→1. **本地状态管理**:在 `PlanOverview.tsx` 中使用 `Set` 跟踪被拒绝的计划ID 542→2. **持久化存储**:使用 localStorage 存储拒绝状态,键名为 `textile_rejected_plans` 543→3. **跨页面同步**:Dashboard 从 localStorage 读取拒绝状态并过滤最近计划 544→4. **视觉反馈**:被拒绝的计划显示灰色背景、"已拒绝"标签,并自动折叠 545→ 546→#### 代码变更 547→- `src/pages/textile/PlanOverview.tsx` - 添加 rejectedPlans 状态和 localStorage 持久化 548→- `src/pages/textile/Dashboard.tsx` - 添加 rejectedPlanIds 状态,过滤最近计划 549→ 550→#### 关键代码 551→```typescript 552→// PlanOverview.tsx - 拒绝时持久化 553→const handleRejectStep = async (step: PlanProcessStep) => { 554→ // ... 提交拒绝原因到数据库 ... 555→ 556→ // 更新本地状态 557→ setRejectedPlans(prev => new Set([...prev, step.plan_id])); 558→ 559→ // 持久化到 localStorage 560→ const stored = localStorage.getItem('textile_rejected_plans'); 561→ const rejectedArray = stored ? JSON.parse(stored) : []; 562→ if (!rejectedArray.includes(step.plan_id)) { 563→ rejectedArray.push(step.plan_id); 564→ localStorage.setItem('textile_rejected_plans', JSON.stringify(rejectedArray)); 565→ } 566→}; 567→ 568→// Dashboard.tsx - 读取并过滤 569→useEffect(() => { 570→ // ... 获取计划列表 ... 571→ 572→ // 从 localStorage 读取拒绝状态 573→ const stored = localStorage.getItem('textile_rejected_plans'); 574→ if (stored) { 575→ setRejectedPlanIds(new Set(JSON.parse(stored))); 576→ } 577→}, []); 578→ 579→// 过滤最近计划 580→const filteredPlans = plans.filter(p => !rejectedPlanIds.has(p.id)); 581→const recentPlans = filteredPlans.slice(0, 5); 582→``` 583→ 584→#### 经验教训 585→- **状态共享**:跨页面状态可考虑使用 localStorage、URL 参数或全局状态管理 586→- **乐观更新**:用户操作后应立即更新 UI,再同步后端状态 587→- **数据过滤**:Dashboard 展示的数据应根据业务规则进行过滤,而非直接展示原始数据 588→ 589→--- 590→ 591→### 2025-05-25 TypeScript 类型兼容性问题 592→ 593→#### 问题描述 594→添加图片功能后出现类型错误: 595→``` 596→Types of property 'image_url' are incompatible.