🎨 chore(web): apply ESLint and Prettier auto-fixes (baseline)

- Ran: bun run eslint:fix && bun run lint:fix
- Inserted AGPL license header via eslint-plugin-header
- Enforced no-multiple-empty-lines and other lint rules
- Formatted code using Prettier v3 (@so1ve/prettier-config)
- No functional changes; formatting-only baseline across JS/JSX files
This commit is contained in:
t0ng7u
2025-08-30 21:15:10 +08:00
parent 105b86c660
commit 6a87808612
274 changed files with 11025 additions and 7659 deletions

View File

@@ -27,7 +27,7 @@ import {
Avatar,
Tabs,
TabPane,
Popover
Popover,
} from '@douyinfe/semi-ui';
import {
IconMail,
@@ -35,7 +35,7 @@ import {
IconGithubLogo,
IconKey,
IconLock,
IconDelete
IconDelete,
} from '@douyinfe/semi-icons';
import { SiTelegram, SiWechat, SiLinux } from 'react-icons/si';
import { UserPlus, ShieldCheck } from 'lucide-react';
@@ -43,7 +43,7 @@ import TelegramLoginButton from 'react-telegram-login';
import {
onGitHubOAuthClicked,
onOIDCClicked,
onLinuxDOOAuthClicked
onLinuxDOOAuthClicked,
} from '../../../../helpers';
import TwoFASetting from '../components/TwoFASetting';
@@ -57,77 +57,89 @@ const AccountManagement = ({
generateAccessToken,
handleSystemTokenClick,
setShowChangePasswordModal,
setShowAccountDeleteModal
setShowAccountDeleteModal,
}) => {
const renderAccountInfo = (accountId, label) => {
if (!accountId || accountId === '') {
return <span className="text-gray-500">{t('未绑定')}</span>;
return <span className='text-gray-500'>{t('未绑定')}</span>;
}
const popContent = (
<div className="text-xs p-2">
<div className='text-xs p-2'>
<Typography.Paragraph copyable={{ content: accountId }}>
{accountId}
</Typography.Paragraph>
{label ? (
<div className="mt-1 text-[11px] text-gray-500">{label}</div>
<div className='mt-1 text-[11px] text-gray-500'>{label}</div>
) : null}
</div>
);
return (
<Popover content={popContent} position="top" trigger="hover">
<span className="block max-w-full truncate text-gray-600 hover:text-blue-600 cursor-pointer">
<Popover content={popContent} position='top' trigger='hover'>
<span className='block max-w-full truncate text-gray-600 hover:text-blue-600 cursor-pointer'>
{accountId}
</span>
</Popover>
);
};
return (
<Card className="!rounded-2xl">
<Card className='!rounded-2xl'>
{/* 卡片头部 */}
<div className="flex items-center mb-4">
<Avatar size="small" color="teal" className="mr-3 shadow-md">
<div className='flex items-center mb-4'>
<Avatar size='small' color='teal' className='mr-3 shadow-md'>
<UserPlus size={16} />
</Avatar>
<div>
<Typography.Text className="text-lg font-medium">{t('账户管理')}</Typography.Text>
<div className="text-xs text-gray-600">{t('账户绑定、安全设置和身份验证')}</div>
<Typography.Text className='text-lg font-medium'>
{t('账户管理')}
</Typography.Text>
<div className='text-xs text-gray-600'>
{t('账户绑定、安全设置和身份验证')}
</div>
</div>
</div>
<Tabs type="card" defaultActiveKey="binding">
<Tabs type='card' defaultActiveKey='binding'>
{/* 账户绑定 Tab */}
<TabPane
tab={
<div className="flex items-center">
<UserPlus size={16} className="mr-2" />
<div className='flex items-center'>
<UserPlus size={16} className='mr-2' />
{t('账户绑定')}
</div>
}
itemKey="binding"
itemKey='binding'
>
<div className="py-4">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
<div className='py-4'>
<div className='grid grid-cols-1 lg:grid-cols-2 gap-4'>
{/* 邮箱绑定 */}
<Card className="!rounded-xl">
<div className="flex items-center justify-between gap-3">
<div className="flex items-center flex-1 min-w-0">
<div className="w-10 h-10 rounded-full bg-slate-100 dark:bg-slate-700 flex items-center justify-center mr-3 flex-shrink-0">
<IconMail size="default" className="text-slate-600 dark:text-slate-300" />
<Card className='!rounded-xl'>
<div className='flex items-center justify-between gap-3'>
<div className='flex items-center flex-1 min-w-0'>
<div className='w-10 h-10 rounded-full bg-slate-100 dark:bg-slate-700 flex items-center justify-center mr-3 flex-shrink-0'>
<IconMail
size='default'
className='text-slate-600 dark:text-slate-300'
/>
</div>
<div className="flex-1 min-w-0">
<div className="font-medium text-gray-900">{t('邮箱')}</div>
<div className="text-sm text-gray-500 truncate">
{renderAccountInfo(userState.user?.email, t('邮箱地址'))}
<div className='flex-1 min-w-0'>
<div className='font-medium text-gray-900'>
{t('邮箱')}
</div>
<div className='text-sm text-gray-500 truncate'>
{renderAccountInfo(
userState.user?.email,
t('邮箱地址'),
)}
</div>
</div>
</div>
<div className="flex-shrink-0">
<div className='flex-shrink-0'>
<Button
type="primary"
theme="outline"
size="small"
type='primary'
theme='outline'
size='small'
onClick={() => setShowEmailBindModal(true)}
>
{userState.user && userState.user.email !== ''
@@ -139,26 +151,31 @@ const AccountManagement = ({
</Card>
{/* 微信绑定 */}
<Card className="!rounded-xl">
<div className="flex items-center justify-between gap-3">
<div className="flex items-center flex-1 min-w-0">
<div className="w-10 h-10 rounded-full bg-slate-100 dark:bg-slate-700 flex items-center justify-center mr-3 flex-shrink-0">
<SiWechat size={20} className="text-slate-600 dark:text-slate-300" />
<Card className='!rounded-xl'>
<div className='flex items-center justify-between gap-3'>
<div className='flex items-center flex-1 min-w-0'>
<div className='w-10 h-10 rounded-full bg-slate-100 dark:bg-slate-700 flex items-center justify-center mr-3 flex-shrink-0'>
<SiWechat
size={20}
className='text-slate-600 dark:text-slate-300'
/>
</div>
<div className="flex-1 min-w-0">
<div className="font-medium text-gray-900">{t('微信')}</div>
<div className="text-sm text-gray-500 truncate">
<div className='flex-1 min-w-0'>
<div className='font-medium text-gray-900'>
{t('微信')}
</div>
<div className='text-sm text-gray-500 truncate'>
{userState.user && userState.user.wechat_id !== ''
? t('已绑定')
: t('未绑定')}
</div>
</div>
</div>
<div className="flex-shrink-0">
<div className='flex-shrink-0'>
<Button
type="primary"
theme="outline"
size="small"
type='primary'
theme='outline'
size='small'
disabled={!status.wechat_login}
onClick={() => setShowWeChatBindModal(true)}
>
@@ -173,25 +190,35 @@ const AccountManagement = ({
</Card>
{/* GitHub绑定 */}
<Card className="!rounded-xl">
<div className="flex items-center justify-between gap-3">
<div className="flex items-center flex-1 min-w-0">
<div className="w-10 h-10 rounded-full bg-slate-100 dark:bg-slate-700 flex items-center justify-center mr-3 flex-shrink-0">
<IconGithubLogo size="default" className="text-slate-600 dark:text-slate-300" />
<Card className='!rounded-xl'>
<div className='flex items-center justify-between gap-3'>
<div className='flex items-center flex-1 min-w-0'>
<div className='w-10 h-10 rounded-full bg-slate-100 dark:bg-slate-700 flex items-center justify-center mr-3 flex-shrink-0'>
<IconGithubLogo
size='default'
className='text-slate-600 dark:text-slate-300'
/>
</div>
<div className="flex-1 min-w-0">
<div className="font-medium text-gray-900">{t('GitHub')}</div>
<div className="text-sm text-gray-500 truncate">
{renderAccountInfo(userState.user?.github_id, t('GitHub ID'))}
<div className='flex-1 min-w-0'>
<div className='font-medium text-gray-900'>
{t('GitHub')}
</div>
<div className='text-sm text-gray-500 truncate'>
{renderAccountInfo(
userState.user?.github_id,
t('GitHub ID'),
)}
</div>
</div>
</div>
<div className="flex-shrink-0">
<div className='flex-shrink-0'>
<Button
type="primary"
theme="outline"
size="small"
onClick={() => onGitHubOAuthClicked(status.github_client_id)}
type='primary'
theme='outline'
size='small'
onClick={() =>
onGitHubOAuthClicked(status.github_client_id)
}
disabled={
(userState.user && userState.user.github_id !== '') ||
!status.github_oauth
@@ -204,28 +231,38 @@ const AccountManagement = ({
</Card>
{/* OIDC绑定 */}
<Card className="!rounded-xl">
<div className="flex items-center justify-between gap-3">
<div className="flex items-center flex-1 min-w-0">
<div className="w-10 h-10 rounded-full bg-slate-100 dark:bg-slate-700 flex items-center justify-center mr-3 flex-shrink-0">
<IconShield size="default" className="text-slate-600 dark:text-slate-300" />
<Card className='!rounded-xl'>
<div className='flex items-center justify-between gap-3'>
<div className='flex items-center flex-1 min-w-0'>
<div className='w-10 h-10 rounded-full bg-slate-100 dark:bg-slate-700 flex items-center justify-center mr-3 flex-shrink-0'>
<IconShield
size='default'
className='text-slate-600 dark:text-slate-300'
/>
</div>
<div className="flex-1 min-w-0">
<div className="font-medium text-gray-900">{t('OIDC')}</div>
<div className="text-sm text-gray-500 truncate">
{renderAccountInfo(userState.user?.oidc_id, t('OIDC ID'))}
<div className='flex-1 min-w-0'>
<div className='font-medium text-gray-900'>
{t('OIDC')}
</div>
<div className='text-sm text-gray-500 truncate'>
{renderAccountInfo(
userState.user?.oidc_id,
t('OIDC ID'),
)}
</div>
</div>
</div>
<div className="flex-shrink-0">
<div className='flex-shrink-0'>
<Button
type="primary"
theme="outline"
size="small"
onClick={() => onOIDCClicked(
status.oidc_authorization_endpoint,
status.oidc_client_id,
)}
type='primary'
theme='outline'
size='small'
onClick={() =>
onOIDCClicked(
status.oidc_authorization_endpoint,
status.oidc_client_id,
)
}
disabled={
(userState.user && userState.user.oidc_id !== '') ||
!status.oidc_enabled
@@ -238,27 +275,35 @@ const AccountManagement = ({
</Card>
{/* Telegram绑定 */}
<Card className="!rounded-xl">
<div className="flex items-center justify-between gap-3">
<div className="flex items-center flex-1 min-w-0">
<div className="w-10 h-10 rounded-full bg-slate-100 dark:bg-slate-700 flex items-center justify-center mr-3 flex-shrink-0">
<SiTelegram size={20} className="text-slate-600 dark:text-slate-300" />
<Card className='!rounded-xl'>
<div className='flex items-center justify-between gap-3'>
<div className='flex items-center flex-1 min-w-0'>
<div className='w-10 h-10 rounded-full bg-slate-100 dark:bg-slate-700 flex items-center justify-center mr-3 flex-shrink-0'>
<SiTelegram
size={20}
className='text-slate-600 dark:text-slate-300'
/>
</div>
<div className="flex-1 min-w-0">
<div className="font-medium text-gray-900">{t('Telegram')}</div>
<div className="text-sm text-gray-500 truncate">
{renderAccountInfo(userState.user?.telegram_id, t('Telegram ID'))}
<div className='flex-1 min-w-0'>
<div className='font-medium text-gray-900'>
{t('Telegram')}
</div>
<div className='text-sm text-gray-500 truncate'>
{renderAccountInfo(
userState.user?.telegram_id,
t('Telegram ID'),
)}
</div>
</div>
</div>
<div className="flex-shrink-0">
<div className='flex-shrink-0'>
{status.telegram_oauth ? (
userState.user.telegram_id !== '' ? (
<Button disabled={true} size="small">
<Button disabled={true} size='small'>
{t('已绑定')}
</Button>
) : (
<div className="scale-75">
<div className='scale-75'>
<TelegramLoginButton
dataAuthUrl='/api/oauth/telegram/bind'
botName={status.telegram_bot_name}
@@ -266,7 +311,7 @@ const AccountManagement = ({
</div>
)
) : (
<Button disabled={true} size="small">
<Button disabled={true} size='small'>
{t('未启用')}
</Button>
)}
@@ -275,25 +320,35 @@ const AccountManagement = ({
</Card>
{/* LinuxDO绑定 */}
<Card className="!rounded-xl">
<div className="flex items-center justify-between gap-3">
<div className="flex items-center flex-1 min-w-0">
<div className="w-10 h-10 rounded-full bg-slate-100 dark:bg-slate-700 flex items-center justify-center mr-3 flex-shrink-0">
<SiLinux size={20} className="text-slate-600 dark:text-slate-300" />
<Card className='!rounded-xl'>
<div className='flex items-center justify-between gap-3'>
<div className='flex items-center flex-1 min-w-0'>
<div className='w-10 h-10 rounded-full bg-slate-100 dark:bg-slate-700 flex items-center justify-center mr-3 flex-shrink-0'>
<SiLinux
size={20}
className='text-slate-600 dark:text-slate-300'
/>
</div>
<div className="flex-1 min-w-0">
<div className="font-medium text-gray-900">{t('LinuxDO')}</div>
<div className="text-sm text-gray-500 truncate">
{renderAccountInfo(userState.user?.linux_do_id, t('LinuxDO ID'))}
<div className='flex-1 min-w-0'>
<div className='font-medium text-gray-900'>
{t('LinuxDO')}
</div>
<div className='text-sm text-gray-500 truncate'>
{renderAccountInfo(
userState.user?.linux_do_id,
t('LinuxDO ID'),
)}
</div>
</div>
</div>
<div className="flex-shrink-0">
<div className='flex-shrink-0'>
<Button
type="primary"
theme="outline"
size="small"
onClick={() => onLinuxDOOAuthClicked(status.linuxdo_client_id)}
type='primary'
theme='outline'
size='small'
onClick={() =>
onLinuxDOOAuthClicked(status.linuxdo_client_id)
}
disabled={
(userState.user && userState.user.linux_do_id !== '') ||
!status.linuxdo_oauth
@@ -311,37 +366,37 @@ const AccountManagement = ({
{/* 安全设置 Tab */}
<TabPane
tab={
<div className="flex items-center">
<ShieldCheck size={16} className="mr-2" />
<div className='flex items-center'>
<ShieldCheck size={16} className='mr-2' />
{t('安全设置')}
</div>
}
itemKey="security"
itemKey='security'
>
<div className="py-4">
<div className="space-y-6">
<div className='py-4'>
<div className='space-y-6'>
<Space vertical className='w-full'>
{/* 系统访问令牌 */}
<Card className="!rounded-xl w-full">
<div className="flex flex-col sm:flex-row items-start sm:justify-between gap-4">
<div className="flex items-start w-full sm:w-auto">
<div className="w-12 h-12 rounded-full bg-slate-100 flex items-center justify-center mr-4 flex-shrink-0">
<IconKey size="large" className="text-slate-600" />
<Card className='!rounded-xl w-full'>
<div className='flex flex-col sm:flex-row items-start sm:justify-between gap-4'>
<div className='flex items-start w-full sm:w-auto'>
<div className='w-12 h-12 rounded-full bg-slate-100 flex items-center justify-center mr-4 flex-shrink-0'>
<IconKey size='large' className='text-slate-600' />
</div>
<div className="flex-1">
<Typography.Title heading={6} className="mb-1">
<div className='flex-1'>
<Typography.Title heading={6} className='mb-1'>
{t('系统访问令牌')}
</Typography.Title>
<Typography.Text type="tertiary" className="text-sm">
<Typography.Text type='tertiary' className='text-sm'>
{t('用于API调用的身份验证令牌请妥善保管')}
</Typography.Text>
{systemToken && (
<div className="mt-3">
<div className='mt-3'>
<Input
readonly
value={systemToken}
onClick={handleSystemTokenClick}
size="large"
size='large'
prefix={<IconKey />}
/>
</div>
@@ -349,10 +404,10 @@ const AccountManagement = ({
</div>
</div>
<Button
type="primary"
theme="solid"
type='primary'
theme='solid'
onClick={generateAccessToken}
className="!bg-slate-600 hover:!bg-slate-700 w-full sm:w-auto"
className='!bg-slate-600 hover:!bg-slate-700 w-full sm:w-auto'
icon={<IconKey />}
>
{systemToken ? t('重新生成') : t('生成令牌')}
@@ -361,26 +416,26 @@ const AccountManagement = ({
</Card>
{/* 密码管理 */}
<Card className="!rounded-xl w-full">
<div className="flex flex-col sm:flex-row items-start sm:justify-between gap-4">
<div className="flex items-start w-full sm:w-auto">
<div className="w-12 h-12 rounded-full bg-slate-100 flex items-center justify-center mr-4 flex-shrink-0">
<IconLock size="large" className="text-slate-600" />
<Card className='!rounded-xl w-full'>
<div className='flex flex-col sm:flex-row items-start sm:justify-between gap-4'>
<div className='flex items-start w-full sm:w-auto'>
<div className='w-12 h-12 rounded-full bg-slate-100 flex items-center justify-center mr-4 flex-shrink-0'>
<IconLock size='large' className='text-slate-600' />
</div>
<div>
<Typography.Title heading={6} className="mb-1">
<Typography.Title heading={6} className='mb-1'>
{t('密码管理')}
</Typography.Title>
<Typography.Text type="tertiary" className="text-sm">
<Typography.Text type='tertiary' className='text-sm'>
{t('定期更改密码可以提高账户安全性')}
</Typography.Text>
</div>
</div>
<Button
type="primary"
theme="solid"
type='primary'
theme='solid'
onClick={() => setShowChangePasswordModal(true)}
className="!bg-slate-600 hover:!bg-slate-700 w-full sm:w-auto"
className='!bg-slate-600 hover:!bg-slate-700 w-full sm:w-auto'
icon={<IconLock />}
>
{t('修改密码')}
@@ -392,26 +447,29 @@ const AccountManagement = ({
<TwoFASetting t={t} />
{/* 危险区域 */}
<Card className="!rounded-xl w-full">
<div className="flex flex-col sm:flex-row items-start sm:justify-between gap-4">
<div className="flex items-start w-full sm:w-auto">
<div className="w-12 h-12 rounded-full bg-slate-100 flex items-center justify-center mr-4 flex-shrink-0">
<IconDelete size="large" className="text-slate-600" />
<Card className='!rounded-xl w-full'>
<div className='flex flex-col sm:flex-row items-start sm:justify-between gap-4'>
<div className='flex items-start w-full sm:w-auto'>
<div className='w-12 h-12 rounded-full bg-slate-100 flex items-center justify-center mr-4 flex-shrink-0'>
<IconDelete size='large' className='text-slate-600' />
</div>
<div>
<Typography.Title heading={6} className="mb-1 text-slate-700">
<Typography.Title
heading={6}
className='mb-1 text-slate-700'
>
{t('删除账户')}
</Typography.Title>
<Typography.Text type="tertiary" className="text-sm">
<Typography.Text type='tertiary' className='text-sm'>
{t('此操作不可逆,所有数据将被永久删除')}
</Typography.Text>
</div>
</div>
<Button
type="danger"
theme="solid"
type='danger'
theme='solid'
onClick={() => setShowAccountDeleteModal(true)}
className="w-full sm:w-auto !bg-slate-500 hover:!bg-slate-600"
className='w-full sm:w-auto !bg-slate-500 hover:!bg-slate-600'
icon={<IconDelete />}
>
{t('删除账户')}