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→<button className="flex items-center gap-2 ...">
 518→  <span className="hidden sm:inline">退出登录</span>
 519→  <LogOut className="w-5 h-5" />
 520→</button>
 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<string>` 跟踪被拒绝的计划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.