# 变更日志 (Changelog)

所有重要的项目变更都会记录在此文件中。

## [2026-05-12] 合同续约、Customer Tier 与 Admin Partners 展示优化

### 合同续约流程梳理与管理端展示增强

#### 1. 合同续约规则调整
- **文件**:
  - `backend/controllers/contracts.controller.js`
  - `backend/controllers/auth.controller.js`
  - `frontend/src/pages/Contract.jsx`
  - `frontend/src/pages/Dashboard.jsx`
- **变更**:
  - 将合同进入可续约状态的阈值统一调整为到期前 `30` 天
  - Partner 续约时不再从“当前时间”起算，而是从“当前合同到期日”顺延 `2` 年
  - 续约成功后保留上一份合同的到期信息，前端展示 “Renewed from previous expiry”
  - `Dashboard` 的合同有效期改为优先读取真实 `validUntil`，并为历史空值数据保留兜底逻辑

#### 2. Signed Agreement History 续约状态与详情弹窗
- **文件**:
  - `backend/controllers/contracts.controller.js`
  - `frontend/src/pages/AdminContracts.jsx`
- **变更**:
  - 已被新合同替换的旧协议在管理端状态显示为 `Renewed`
  - Signed Agreement History 支持点击记录弹窗查看签约详情与续约链路
  - 弹窗中增加同一伙伴、同一 program 的历次签约记录展示
  - `Send Reminder` 按钮仍保留为催办用途，不会直接改写合同状态或有效期

#### 3. Signed Agreement History 改为按伙伴分组展示
- **文件**: `frontend/src/pages/AdminContracts.jsx`
- **变更**:
  - 将已签约历史从平铺列表改为按 partner group 聚合展示
  - 同一伙伴的协议放在一起，点击单条记录查看历次签约记录
  - 保留 `Edit Validity` 与 `Send Reminder` 操作，并避免按钮点击误触弹窗

### Customer Tier 功能新增

#### 1. 数据库与后端支持
- **文件**:
  - `database/029_partner_customer_tier.sql`
  - `backend/controllers/admin.controller.js`
  - `backend/controllers/auth.controller.js`
- **变更**:
  - 在 `partner_groups` 新增 `customer_tier` 字段，支持 `Silver` / `Gold` / `Platinum`
  - Partner Group 详情、列表和 `/auth/me` 均返回 `customerTier`
  - 更新 partner group 时支持保存 `customerTier`

#### 2. Admin Partners 与伙伴端展示
- **文件**:
  - `frontend/src/pages/AdminPartners.jsx`
  - `frontend/src/pages/Account.jsx`
  - `frontend/src/components/Layout.jsx`
  - `frontend/src/pages/Dashboard.jsx`
  - `frontend/src/context/AuthContext.jsx`
- **变更**:
  - Admin Partners 列表、详情页标题、Company Information 中增加 `Customer Tier`
  - 伙伴端账户页展示 `Customer Tier`
  - 伙伴端左下角公司名称后增加 `Customer Tier`
  - 伙伴端 Dashboard 公司名后追加 `Customer Tier`
  - 去掉 Tier badge 前置小图标，统一为纯文字 + 颜色展示

### Admin Partners 页面体验优化

#### 1. 列表展示增强与表格布局调整
- **文件**: `frontend/src/pages/AdminPartners.jsx`
- **变更**:
  - Admin Partners 桌面表格新增独立 `Tier` 列
  - 多轮调整 `Company` / `Tier` / `Primary Contact` / `Region` / `Members` / `Opps` / `Status` 列宽
  - 将表格调整为在可视宽度内尽量完整展示，减少或去除横向滚动依赖
  - 优化表头换行、列名对齐和数据密度，避免列名与内容重叠
  - `Status` 列标题改为居中显示

#### 2. PingCAP Sales Assigned 展示增强
- **文件**:
  - `backend/controllers/admin.controller.js`
  - `frontend/src/pages/AdminPartners.jsx`
- **变更**:
  - 后端返回 `pingcapAssignedSalesEmail`
  - 管理端详情、移动卡片、桌面列表统一显示为 `姓名 <邮箱>`

#### 3. 已终止伙伴禁止编辑
- **文件**:
  - `backend/controllers/admin.controller.js`
  - `frontend/src/pages/AdminPartners.jsx`
- **变更**:
  - `Terminated` partner group 不再显示 `Edit Company Info` / `Edit Programs`
  - 详情页增加只读提示
  - 后端禁止更新已终止 partner group，防止绕过前端直接修改

### Task 模块按 Customer Tier 分发

#### 1. 任务目标类型扩展
- **文件**:
  - `database/026_tasks_table.sql`
  - `backend/controllers/task.controller.js`
  - `frontend/src/pages/AdminTasks.jsx`
- **变更**:
  - `tasks.target_type` 新增 `customer_tier`
  - Admin 创建任务时，`Assign To` 增加 `Customer Tier` 选项
  - 支持选择 `Silver` / `Gold` / `Platinum` 进行定向发布
  - Partner 端按所属 partner group 的 `customer_tier` 命中任务
  - 任务详情与列表中增加针对 `Tier` 目标的展示文案

#### 2. Partner 数据源补充
- **文件**: `backend/routes/partners.routes.js`
- **变更**:
  - `/partners/all` 接口增加 `customerTier` 字段，便于任务、列表和后续展示复用

### Dashboard 与伙伴端信息补充

#### 1. PingCAP Sales Contact 邮箱展示
- **文件**:
  - `backend/controllers/auth.controller.js`
  - `frontend/src/pages/Dashboard.jsx`
- **变更**:
  - `/auth/me` 增加 `pingcapAssignedSalesEmail`
  - Dashboard 头部的 `PingCAP Sales Contact` 展示为 `姓名 <邮箱>`

#### 2. Partner News 区块精简
- **文件**: `frontend/src/pages/Dashboard.jsx`
- **变更**:
  - 去掉 `Partner News` 标题右侧的 `Open Collateral` 按钮

### 数据补齐与后台维护

#### 1. 合同与伙伴数据补齐
- **涉及内容**:
  - 补齐历史 partner group 的 `contract_expires_at`
  - 为已批准伙伴随机补齐 `customer_tier`
  - 为已批准伙伴补齐缺失的 `approved_at` 与 `approved_by`
  - 仅为已批准且缺失销售归属的伙伴随机补齐 `PingCAP Sales Assigned`
- **说明**:
  - 以上补齐均基于现有业务字段完成，避免影响未批准或已存在的记录

## [2026-05-12] Admin Management 与 Contract Management 功能增强

### Admin Management 页面导出功能

#### 1. 员工数据导出 CSV
- **文件**: `frontend/src/pages/AdminManagement.jsx`
- **变更**:
  - 添加 "Export CSV" 按钮，位于搜索框右侧
  - 导出字段：Name、Email、Role、Managed Regions
  - 支持导出当前筛选后的员工数据
  - CSV 格式正确处理特殊字符

#### 2. 导出审计日志记录
- **文件**:
  - `backend/controllers/admin.controller.js`
  - `backend/routes/admin.routes.js`
- **变更**:
  - 新增 `logPingcapersExport` 函数记录导出审计日志
  - 新增 `POST /api/admin/pingcapers/export-log` 路由
  - 仅限 admin 角色访问
  - 日志格式：`Exported PingCAP employees data to CSV (X records)`

### Contract Management Signed Agreement History 功能增强

#### 1. 导出 CSV 功能
- **文件**: `frontend/src/pages/AdminContracts.jsx`
- **变更**:
  - 在 Signed Agreement History 标题右侧添加红色 "Export CSV" 按钮
  - 导出字段：Partner、Agreement、Source、Signed Date、Signer、Valid From、Valid Until、Status

#### 2. 导出审计日志记录
- **文件**:
  - `backend/controllers/contracts.controller.js`
  - `backend/routes/contracts.routes.js`
- **变更**:
  - 新增 `logSignedAgreementsExport` 函数记录导出审计日志
  - 新增 `POST /api/contracts/admin/signed-agreements/export-log` 路由
  - 仅限 admin 角色访问
  - 日志格式：`Exported Signed Agreements data to CSV (X records)`

#### 3. 搜索功能
- **文件**: `frontend/src/pages/AdminContracts.jsx`
- **变更**:
  - 在 Signed Agreement History 表格上方添加搜索输入框
  - 支持搜索：Partner、Agreement、Signer Name、Signer Email、Source
  - 实时搜索，输入内容时立即过滤
  - 前端过滤，无需后端接口

### Contract Management 上传表单改为模态框

#### 1. Create 按钮添加
- **文件**: `frontend/src/pages/AdminContracts.jsx`
- **变更**:
  - 页面头部右侧添加红色 "Create" 按钮
  - 点击按钮弹出上传新合同版本的模态框

#### 2. 上传表单模态框化
- **文件**: `frontend/src/pages/AdminContracts.jsx`
- **变更**:
  - 将原来的内嵌表单改为模态框形式
  - 模态框包含 Contract Title、Version、Partner Program 和 PDF File 字段
  - 添加关闭按钮（X）和取消按钮
  - 上传成功后自动关闭模态框

### AdminPartners Export CSV 按钮样式修改

#### 1. 按钮颜色改为红色
- **文件**: `frontend/src/pages/AdminPartners.jsx`
- **变更**:
  - Export CSV 按钮背景色从绿色 `bg-green-600` 改为红色 `bg-pingcap-red`
  - Hover 状态从 `bg-green-700` 改为 `bg-pingcap-red-dark`
  - 与其他 Export CSV 按钮样式保持一致

### Partner Agreements Offline Agreement Renew 问题修复

#### 1. 过滤已被替换的合同记录
- **文件**: `backend/controllers/contracts.controller.js`
- **问题**: Partner 用户 Renew Offline Agreement 时，每次都会创建新的合同记录而不是更新原有记录
- **原因**: `listGroupAssignments` 查询没有过滤已被替换的合同（`replaced_by_assignment_id IS NOT NULL`）
- **修复**: 在查询中添加条件 `AND a.replaced_by_assignment_id IS NULL`，排除已被替换的旧合同记录

### Admin Opportunities 页面样式优化

#### 1. 表格列宽优化
- **文件**: `frontend/src/pages/AdminOpportunities.jsx`
- **变更**:
  - 将固定窄宽度（w-24, w-28）改为最小宽度（min-w-[120px] ~ min-w-[240px]）
  - End User 列宽度增加到 200px 以显示完整内容
  - 确保各列有足够空间显示内容
  - 操作列宽度增加以容纳两个按钮

#### 2. 表格横向滚动
- **文件**: `frontend/src/pages/AdminOpportunities.jsx`
- **变更**:
  - 添加 `overflow-x-auto` 容器支持横向滚动
  - 设置表格最小宽度为 1400px
  - 当内容超出屏幕宽度时自动显示滚动条

#### 3. 表格内容溢出处理
- **文件**: `frontend/src/pages/AdminOpportunities.jsx`
- **变更**:
  - End User 列去掉 `truncate` 限制，使用 `whitespace-normal` 允许换行显示完整内容
  - 其他列保留 `truncate` 防止溢出，添加 `title` 属性悬停查看完整内容
  - 日期列添加 `whitespace-nowrap` 防止换行

#### 4. Export CSV 按钮颜色统一
- **文件**: `frontend/src/pages/AdminOpportunities.jsx`
- **变更**:
  - 按钮背景色从绿色 `bg-green-600` 改为红色 `bg-pingcap-red`
  - Hover 状态从 `bg-green-700` 改为 `bg-pingcap-red-dark`

### AdminContracts All Contract Versions 移除选择框

#### 1. 移除批量选择功能
- **文件**: `frontend/src/pages/AdminContracts.jsx`
- **变更**:
  - 移除表格头部的全选复选框
  - 移除表格行中的选择框
  - 删除 `selected` 和 `bulkActivating` 状态
  - 删除 `toggleSelect`, `toggleSelectAll`, `handleBulkActivate` 函数
  - 移除标题栏的批量操作按钮区域
  - 简化表格行样式（移除选中高亮效果）

---

## [2026-05-11] Task 页面拆分与 Partner 端功能完善

### Tasks 页面拆分

#### 1. AdminTasks 页面创建
- **文件**: `frontend/src/pages/AdminTasks.jsx`
- **变更**:
  - 新建独立的 Admin 端任务管理页面
  - 保留原有 pingcaper 权限操作（创建、编辑、查看详情、删除）
  - 列表展示任务状态、类型、优先级、截止日期、创建者等信息
  - 支持按状态筛选（active/completed/cancelled）

#### 2. PartnerTasks 页面创建
- **文件**: `frontend/src/pages/PartnerTasks.jsx`
- **变更**:
  - 新建独立的 Partner 端任务页面
  - 区分展示待完成和已完成任务
  - 待完成任务按优先级排序（Urgent > High > Medium > Low）
  - 支持点击任务查看详情并标记为完成
  - 过期任务高亮显示提醒

#### 3. 路由配置更新
- **文件**: `frontend/src/App.jsx`
- **变更**:
  - 创建 `TasksRoute` 组件，根据用户角色动态路由
  - `admin`、`regional_admin`、`employee` 角色 → 路由到 `AdminTasks` 页面
  - `partner` 角色 → 路由到 `PartnerTasks` 页面

### Partner 端任务功能完善

#### 1. 标签切换功能
- **文件**: `frontend/src/pages/PartnerTasks.jsx`
- **变更**:
  - 在任务列表上方添加两个可点击标签（To Do / Completed）
  - 每个标签右侧显示对应类别的任务数量
  - 点击标签可切换显示对应类别的任务
  - 空状态时显示友好提示信息

#### 2. 已完成任务详情面板优化
- **文件**: `frontend/src/pages/PartnerTasks.jsx`
- **变更**:
  - 已完成任务去掉输入框，展示之前填写的 completionNotes
  - 去掉取消按钮，仅保留 Close 按钮
  - 完成时间显示具体时分秒（使用 `toLocaleString()`）
  - 去掉已完成任务标题的删除线样式

#### 3. 后端任务查询修复
- **文件**: `backend/controllers/task.controller.js`
- **修复**:
  - 修复 `getPartnerTaskScope` 函数中 `partnerGroupId` 类型问题
  - 使用 `EXISTS` 子查询替代 LEFT JOIN 检查任务完成状态
  - 确保已完成任务正确从待完成列表中移除

#### 4. Regional Admin 任务权限限制
- **文件**: `backend/controllers/task.controller.js`
- **变更**:
  - Regional Admin 只能看到自己发布的任务
  - 任务列表查询时增加 `created_by = ?` 条件
  - 编辑和删除操作只允许对自己创建的任务

---

## [2026-05-11] Opportunities 页面布局优化与 Task 功能增强

### Opportunities 页面布局优化

#### 1. Partner 端 Region 列独立展示
- **文件**: `frontend/src/pages/Opportunities.jsx`
- **变更**:
  - 将 Region 从 Customer 列中分离为独立列
  - Region 列显示 `endUserCountryRegion` 和 `endUserRegion`（用 `/` 分隔）
  - Customer 列现在只显示客户名称
  - 调整各列宽度以适应新布局

#### 2. Admin 端 Region 列拆分
- **文件**: `frontend/src/pages/AdminOpportunities.jsx`
- **变更**:
  - 将原来的 "Region" 列拆分为 "End User Country" 和 "End User Region" 两列
  - 将原来的 "Partner Region" 列拆分为 "Partner Country" 和 "Partner Region" 两列
  - End User Country 列显示 `endUserCountryRegion`
  - End User Region 列显示 `endUserRegion`
  - Partner Country 列显示 `partnerCountryRegion`
  - Partner Region 列显示 `partnerRegion`
  - STATUS 列标题设置为右对齐

#### 3. Partners 管理页面列宽调整
- **文件**: `frontend/src/pages/AdminPartners.jsx`
- **变更**:
  - Opportunities 列宽度从 `w-[11%]` 增加到 `w-[12%]`
  - Status 列宽度从 `w-[11%]` 增加到 `w-[12%]`
  - Company 列宽度从 `w-[24%]` 调整为 `w-[22%]`
  - Primary Contact 列宽度从 `w-[20%]` 调整为 `w-[22%]`

#### 4. Partner 端列宽优化
- **文件**: `frontend/src/pages/Opportunities.jsx`
- **变更**:
  - 增加内边距从 `px-3` 改为 `px-4`
  - Sales Stage 列宽度从 `w-32` 增加到 `w-36`
  - Status 列宽度从 `w-24` 增加到 `w-28`
  - Customer 列最小宽度从 `min-w-[120px]` 增加到 `min-w-[180px]`
  - Region 列宽度从 `w-32` 增加到 `w-36`
  - Registered By 列最小宽度从 `min-w-[100px]` 增加到 `min-w-[120px]`
  - ID 和 ARR 列适当减小宽度以平衡整体布局

### Task 功能增强

#### 1. Task 分配方式优化
- **文件**: `frontend/src/pages/Tasks.jsx`
- **变更**:
  - 移除 "By Tier (Platinum/Gold/Silver)" 选项
  - 新增 "By Region" 选项，支持多选区域
  - 数据来源于 `/wiki/regions` API（字典表）
  - 优化 "Specific Partners" 选项，支持多选伙伴
  - 数据来源于 `/partners/all` API
  - 切换选项时自动清空之前的选择
  - 提交时验证必须至少选择一个区域或伙伴

#### 2. Task 创建面板样式优化
- **文件**: `frontend/src/pages/Tasks.jsx`
- **变更**:
  - 面板宽度从 `max-w-lg`（约512px）增加到 `max-w-3xl`（约800px）
  - 添加搜索输入框，支持快速搜索合作伙伴
  - 添加滚动容器 `max-h-48 overflow-y-auto`，限制高度并支持滚动
  - 优化按钮样式：
    - 字号从 `text-sm` 缩小到 `text-xs`
    - 内边距从 `px-3 py-1.5` 缩小到 `px-3 py-1`
    - 添加 `whitespace-nowrap` 防止文字换行
  - 添加选中状态提示：显示已选择的数量和"Clear all"清除按钮
  - 搜索结果为空时显示友好提示
  - 选中项以红色背景高亮显示
  - 为所有区域和伙伴选择按钮添加 `type="button"` 属性，防止自动提交

#### 3. 后端 API 修复
- **文件**:
  - `backend/routes/partners.routes.js`
  - `backend/controllers/task.controller.js`
- **修复**:
  - 修复 `/api/partners/all` API 的数据库字段名问题
    - 将 `approved` 改为 `approved_by_pingcap`
    - 将 `company` 改为 `company_legal_name`
  - 移除 `/api/partners/all` API 的角色权限限制，允许所有已认证用户访问
  - 更新 `task.controller.js` 中的 `TARGET_TYPES` 数组
    - 将 `["all", "tier", "partner"]` 改为 `["all", "region", "partner"]`

#### 4. 数据库变更
- **文件**: `database/029_update_task_target_type.sql`
- **变更**:
  - 将 `tasks` 表的 `target_type` ENUM 值从 `('all', 'tier', 'partner')` 更新为 `('all', 'region', 'partner')`
  - 将所有现有的 `tier` 类型记录迁移到 `all`（因为 tier 选项已被移除）

### 验证与服务

- **验证**:
  - 执行 `node --check backend/controllers/task.controller.js` 通过
  - 执行 `node --check backend/routes/partners.routes.js` 通过
  - 执行 `npm run build` 通过
- **服务**:
  - 多次重启后端服务，监听 `http://localhost:3001`
  - 使用 `NODE_TLS_REJECT_UNAUTHORIZED=0` 参数启动

---

## [2026-05-11] Opportunity、Task 与角色权限规则修复

### Opportunity 更新规则

#### 1. Partner 关闭商机规则
- **文件**:
  - `backend/controllers/opportunities.controller.js`
  - `frontend/src/pages/OpportunityDetail.jsx`
- **规则**:
  - Partner 将商机阶段更新为 `Closed Lost` 时，必须填写 `Latest Update / Lost Reason`
  - 商机进入 `Closed Lost` 或 `Launched` 后，Partner 不能继续更新
  - 前端隐藏不可更新商机的 Update 入口，并显示只读提示

#### 2. Admin 更新规则
- **文件**:
  - `backend/controllers/opportunities.controller.js`
  - `frontend/src/pages/OpportunityDetail.jsx`
- **规则**:
  - Admin / Regional Admin 不能在商机未 `Approved` 前直接 update
  - `Closed Lost` 或 `Launched` 的商机不允许继续 update
  - 详情页同步限制 Update 按钮显示

### 左侧菜单与角色权限

#### 1. Regional Admin 菜单整理
- **文件**: `frontend/src/components/Layout.jsx`
- **修复**:
  - 去除重复的 `Collateral`
  - 修复不可访问菜单导致点击后跳转混乱的问题
  - Regional Admin 菜单保留实际可访问入口

#### 2. Sales 只读 Partner 信息
- **文件**:
  - `frontend/src/pages/AdminPartners.jsx`
  - `backend/routes/admin.routes.js`
- **规则**:
  - Sales 可以查看自己负责的 Partner
  - Sales 不能编辑 Partner 信息
  - Sales 不能审批、拒绝、终止 Partner Group 或 Partner Member
  - Sales 不能修改 Partner Program
  - Partner 详情中显示只读提示：如需修改请联系 Regional Admin

#### 3. Sales 不可访问 Task 模块
- **文件**:
  - `frontend/src/components/Layout.jsx`
  - `frontend/src/App.jsx`
  - `frontend/src/pages/Tasks.jsx`
  - `backend/routes/task.routes.js`
- **规则**:
  - Sales 左侧菜单不显示 `Tasks`
  - Sales 直接访问 `/tasks` 会被前端路由拦截
  - 后端 Task 列表、统计、完成明细接口不再授予 Sales 权限

### Partner Task 与 Partner News

#### 1. Partner 可查看分配给自己的 Task
- **文件**:
  - `backend/controllers/task.controller.js`
  - `backend/routes/task.routes.js`
  - `frontend/src/App.jsx`
  - `frontend/src/components/Layout.jsx`
  - `frontend/src/pages/Tasks.jsx`
- **规则**:
  - Partner 可进入 `Tasks`
  - `/tasks/my` 只返回分配给当前 Partner Group 的 active task
  - 支持按 `all`、`region`、`partner` 三种 target 类型过滤
  - Partner 不能完成未分配给自己的 task
  - Partner task completion 接口要求账号处于 active 状态

#### 2. Partner News 合并 Task
- **文件**: `frontend/src/pages/Dashboard.jsx`
- **变更**:
  - Partner Dashboard 的 `Partner News` 合并展示未完成 task 与 Collateral/news
  - Task 条目点击跳转到 `/tasks`
  - News 条目点击跳转到 `/wiki`
  - 条目增加 `Task` / `News` 标签

#### 3. Task completion 字段修复
- **文件**: `database/030_task_completion_partner_id_bigint.sql`
- **修复**:
  - `task_completions.partner_id` 改为 `BIGINT`
  - 避免 TiDB `AUTO_RANDOM` 生成的大 Partner Group ID 写入 completion 时溢出

### Regional Admin 发布 Task

#### 1. 区域内发布权限
- **文件**:
  - `backend/controllers/task.controller.js`
  - `backend/routes/task.routes.js`
  - `frontend/src/App.jsx`
  - `frontend/src/components/Layout.jsx`
  - `frontend/src/pages/Tasks.jsx`
- **规则**:
  - Regional Admin 可进入 `Tasks`
  - Regional Admin 可创建 task 给自己 managed region 内全部 Partner
  - Regional Admin 可选择自己 managed region 内指定 Partner
  - Regional Admin 不能创建全局 `all` task
  - 后端校验 `targetType` / `targetValue`，防止绕过前端跨区域发布
  - Regional Admin 可查看区域相关 task；全局 task 可见但不可编辑/删除

#### 2. Select Partners 区域过滤
- **文件**:
  - `backend/routes/partners.routes.js`
  - `frontend/src/pages/Tasks.jsx`
- **修复**:
  - `/api/partners/all` 对 Regional Admin 实时读取 `pingcapers.managed_regions`
  - Partner 列表仅返回当前 Regional Admin 管理区域内的 Partner Group
  - 区域匹配统一使用 `dict_country_region.Country_Name = partner_groups.country_region`
  - 移除本流程中对 `ISO_Code` 的依赖
  - 前端打开 Task 弹窗时重新获取 `/auth/me`，防止旧登录态导致区域过滤错误
  - 前端 Select Partners 根据后端返回的 `region` 再做防御性过滤

### Partner News 区域一致性

#### 1. 区域映射统一
- **文件**:
  - `backend/controllers/wiki.controller.js`
  - `backend/controllers/auth.controller.js`
  - `backend/controllers/task.controller.js`
  - `backend/routes/partners.routes.js`
- **修复**:
  - 区域匹配统一按 `Country_Name`
  - 移除相关路径中的 `ISO_Code` 匹配，避免不同存储格式导致 Partner News 数量不一致

### 验证

- **后端语法检查**:
  - `node --check backend/controllers/task.controller.js`
  - `node --check backend/controllers/wiki.controller.js`
  - `node --check backend/controllers/auth.controller.js`
  - `node --check backend/controllers/opportunities.controller.js`
  - `node --check backend/routes/task.routes.js`
  - `node --check backend/routes/partners.routes.js`
- **前端构建**:
  - 多次执行 `npm run build` 通过
  - 仅保留现有 Vite chunk size warning

---

## [2026-05-10] Collateral 功能完善与权限修复

### Collateral PDF 预览和下载修复

#### 1. 下载路由注册
- **文件**: `backend/routes/wiki.routes.js`
- **描述**: 注册 `GET /api/wiki/:id/download` 路由

#### 2. 预览与下载分离
- **文件**: `backend/controllers/wiki.controller.js`
- **描述**:
  - 新增 `previewResource` 函数（不记录审计日志）
  - 保留 `downloadResource` 函数（记录审计日志）
- **路由**:
  - `GET /api/wiki/:id/preview` - 预览文件（无日志）
  - `GET /api/wiki/:id/download` - 下载文件（有日志）

#### 3. 前端调用调整
- **文件**: `frontend/src/pages/Wiki.jsx`
- **描述**: 预览功能调用 `/preview` 接口，下载功能调用 `/download` 接口

### Collateral 审计日志

#### 1. 操作记录
- **文件**: `backend/controllers/wiki.controller.js`
- **记录操作**:
  - CREATE - 创建资源：记录名称、文件名、分类、区域、是否公开
  - UPDATE - 更新资源：记录每个字段的原值和新值
  - DELETE - 删除资源：记录名称和ID
  - DELETE FILE - 删除文件：记录资源ID
  - DOWNLOAD - 下载资源：记录名称、文件名、ID

### Partner 用户区域权限修复

#### 1. 区域查询逻辑修复
- **文件**: `backend/controllers/wiki.controller.js`
- **问题**: Partner 用户无法看到所属区域的资源
- **原因**: 使用 `ISO_Code` 匹配区域，应为 `Country_Name`
- **修复**: 将查询条件从 `WHERE ISO_Code = ?` 改为 `WHERE Country_Name = ?`

#### 2. 预览/下载权限检查
- **文件**: `backend/controllers/wiki.controller.js`
- **描述**: 在 `previewResource` 和 `downloadResource` 函数中添加数据库查询逻辑
- **逻辑**: 当 `managedRegions` 为空时，从 `partners` 表查询 `country_region`，再通过 `dict_country_region` 表转换为区域名称

### 后续补充变更

#### 1. 后端服务启动参数
- **描述**: 使用 `NODE_TLS_REJECT_UNAUTHORIZED=0` 参数启动后端服务

#### 2. 任务模块（Tasks）新增
- **数据库表**:
  - `tasks` - 任务表
  - `task_completions` - 任务完成记录表
- **后端**:
  - `backend/controllers/task.controller.js` - 任务控制器（CRUD操作）
  - `backend/routes/task.routes.js` - 任务路由
- **前端**:
  - `frontend/src/pages/Tasks.jsx` - 任务页面组件
  - `frontend/src/components/Layout.jsx` - 侧边栏添加 Tasks 菜单
- **功能**:
  - PingCAP 管理员可以向全部/部分合作伙伴下发任务
  - 支持任务类型：必读文档、协议续约、完成调查等
  - 支持任务分配、状态跟踪、完成记录

#### 3. 数据库变更
- **新增表**: `tasks`（任务表）
  - `task_id` - 任务ID（主键）
  - `title` - 任务标题
  - `description` - 任务描述
  - `task_type` - 任务类型（read_document, renew_agreement, complete_survey, other）
  - `target_partners` - 目标合作伙伴（JSON数组，为空时表示全部合作伙伴）
  - `due_date` - 截止日期
  - `created_at` - 创建时间
  - `created_by` - 创建人ID
- **新增表**: `task_completions`（任务完成记录表）
  - `completion_id` - 完成记录ID（主键）
  - `task_id` - 关联任务ID
  - `partner_id` - 合作伙伴ID
  - `completed_at` - 完成时间
  - `completed_by` - 完成人ID

### 今日后续补充变更

#### 1. Partner Agreements 页面修复与审计日志
- **文件**:
  - `backend/controllers/contracts.controller.js`
  - `frontend/src/pages/Contract.jsx`
  - `frontend/src/pages/AuditLogs.jsx`
- **修复**:
  - 修复进入 Partner Agreements 页面时自动触发下载的问题
  - 预览改为通过文件接口加载 blob URL，下载仅由 Download 操作触发
- **审计日志**:
  - Partner Agreements 页面加载记录 `VIEW`
  - 合同预览记录 `VIEW`
  - 合同下载记录 `DOWNLOAD`
  - 合同签署记录 `UPDATE`
  - Audit Logs 操作类型增加 `DOWNLOAD`

#### 2. Opportunities 业务规则增强
- **文件**:
  - `backend/controllers/opportunities.controller.js`
  - `frontend/src/pages/OpportunityDetail.jsx`
- **规则**:
  - Partner 将商机阶段改为 `Closed Lost` 时必须填写 `Latest Update / Lost Reason`
  - Partner 对已处于 `Closed Lost` 或 `Launched` 阶段的商机不能继续更新
  - 前端同步隐藏不可更新商机的 Update 操作，并显示只读提示

#### 3. Partners 页面区域显示与排序
- **文件**:
  - `backend/controllers/admin.controller.js`
  - `frontend/src/pages/AdminPartners.jsx`
- **变更**:
  - Partner Group 列表和详情接口返回从 `dict_country_region` 映射出的 `region`
  - Partners 列表将 `Region` 从 `Country` 中拆出为独立列
  - 支持点击 `Region` 表头按区域升序/降序排序
  - 搜索框支持按区域搜索
  - Partner 详情 `Company Information` 中增加 `Region`

#### 4. Opportunities 页面国家与区域显示
- **文件**:
  - `backend/controllers/opportunities.controller.js`
  - `backend/controllers/admin.controller.js`
  - `frontend/src/pages/AdminOpportunities.jsx`
  - `frontend/src/pages/Opportunities.jsx`
  - `frontend/src/pages/AdminPartnerOpportunities.jsx`
  - `frontend/src/pages/OpportunityDetail.jsx`
- **变更**:
  - Opportunity 接口返回客户侧 `endUserCountryRegion` / `endUserRegion`
  - Opportunity 接口返回 Partner 侧 `partnerCountryRegion` / `partnerRegion`
  - Admin Opportunities 显示 End User 和 Partner 的国家/区域
  - Partner Opportunities 和 Partner 详情进入的 Opportunities 列表显示客户国家/区域
  - Opportunity Detail 客户信息中增加 `Region`
  - Admin 查看 Opportunity Detail 时在 Partner Name 下方显示 Partner 国家/区域

#### 5. Sales 与 Employee 权限调整
- **文件**:
  - `backend/routes/admin.routes.js`
  - `backend/routes/opportunities.routes.js`
  - `backend/controllers/admin.controller.js`
  - `backend/controllers/opportunities.controller.js`
  - `frontend/src/App.jsx`
  - `frontend/src/components/Layout.jsx`
  - `frontend/src/pages/AdminPartners.jsx`
  - `frontend/src/pages/AdminOpportunities.jsx`
  - `frontend/src/pages/OpportunityDetail.jsx`
- **Sales 权限**:
  - Sales 登录后可见 `Partners`、`Opportunities`、`Collateral`
  - Partners 仅返回 `PingCAP Sales Assigned` 匹配当前 Sales 姓名或邮箱的数据
  - Opportunities 仅返回当前 Sales 名下 Partner 关联的商机
  - Sales 仅允许查看，不允许审批、编辑 Partner 或 Opportunity
- **Employee 权限**:
  - Employee 登录后仅保留 `Collateral/Wiki`
  - 前端访问其它页面会重定向，后端管理接口不授予 Employee 访问权限

#### 6. Agreements 与 Partners 细节修复
- **文件**: `frontend/src/pages/AdminPartners.jsx`
- **变更**:
  - 选择 `Offline Agreement` 时禁用并清空其它 agreement 选项
  - Rejected 状态的 Partner Group 允许直接 Approve，不再强制先编辑保存
  - 重复 Account warning 中增加区域信息，帮助 Regional Admin 判断 Active account 所属区域

#### 7. 验证与服务
- **验证**:
  - 多次执行 `node --check` 检查后端控制器与路由语法
  - 多次执行 `npm run build` 验证前端构建通过
- **服务**:
  - 根据代码变更多次重启 backend dev 服务，监听 `http://localhost:3001`

#### 8. 合同管理有效期与续约
- **文件**:
  - `database/028_contract_validity_period.sql`
  - `backend/controllers/contracts.controller.js`
  - `backend/routes/contracts.routes.js`
  - `backend/controllers/admin.controller.js`
  - `backend/services/email.service.js`
  - `frontend/src/pages/Contract.jsx`
  - `frontend/src/pages/AdminContracts.jsx`
  - `backend/migrate.js`
- **数据库**:
  - `partner_contract_assignments` 增加 `valid_from`、`valid_until`、`agreement_source`、`replaced_by_assignment_id`、`reminder_sent_at`、`validity_notes`
  - 移除旧的 `(partner_group_id, program_type)` 唯一约束，允许同一协议保留历史签署记录
  - 已签署历史协议按签署时间回填 2 年有效期
- **合作伙伴端**:
  - 线上签署协议默认有效期 2 年
  - Partner Agreements 展示所有历史协议、签署日期、有效期、来源和状态
  - 到期或临期协议支持线上续约，续约后新增历史签署记录
  - 线下协议记录可展示有效期；临期/到期时可引导线上续约
- **PingCAP 端**:
  - Contract Management 新增 Signed Agreement History
  - 统一展示线上签署和历史线下签约协议
  - 支持编辑线下/历史协议有效期与备注
  - 临期或到期协议支持发送续约提醒邮件
- **迁移**:
  - 全量迁移因历史 `026_pingcapers_sub_admin.sql` 重复字段中断，本次已单独执行 `028_contract_validity_period.sql`
  - `backend/migrate.js` 支持 `TIDB_SSL_REJECT_UNAUTHORIZED=0` 以便本地迁移 TiDB Cloud

---

## [2026-05-09] 本轮页面与审计功能优化

### Audit Logs 页面优化

#### 1. 日期范围查询修复
- **文件**: `backend/controllers/audit.controller.js`
- **描述**: 修复结束日期只匹配当天 00:00:00 的问题
- **变更**: `endDate` 改为按次日 00:00:00 前的半开区间查询，确保选择 5-8 到 5-9 时包含 5 月 9 日整天记录

#### 2. CSV 导出功能
- **文件**: `frontend/src/pages/AuditLogs.jsx`
- **描述**: 完善 Export 按钮，支持按当前筛选条件导出全部匹配审计日志
- **导出格式**: CSV
- **导出字段**: Operation Type, Operation Content, Operation Time, Operator Email, Operator Role, Page, IP Address

#### 3. 页面展示与筛选体验
- **文件**: `frontend/src/pages/AuditLogs.jsx`
- **描述**:
  - 默认日期范围调整为最近 7 天
  - 默认每页展示 50 条记录
  - 优化 Filters 区域布局、字段标签、按钮比例和视觉样式
  - 扩大 Content 列显示比例，压缩其他列宽
  - 移除表格内部滚动区域，提升页面可视范围

#### 4. 日志详情面板
- **文件**: `frontend/src/pages/AuditLogs.jsx`
- **描述**: 点击审计日志行后，从右侧弹出详情面板
- **展示内容**: 完整操作类型、时间、操作者、角色、页面、IP 和完整 Operation Content
- **增强**: JSON 格式的 Operation Content 自动格式化展示

#### 5. 自定义英文日期选择器
- **文件**: `frontend/src/pages/AuditLogs.jsx`
- **描述**: 替换原生 `type="date"` 控件，避免浏览器/系统语言导致日期选择器显示中文
- **功能**:
  - 月份、星期、Prev/Next 全部使用英文
  - Start Date 与 End Date 联动，选择 Start Date 后自动弹出 End Date
  - 优化日期选择器尺寸，使其与筛选栏其他控件对齐

### Admin Management 页面重构

#### 1. 页面备份
- **文件**: `frontend/src/pages/AdminManagement.jsx.bak`
- **描述**: 重构前备份原 Admin Management 页面

#### 2. 统一员工列表
- **文件**: `frontend/src/pages/AdminManagement.jsx`
- **描述**:
  - 移除 Admins / Regional Admins / Employees 分区
  - 所有 PingCAP 员工统一展示在一个表格中
  - 新增 Role 列显示当前分类
  - 支持按姓名、邮箱、角色搜索

#### 3. 角色与区域编辑
- **文件**: `frontend/src/pages/AdminManagement.jsx`
- **描述**:
  - 每行新增 Edit 操作
  - 编辑时可通过下拉框选择 Admin / Regional Admin / Employee
  - 选择 Regional Admin 时可编辑 Managed Regions
  - 非 Regional Admin 角色会自动清空 Managed Regions
- **修复**: 保存请求统一改用 `frontend/src/api/client.js`，避免手写 Authorization 导致 token 状态不一致

#### 4. Admin Management 审计日志
- **文件**: `backend/controllers/admin.controller.js`
- **记录操作**:
  - 预创建 PingCAP employee（CREATE）
  - 修改 PingCAP employee role（UPDATE）
  - 修改 PingCAP employee managed regions（UPDATE）
- **日志内容**: 包含目标员工 ID、邮箱、修改前值和修改后值

### Partners 页面审批流程优化

#### 1. Edit Company Info 与 Approve 联动
- **文件**: `frontend/src/pages/AdminPartners.jsx`
- **描述**:
  - 点击 Edit Company Info 后，Approve Group 按钮禁用
  - 必须 Save Changes 成功后才允许 Approve
  - 未保存时在 Final approval step 区域显示提示

#### 2. 审批错误提示位置调整
- **文件**: `frontend/src/pages/AdminPartners.jsx`
- **描述**: 将审批错误提示移动到 Final approval step 卡片下方，靠近 Reject / Approve 按钮区域
- **示例提示**: `No active contract is available for: Service Partner.`

### 后续补充变更

#### 1. 腾讯云 COS 存储适配与测试
- **文件**:
  - `backend/controllers/contracts.controller.js`
  - `backend/controllers/wiki.controller.js`
  - `backend/package.json`
  - `backend/scripts/test-cos-s3.js`
- **描述**:
  - 保留原 AWS S3 初始化代码注释，新增腾讯云 COS 兼容配置
  - 使用现有 AWS SDK S3 Client 通过 `endpoint`、`region`、`forcePathStyle` 访问 COS
  - 新增 `npm run test:cos` 脚本，用于测试 PUT / GET / DELETE
- **验证**:
  - COS SDK 兼容性测试通过
  - 合同 PDF 上传接口测试通过
- **注意**: 本地测试曾因代理证书出现 TLS 校验问题，使用 `NODE_TLS_REJECT_UNAUTHORIZED=0` 仅用于本地验证，生产环境不应使用该配置

#### 2. Partners 页面 Partner Program 展示修复
- **文件**:
  - `backend/controllers/admin.controller.js`
  - `frontend/src/pages/AdminPartners.jsx`
- **问题**: `Partner Program Enrolled` 保存后仍显示旧值
- **原因**:
  - 列表接口原先优先展示 partner 注册时的申请意向字段
  - 保存后的实际 enrolled program 存在 `partner_contract_assignments.program_type`
- **修复**:
  - `GET /api/admin/partner-groups` 优先返回实际分配的 `partner_contract_assignments`
  - 前端新增 `Currently Enrolled` 展示实际 enrolled programs
  - 保存后同步更新左侧列表状态

#### 3. Partner Group 保存与审批职责拆分
- **文件**:
  - `backend/controllers/admin.controller.js`
  - `frontend/src/pages/AdminPartners.jsx`
- **描述**:
  - 将 agreement 选择、合同模板校验、`Foundation Agreement` 自动补全、`Offline Agreement` 自动签署、`partner_contract_assignments` 重建逻辑移动到 `updatePartnerGroup`
  - `setPartnerGroupApproval` 调整为只负责审批状态更新、manager 自动审批、active 状态同步和审计日志
  - `Approve Group` 前端请求改为只传 `{ approved: true }`
  - `Save Programs` 改为调用 `PATCH /api/admin/partner-groups/:id`
- **效果**: 编辑 `Edit Company Info` 后点击 Save Changes 即可保存 company info 与 agreements，审批通过不再承担保存 agreement 的职责

#### 4. Approved Groups 数据恢复
- **数据库**: `partner_groups`
- **描述**: 将 20 条 `Approved Groups` 数据恢复为 pending 状态
- **更新字段**:
  - `approved_by_pingcap = 0`
  - `approved_by = NULL`
  - `approved_at = NULL`
  - `is_active = 0`
  - `contract_accepted_at = NULL`
  - `onboarding_email_sent_at = NULL`
  - `rejected_at = NULL`
  - `rejected_by = NULL`
  - `terminated_at = NULL`
- **说明**: 未删除 `partner_contract_assignments`，已保存的 Partner Program / agreement 配置保留

---

## [2026-05-09] 审计日志功能

### 新增功能

#### 1. 审计日志表
- **文件**: `backend/database/audit_logs.sql`
- **表名**: `audit_logs`
- **字段说明**:
  - `operation_type`: 操作类型（CREATE, UPDATE, DELETE, APPROVE, REJECT, LOGIN, VIEW）
  - `operation_content`: 操作内容描述
  - `operation_time`: 操作时间
  - `operator_id/email/name/role`: 操作人信息
  - `page_name`: 操作页面/路径
  - `ip_address`: IP地址

#### 2. 日志记录工具
- **文件**: `backend/utils/auditLogger.js`
- **函数**: `logAudit(operationType, operationContent, req)`
- **功能**: 记录操作到 audit_logs 表

#### 3. 日志查询 API
- **文件**: `backend/controllers/audit.controller.js`
- **路由**: `backend/routes/audit.routes.js`
- **接口**:
  - `GET /api/audit/admin/logs` - 获取日志列表（支持分页和筛选）
  - `GET /api/audit/admin/logs/:id` - 获取单条日志详情
- **权限**: 仅 admin 角色可访问

#### 4. 审计日志页面
- **文件**: `frontend/src/pages/AuditLogs.jsx`
- **路径**: `/admin/logs`
- **功能**:
  - 日志列表展示
  - 按操作类型、用户邮箱、日期范围筛选
  - 分页导航
  - 操作类型彩色标签区分

#### 5. 导航菜单
- **文件**: `frontend/src/components/Layout.jsx`
- **描述**: Admin 用户侧边栏添加 "Audit Logs" 菜单项

#### 6. 操作日志记录
- **文件**: `backend/controllers/admin.controller.js`
- **记录操作**:
  - 合作伙伴组批准（APPROVE）
  - 合作伙伴组拒绝（REJECT）
  - 合作伙伴组更新（UPDATE）
- **文件**: `backend/controllers/opportunities.controller.js`
- **记录操作**:
  - 机会批准（APPROVE）
  - 机会拒绝（REJECT）
  - 机会状态更新（UPDATE）

---

## [2026-05-09] PingCAP Sales Assigned 功能增强

### 新增功能

#### 1. PingCAP Sales Assigned 下拉选择器
- **文件**: `frontend/src/pages/AdminPartners.jsx`
- **描述**: 将 PingCAP Sales Assigned 字段改为下拉选择器
- **数据来源**: `pingcapers` 表
- **显示格式**: `FirstName LastName (role)`，如 `John Doe (regional_admin)`
- **存储值**: 仅存储名字（`FirstName LastName`）

#### 2. 角色权限过滤
- **文件**: `backend/controllers/admin.controller.js`
- **描述**: 根据登录用户角色过滤可分配的销售代表
- **Admin**: 可以查看和分配所有角色的员工（admin、regional_admin、employee）
- **Regional Admin**: 只能查看和分配非 admin 角色的员工（regional_admin、employee）

#### 3. 必填验证
- **文件**: `frontend/src/pages/AdminPartners.jsx`
- **描述**: 批准 Partner Group 前必须选择 PingCAP Sales Assigned
- **错误提示**: "Please select a PingCAP Sales Assigned."

#### 4. EditableRow 组件增强
- **文件**: `frontend/src/pages/AdminPartners.jsx`
- **描述**: 支持对象格式的 options（`{value, label}`）

---

## [2026-05-09] Regional Admin 角色优化

### 功能变更

#### 1. Sub Admin 角色重命名为 Regional Admin
- **文件**: `backend/controllers/admin.controller.js`, `backend/routes/admin.routes.js`, `backend/controllers/auth.controller.js`, `backend/complete-server.js`, `frontend/src/components/Layout.jsx`, `frontend/src/App.jsx`, `frontend/src/pages/AdminManagement.jsx`
- **描述**: 将所有 `sub_admin` 角色名称统一改为 `regional_admin`
- **数据库变更**:
  - 更新 `pingcapers` 表的 `role` 字段枚举，添加 `regional_admin` 值
  - 将所有现有 Sub Admin 用户的角色更新为 `regional_admin`
- **涉及用户**: wanglu@pingcap.com, admin3@pingcap.com, manager2@pingcap.com, momo@pingcap.com, admin1@pingcap.com, manager1@pingcap.com

#### 2. Regional Admin 权限限制
- **文件**: `frontend/src/components/Layout.jsx`
- **描述**: Regional Admin 用户不再显示 Contract Management 导航项
- **可见菜单**: Dashboard, Partners, Opportunities, Collateral

#### 3. Dashboard 数据区域过滤
- **文件**: `backend/controllers/admin.controller.js`
- **描述**: Regional Admin 用户登录后，Dashboard 页面显示的数据会根据其管理区域进行过滤
- **过滤范围**:
  - Partner Groups 统计数据
  - Opportunities 统计数据
  - Pending Partners 统计数据

---

## [2026-05-08] Sub Admin 角色管理

### 新增功能

#### 1. Sub Admin 角色
- **文件**: `backend/controllers/admin.controller.js`, `backend/routes/admin.routes.js`, `backend/routes/country-region.routes.js`, `frontend/src/pages/AdminManagement.jsx`
- **描述**: 在 Admin Management 界面中新增了 Sub Admin 角色，支持区域管理功能
- **区域数据来源**: `dict_country_region` 表的 `region` 字段

#### 2. 数据库变更
- **表**: `pingcapers`
- **变更**:
  - 修改 `role` 字段，添加 `sub_admin` 枚举值
  - 新增 `managed_regions` 字段（TEXT 类型），JSON 格式存储管理区域列表

#### 3. API 接口
- `GET /api/country-region/regions` - 获取所有区域列表
- `PATCH /api/admin/pingcapers/:id/managed-regions` - 更新用户管理区域

#### 4. 前端界面更新
- 支持三种角色：Admin、Sub Admin、Employee
- 添加用户时可选择角色类型
- Sub Admin 必须至少选择一个管理区域
- 支持编辑已有 Sub Admin 的管理区域

### 修复问题
- 修复 Admin Management 页面加载失败的问题
- 修复数据库字段缺失导致的 API 错误

---

## [2026-05-08] 搜索功能增强

### 新增功能

#### 1. 用户名/密码登录功能
- **文件**: `backend/controllers/auth-user.controller.js`, `backend/routes/auth-user.routes.js`, `backend/server.js`
- **描述**: 新增用户名/密码登录功能，支持管理员（pingcapers表）和合作伙伴（partners表）两种登录方式
- **路由**: `/api/auth-user/login`
- **配置**: `ENABLE_USERNAME_PASSWORD_LOGIN=true` (在 `.env` 和 `.env.example` 中)

#### 2. 测试账户
- **描述**: 在数据库中创建了多个测试账户，密码均为 `admin123`
- **管理员账户**:
  - admin@pingcap.com (admin)
  - admin1@pingcap.com (admin)
  - admin2@pingcap.com (admin)
  - admin3@pingcap.com (admin)
  - manager1@pingcap.com (employee)
  - manager2@pingcap.com (employee)
- **合作伙伴**: partners 表中所有 45 个账户密码已设置为 `admin123`

#### 3. Partners 页面搜索功能
- **文件**: `frontend/src/pages/AdminPartners.jsx`
- **描述**: 在管理员 Partners 页面添加搜索功能
- **搜索字段**: 公司名称、主要联系人姓名、邮箱、国家/地区、PingCAP销售代表
- **功能**: 支持实时搜索和清除搜索

#### 4. Opportunities 页面搜索功能
- **文件**: `frontend/src/pages/Opportunities.jsx`
- **描述**: 在合作伙伴 Opportunities 页面添加搜索功能
- **搜索字段**: 客户名称、机会名称、机会ID、提交者姓名、提交者邮箱、机会类型
- **功能**: 支持实时搜索和清除搜索

#### 5. 管理员 Opportunities 页面搜索功能
- **文件**: `frontend/src/pages/AdminOpportunities.jsx`
- **描述**: 在管理员 Opportunities 页面添加搜索功能
- **搜索字段**: 最终用户公司名称、国家/地区、机会标题、合作伙伴公司名称、机会类型、关闭日期
- **功能**: 支持实时搜索和清除搜索

### 配置更新

#### .env.example 更新
- 新增配置项: `ENABLE_USERNAME_PASSWORD_LOGIN=true`

### 文档更新

#### README.md 更新
- 添加了测试账户信息表格
- 添加了登录页面 URL 说明
- 添加了 `ENABLE_USERNAME_PASSWORD_LOGIN` 配置说明
