

# 进销存数据开放平台（API+后台管理系统）需求规格说明书 (PRD)

## 1. 业务背景与建设目标

### 1.1 背景概述

目前，客户核心的进销存数据存储于本地的 **SQL Server** 数据库中。随着业务发展，大量的上下游合作伙伴（供货商、分销商、医院/客户等）提出高频对接数据的需求，希望实时获取“入库记录”和“出库记录”以实现自身系统的自动化同步。

### 1.2 核心痛点

1. **多客户直接连数据库风险高**：无法直接将 SQL Server 暴露给多方，存在严重的数据泄露和安全隐患。
2. **权限粒度难以控制**：不同上下游客户只能看到自身相关的数据（例如：A供货商只能看A的入库，B医院只能看B的出库），现有进销存无法做到API级别的精细化分权。
3. **缺乏管控手段**：无法随时对某个合作方进行账号开通、权限调整、流量限制或紧急关停。

### 1.3 建设目标

本项目的核心是搭建一个“防盗门+分发器”：

* **对内（后台管理系统）**：供客户管理层使用。用于管理上下游客户账号，一键开通/关停，分配API数据查看权限（按客户名称过滤数据）。
* **对外（受控API接口）**：供上下游技术人员调用。基于业界标准的安全认证（API Key/Secret），根据后台配置的权限，安全、高效地拉取指定范围的出入库数据。

---

## 2. 系统总体架构与数据流向

为确保客户本地服务器与进销存数据库的安全，建议采用以下轻量化架构：

```
[ 上游供应商 / 下游客户系统 ]
         │ (通过 HTTPS API 请求数据，携带 API Key & 签名)
         ▼
┌────────────────────────────────────────────────────────┐
│              进销存数据开放平台（本期开发）              │
│                                                        │
│  ┌────────────────────────┐  ┌──────────────────────┐  │
│  │   安全网关与 API 接口    │  │  后台管理系统 (Web)   │  │
│  │  (鉴权、限流、日志、分发) │  │ (账号、权限、开关)   │  │
│  └───────────┬────────────┘  └───────────┬──────────┘  │
└──────────────┼───────────────────────────┼─────────────┘
               │ (读取配置/写日志)          │ (管理配置)
               ▼                           ▼
┌────────────────────────────────────────────────────────┐
│            平台自身数据库（如 MySQL / SQLite）            │
│         (存储：客户账号、API密钥、权限规则、调用日志)        │
└────────────────────────────────────────────────────────┘
               │ (只读跨库查询)
               ▼
┌────────────────────────────────────────────────────────┐
│         客户本地进销存数据库 (SQL Server)               │
│          (只读读取：入库表、出库表、产品基础资料)          │
└────────────────────────────────────────────────────────┘

```

### 核心安全原则：

1. **只读连接**：开放平台对进销存 SQL Server 数据库**仅拥有只读（SELECT）权限**，绝不写入、不修改任何进销存原有数据，保证原生系统稳定性。
2. **环境隔离**：开放平台可部署在客户自有服务器的隔离环境或云服务器上，通过安全内网或白名单连接 SQL Server。

---

## 3. 后台管理系统功能需求（Web端）

该后台由客户管理人员操作，主要负责上下游账号的“生老病死”与权限配置。

### 3.1 仪表盘（首页看板）

* **客户看得懂**：今天有哪些客户调用了接口？调了多少次？有没有异常？
* **技术实现**：
* 统计指标：今日总调用次数、活跃上下游客户数、异常调用数。
* 图表展示：24小时内API调用流量趋势图（折线图）。



### 3.2 上下游客户账号管理

* **功能描述**：管理所有需要获取数据的外围客户。
* **界面字段**：客户名称、客户类型（上游供应商/下游分销商/医院等）、联系人、手机号、账号状态（启用/禁用）。
* **核心操作**：
* **【新建账号】**：录入上下游客户信息。
* **【开启/关停开关】**：**一键禁用/启用。** 禁用后，该客户持有的 API 密钥立即失效，API 接口返回 `403 Forbidden`。
* **【生成 API 密钥】**：为该客户系统自动生成唯一的 `API Key`（应用标识）和 `API Secret`（签名密钥，仅可见一次，用于接口安全校验）。



### 3.3 API 权限与数据隔离配置（核心功能）

* **功能描述**：决定这个账号能看什么数据。**必须实现“数据隔离”，防止 A 客户看到 B 客户的数据。**
* **配置项**：
1. **接口权限勾选**：
* [ ] 出库数据查询接口 (`/api/v1/chuku`)
* [ ] 入库数据查询接口 (`/api/v1/ruku`)


2. **数据过滤规则（关键）**：
* **绑定销方/供方全称**：设置一个或多个文本/编码。例如，当下游客户“喀喇沁旗中医蒙医医院”调用出库接口时，系统自动在 SQL Server 查询语句后加上 `WHERE 销方全称 = '喀喇沁旗中医蒙医医院'`。
* **全量数据开关**：针对极少数核心大户，可勾选“允许查看全量数据”。





### 3.4 API 调用日志审计

* **功能描述**：记录谁、在什么时间、传了什么参数、查了多少条数据、耗时多久。用于对账、排查技术问题及防爬虫滥用。

---

## 4. 外部 API 接口技术需求（技术实现核心）

上下游技术人员不关心 Web 界面，他们直接对接此处的 API。

### 4.1 接口通用规范

* **请求方式**：统一使用 `GET` 或 `POST` 请求，返回格式统一为 `JSON`。
* **字符编码**：`UTF-8`。
* **安全鉴权机制（推荐签名验证）**：
* 请求头（Headers）中必须携带：
* `X-API-Key`: 平台分配的客户端唯一标识。
* `X-Timestamp`: 发起请求的时间戳（10位或13位），防止重放攻击（超过5分钟则失效）。
* `X-Sign`: 签名字符串。生成规则：将所有请求参数按照字母排序后，结合 `API Secret` 进行 MD5 或 SHA256 加密。





### 4.2 接口 1：出库数据拉取接口

* **接口地址**：`/api/v1/chuku`
* **请求参数 (Query Params / JSON Body)**：
| 参数名 | 类型 | 是否必填 | 说明 | 示例 |
| --- | --- | --- | --- | --- |
| `start_date` | String | 否 | 开始日期 (YYYY-MM-DD) | `2026-06-16` |
| `end_date` | String | 否 | 结束日期 (YYYY-MM-DD) | `2026-06-16` |
| `page` | Integer | 否 | 页码，默认 1 | `1` |
| `limit` | Integer | 否 | 每页条数，默认 100，最大 500 | `100` |


* **数据隔离逻辑（后台自动追加）**：
技术人员在后台根据当前请求的 `API Key` 识别出对应客户，自动关联 SQL Server 出库表中的 `[销方全称]` 或 `[客户编码]` 进行过滤。
* **返回数据字段样例（基于客户真实出库字段）**：
```json
{
  "code": 200,
  "msg": "success",
  "total": 1250,
  "data": [
    {
      "line_no": 1.0,
      "type": "出库登记",
      "ticket_no": "A01C202606160002",
      "operator": "张洪艳",
      "salesman": "翟智永",
      "customer_name": "喀喇沁旗中医蒙医医院",
      "product_no": "400102",
      "product_name": "川芎",
      "specification": "片",
      "origin_place": "四川彭州",
      "quantity": 10.0,
      "unit": "kg",
      "unit_price": 33.5,
      "amount": 335.0,
      "batch_no": "2604799116",
      "expiry_date": "2029-05-01", 
      "manufacturer": "安国市祁澳中药饮片有限公司",
      "date": "2026-06-16"
    }
  ]
}

```


*(注：技术开发时，需将 SQL Server 内部存储的日期数字格式如 46189.0 或 47222.0 自动转换为标准日期字符串 YYYY-MM-DD 给到上下游。)*

### 4.3 接口 2：入库数据拉取接口

* **接口地址**：`/api/v1/ruku`
* **请求参数**：同出库接口（支持按日期、分页查询）。
* **数据隔离逻辑**：技术人员根据 `API Key` 自动关联 SQL Server 入库表中的 `[供方全称]` 或 `[供方编码]` 进行过滤。
* **返回数据字段样例（基于客户真实入库字段）**：
```json
{
  "code": 200,
  "msg": "success",
  "total": 80,
  "data": [
    {
      "line_no": 1.0,
      "ticket_no": "A01Q202606160002",
      "operator": "高紫叶",
      "supplier_code": "1533",
      "supplier_name": "通化华夏药业有限责任公司",
      "product_no": "900169",
      "product_name": "苦碟子注射液",
      "specification": "20ml*4支",
      "unit": "支",
      "warehouse": "Z01",
      "quantity": 3960.0,
      "dosage_form": "注射剂",
      "product_category": "中成药",
      "unit_price": 25.73,
      "amount": 101890.8,
      "batch_no": "260209",
      "expiry_date": "2027-08-15",
      "date": "2026-06-16"
    }
  ]
}

```



---

## 5. 非功能性与安全需求（技术必看）

### 5.1 性能与高并发保护（限流机制）

* **痛点**：防止上下游客户写错代码，用 `while(true)` 死循环调用接口，导致客户的 SQL Server 崩溃。
* **技术实现**：
* 后台必须支持**API限流（Rate Limiting）**。
* 默认限制：单个账号每分钟最多调用 60 次，每天最多调用 5000 次（可在后台针对特定大客户调高）。
* 触发限流返回 `429 Too Many Requests`。



### 5.2 数据库连接优化

* **慢查询防护**：由于 SQL Server 属于传统进销存，直接做高频大表查询容易锁表。
* **技术实现**：
* API 必须强制要求**分页**（限制单次最大返回 500 条）。
* 必须在 SQL Server 对应的查询字段（如 `日期`、`销方全称`、`供方全称`）上建立**索引 (Index)**，以保障查询在毫秒级完成。
* 可视情况引入**轻量缓存机制（如 Redis 或内存缓存）**，对不常变动的历史数据进行缓存。



### 5.3 异常处理与网络安全

* 所有的 API 必须通过 **HTTPS** 传输，严禁明文 HTTP。
* SQL 查询必须使用**参数化查询（Prepared Statements）**，坚决防止上下游通过接口参数进行 **SQL 注入**。

---

## 6. 项目交付物与验收标准

### 6.1 交付物清单

1. 开放平台后台系统（可运行的系统、前后端源码）。
2. 面向上下游客户系统的 **《API 对接技术文档》**（含接口地址、鉴权签名算法、字段说明、代码示例）。
3. 平台数据库表结构设计文档。

### 6.2 验收核心场景测试

1. **开关测试**：在后台关停 A 客户，A 客户系统调用 API 应立刻失败。
2. **越权隔离测试**：A 客户传入 B 客户的名称作为参数，或者不传参数，API **绝对不能**返回 B 客户的数据，只能返回 A 自身的数据。
3. **压力保护测试**：模拟超过限流频次的调用，系统能正确拒绝请求，不拖垮本地 SQL Server。

