feat(admin): 添加用户管理和Linux.do登录功能

- 新增AdminUser类型定义及用户管理API接口
- 实现用户列表查询、保存和删除功能
- 添加Linux.do第三方登录支持
- 集成Linux.do OAuth认证流程
- 在系统设置中添加Linux.do登录配置选项
- 实现算力点余额调整记录功能
- 优化搜索组件关键词状态管理
- 更新数据库迁移添加credit_logs表
- 完善用户状态和信用等级验证逻辑
This commit is contained in:
HouYunFei
2026-05-25 11:21:09 +08:00
parent f871a5d015
commit b2cae2471d
25 changed files with 1023 additions and 117 deletions
+13 -3
View File
@@ -23,6 +23,7 @@ export default function AdminAssetsPage() {
const { assets, tags, keyword, kind, tag, page, pageSize, total, isLoading, searchAssets, changeKind, changeTag, changePage, changePageSize, resetFilters, refreshAssets, saveAsset: saveAdminAsset, deleteAsset } = useAdminAssets();
const copyText = useCopyText();
const [form] = Form.useForm<AssetFormValues>();
const [keywordText, setKeywordText] = useState(keyword);
const [editingAsset, setEditingAsset] = useState<Partial<AdminAsset> | null>(null);
const [detailAsset, setDetailAsset] = useState<AdminAsset | null>(null);
const [deletingAsset, setDeletingAsset] = useState<AdminAsset | null>(null);
@@ -33,6 +34,8 @@ export default function AdminAssetsPage() {
if (editingAsset) form.setFieldsValue({ ...editingAsset, tagText: editingAsset.tags?.join(", ") || "" });
}, [editingAsset, form]);
useEffect(() => setKeywordText(keyword), [keyword]);
const saveAsset = async () => {
const value = await form.validateFields();
const nextType = value.type || "text";
@@ -119,7 +122,7 @@ export default function AdminAssetsPage() {
<Row gutter={16} align="bottom">
<Col flex="360px">
<Form.Item label="关键词">
<Input.Search value={keyword} placeholder="搜索标题、内容或标签" allowClear enterButton={<SearchOutlined />} onSearch={searchAssets} onChange={(event) => searchAssets(event.target.value)} />
<Input.Search value={keywordText} placeholder="搜索标题、内容或标签" allowClear enterButton={<SearchOutlined />} onSearch={() => searchAssets(keywordText)} onChange={(event) => setKeywordText(event.target.value)} />
</Form.Item>
</Col>
<Col flex="180px">
@@ -135,8 +138,15 @@ export default function AdminAssetsPage() {
<Col flex="none">
<Form.Item>
<Space>
<Button onClick={resetFilters}></Button>
<Button type="primary" icon={<ReloadOutlined />} onClick={refreshAssets}>
<Button
onClick={() => {
setKeywordText("");
resetFilters();
}}
>
</Button>
<Button type="primary" icon={<ReloadOutlined />} onClick={() => searchAssets(keywordText)}>
</Button>
</Space>