# 合同流转审批系统

这是一个基于 Next.js 的合同流转审批系统。

## 如何启动服务

### 开发环境

1.  安装依赖:
    ```bash
    npm install
    ```

2.  启动开发服务:
    ```bash
    npm run dev
    ```

    服务将在 `http://localhost:3000` 上运行。

### 生产环境

1.  安装依赖:
    ```bash
    npm install
    ```

2.  构建项目:
    ```bash
    npm run build
    ```

3.  启动生产服务:
    ```bash
    npm run start
    ```

    服务将在 `http://localhost:3000` 上运行。

## 部署到服务器

1.  **环境要求**:
    *   Node.js >= 18.x
    *   一个用于运行 Node.js 应用的进程管理器，如 PM2。

2.  **部署步骤**:
    1.  将项目代码上传到服务器。
    2.  在服务器上进入项目根目录。
    3.  安装依赖:
        ```bash
        npm install
        ```
    4.  构建项目:
        ```bash
        npm run build
        ```
    5.  使用 PM2 启动服务:
        ```bash
        pm2 start npm --name "contract-approval-system" -- run start
        ```

3.  **数据持久化**:
    *   本应用使用 SQLite 数据库，数据库文件位于 `data/database.sqlite`。在部署时，请确保此文件及其所在目录具有正确的读写权限，并且在更新部署时不会被意外覆盖。
    *   上传的文件存储在 `public/uploads` 目录，也需要注意持久化和备份。

## 数据库架构

数据库采用 SQLite，包含以下数据表：

### `departments` - 部门表

存储公司部门信息。

| 字段名 | 类型 | 描述 |
| --- | --- | --- |
| `id` | INTEGER | 主键, 自增 |
| `name` | TEXT | 部门名称, 唯一 |
| `created_at` | DATETIME | 创建时间 |

### `users` - 用户表

存储系统用户信息。

| 字段名 | 类型 | 描述 |
| --- | --- | --- |
| `id` | INTEGER | 主键, 自增 |
| `username` | TEXT | 用户名, 唯一 |
| `password` | TEXT | 密码 (bcrypt 加密) |
| `real_name` | TEXT | 真实姓名 |
| `role` | TEXT | 角色 (e.g., `employee`, `supervisor`, `finance`, `secretary`, `admin`) |
| `department_id` | INTEGER | 所属部门ID, 外键关联 `departments(id)` |
| `status` | INTEGER | 状态 (1: 正常, 0: 禁用) |
| `created_at` | DATETIME | 创建时间 |

### `partners` - 合作伙伴表

存储合作伙伴公司信息。

| 字段名 | 类型 | 描述 |
| --- | --- | --- |
| `id` | INTEGER | 主键, 自增 |
| `name` | TEXT | 公司全称 |
| `short_name` | TEXT | 公司简称 |
| `english_name` | TEXT | 英文名称 |
| `website` | TEXT | 公司官网 |
| `logo` | TEXT | Logo 文件路径 |
| `address` | TEXT | 公司地址 |
| `description` | TEXT | 公司简介 |
| `is_deleted` | INTEGER | 是否删除 (0: 未删除, 1: 已删除) |
| `created_at` | DATETIME | 创建时间 |

### `contracts` - 合同表

存储合同主体信息和审批流转状态。

| 字段名 | 类型 | 描述 |
| --- | --- | --- |
| `id` | INTEGER | 主键, 自增 |
| `project_name` | TEXT | 项目名称 |
| `partner_id` | INTEGER | 合作伙伴ID, 外键关联 `partners(id)` |
| `partner_name` | TEXT | 合作伙伴名称 |
| `contract_content` | TEXT | 合同内容简介 |
| `contract_years` | INTEGER | 合同年限 |
| `contract_amount` | REAL | 合同金额 |
| `estimated_profit` | REAL | 预估利润 |
| `payment_type` | TEXT | 收付款类型 (`receive`/`pay`) |
| `sign_date` | TEXT | 签订日期 |
| `status` | TEXT | 审批状态 (e.g., `pending_supervisor`, `pending_finance`, `approved`) |
| `creator_id` | INTEGER | 创建人ID, 外键关联 `users(id)` |
| `creator_name` | TEXT | 创建人姓名 |
| `department_id` | INTEGER | 所属部门ID, 外键关联 `departments(id)` |
| `department_name` | TEXT | 所属部门名称 |
| `project_leader` | TEXT | 项目负责人 |
| `supervisor_opinion` | TEXT | 主管审批意见 |
| `supervisor_approved` | INTEGER | 主管审批结果 (1: 通过, 0: 驳回) |
| `supervisor_id` | INTEGER | 主管ID |
| `supervisor_name` | TEXT | 主管姓名 |
| `supervisor_time` | DATETIME | 主管审批时间 |
| `finance_opinion` | TEXT | 财务审批意见 |
| `finance_approved` | INTEGER | 财务审批结果 |
| `finance_id` | INTEGER | 财务ID |
| `finance_name` | TEXT | 财务姓名 |
| `finance_time` | DATETIME | 财务审批时间 |
| `secretary_opinion` | TEXT | 秘书审批意见 |
| `secretary_approved` | INTEGER | 秘书审批结果 |
| `secretary_id` | INTEGER | 秘书ID |
| `secretary_name` | TEXT | 秘书姓名 |
| `secretary_time` | DATETIME | 秘书审批时间 |
| `reject_reason` | TEXT | 驳回原因 |
| `created_at` | DATETIME | 创建时间 |
| `updated_at` | DATETIME | 更新时间 |

### `contract_attachments` - 合同附件表

存储合同的附件文件信息。

| 字段名 | 类型 | 描述 |
| --- | --- | --- |
| `id` | INTEGER | 主键, 自增 |
| `contract_id` | INTEGER | 合同ID, 外键关联 `contracts(id)` |
| `file_name` | TEXT | 文件名 |
| `file_path` | TEXT | 文件存储路径 |
| `file_size` | INTEGER | 文件大小 (bytes) |
| `created_at` | DATETIME | 创建时间 |

### `system_config` - 系统配置表

存储系统级别的配置项。

| 字段名 | 类型 | 描述 |
| --- | --- | --- |
| `id` | INTEGER | 主键, 自增 |
| `config_key` | TEXT | 配置键, 唯一 |
| `config_value` | TEXT | 配置值 |
| `updated_at` | DATETIME | 更新时间 |

### `role_permissions` - 角色权限表

定义不同角色的菜单可见性。

| 字段名 | 类型 | 描述 |
| --- | --- | --- |
| `id` | INTEGER | 主键, 自增 |
| `role` | TEXT | 角色名 |
| `menu_key` | TEXT | 菜单标识 |
| `visible` | INTEGER | 是否可见 (1: 可见, 0: 不可见) |
