# 获取卖家交易评价列表接口文档（分页版）

## 接口概述

### 接口信息

| 项目 | 内容 |
|------|------|
| 接口名称 | 获取用户作为卖家的交易评价列表（分页） |
| 接口路径 | `/secondTradeRecord/getSellerEvaluationList` |
| 请求方式 | GET |
| 接口版本 | v1.1（支持分页） |
| 开发时间 | 2025-11-18 |
| 接口状态 | ✅ 已完成 |

### 功能描述

用于用户主页展示该用户作为卖家收到的所有交易评价，**支持分页查询**，包含：
- 买家完整信息（昵称、头像、真实姓名、性别、简介等）
- 评价内容和评分
- 买家和卖家的信用积分
- 买家和卖家的风控评分等级
- 交易商品信息
- 交易基本信息

---

## 请求参数

### Query Parameters

| 参数名 | 类型 | 必填 | 描述 | 示例值 | 默认值 |
|--------|------|------|------|--------|--------|
| sellerId | Integer | ✅ 是 | 卖家用户ID（主页用户ID） | 123 | - |
| pageNum | Integer | ❌ 否 | 页码（从1开始） | 1 | 1 |
| pageSize | Integer | ❌ 否 | 每页条数（最大100） | 10 | 10 |

**参数说明：**
- `pageNum`: 页码从1开始，传入小于1的值自动修正为1
- `pageSize`: 每页条数，传入小于1的值自动修正为10，超过100自动限制为100

### 请求示例

#### cURL

```bash
# 获取第1页，每页10条（使用默认值）
curl -X GET "http://localhost:8080/secondTradeRecord/getSellerEvaluationList?sellerId=123" \
  -H "Authorization: Bearer your_token_here"

# 获取第2页，每页20条
curl -X GET "http://localhost:8080/secondTradeRecord/getSellerEvaluationList?sellerId=123&pageNum=2&pageSize=20" \
  -H "Authorization: Bearer your_token_here"
```

#### JavaScript (Axios)

```javascript
// 基本用法
axios.get('/secondTradeRecord/getSellerEvaluationList', {
  params: {
    sellerId: 123,
    pageNum: 1,
    pageSize: 10
  },
  headers: {
    'Authorization': 'Bearer your_token_here'
  }
})
.then(response => {
  const { records, total, pages, current, size } = response.data.data;
  console.log(`当前第${current}页，每页${size}条`);
  console.log(`共${total}条数据，${pages}页`);
  console.log('评价列表：', records);
})
.catch(error => {
  console.error(error);
});

// 结合分页组件使用
function loadEvaluations(sellerId, pageNum = 1, pageSize = 10) {
  return axios.get('/secondTradeRecord/getSellerEvaluationList', {
    params: { sellerId, pageNum, pageSize }
  });
}

// 加载下一页
function loadNextPage(currentPage) {
  loadEvaluations(123, currentPage + 1, 10)
    .then(response => {
      // 处理数据
    });
}
```

#### Java (RestTemplate)

```java
String url = "http://localhost:8080/secondTradeRecord/getSellerEvaluationList" +
             "?sellerId=123&pageNum=1&pageSize=10";
RestTemplate restTemplate = new RestTemplate();
R<IPage<SellerEvaluationVo>> result = restTemplate.getForObject(url, R.class);

IPage<SellerEvaluationVo> page = result.getData();
System.out.println("总记录数：" + page.getTotal());
System.out.println("总页数：" + page.getPages());
System.out.println("当前页：" + page.getCurrent());
System.out.println("每页条数：" + page.getSize());
List<SellerEvaluationVo> records = page.getRecords();
```

---

## 响应参数

### 响应结构

| 字段名 | 类型 | 描述 |
|--------|------|------|
| code | Integer | 响应状态码，200表示成功 |
| msg | String | 响应消息 |
| data | IPage&lt;SellerEvaluationVo&gt; | 分页数据对象 |

### IPage 分页对象结构

| 字段名 | 类型 | 描述 | 示例值 |
|--------|------|------|--------|
| records | Array&lt;SellerEvaluationVo&gt; | 当前页的评价列表 | [...] |
| total | Long | 总记录数 | 45 |
| size | Long | 每页条数 | 10 |
| current | Long | 当前页码 | 1 |
| pages | Long | 总页数 | 5 |

### SellerEvaluationVo 对象结构

#### 交易基本信息

| 字段名 | 类型 | 是否必返 | 描述 | 示例值 |
|--------|------|----------|------|--------|
| id | Integer | ✅ | 交易记录ID | 1 |
| tradeNo | String | ✅ | 交易编号 | S2025111800001 |
| transactionTime | String | ✅ | 交易时间 | 2025-11-18 10:00:00 |
| transactionAmount | BigDecimal | ✅ | 交易金额（元） | 3800.00 |
| tradeStatus | Integer | ✅ | 交易状态 | 4 |
| createdTime | String | ✅ | 创建时间 | 2025-11-18 09:00:00 |

#### 商品信息

| 字段名 | 类型 | 是否必返 | 描述 | 示例值 |
|--------|------|----------|------|--------|
| goodsId | Integer | ✅ | 商品ID | 100 |
| goodsTitle | String | ❌ | 商品标题 | 二手iPhone 13 128G 白色 95新 |
| goodsHomeImage | String | ❌ | 商品封面图片URL | https://cdn.example.com/goods/iphone13.jpg |
| goodsPrice | BigDecimal | ❌ | 商品价格（元） | 3999.00 |

#### 买家信息

| 字段名 | 类型 | 是否必返 | 描述 | 示例值 |
|--------|------|----------|------|--------|
| buyerId | Integer | ✅ | 买家ID | 456 |
| buyerName | String | ❌ | 买家昵称 | 张三 |
| buyerImage | String | ❌ | 买家头像URL | https://cdn.example.com/avatar/user456.jpg |
| buyerPhone | String | ❌ | 买家手机号 | 13800138000 |
| buyerRealName | String | ❌ | 买家真实姓名 | 张三三 |
| buyerSex | String | ❌ | 买家性别 | 男 |
| buyerJianjie | String | ❌ | 买家简介 | 热爱数码产品，诚信交易 |

#### 买家评价信息

| 字段名 | 类型 | 是否必返 | 描述 | 示例值 |
|--------|------|----------|------|--------|
| buyerEvaluate | String | ✅ | 买家评价内容 | 商品质量很好，和描述一致，卖家态度也不错，推荐！ |
| buyerRating | Integer | ❌ | 买家评分（1-5分） | 5 |
| buyerCreditScore | Integer | ✅ | 买家信用积分 | 450 |
| buyerCreditLevel | String | ✅ | 买家风控评分等级 | A |

#### 卖家信息

| 字段名 | 类型 | 是否必返 | 描述 | 示例值 |
|--------|------|----------|------|--------|
| sellerId | Integer | ✅ | 卖家ID | 123 |
| sellerName | String | ❌ | 卖家昵称 | 李四 |
| sellerImage | String | ❌ | 卖家头像URL | https://cdn.example.com/seller.jpg |
| sellerCreditScore | Integer | ✅ | 卖家信用积分 | 500 |
| sellerCreditLevel | String | ✅ | 卖家风控评分等级 | O |

---

## 枚举说明

### 交易状态 (tradeStatus)

| 状态值 | 状态名称 | 说明 |
|--------|----------|------|
| 1 | 待确认 | 买家发起交易请求，等待卖家确认 |
| 2 | 已拒绝 | 卖家拒绝了交易请求 |
| 3 | 待交易 | 双方确认交易，等待线下交易 |
| 4 | 交易成功 | 交易完成，双方确认成功 |
| 5 | 交易失败 | 交易失败 |
| 6 | 交易取消 | 交易被取消 |

### 风控评分等级 (creditLevel)

| 等级 | 违规次数 | 等级说明 | 风险程度 |
|------|----------|----------|----------|
| O | 0次 | 无违规记录 | 🟢 无风险（最优） |
| A | 1-2次 | 轻微违规 | 🟢 低风险 |
| B | 3-5次 | 一般违规 | 🟡 中等风险 |
| C | 6-9次 | 较严重违规 | 🟡 较高风险 |
| D | 10-14次 | 严重违规 | 🔴 高风险 |
| E | ≥15次 | 极差 | 🔴 极高风险（最差） |

---

## 响应示例

### 成功响应（有数据）

```json
{
  "code": 200,
  "msg": "成功",
  "data": {
    "records": [
      {
        "id": 1,
        "tradeNo": "S2025111800001",
        "goodsId": 100,
        "goodsTitle": "二手iPhone 13 128G 白色 95新",
        "goodsHomeImage": "https://cdn.example.com/goods/iphone13.jpg",
        "goodsPrice": 3999.00,
        "transactionAmount": 3800.00,
        "buyerId": 456,
        "buyerName": "张三",
        "buyerImage": "https://cdn.example.com/avatar/user456.jpg",
        "buyerPhone": "13800138000",
        "buyerRealName": "张三三",
        "buyerSex": "男",
        "buyerJianjie": "热爱数码产品，诚信交易",
        "buyerEvaluate": "商品质量很好，和描述一致，卖家态度也不错，推荐！",
        "buyerRating": 5,
        "buyerCreditScore": 450,
        "buyerCreditLevel": "A",
        "sellerId": 123,
        "sellerName": "李四",
        "sellerImage": "https://cdn.example.com/avatar/user123.jpg",
        "sellerCreditScore": 500,
        "sellerCreditLevel": "O",
        "transactionTime": "2025-11-18 10:00:00",
        "tradeStatus": 4,
        "createdTime": "2025-11-18 09:00:00"
      }
    ],
    "total": 45,
    "size": 10,
    "current": 1,
    "pages": 5
  }
}
```

### 空数据响应

```json
{
  "code": 200,
  "msg": "成功",
  "data": {
    "records": [],
    "total": 0,
    "size": 10,
    "current": 1,
    "pages": 0
  }
}
```

### 错误响应

#### 参数缺失

```json
{
  "code": 500,
  "msg": "获取评价列表失败: 卖家ID不能为空",
  "data": null
}
```

#### 系统异常

```json
{
  "code": 500,
  "msg": "获取评价列表失败: 数据库连接异常",
  "data": null
}
```

---

## 分页计算说明

### 分页参数

- **pageNum**: 当前页码，从 1 开始
- **pageSize**: 每页显示条数
- **total**: 总记录数
- **pages**: 总页数 = Math.ceil(total / pageSize)

### 分页示例

假设某卖家有 45 条评价：

| pageNum | pageSize | 返回记录 | 页面显示 |
|---------|----------|----------|----------|
| 1 | 10 | 1-10 | 第1页，共5页，显示10条 |
| 2 | 10 | 11-20 | 第2页，共5页，显示10条 |
| 3 | 10 | 21-30 | 第3页，共5页，显示10条 |
| 4 | 10 | 31-40 | 第4页，共5页，显示10条 |
| 5 | 10 | 41-45 | 第5页，共5页，显示5条 |

---

## 业务规则

### 查询规则

1. **数据过滤**
   - ✅ 只返回有买家评价内容的记录（`buyer_evaluate IS NOT NULL AND buyer_evaluate != ''`）
   - ✅ 只返回未删除的记录（`delete_flag = 0`）
   - ✅ 按创建时间倒序排列（最新评价在前）

2. **分页限制**
   - ✅ pageNum < 1 时自动修正为 1
   - ✅ pageSize < 1 时自动修正为 10
   - ✅ pageSize > 100 时自动限制为 100（防止数据量过大）

3. **数据关联**
   - 商品信息：通过 `goods_record_id` 关联 `second_goods_record` 表
   - 买家信息：通过 `buyer_id` 关联 `life_user` 表
   - 卖家信息：通过 `seller_id` 关联 `life_user` 表
   - 信用积分：通过 `user_id` 关联 `second_user_credit` 表
   - 风控等级：实时计算，查询 `second_risk_control_record` 表

4. **性能优化**
   - 使用 MyBatis Plus 分页插件
   - 批量查询避免 N+1 问题
   - 关联数据使用 Map 索引，时间复杂度 O(1)
   - 只查询当前页的交易记录，再批量关联其他信息

---

## 错误码说明

| HTTP状态码 | code | msg | 说明 | 解决方案 |
|-----------|------|-----|------|----------|
| 200 | 200 | 成功 | 请求成功 | - |
| 200 | 500 | 卖家ID不能为空 | 未传入 sellerId 参数 | 检查请求参数，确保传入 sellerId |
| 200 | 500 | 获取评价列表失败: xxx | 系统异常 | 查看日志，联系后端开发人员 |
| 500 | - | - | 服务器内部错误 | 联系后端开发人员 |

---

## 前端分页实现示例

### Vue 3 + Element Plus

```vue
<template>
  <div class="evaluation-list">
    <!-- 评价列表 -->
    <div v-for="item in evaluations" :key="item.id" class="evaluation-item">
      <div class="buyer-info">
        <img :src="item.buyerImage" :alt="item.buyerName" />
        <span>{{ item.buyerName }}</span>
        <el-rate :model-value="item.buyerRating" disabled />
      </div>
      <div class="evaluation-content">{{ item.buyerEvaluate }}</div>
      <div class="evaluation-time">{{ item.createdTime }}</div>
    </div>
    
    <!-- 分页组件 -->
    <el-pagination
      v-model:current-page="pageNum"
      v-model:page-size="pageSize"
      :page-sizes="[10, 20, 50, 100]"
      :total="total"
      layout="total, sizes, prev, pager, next, jumper"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import axios from 'axios';

const sellerId = ref(123);
const pageNum = ref(1);
const pageSize = ref(10);
const total = ref(0);
const evaluations = ref([]);

// 加载评价列表
const loadEvaluations = async () => {
  try {
    const response = await axios.get('/secondTradeRecord/getSellerEvaluationList', {
      params: {
        sellerId: sellerId.value,
        pageNum: pageNum.value,
        pageSize: pageSize.value
      }
    });
    
    const { records, total: totalCount } = response.data.data;
    evaluations.value = records;
    total.value = totalCount;
  } catch (error) {
    console.error('加载失败:', error);
  }
};

// 每页条数改变
const handleSizeChange = (newSize) => {
  pageSize.value = newSize;
  pageNum.value = 1; // 重置到第一页
  loadEvaluations();
};

// 当前页改变
const handleCurrentChange = (newPage) => {
  pageNum.value = newPage;
  loadEvaluations();
};

onMounted(() => {
  loadEvaluations();
});
</script>
```

### React + Ant Design

```jsx
import React, { useState, useEffect } from 'react';
import { Pagination, Rate, Avatar, List } from 'antd';
import axios from 'axios';

function SellerEvaluationList({ sellerId }) {
  const [pageNum, setPageNum] = useState(1);
  const [pageSize, setPageSize] = useState(10);
  const [total, setTotal] = useState(0);
  const [evaluations, setEvaluations] = useState([]);
  const [loading, setLoading] = useState(false);

  // 加载评价列表
  const loadEvaluations = async () => {
    setLoading(true);
    try {
      const response = await axios.get('/secondTradeRecord/getSellerEvaluationList', {
        params: { sellerId, pageNum, pageSize }
      });
      
      const { records, total: totalCount } = response.data.data;
      setEvaluations(records);
      setTotal(totalCount);
    } catch (error) {
      console.error('加载失败:', error);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    loadEvaluations();
  }, [pageNum, pageSize, sellerId]);

  // 页码改变
  const handlePageChange = (page, size) => {
    setPageNum(page);
    setPageSize(size);
  };

  return (
    <div>
      <List
        loading={loading}
        dataSource={evaluations}
        renderItem={(item) => (
          <List.Item>
            <List.Item.Meta
              avatar={<Avatar src={item.buyerImage} />}
              title={
                <div>
                  <span>{item.buyerName}</span>
                  <Rate value={item.buyerRating} disabled style={{ marginLeft: 10 }} />
                </div>
              }
              description={
                <>
                  <div>{item.buyerEvaluate}</div>
                  <div style={{ color: '#999', fontSize: 12, marginTop: 5 }}>
                    {item.createdTime}
                  </div>
                </>
              }
            />
          </List.Item>
        )}
      />
      
      <Pagination
        current={pageNum}
        pageSize={pageSize}
        total={total}
        onChange={handlePageChange}
        showSizeChanger
        showQuickJumper
        showTotal={(total) => `共 ${total} 条`}
        pageSizeOptions={[10, 20, 50, 100]}
      />
    </div>
  );
}

export default SellerEvaluationList;
```

---

## 注意事项

### ⚠️ 重要提示

1. **必传参数**
   - `sellerId` 为必传参数，用于查看指定用户的评价列表
   - 不传或传空会返回错误：`"卖家ID不能为空"`

2. **分页参数**
   - `pageNum` 和 `pageSize` 为可选参数，有默认值
   - pageSize 最大值限制为 100，超过自动修正

3. **数据权限**
   - 接口不做权限校验，任何人都可以查看用户主页的公开评价
   - 如需增加权限控制，请联系后端开发人员

4. **空数据处理**
   - 如果该用户没有收到任何评价，返回空数组 `[]`
   - total 为 0，pages 为 0
   - 前端需要处理空状态展示

5. **字段可空性**
   - 部分字段可能为 `null`，前端需要做空值判断
   - 建议使用可选链操作符或空值合并运算符

---

## 版本历史

| 版本 | 日期 | 修改内容 | 修改人 |
|------|------|----------|--------|
| v1.0 | 2025-11-18 | 初始版本，返回全部数据 | 开发团队 |
| v1.1 | 2025-11-18 | **新增分页功能** | 开发团队 |
| v1.1 | 2025-11-18 | 优化查询方式，使用 MyBatis Plus | 开发团队 |
| v1.1 | 2025-11-18 | 增加风控评分等级计算 | 开发团队 |
| v1.1 | 2025-11-18 | 增加更多用户信息字段 | 开发团队 |

---

## 联系方式

如有问题或建议，请联系：

- **开发团队**：二手交易平台开发组
- **服务名称**：alien-second
- **文档路径**：`alien-second/doc/获取卖家交易评价列表接口文档.md`

---

*最后更新时间：2025-11-18（v1.1 - 支持分页）*
