后端生成闸+多项修复;前端全站更新;QA 审计与报告
后端: - 新增 celery_health 生成前置闸——无 worker 在线时图片/视频生成入口 一律 503,防"提交到 ARK 后无人轮询、结果悬空+额度冻结"的数据丢失 - 拼接导出:帧率跟随源众数、字幕逐句重映射、原声/BGM 混音修复 - 资金核算审计脚本 + genesis 账目回填 + 滞留预留清理命令 - 接入 yunqi provider 与豆包 TTS 模型(catalog/migrations/bootstrap 命令) 前端:全站页面更新(pipeline/library/products/projects/team/account 等), 新增共享 pager 分页组件 QA:刷新 function-audit 全量输出,新增 full-qa 报告 文档:BP 产品介绍资料、design/CLAUDE.md Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { CircleDollarSign, KeyRound, UserPlus } from "lucide-react";
|
||||
import type { BillingSummary, Notification, Team, TeamMember, User } from "../types";
|
||||
import type { Page } from "./route-config";
|
||||
import { money } from "./stage-config";
|
||||
import { ConfirmModal, TeamModal } from "../components/overlays";
|
||||
import { Pager } from "../components/pager";
|
||||
|
||||
const MEMBERS_PER_PAGE = 10;
|
||||
|
||||
// 角色 → pill key/label(对齐 api-bridge roleUi)
|
||||
function roleUi(role: string): { key: "super" | "admin" | "member"; label: string } {
|
||||
@@ -84,6 +87,12 @@ export function TeamPage({ team, user, members, billing, notifications = [], nav
|
||||
const email = member.user.email || "";
|
||||
return !needle || `${name} ${email}`.toLowerCase().includes(needle);
|
||||
});
|
||||
// 成员分页:每页 10 人,搜索变化回第 1 页
|
||||
const [memberPage, setMemberPage] = useState(1);
|
||||
useEffect(() => { setMemberPage(1); }, [search]);
|
||||
const memberTotalPages = Math.max(1, Math.ceil(list.length / MEMBERS_PER_PAGE));
|
||||
const memberCurPage = Math.min(memberPage, memberTotalPages);
|
||||
const pagedMembers = list.slice((memberCurPage - 1) * MEMBERS_PER_PAGE, memberCurPage * MEMBERS_PER_PAGE);
|
||||
|
||||
function openEdit(member: TeamMember) {
|
||||
setEditTarget(member);
|
||||
@@ -93,13 +102,15 @@ export function TeamPage({ team, user, members, billing, notifications = [], nav
|
||||
|
||||
async function submitCreate() {
|
||||
if (!cuUser.trim() || cuPass.length < 8) return;
|
||||
await onCreateMember({
|
||||
const created = await onCreateMember({
|
||||
username: cuUser.trim(),
|
||||
password: cuPass,
|
||||
name: cuName.trim() || undefined,
|
||||
role: cuRole,
|
||||
monthly_credit_limit: Number(cuMonthly) || 0
|
||||
});
|
||||
// 创建失败(action 报错返回 null)时保持弹窗与已填内容,只成功才关闭并清空
|
||||
if (!created) return;
|
||||
setModal("");
|
||||
setCuUser("");
|
||||
setCuPass("");
|
||||
@@ -241,6 +252,7 @@ export function TeamPage({ team, user, members, billing, notifications = [], nav
|
||||
<span className="spacer"></span>
|
||||
<input className="input" id="member-search" placeholder="搜索姓名 / 手机号" style={{ height: "32px", fontSize: "12px", width: "220px" }} value={search} onChange={(event) => setSearch(event.target.value)} />
|
||||
</div>
|
||||
<div className="members-table-wrap">
|
||||
<table className="t members-table" style={{ border: 0, borderRadius: 0 }}>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -253,7 +265,7 @@ export function TeamPage({ team, user, members, billing, notifications = [], nav
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="members-tbody">
|
||||
{list.map((member) => {
|
||||
{pagedMembers.map((member) => {
|
||||
const rawName = (member.user.username || "").trim();
|
||||
const email = (member.user.email || "").trim();
|
||||
// 用户名是邮箱时取 @ 前作为显示名,完整邮箱作副行,避免名字与邮箱重复显示
|
||||
@@ -287,6 +299,8 @@ export function TeamPage({ team, user, members, billing, notifications = [], nav
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<Pager page={memberCurPage} total={list.length} pageSize={MEMBERS_PER_PAGE} onChange={setMemberPage} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user