feat: 忘记密码/修改密码 + 设置页结构重组 + barrel cleanup + LoginPage 版本统一
新增: - ForgotPasswordModal — 手机号+短信验证码重置密码 (AuthAPI.resetPassword) - ChangePasswordModal — 当前密码验证后修改密码 (AuthAPI.changePassword) - useSmsCooldown Hook — 通用短信发送冷却逻辑,供注册/忘记密码复用 - PasswordSetting — 设置页账号安全区块,双选项:修改密码 / 短信验证码重置 修改: - LoginForm \"忘记密码?\" 链接接入 ForgotPasswordModal(替换 TODO) - LoginPage 移除 edition 业务版本 UI 区分,登录/注册 Tab 全局统一 - 设置页 Section 组件移入 blocks/ 子目录(git mv 保留历史) - auth.ts sendSms URL 修正: /sms/send → /send-sms 清理: - settings/index.ts 移除 4 个未使用 re-export,精简为仅 SettingsPage - navbar/index.ts 移除未使用 re-export,精简为仅 NavBar 文档: - WORKLOG.md 新增 2026-06-08 工作日志 - ARCHITECTURE.md / PROJECT.md 更新设置页目录结构与新组件 - TODO.md 忘记密码流程标记已完成 + 短信人机验证列入后期优化
This commit is contained in:
@@ -13,10 +13,11 @@
|
||||
import { Modal } from 'antd';
|
||||
import { SettingOutlined } from '@ant-design/icons';
|
||||
import { useAppContext } from '@/contexts/app-context';
|
||||
import { ThemeSetting } from './ThemeSetting';
|
||||
import { StoragePathSetting } from './StoragePathSetting';
|
||||
import { SystemInfoSetting } from './SystemInfoSetting';
|
||||
import { UpdateSetting } from './UpdateSetting';
|
||||
import { ThemeSetting } from './blocks/ThemeSetting';
|
||||
import { StoragePathSetting } from './blocks/StoragePathSetting';
|
||||
import { SystemInfoSetting } from './blocks/SystemInfoSetting';
|
||||
import { UpdateSetting } from './blocks/UpdateSetting';
|
||||
import { PasswordSetting } from './blocks/PasswordSetting';
|
||||
|
||||
interface SettingsPageProps {
|
||||
open: boolean;
|
||||
@@ -24,31 +25,32 @@ interface SettingsPageProps {
|
||||
}
|
||||
|
||||
export function SettingsPage({ open, onClose }: SettingsPageProps) {
|
||||
const { edition } = useAppContext();
|
||||
const { edition } = useAppContext();
|
||||
|
||||
return (
|
||||
<Modal
|
||||
open={open}
|
||||
width={480}
|
||||
onCancel={onClose}
|
||||
destroyOnHidden={true}
|
||||
mask={{ closable: false }}
|
||||
keyboard={false}
|
||||
footer={null}
|
||||
title={
|
||||
<span className="flex items-center gap-2">
|
||||
<SettingOutlined />
|
||||
设置
|
||||
</span>
|
||||
}
|
||||
styles={{ body: { padding: 0, maxHeight: '70vh', overflow: 'auto' } }}
|
||||
>
|
||||
<div className="flex flex-col gap-4 p-4">
|
||||
<ThemeSetting />
|
||||
<StoragePathSetting edition={edition} />
|
||||
<SystemInfoSetting />
|
||||
<UpdateSetting />
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
return (
|
||||
<Modal
|
||||
open={open}
|
||||
width={480}
|
||||
onCancel={onClose}
|
||||
destroyOnHidden={true}
|
||||
mask={{ closable: false }}
|
||||
keyboard={false}
|
||||
footer={null}
|
||||
title={
|
||||
<span className="flex items-center gap-2">
|
||||
<SettingOutlined />
|
||||
设置
|
||||
</span>
|
||||
}
|
||||
styles={{ body: { padding: 0, maxHeight: '70vh', overflow: 'auto' } }}
|
||||
>
|
||||
<div className="flex flex-col gap-4 p-4">
|
||||
<ThemeSetting />
|
||||
<StoragePathSetting edition={edition} />
|
||||
<SystemInfoSetting />
|
||||
<PasswordSetting />
|
||||
<UpdateSetting />
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
52
src/pages/settings/blocks/PasswordSetting.tsx
Normal file
52
src/pages/settings/blocks/PasswordSetting.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
// ============================================================
|
||||
// PasswordSetting — 账号安全区块(密码操作入口)
|
||||
//
|
||||
// 提供两种密码操作,用户自选:
|
||||
// 1. 修改密码 — 通过当前密码验证后设置新密码
|
||||
// 2. 忘记密码 — 通过手机短信验证码重置密码
|
||||
// ============================================================
|
||||
|
||||
import { useState } from 'react';
|
||||
import { Card, Button, Typography } from 'antd';
|
||||
import { LockOutlined, PhoneOutlined } from '@ant-design/icons';
|
||||
|
||||
import { ChangePasswordModal } from '@/pages/login/components/ChangePasswordModal';
|
||||
import { ForgotPasswordModal } from '@/pages/login/components/ForgotPasswordModal';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
export function PasswordSetting() {
|
||||
const [changePwdOpen, setChangePwdOpen] = useState(false);
|
||||
const [forgotPwdOpen, setForgotPwdOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card size="small" title="账号安全" className="rounded-md!">
|
||||
<div className="flex flex-col gap-3">
|
||||
{/* 修改密码:通过旧密码 */}
|
||||
<div className="flex items-center justify-between">
|
||||
<Text type="secondary" className="text-sm">
|
||||
通过当前密码修改
|
||||
</Text>
|
||||
<Button icon={<LockOutlined />} onClick={() => setChangePwdOpen(true)}>
|
||||
修改密码
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* 忘记密码:通过手机验证码重置 */}
|
||||
<div className="flex items-center justify-between">
|
||||
<Text type="secondary" className="text-sm">
|
||||
忘记密码?通过手机验证码重置
|
||||
</Text>
|
||||
<Button icon={<PhoneOutlined />} onClick={() => setForgotPwdOpen(true)}>
|
||||
短信验证码重置
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<ChangePasswordModal open={changePwdOpen} onClose={() => setChangePwdOpen(false)} />
|
||||
<ForgotPasswordModal open={forgotPwdOpen} onClose={() => setForgotPwdOpen(false)} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -159,8 +159,14 @@ function PathRow({
|
||||
}
|
||||
|
||||
export function StoragePathSetting({ edition }: StoragePathSettingProps) {
|
||||
const { outputPath, teamRepoPath, setOutputPath, setTeamRepoPath, clearOutputPath, clearTeamRepoPath } =
|
||||
useSettings();
|
||||
const {
|
||||
outputPath,
|
||||
teamRepoPath,
|
||||
setOutputPath,
|
||||
setTeamRepoPath,
|
||||
clearOutputPath,
|
||||
clearTeamRepoPath,
|
||||
} = useSettings();
|
||||
|
||||
const isEnterprise = edition === 'enterprise';
|
||||
|
||||
@@ -65,15 +65,8 @@ function renderChangelog(markdown: string) {
|
||||
}
|
||||
|
||||
export function UpdateSetting() {
|
||||
const {
|
||||
status,
|
||||
info,
|
||||
progress,
|
||||
error,
|
||||
checkForUpdates,
|
||||
downloadUpdate,
|
||||
installUpdate,
|
||||
} = useUpdater();
|
||||
const { status, info, progress, error, checkForUpdates, downloadUpdate, installUpdate } =
|
||||
useUpdater();
|
||||
|
||||
const [detailOpen, setDetailOpen] = useState(false);
|
||||
|
||||
@@ -210,15 +203,15 @@ export function UpdateSetting() {
|
||||
title={`更新详情 — v${info?.version || ''}`}
|
||||
open={detailOpen}
|
||||
onCancel={() => setDetailOpen(false)}
|
||||
footer={
|
||||
<Button onClick={() => setDetailOpen(false)}>关闭</Button>
|
||||
}
|
||||
footer={<Button onClick={() => setDetailOpen(false)}>关闭</Button>}
|
||||
width={520}
|
||||
>
|
||||
<div className="max-h-96 overflow-y-auto py-2">
|
||||
{info?.releaseNotes
|
||||
? renderChangelog(info.releaseNotes)
|
||||
: <Text type="secondary">暂无更新详情</Text>}
|
||||
{info?.releaseNotes ? (
|
||||
renderChangelog(info.releaseNotes)
|
||||
) : (
|
||||
<Text type="secondary">暂无更新详情</Text>
|
||||
)}
|
||||
</div>
|
||||
</Modal>
|
||||
</Card>
|
||||
@@ -3,7 +3,3 @@
|
||||
// ============================================================
|
||||
|
||||
export { SettingsPage } from './SettingsPage';
|
||||
export { ThemeSetting } from './ThemeSetting';
|
||||
export { StoragePathSetting } from './StoragePathSetting';
|
||||
export { SystemInfoSetting } from './SystemInfoSetting';
|
||||
export { UpdateSetting } from './UpdateSetting';
|
||||
|
||||
Reference in New Issue
Block a user