fix(merge): 本地整合 - 保留主分支交互与样式并排除不安全用户删除
This commit is contained in:
@@ -118,6 +118,14 @@ description: 影策后端核心持久化表与状态边界
|
||||
| `channel_model_price_tiers` | 保存系统模型按规格匹配的上游 SKU 与价格 | 价格档与渠道模型同事务保存;未启用或未完成定价的规格不进入普通用户目录 |
|
||||
| `logical_models` | 保存前台模型的公开名称、Logo、能力类型和归档状态 | 前台模型与系统渠道模型分别维护展示信息;供应线路通过 revision 和 route 关联;`code` 仅在 `archived_at IS NULL` 的活动记录中唯一,归档后可用同 code 重建目录项 |
|
||||
|
||||
图片分档尺寸保存在现有模型能力 JSON 的 `image.size.presets` 中,不新增表、列或 SQL 迁移。每项结构为 `{ tier, ratio, size, width, height }`,例如 `{ "tier": "1k", "ratio": "16:9", "size": "1824x1024", "width": 1824, "height": 1024 }`。
|
||||
|
||||
- `tier` 仅允许 `1k`、`2k`、`4k`,管理员分别配置各档支持的比例;新增比例自动计算像素,原有精确尺寸不被重算。
|
||||
- 同档等价比例不能重复。比例须为正整数比且不超过 3:1;像素最长边不超过 3840,总像素为 655360–8294400,并与比例及 `size` 一致(允许 2.5% 比例取整误差)。这些档位是工作台预设,不保证上游返回完全相同的像素。
|
||||
- `parameter=size` 的支持值与请求使用精确像素;`parameter=aspect_ratio` 使用比例,独立分辨率由协议质量值映射。未允许自定义且质量值对应明确档位时,保存默认配置和创建任务均校验已声明的“档位 × 比例”组合,不能借用其他档位的比例。
|
||||
- `allowCustom` 只开放支持值之外的输入,不新增上游分辨率能力;比例协议未配置对应质量值时不开放该档位。模型声明的精确像素可不满足 16px 对齐;自定义像素仍须满足请求端的 16px 对齐及尺寸限制。
|
||||
- 未声明 `presets` 时,界面从已有支持值推导候选;禁用尺寸参数时清除分档配置。发布与回滚均无需数据库迁移,但旧程序不识别分档组合约束,回滚前应核对相关模型配置。
|
||||
|
||||
## 插件管理
|
||||
|
||||
| 表 | 用途 | 关键边界 |
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"code-map",
|
||||
"backend-database",
|
||||
"task-runtime-stability",
|
||||
"newapi-channel-2",
|
||||
"system-update",
|
||||
"protocol-plugins",
|
||||
"canvas-data-structure"
|
||||
|
||||
51
docs/content/docs/backend/newapi-channel-2.mdx
Normal file
51
docs/content/docs/backend/newapi-channel-2.mdx
Normal file
@@ -0,0 +1,51 @@
|
||||
---
|
||||
title: NewAPI Video Generations Channel 2
|
||||
description: Channel 2 视频任务创建、轮询与上游任务同步延迟处理
|
||||
---
|
||||
|
||||
# NewAPI Video Generations Channel 2
|
||||
|
||||
## 请求流程
|
||||
|
||||
声明式插件使用以下接口:
|
||||
|
||||
- 创建:`POST /v1/video/generations`
|
||||
- 查询:`GET /v1/video/generations/{taskId}`
|
||||
|
||||
创建响应支持顶层 `id`、`task_id`、`taskId`,以及 `data.id`、`data.task_id`、`data.taskId`。当中转包装 ID 与真实上游任务 ID 同时存在时,按 `data.task_id`、`data.taskId`、顶层 `task_id`、顶层 `taskId`、`data.id`、顶层 `id` 的顺序解析,避免把中转内部记录 ID 用作上游查询 ID。宿主把解析出的值保存为 `provider_request_id`,后续查询始终使用该值,并对路径参数进行 URL 编码。
|
||||
|
||||
查询响应进入成功状态后,插件会从 `data.result_url`、`data.video_url`、`data.output_url`、`data.url`、`data.metadata.url` 以及对应的 `data.data.*` 嵌套字段读取视频地址,再回退到兼容的顶层结果字段。只返回成功状态而没有任何结果地址时,宿主仍按协议异常处理,不会创建空资源。
|
||||
|
||||
## 上游同步延迟
|
||||
|
||||
创建接口返回任务 ID 后,Channel 2 可能在数百毫秒到数秒内仍对查询接口返回结构化的 `400`:
|
||||
|
||||
```json
|
||||
{"code":"task_not_exist","message":"task_not_exist"}
|
||||
```
|
||||
|
||||
宿主只在同时满足以下条件时把该响应视为“任务状态尚未同步”:
|
||||
|
||||
1. 渠道接口类型精确为 `newapi-channel-2`;
|
||||
2. 已经保存非空 Provider Task ID;
|
||||
3. HTTP 状态为 `400`;
|
||||
4. JSON 的 `code` 或 `message` 精确等于 `task_not_exist`。
|
||||
|
||||
不符合条件的 HTTP 错误、非 JSON 正文或其他错误码仍立即按失败语义处理。
|
||||
|
||||
## 轮询与延期
|
||||
|
||||
新任务首次查询前等待 `2` 秒;同步错误在同一次执行中按 `2` 秒、`3` 秒、`5` 秒、`5` 秒退避,最多短期查询 5 次。短期窗口耗尽后,Worker 不发送新的创建请求,也不切换渠道或退款,而是:
|
||||
|
||||
- 保持本地任务状态为 `running`;
|
||||
- 保留原 `provider_request_id` 和计费状态;
|
||||
- 释放当前租约并把 `next_poll_at` 延后 15 秒;
|
||||
- 下一轮从已保存的 Provider Task ID 恢复,只发送查询请求。
|
||||
|
||||
`task_not_exist` 的跨轮次同步等待从本地任务首次开始执行起最多持续 5 分钟。超过该上限仍未得到有效任务状态时,Worker 将任务置为失败并释放活跃任务与计费预留,避免无效 Provider Task ID 永久占用用户任务名额。该限制只针对持续的 `task_not_exist`;查询接口已经返回正常 pending/running 状态后的长视频生成仍按视频任务超时和延期策略恢复。
|
||||
|
||||
因此,上游生成耗时 500 至 600 秒时,只要查询接口返回有效的处理中状态,本地会持续以低频查询等待完成,不会把正常排队误报为“模型服务拒绝了请求”。视频真正返回失败状态时,仍按供应商失败处理。
|
||||
|
||||
## 兼容边界
|
||||
|
||||
该容错只适用于 `newapi-channel-2` 视频任务。其他 NewAPI 接口、其他 Provider、缺少 Provider Task ID 的任务,以及真实参数错误不进入延期路径。
|
||||
@@ -5,6 +5,83 @@ description: 当前项目已实现功能的手工验证清单与未确认边界
|
||||
|
||||
# 待测试
|
||||
|
||||
## 创作页面附件缩略图
|
||||
|
||||
- 聊天消息与分镜简报附件的放大图标样式排除 `.cached-resource-image-shell`,避免缓存图片容器被误设为透明和绝对定位;悬停与键盘聚焦仍显示放大图标。
|
||||
- [ ] 在真实创作会话中确认远端图片加载后无需悬停即可显示,移开鼠标后保持可见,点击可放大;同时确认分镜简报附件、本地图片和视频预览正常。
|
||||
|
||||
## MiniMax H3 分辨率能力与价格档
|
||||
|
||||
- 视频能力比较复用请求意图和价格档的分辨率别名归一规则,修复 MiniMax H3 供应线路配置 2K 价格档后,前台模型声明 2K 时误报「创作端参数超出供应线路能力:vquality」。内部价格档仍使用归一值,MiniMax 请求保持官方参数 `resolution: "2K"`。
|
||||
- [x] 回归测试在修复前复现相同保存校验错误,修复后通过;相关能力匹配、线路覆盖和 MiniMax 专项测试通过。模拟 HTTP 请求验证 2K 与内部 1440p 均发送 2K,未声明的 4K 仍被拒绝,图片 quality 参数不受视频别名影响。
|
||||
- [ ] 在实际 `/admin/channels` 配置 768P / 2K 价格档后,于 `/admin/models` 保存包含 2K 的模型能力,确认创作端可选并正确报价;未调用真实收费生成接口或部署服务。
|
||||
|
||||
## 对象存储优先发送媒体 URL
|
||||
|
||||
- 开启对象存储后,参考图、视频、音频发给上游时:协议支持 URL 就优先发对象存储签名链接;协议必须传文件字节时仍走 Base64 或 multipart。不会在上游失败后再自动重发一次生成。
|
||||
- 强制 URL:NewAPI 系列、火山方舟视频、MiniMax 视频,以及声明需要公网媒体 URL 的插件协议。优先 URL:chat-completion、openai-response、claude-api、Grok 图片、火山方舟图片、xAI/Novita/Grok/Seedance 视频等。Gemini 图片、Gemini Veo、带蒙版的 OpenAI 图片编辑继续走字节。
|
||||
- 本地资源在“优先 URL”协议下仍读成 Base64;对象存储资源签发失败、资源不存在或未就绪会直接报错,不会伪装成“不支持 URL”。存储桶不必公开读,使用短期签名链接即可。
|
||||
- [x] 后端专项测试覆盖协议策略、OSS 强制 URL、本地强制 URL,以及 preferURL 时对象存储走签名 URL、本地回退 Base64。
|
||||
- [ ] 用户浏览器验收:开启 OSS/COS/七牛/S3 后,图生图或视频参考素材应发对象存储 URL;Gemini 或蒙版编辑仍发文件字节。签名失败不能变成静默回退 Base64。
|
||||
|
||||
## 管理后台系统性能
|
||||
|
||||
- 管理后台「系统配置」新增独立「系统性能」页面,集中展示主机与 Go 进程、数据目录所在磁盘、系统/进程内存、数据库连接池与 Schema、PostgreSQL 统计、Redis 运行状态和运行时缓存 key 数量;连接地址、账号、密码、DSN 与 Redis URL 不返回前端。
|
||||
- 页面提供 15 秒自动刷新、手动刷新、降级提示和紧凑 KPI。SQLite 环境明确隐藏 PostgreSQL 专属统计,Redis 未配置时显示单实例本地协调状态;macOS 无可靠系统可用内存时降级展示 Go 堆内存,避免把未知可用量误报为 100% 占用。
|
||||
- 缓存维护仅接受 `runtime` scope,通过 Redis `SCAN + UNLINK` 清理请求频控、渠道失败/熔断和线路临时禁用四类白名单;保留活动并发租约、跨实例目录版本以及用户、任务、素材、模型配置和数据库数据,同时清理可重建的进程内读缓存并写入管理员审计。
|
||||
- [x] 后端专项测试覆盖管理员权限、SQLite/无 Redis 状态、非法 scope 拒绝、本地缓存清理和审计写入;专项竞态测试、handler 路由注册、repository/service 和前端生产构建通过。Redis 白名单删除与保留边界的集成用例已实现,但本机无 `redis-server`,本轮自动跳过。
|
||||
- [x] 浏览器 mock 已验证 PostgreSQL + Redis 完整态、SQLite + 本地协调降级态、桌面浅色与 390px 深色布局、无横向溢出,以及缓存清理二次确认文案;未调用真实清理接口。
|
||||
- [ ] 在真实部署的 `/admin/settings/system-performance` 验证 PostgreSQL 统计、Redis 指标、自动刷新和 Redis 断连降级;仅在测试环境执行缓存清理,确认流量高峰期间不影响活动并发租约和业务数据。
|
||||
|
||||
## 图片组预览、连线菜单与尺寸设置
|
||||
|
||||
- 折叠图片组背板读取真实子图,排除当前主图、最多显示五张,并复用资源缓存与视口懒加载;未完成的子图保留占位背板。
|
||||
- 连线创建菜单的说明与禁用原因可换行,菜单限制在视口宽高内并允许纵向滚动。隔离组件页已通过浏览器确认真实图片背板与长说明显示。
|
||||
- 管理员固定展示 1K / 2K / 4K 三组,可选择或手动输入每档比例,等价比例归一去重;1K + 16:9 自动换算为 1824x1024,已有精确像素保持原值。未配置分档时,从已有尺寸按总像素推导档位(例如 1920x1080 为 2K)。
|
||||
- 图片协议的尺寸参数独占首行,输出数量与可选参数移到下方;每个分辨率档位用横向比例卡片直接点选,额外比例通过输入框添加,默认输出也改为直接点选,不再使用比例下拉框。窄容器自动改为单列,视频协议布局保持不变。
|
||||
- 后台未保存的新增模型表单已验证:比例选中/取消、32:18 等价去重、17:11 添加与像素展示、0:9 错误提示、默认输出切换、Enter 添加而非提交表单;1440px 桌面尺寸卡片独占整行,390px 明暗主题和长比例标签无横向溢出,焦点轮廓可见。验证后已取消表单、放弃测试修改并恢复原主题。截图工具未成功,本轮布局依据浏览器 DOM 几何测量与交互结果,视觉效果仍待人工确认。
|
||||
- 画布、创作和短剧生产接入同一“分辨率 → 宽高比 → 像素展示”组件。用户端仅显示协议支持且已配置比例的档位:例如 2K 比例为空时隐藏 2K,允许自定义也不额外显示空档位;剩余按钮等宽填充。管理员仍保留三档配置入口。允许自定义时开放比例或像素输入,切档尽量保持比例;重新打开保留真实自定义尺寸展示,不将已隐藏档位的旧尺寸伪装成其他档位选中,也不自动改写尺寸。
|
||||
- 空档位隐藏已在隔离组件页验证:仅配置 1K/4K 时无 2K 按钮,选择 4K 返回 3840x2160;仅一档时按钮铺满可用宽度,全空时隐藏分辨率标题和按钮,保留自动尺寸与自定义入口。未保存模型或发起生成,真实路由仍待人工复验。
|
||||
- 比例请求配置 aspect_ratio;精确像素配置 size。独立分辨率字段由对应模型协议适配,仅比例不能保证输出像素。模型声明的精确像素预设不受自定义尺寸的 16 倍数对齐限制,保持原值发送,其余尺寸边界继续校验。
|
||||
- 浏览器隔离组件页已确认:旧比例配置切 4K 实际交给请求转换函数的是 3840x2160;自定义 2:1 后切 2K 保持比例;0:9 显式报错且不改已选值;管理员输入 32:18 去重、17:11 自动计算并同步用户选项;Grok 禁用 4K。390px 视口内的 264px 面板在明暗主题下测得无横向溢出,含长比例标签。以上不等同于真实上游生成或三个路由的完整验收。
|
||||
- 前端 29 项尺寸、协议及能力专项测试和生产构建通过,包含空档位隐藏、比例无下拉框、禁用状态与图片/视频布局隔离回归;此前后端尺寸预设、能力规格转换及图片任务相关测试通过,覆盖默认组合拒绝、跨档位比例拒绝及 JSON 往返,本轮纯 UI 改造未重跑后端。构建仍有既有的大分包与无效动态导入警告。
|
||||
- [ ] 复验画布、创作、短剧真实路由中的模型切换、保存后重开、默认档位与比例组合、明暗主题和键盘交互;管理员真实保存由用户确认后执行。
|
||||
- [ ] 用真实模型确认新增尺寸是否受上游支持、实际输出与计费档位是否一致;本次未修改已保存模型配置或执行收费生成。
|
||||
|
||||
## Issue #432 多角度编辑器
|
||||
|
||||
- 多角度编辑器改为居中 Modal,复用遮罩点击、Escape 和关闭按钮的取消行为,不再定位到节点底部或随节点拖拽卸载。
|
||||
- #428、#429、#432 的定向源码回归检查与前端生产构建通过;浏览器访问现有服务停在登录页,未完成真实登录态交互验收。构建保留现有大分包和混合静动态导入警告。
|
||||
- [ ] 人工复验不同缩放和明暗主题下的位置、遮罩与 Escape 关闭、重新打开重置参数、预设与角度拖动;本轮不执行收费生成。
|
||||
|
||||
## Issue #429 文本节点选中
|
||||
|
||||
- 普通文本和富文本预览恢复鼠标事件冒泡,单击进入节点选中和编辑面板流程;编辑中的输入框仍隔离拖拽和滚轮。
|
||||
- [ ] 人工复验正文单击、标题拖拽、富文本、组合键多选、双击编辑和正文滚动。
|
||||
|
||||
## Issue #428 插件协议分类
|
||||
|
||||
- 分类筛选同时限制展示分区,避免音视频协议在音频筛选结果中重复展示;全部分类仍展示各自支持的能力分区。
|
||||
- [ ] 人工复验 AutoDL 在音频、视频和全部分类中的展示,以及搜索、状态筛选和详情入口。
|
||||
|
||||
## 画布多图分组与展开动画
|
||||
|
||||
- 新生成的多图组默认收起;复制图片或替换节点生成多图时,结果也保留分组归属,可展开、收起和设置主图。
|
||||
- 子图入场动画仅在主动展开图片组时触发;普通选择、拖动或重新进入视口不播放入场动画,快速切换展开与收起时清理上一轮动画状态。
|
||||
- 22 项相关测试及前端生产构建通过,包含子图普通挂载、选中与展开/收起的组件渲染回归;浏览器已确认本地画布可加载,尚未复验截图中的多图场景。
|
||||
- [ ] 人工确认多图生成后的堆叠预览、数量按钮展开/收起、子图点击与拖动、主图切换,以及保存后重新打开画布。已有画布保留用户保存的展开状态。
|
||||
|
||||
|
||||
## PR #426 本地整合验收
|
||||
|
||||
- 保留主分支图片尺寸选择器、后台尺寸预设布局、插件分类筛选、文本节点单击编辑、多角度居中弹窗、附件缩略图、站点外观与系统性能页面;接入 PR 的 UI 组件族和创作会话交互。
|
||||
- 创作结果添加到画布前继续校验全部结果均有归属明确的素材记录,避免部分结果尚未落库时只转交部分素材;测试同步到消息级结果组件。
|
||||
- 本次不接入 PR 新增的用户彻底删除功能,移除其按钮、客户端调用、路由和级联实现,原有停用/启用及素材回收站功能保持不变。临时 SQLite 回归已复现原实现成功返回后残留镜头修订和素材展示记录;其资源物理清理、账务保留与事务边界需单独完善后再接入。
|
||||
- 无新增数据库迁移,不运行开发服务、不操作真实用户数据、不推送远程或部署。
|
||||
- [x] 前端生产构建、前端主测试及主分支交互/外观和剪辑专项测试通过;后端 `go test ./...` 全量通过。
|
||||
- [ ] 浏览器验收:明暗主题下图片分辨率/比例、自定义尺寸、后台模型能力预设、插件分类、文本节点编辑、多角度弹窗、附件常显、创作历史与完整结果转交画布。
|
||||
- [ ] 确认后台用户管理保留查看/编辑/启用/停用入口,不展示未完成的用户彻底删除功能;实际生成与剪辑链路由用户验证后再决定是否推送。
|
||||
|
||||
## UI 组件同角色迁移(P0,2026-09-06)
|
||||
|
||||
依据 `docs/plans/ui-kit-consumption-audit.md` 实施:主界面/后台同角色控件统一消费 `components/ui`,消除 antd 与 ui 双观感。变更范围:Tooltip 29 处、Switch 10 处、朴素单选 Select 12 处、Checkbox.Group 1 处迁移至 ui 族;同步清理 globals.css 中 3 段 antd Checkbox 死选择器。antd `Switch`/`Checkbox`/`Tooltip` 全库归零;Empty/Alert/Badge/状态 Tag 维持零。
|
||||
@@ -130,6 +207,15 @@ description: 当前项目已实现功能的手工验证清单与未确认边界
|
||||
- [x] PR #423 合并验证:前端完整测试脚本 1139 项通过、生产构建通过;后端邮件、任务摘要和图片计价专项通过。后端全量仍有 4 项既有失败(私网上游校验 2 项、视频恢复策略 2 项),已在未合并的 `main` 基线上复现;最后一轮另有资源清理测试 SQLite 表锁失败,该项在合并分支与基线单独复跑均通过。未为通过测试而放宽安全或恢复策略。
|
||||
- [ ] 真实 SMTP 投递、浏览器刷新恢复和收费生成仍待人工验证。本次不触发外部邮件或收费请求。
|
||||
|
||||
## NewAPI Video Generations Channel 2 轮询恢复
|
||||
|
||||
- [x] 官方插件兼容从 `data.task_id` 和 `data.taskId` 读取上游任务 ID;Channel 2 创建成功后首次查询等待 2 秒,仅将结构化 `400 task_not_exist` 识别为上游同步延迟,并按 2 秒、3 秒、5 秒、5 秒退避复查同一任务。
|
||||
- [x] 短期重试耗尽后,Worker 保留本地任务 `running`、原 `provider_request_id` 和计费状态,延后 15 秒继续查询;恢复过程不重复发送创建请求、不切换渠道,也不立即失败或退款。其他接口类型、HTTP 状态和错误码仍按原失败语义处理。
|
||||
- [x] 合并补修为跨轮次 `task_not_exist` 增加 5 分钟总同步上限;超过上限进入明确失败态并释放任务与计费资源,正常 pending/running 长视频仍可跨执行窗口恢复。
|
||||
- [x] Channel 2 终态响应兼容 `data.result_url`、`data.video_url`、`data.output_url`、`data.url`、`data.metadata.url` 及对应的 `data.data.*` 嵌套路径;API 调用日志在该接口下优先记录嵌套真实任务 ID。协议与日志富化专项回归测试通过。
|
||||
- [ ] 使用真实 Channel 2 分别验证上游任务 ID 短暂不可见和生成耗时 500 至 600 秒的任务:本地不再提示“模型服务拒绝了请求”,创建请求只出现一次,后续始终查询同一 Provider Task ID,最终视频正常回写;真实参数错误仍应及时失败。
|
||||
- [ ] 使用返回 `SUCCESS` 且视频地址位于 `data.result_url` 或 `data.data.video_url` 的真实任务,确认不再提示“声明式协议已完成但没有返回结果”,并在当前 OSS 配置下成功下载并持久化为本地资源。
|
||||
|
||||
## 编辑器(M2 命令状态机)
|
||||
|
||||
- [x] 命令协议黄金文件:`editor-commands` 8 个黄金 op(addClip/moveClip/trimClip/splitClip/removeClip/setClipProperty/addSubtitle/removeSubtitle)全量快照比对通过;未知 op、非法 payload 一律抛错(fail-closed)且输入不可变。
|
||||
@@ -496,6 +582,13 @@ description: 当前项目已实现功能的手工验证清单与未确认边界
|
||||
- [ ] 在画布中分别选择按次图片模型、按秒视频模型和前台逻辑模型,确认修改数量、时长、分辨率和参考素材后价格立即更新且与实际账单一致。
|
||||
- [ ] 在浅色/深色主题及生成中、禁用状态下确认胶囊价格可读、圆形操作区清晰且不挤压模型与参数控件。
|
||||
|
||||
## 系统渠道模型批量删除
|
||||
|
||||
- [x] 管理员可勾选最多 100 个渠道模型并一次删除;任一模型仍被活动线路或进行中任务引用时整批拒绝,不产生部分删除。
|
||||
- [x] 合并补修将兼容 `models_json` 的重建收进删除事务,并由 repository 在取得渠道写锁后读取当前启用模型;模型保存后的目录同步也复用同一锁定入口,避免并发管理员操作用事务外旧快照覆盖较新的模型目录。
|
||||
- [x] 后端批量删除与引用拒绝专项测试、前端管理页回归测试和格式检查通过。
|
||||
- [ ] 在 PostgreSQL 测试环境由两个管理员并发执行模型新增、启停和批量删除,确认 `channel_models` 与渠道 `models_json` 最终一致,删除失败时列表不发生部分变化。
|
||||
|
||||
## 系统渠道默认积分价格
|
||||
|
||||
- [x] 新建渠道模型默认使用“所有规格统一价格”,管理员只需填写一次积分;1K/2K/4K、画幅和生成方式差异定价收进可选的“按规格定价”。
|
||||
@@ -1144,7 +1237,3 @@ v2(用户反馈首版难看后重做):菜单改用 antd Dropdown(placeme
|
||||
- [ ] 让 AI 回复含多行代码(如 markdown 围栏 ```ts```):代码块顶部有语言标签 + 复制按钮,点复制后变「已复制」,粘贴内容正确(不含语言标记行)。
|
||||
- [ ] 代码块圆角/边框/底色在明暗主题均可辨;长代码横向滚动不破版;流式输出中代码块容器稳定不跳动、复制按钮可用。
|
||||
- [ ] 消息中的行内代码(如 `const x`)样式不受影响;画布 Agent 消息里的代码块同样获得新外壳。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user