# MRO Data Viewer - 数据查询页面设计

## 概述

为 mro-data-viewer 项目实现两个数据查询页面，用于浏览和查询 PostgreSQL 数据库中的 FA 固定资产明细和 CRM 客户联系人变更数据。同时集成 NextAuth 鉴权，仅允许管理员账号登录。

## 技术选型

| 项目 | 选型 | 原因 |
|------|------|------|
| 鉴权 | NextAuth v5 (Auth.js) Credentials Provider | 单管理员账号，环境变量存储，最简方案 |
| 数据库连接 | `pg` 驱动直连 PostgreSQL | 表名有非标准前缀，直连最简单高效 |
| 查询方式 | Server Actions | 类型安全，不暴露连接到前端 |
| UI 组件 | shadcn/ui DataTable + 自定义筛选 | 项目已集成 shadcn/ui |
| 导出 | 服务端生成 CSV，客户端下载 | 简单可靠 |

## 数据概况

- **yhdmro_fa_fa_details**（FA 固定资产明细）：~60 万行，字段包括单据号、日期、供应商、金额、物料、审批状态等
- **yhdmro_crm_cust_contact_change**（CRM 客户联系人变更）：~4.7 万行，字段结构与 FA 表几乎相同，status 为中文值（审核完成/审核中/未发起/拒绝/撤回申请）

两张表共享核心字段：id, document_number, document_date, vendor_code, vendor_name, amount, currency, description, material_code, material_name, status, payment_status 等。

## 鉴权设计

- **Provider**：NextAuth Credentials Provider
- **账号存储**：环境变量 `ADMIN_USERNAME` 和 `ADMIN_PASSWORD`
- **Session**：JWT 模式（无数据库 session 存储）
- **中间件**：`middleware.ts` 保护 `/fa-details`、`/crm-contacts` 等路由，未登录重定向 `/login`
- **登录页**：`/login` 路由，简单的账号密码表单
- **登出**：支持登出功能

## 页面设计

### 导航结构

- `/` — 首页（导航到两个查询页面的入口）
- `/login` — 登录页
- `/fa-details` — FA 固定资产明细查询
- `/crm-contacts` — CRM 客户联系人变更查询

### 查询页面功能

每个查询页面包含：

1. **筛选栏**：顶部筛选区域
   - 单据号（模糊搜索）
   - 供应商名称（模糊搜索）
   - 日期范围（起止日期选择器）
   - 状态（下拉选择，CRM 表为中文枚举值）
   - 重置筛选按钮

2. **统计汇总栏**：筛选结果下方
   - 记录总数
   - 金额合计
   - 税额合计
   - 总金额合计

3. **数据表格**：
   - 关键列：单据号、日期、供应商编码、供应商名称、物料名称、数量、单价、金额、状态
   - 默认按 document_date DESC 排序
   - 分页：每页 20 条，可选 50 条
   - 行数显示：当前页范围 + 总数

4. **导出按钮**：导出当前筛选结果为 CSV

### 列配置

**FA 固定资产明细列**：
| 列 | 字段 | 说明 |
|----|------|------|
| 单据号 | document_number | |
| 单据日期 | document_date | |
| 供应商编码 | vendor_code | |
| 供应商名称 | vendor_name | |
| 物料编码 | material_code | |
| 物料名称 | material_name | |
| 物料规格 | material_spec | |
| 数量 | quantity | |
| 单价 | unit_price | |
| 金额 | amount | |
| 税率 | tax_rate | |
| 税额 | tax_amount | |
| 总金额 | total_amount | |
| 状态 | status | |
| 审批人 | approver | |

**CRM 客户联系人变更列**：
| 列 | 字段 | 说明 |
|----|------|------|
| 单据号 | document_number | |
| 单据日期 | document_date | |
| 供应商编码 | vendor_code | |
| 供应商名称 | vendor_name | |
| 描述 | description | |
| 金额 | amount | |
| 总金额 | total_amount | |
| 状态 | status | 中文枚举：审核完成/审核中/未发起/拒绝/撤回申请 |
| 审批人 | approver | |

## 数据层设计

### 连接池

```typescript
// lib/db.ts
import pg from 'pg';
const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL });
```

### 共享查询逻辑

两张表结构几乎相同，抽象通用查询函数：

```typescript
// lib/query.ts
interface QueryParams {
  tableName: string;
  filters: {
    documentNumber?: string;
    vendorName?: string;
    startDate?: string;
    endDate?: string;
    status?: string;
  };
  page: number;
  pageSize: number;
}

async function queryTable(params: QueryParams): Promise<{ rows, total, summary }>
async function exportTable(params: QueryParams): Promise<string> // CSV
```

- `queryTable`：返回分页数据 + 总数 + 统计汇总（金额合计等）
- `exportTable`：返回筛选结果全部数据的 CSV 字符串
- SQL 构建：动态 WHERE 条件，参数化查询防注入
- FA 表 60 万行需高效分页：使用 offset+limit，配合筛选条件减少扫描量

### Server Actions

```typescript
// app/fa-details/actions.ts
export async function fetchFaDetails(filters, page, pageSize) -> ActionResult
export async function exportFaDetails(filters) -> CSV string

// app/crm-contacts/actions.ts
export async function fetchCrmContacts(filters, page, pageSize) -> ActionResult
export async function exportCrmContacts(filters) -> CSV string
```

## 环境变量

```env
DATABASE_URL=postgresql://foldspace_dev:yRt4QoFwbmaB2E6sDdk9@frpdx.xhyonline.com:15281/foldspace_dev
NEXTAUTH_SECRET=<random-secret>
NEXTAUTH_URL=http://localhost:3000
ADMIN_USERNAME=admin
ADMIN_PASSWORD=<password>
```

## 文件结构

```
app/
  layout.tsx              — 更新：添加导航 + AuthProvider
  page.tsx                — 更新：首页导航入口
  login/
    page.tsx              — 登录表单页面
  fa-details/
    page.tsx              — FA 查询页面
    actions.ts            — FA Server Actions
  crm-contacts/
    page.tsx              — CRM 查询页面
    actions.ts            — CRM Server Actions
  api/
    auth/
      [...nextauth]/route.ts — NextAuth API 路由
components/
  data-table.tsx          — 通用数据表格组件（分页、排序）
  data-filter.tsx         — 通用筛选栏组件
  data-summary.tsx        — 统计汇总栏组件
  nav-bar.tsx             — 顶部导航栏
lib/
  db.ts                   — pg 连接池
  query.ts                — 共享查询逻辑
  auth.ts                 — NextAuth 配置
  export.ts               — CSV 导出工具
middleware.ts             — 路由保护中间件
```

## 安全考虑

- 所有数据库查询通过 Server Actions，不暴露连接信息到前端
- SQL 参数化查询，防止注入
- 环境变量存储敏感信息（数据库密码、管理员密码）
- middleware.ts 保护所有数据页面路由
- JWT session 不存储在数据库中