复现已有算法
This commit is contained in:
+238
@@ -0,0 +1,238 @@
|
||||
# 接口文档
|
||||
|
||||
## 通用响应
|
||||
|
||||
后端接口统一返回:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"msg": "success",
|
||||
"data": {}
|
||||
}
|
||||
```
|
||||
|
||||
`status` 为 `0` 表示成功,非 `0` 表示业务失败。
|
||||
|
||||
## 系统接口
|
||||
|
||||
### GET /api/system/health
|
||||
|
||||
返回服务健康状态。
|
||||
|
||||
成功响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"status": "ok"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/system/version
|
||||
|
||||
返回服务版本信息。
|
||||
|
||||
成功响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"name": "wind_power_cal",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 风功率计算接口
|
||||
|
||||
### POST /api/wind/jobs/start
|
||||
|
||||
创建风功率计算任务。前端已完成 Excel 表头解析和字段映射,后端只保存任务元数据。
|
||||
|
||||
请求:
|
||||
|
||||
```json
|
||||
{
|
||||
"files": [
|
||||
{
|
||||
"file_name": "01_风机历史数据.xls",
|
||||
"row_count": 51906
|
||||
}
|
||||
],
|
||||
"mapping": {
|
||||
"time": "时间",
|
||||
"fan_id": "风机编号",
|
||||
"wind_speed": "风速(m/s)",
|
||||
"active_power": "有功功率(kW)",
|
||||
"generator_speed": "发电机转速(rpm)"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
成功响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"job_id": "job_123"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### POST /api/wind/jobs/chunk
|
||||
|
||||
上传标准化后的数据分片。每行字段必须使用标准字段名。
|
||||
|
||||
请求:
|
||||
|
||||
```json
|
||||
{
|
||||
"job_id": "job_123",
|
||||
"chunk_index": 0,
|
||||
"rows": [
|
||||
{
|
||||
"time": "2024-09-01 14:00:00",
|
||||
"fan_id": "01#",
|
||||
"wind_speed": 3.414,
|
||||
"active_power": 114.3471,
|
||||
"generator_speed": 1109.3143
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
成功响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"accepted_rows": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### POST /api/wind/jobs/finish
|
||||
|
||||
完成任务并执行清洗、排序、分箱和功率曲线计算。
|
||||
|
||||
请求:
|
||||
|
||||
```json
|
||||
{
|
||||
"job_id": "job_123",
|
||||
"options": {
|
||||
"rated_power": 4800,
|
||||
"rated_wind_speed": 18,
|
||||
"power_step": 5,
|
||||
"cleaning_wind_speed_step": 0.25,
|
||||
"curve_wind_speed_step": 0.5,
|
||||
"wind_speed_change_threshold": 1,
|
||||
"iqr_lower_multiplier": 1.8,
|
||||
"iqr_upper_multiplier": 2,
|
||||
"minimum_generator_speed": 1,
|
||||
"generator_speed_k": 0.9
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
成功响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"summary": {
|
||||
"raw_rows": 51906,
|
||||
"valid_rows": 38017,
|
||||
"invalid_rows": 13889,
|
||||
"duplicate_rows": 0,
|
||||
"limit_power_rows": 0,
|
||||
"tip_speed_ratio_outlier_rows": 0,
|
||||
"speed_power_outlier_rows": 0,
|
||||
"invalid_reasons": {
|
||||
"invalid_active_power": 13889,
|
||||
"limit_power": 0,
|
||||
"tip_speed_ratio_outlier": 0,
|
||||
"speed_power_outlier": 0
|
||||
},
|
||||
"fan_count": 1
|
||||
},
|
||||
"fans": ["01#"],
|
||||
"curves": {
|
||||
"01#": [
|
||||
{
|
||||
"wind_speed_start": 3.0,
|
||||
"wind_speed_end": 3.5,
|
||||
"wind_speed": 3.25,
|
||||
"sample_count": 120,
|
||||
"average_power": 180.5,
|
||||
"median_power": 176.2,
|
||||
"stddev_power": 32.1,
|
||||
"p25_power": 150.0,
|
||||
"p75_power": 205.0,
|
||||
"confidence": "脚本分箱"
|
||||
}
|
||||
]
|
||||
},
|
||||
"bins": {
|
||||
"01#": []
|
||||
},
|
||||
"scatter_points": {
|
||||
"01#": [
|
||||
{
|
||||
"wind_speed": 3.414,
|
||||
"active_power": 114.3471
|
||||
}
|
||||
]
|
||||
},
|
||||
"filtered_points": {
|
||||
"01#": [
|
||||
{
|
||||
"wind_speed": 5.2,
|
||||
"active_power": 430.0,
|
||||
"reason": "speed_power_outlier"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
清洗规则:
|
||||
|
||||
- `active_power <= 0` 的数据剔除。
|
||||
- `generator_speed < generator_speed_k * minimum_generator_speed` 的数据剔除。
|
||||
- 时间不可解析的数据剔除。
|
||||
- 风机编号为空的数据剔除。
|
||||
- `wind_speed <= 0` 的数据剔除。
|
||||
- 同一风机同一时间重复记录保留第一条。
|
||||
- 限功率识别按参考脚本执行:按功率分箱、按日期分组,组内风速跨度大于阈值时剔除。
|
||||
- 叶尖速比使用参考脚本公式 `generator_speed * 3.14 * 162 * 78 * 30 / wind_speed`,按风速分箱做 IQR 清洗。
|
||||
- 风速-功率关系按同一风速分箱和 IQR 参数清洗。
|
||||
- 最终曲线按 `curve_wind_speed_step` 左开右闭分箱,区间非空即输出平均功率点。
|
||||
- `scatter_points` 返回清洗后保留点,`filtered_points` 返回限功率和 IQR 阶段滤除的点。
|
||||
|
||||
### DELETE /api/wind/jobs/{job_id}
|
||||
|
||||
清理未完成任务的临时文件。
|
||||
|
||||
成功响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"msg": "success",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,353 @@
|
||||
# 风机历史数据无效值清洗与功率计算设计
|
||||
|
||||
## 背景与目标
|
||||
|
||||
当前 `docs/完整年数据/` 目录下保存了 16 台风机从 `2024-09-01 14:00:00` 到 `2025-09-01 14:00:00` 的历史数据。以 `01_2024-09-01_14-00-00-2025-09-01_14-00-00_风机历史数据.xls` 为例,文件为 10 分钟粒度历史数据,包含风速、发电机转速、桨叶角度和有功功率等字段。
|
||||
|
||||
本文档定义两类计算口径:
|
||||
|
||||
- 无效值清洗:从历史数据中剔除停机、无风、无功率、异常转速、异常风速、疑似限功率和统计离群点。
|
||||
- 风机功率计算:直接使用实测 `有功功率(kW)` 作为时刻功率,并基于清洗后的数据计算风速-功率曲线和发电量。
|
||||
|
||||
## 数据输入
|
||||
|
||||
当前历史数据字段如下:
|
||||
|
||||
| 字段 | 单位 | 用途 |
|
||||
| --- | --- | --- |
|
||||
| 时间 | - | 数据时间戳,当前主要为 10 分钟间隔 |
|
||||
| 风机编号 | - | 区分风机,如 `01#` |
|
||||
| 风机限功率时间(s) | s | 累计类字段,不能直接用 `> 0` 判断当前是否限功率 |
|
||||
| 变流器发电机转速(rpm) | rpm | 辅助判断运行状态和转速异常 |
|
||||
| 发电机转速(rpm) | rpm | 判断是否发电、计算叶尖速比时使用 |
|
||||
| 风速(m/s) | m/s | 风速分箱和功率曲线计算 |
|
||||
| 当前桨叶角度(°) | ° | 辅助识别停机、顺桨、限功率或异常状态 |
|
||||
| 有功功率(kW) | kW | 实测输出功率,作为风机时刻功率 |
|
||||
|
||||
## 设计原则
|
||||
|
||||
- 先清洗后计算,所有功率曲线、发电量、性能指标均基于清洗后的有效数据。
|
||||
- 实测功率优先,已有 `有功功率(kW)` 时不使用理论风功率公式反推时刻功率。
|
||||
- 清洗规则分层执行,基础无效值直接剔除,疑似限功率和统计离群点应可追溯标记。
|
||||
- 每个风速区间必须输出样本数,样本不足的区间不能作为正式功率曲线点。
|
||||
- 额定功率、额定风速、叶轮直径、齿轮箱速比等机型参数必须配置化,不能写死为旧脚本中的 `4800` 或 `6700`。
|
||||
|
||||
## 无效值清洗方案
|
||||
|
||||
### 1. 字段校验
|
||||
|
||||
读取每个 `.xls` 文件后,先检查必需字段:
|
||||
|
||||
```text
|
||||
时间
|
||||
风机编号
|
||||
发电机转速(rpm)
|
||||
风速(m/s)
|
||||
当前桨叶角度(°)
|
||||
有功功率(kW)
|
||||
```
|
||||
|
||||
如果缺少 `有功功率(kW)` 或 `风速(m/s)`,该文件不能用于功率曲线计算。如果缺少 `发电机转速(rpm)` 或 `当前桨叶角度(°)`,仍可做基础风速-功率统计,但不能执行完整运行状态清洗。
|
||||
|
||||
### 2. 时间清洗
|
||||
|
||||
时间字段需转换为标准时间戳。以下数据应剔除或单独标记:
|
||||
|
||||
- 时间为空或无法解析。
|
||||
- 同一风机同一时间重复记录。
|
||||
- 时间倒序记录。
|
||||
- 与前一条记录间隔明显异常的数据段。
|
||||
|
||||
当前数据主要为 10 分钟粒度。若用于发电量积分,建议对异常间隔单独处理,不要默认每条都是 10 分钟。
|
||||
|
||||
### 3. 基础有效发电点过滤
|
||||
|
||||
用于计算风速-功率曲线时,建议保留满足以下条件的数据:
|
||||
|
||||
```text
|
||||
风速(m/s) > 0
|
||||
有功功率(kW) > 0
|
||||
发电机转速(rpm) > 1
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- `有功功率(kW) = 0` 通常表示未发电、停机、待机或数据无效,不应参与功率曲线均值。
|
||||
- `发电机转速(rpm) <= 1` 通常表示机组未处于正常发电转动状态。
|
||||
- 风速为 0 或负数不符合功率曲线计算输入条件。
|
||||
|
||||
### 4. 物理边界过滤
|
||||
|
||||
按机型参数增加边界过滤:
|
||||
|
||||
| 指标 | 建议规则 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| 风速 | `0 < 风速 <= 35` | 超出范围优先视为传感器或导出异常 |
|
||||
| 有功功率 | `0 < 有功功率 <= 额定功率 * 1.10` | 保留少量超额定裕度,过高视为异常 |
|
||||
| 发电机转速 | `0 < 转速 <= 最大允许转速 * 1.05` | 最大允许转速从机型配置获取 |
|
||||
| 桨叶角度 | `-10 <= 桨叶角度 <= 95` | 极端负角度或过大角度需结合状态判断 |
|
||||
|
||||
当前 01 号文件最大有功功率约为 `3307 kW`,因此该机组额定功率应按约 `3300 kW` 级配置,不能使用旧脚本中的 `4800 kW` 或 `6700 kW`。
|
||||
|
||||
### 5. 疑似限功率识别
|
||||
|
||||
`风机限功率时间(s)` 是累计时间类字段,当前文件中全量数据均大于 0,不能用 `风机限功率时间(s) > 0` 判断当前记录是否限功率。
|
||||
|
||||
建议使用相邻记录增量辅助判断:
|
||||
|
||||
```text
|
||||
限功率时间增量 = 当前行 风机限功率时间(s) - 上一行 风机限功率时间(s)
|
||||
```
|
||||
|
||||
疑似限功率点可按以下条件组合识别:
|
||||
|
||||
- 限功率时间增量大于 0。
|
||||
- 风速较高,但有功功率长期低于同风速段正常中位功率。
|
||||
- 相邻多个 10 分钟点功率接近同一平台值,但风速变化明显。
|
||||
- 桨叶角度明显偏大,且功率未随风速增加。
|
||||
|
||||
建议先把疑似限功率数据标记为 `is_limited = true`,不要直接删除。计算正常功率曲线时排除;分析限功率损失时保留。
|
||||
|
||||
### 6. 叶尖速比异常过滤
|
||||
|
||||
如果需要使用叶尖速比辅助清洗,应采用标准公式,不建议沿用旧脚本中的硬编码乘法。
|
||||
|
||||
叶尖速比计算公式:
|
||||
|
||||
```text
|
||||
叶轮转速(rpm) = 发电机转速(rpm) / 齿轮箱速比
|
||||
叶尖速比 = 叶轮转速(rpm) * 2π / 60 * 叶轮半径(m) / 风速(m/s)
|
||||
```
|
||||
|
||||
示例:
|
||||
|
||||
```text
|
||||
lambda = generator_rpm / gearbox_ratio * 2π / 60 * rotor_radius / wind_speed
|
||||
```
|
||||
|
||||
叶轮半径、齿轮箱速比必须来自机型配置。清洗时可按风速分箱,对每个风速区间内的叶尖速比使用 IQR 或 MAD 剔除离群点。
|
||||
|
||||
### 7. 风速-功率离群点过滤
|
||||
|
||||
按风速分箱后,对每个风速区间内的 `有功功率(kW)` 做统计过滤。
|
||||
|
||||
推荐分箱宽度:
|
||||
|
||||
```text
|
||||
0.5 m/s
|
||||
```
|
||||
|
||||
样本数规则:
|
||||
|
||||
| 区间样本数 | 处理方式 |
|
||||
| --- | --- |
|
||||
| `< 10` | 不剔除,但标记为样本不足,不参与正式曲线 |
|
||||
| `10 - 29` | 可做宽松离群过滤,结果标记为低置信度 |
|
||||
| `>= 30` | 执行正式离群过滤,可用于功率曲线 |
|
||||
|
||||
IQR 过滤规则:
|
||||
|
||||
```text
|
||||
Q1 = 区间功率 25% 分位数
|
||||
Q3 = 区间功率 75% 分位数
|
||||
IQR = Q3 - Q1
|
||||
下限 = Q1 - 1.5 * IQR
|
||||
上限 = Q3 + 1.5 * IQR
|
||||
保留 下限 <= 有功功率 <= 上限 的数据
|
||||
```
|
||||
|
||||
高风速额定平台区建议额外处理。额定风速以上,功率应接近额定功率;如果出现大量高风速低功率点,应优先判断为限功率、停机、故障或弃风,不应简单参与正常功率曲线均值。
|
||||
|
||||
## 风机功率计算方案
|
||||
|
||||
### 1. 时刻功率
|
||||
|
||||
历史数据中已有实测功率字段,时刻功率直接取:
|
||||
|
||||
```text
|
||||
风机时刻功率(kW) = 有功功率(kW)
|
||||
```
|
||||
|
||||
不建议使用以下理论公式替代实测时刻功率:
|
||||
|
||||
```text
|
||||
P = 0.5 * ρ * A * Cp * v^3
|
||||
```
|
||||
|
||||
该公式适合估算风能理论功率或做性能分析,需要空气密度、叶轮扫掠面积和功率系数,不适合在已有实测有功功率时反算实际输出。
|
||||
|
||||
### 2. 风速-功率曲线
|
||||
|
||||
风速-功率曲线用于描述不同风速下机组的实测输出能力。计算步骤:
|
||||
|
||||
```text
|
||||
1. 使用清洗后的有效发电点。
|
||||
2. 按风速分箱,建议 0.5 m/s 一个区间。
|
||||
3. 每个区间统计有功功率。
|
||||
4. 输出平均功率、中位数功率、样本数、标准差和分位数。
|
||||
5. 样本不足或疑似限功率区间只标记,不作为正式曲线点。
|
||||
```
|
||||
|
||||
区间定义建议采用左开右闭:
|
||||
|
||||
```text
|
||||
(区间起点, 区间终点]
|
||||
```
|
||||
|
||||
例如:
|
||||
|
||||
```text
|
||||
(3.75, 4.25] -> 风速中心 4.0 m/s
|
||||
(4.25, 4.75] -> 风速中心 4.5 m/s
|
||||
```
|
||||
|
||||
输出字段:
|
||||
|
||||
| 字段 | 说明 |
|
||||
| --- | --- |
|
||||
| 风机编号 | 当前风机 |
|
||||
| 风速区间起点 | 左边界 |
|
||||
| 风速区间终点 | 右边界 |
|
||||
| 风速中心 | 区间中点 |
|
||||
| 样本数 | 清洗后有效点数量 |
|
||||
| 平均功率(kW) | 区间功率均值 |
|
||||
| 中位数功率(kW) | 区间功率中位数 |
|
||||
| 功率标准差(kW) | 区间功率离散程度 |
|
||||
| P25功率(kW) | 25% 分位数 |
|
||||
| P75功率(kW) | 75% 分位数 |
|
||||
| 置信度 | 正常、低样本、样本不足、疑似限功率 |
|
||||
|
||||
### 3. 发电量计算
|
||||
|
||||
若需要计算年发电量,应对功率按时间积分。
|
||||
|
||||
若确认每条数据为 10 分钟间隔:
|
||||
|
||||
```text
|
||||
单条发电量(kWh) = 有功功率(kW) * 10 / 60
|
||||
总发电量(kWh) = 所有单条发电量求和
|
||||
```
|
||||
|
||||
更稳妥的通用算法是使用相邻时间戳差值:
|
||||
|
||||
```text
|
||||
时间间隔(h) = 下一条时间 - 当前时间
|
||||
单条发电量(kWh) = 当前有功功率(kW) * 时间间隔(h)
|
||||
```
|
||||
|
||||
时间间隔异常时建议标记,不直接参与年发电量统计,或按业务规则补齐。
|
||||
|
||||
### 4. 理论风功率和性能指标
|
||||
|
||||
如需评估风能利用效率,可额外计算理论风功率:
|
||||
|
||||
```text
|
||||
扫掠面积 A = π * 叶轮半径^2
|
||||
理论风功率(kW) = 0.5 * 空气密度 * A * 风速^3 / 1000
|
||||
功率系数 Cp = 有功功率(kW) / 理论风功率(kW)
|
||||
```
|
||||
|
||||
注意:
|
||||
|
||||
- 空气密度应使用温度、气压、湿度或场站海拔修正。
|
||||
- Cp 只用于性能分析,不用于替代实测 `有功功率(kW)`。
|
||||
- Cp 超出合理范围时,应优先检查风速测量、空气密度、功率单位和数据清洗规则。
|
||||
|
||||
## 数据处理流程
|
||||
|
||||
```text
|
||||
读取 XLS 文件
|
||||
-> 字段校验
|
||||
-> 时间解析与排序
|
||||
-> 基础有效发电点过滤
|
||||
-> 物理边界过滤
|
||||
-> 标记疑似限功率
|
||||
-> 可选:叶尖速比异常过滤
|
||||
-> 风速-功率分箱离群过滤
|
||||
-> 输出清洗后明细
|
||||
-> 输出风速-功率曲线表
|
||||
-> 输出功率曲线图
|
||||
-> 可选:计算发电量和性能指标
|
||||
```
|
||||
|
||||
## 参数配置建议
|
||||
|
||||
| 参数 | 建议默认值 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| 风速分箱宽度 | `0.5 m/s` | 功率曲线统计常用粒度 |
|
||||
| 最小正式样本数 | `30` | 低于该值标记低置信度 |
|
||||
| 最小保留样本数 | `10` | 低于该值不参与正式曲线 |
|
||||
| IQR 系数 | `1.5` | 常规离群点过滤 |
|
||||
| 发电机最小转速 | `1 rpm` | 判断是否发电 |
|
||||
| 功率上限 | `额定功率 * 1.10` | 防止异常高功率 |
|
||||
| 风速上限 | `35 m/s` | 防止异常风速 |
|
||||
|
||||
机型配置建议包含:
|
||||
|
||||
```text
|
||||
风机编号
|
||||
额定功率(kW)
|
||||
额定风速(m/s)
|
||||
叶轮直径(m)
|
||||
齿轮箱速比
|
||||
最大允许发电机转速(rpm)
|
||||
切入风速(m/s)
|
||||
切出风速(m/s)
|
||||
```
|
||||
|
||||
## 验证计划
|
||||
|
||||
### 脚本验证
|
||||
|
||||
- 读取 01 号风机文件,确认字段数量和字段名正确。
|
||||
- 统计原始行数、有效发电点数量、剔除数量和剔除原因。
|
||||
- 输出每个风速区间的样本数、平均功率和中位数功率。
|
||||
- 检查空文件、缺字段文件、全无有效数据文件不会报错。
|
||||
|
||||
### 结果验证
|
||||
|
||||
- 功率曲线应随风速整体上升,并在额定风速附近进入平台。
|
||||
- 01 号风机最大实测功率约 `3307 kW`,额定功率配置应与该量级一致。
|
||||
- 高风速低功率点应被标记为疑似限功率、停机或异常,而不是直接拉低正式曲线。
|
||||
- 样本数不足的风速区间应在结果中明确标记。
|
||||
|
||||
### 人工复核
|
||||
|
||||
- 抽查被剔除的数据,确认不是正常发电点被误删。
|
||||
- 抽查疑似限功率点,结合桨叶角度和限功率时间增量确认规则有效。
|
||||
- 对比厂家功率曲线或历史报告,确认实测曲线形态合理。
|
||||
|
||||
## 风险与对策
|
||||
|
||||
| 风险 | 影响 | 对策 |
|
||||
| --- | --- | --- |
|
||||
| 额定功率配置错误 | 功率上限过滤和平台判断失真 | 按每台机组实测最大功率和机型资料确认 |
|
||||
| 把累计限功率时间误当状态量 | 大量正常数据被误删 | 使用相邻增量和功率形态综合判断 |
|
||||
| 分箱样本数过少 | 曲线点随机波动大 | 输出样本数和置信度,低样本不参与正式曲线 |
|
||||
| 叶尖速比公式错误 | 清洗结果偏差 | 使用标准公式,并配置叶轮半径和齿轮箱速比 |
|
||||
| 时间间隔异常 | 发电量计算偏差 | 使用相邻时间差,并对异常间隔标记 |
|
||||
|
||||
## 后续实施建议
|
||||
|
||||
建议将现有两个脚本整理为一个可配置处理流程:
|
||||
|
||||
```text
|
||||
clean_wind_history.py
|
||||
- 读取单台或多台风机历史数据
|
||||
- 输出清洗后明细
|
||||
- 输出风速-功率曲线统计表
|
||||
- 输出功率曲线图
|
||||
- 输出清洗摘要报告
|
||||
```
|
||||
|
||||
同时保留每条数据的清洗标记字段,例如:
|
||||
|
||||
```text
|
||||
is_valid_generation
|
||||
is_out_of_physical_range
|
||||
is_suspected_limited
|
||||
is_power_outlier
|
||||
invalid_reason
|
||||
```
|
||||
|
||||
这样后续既能生成正式曲线,也能追溯每条数据为什么被保留或剔除。
|
||||
Reference in New Issue
Block a user