🐛 fix(auth): Update authentication configuration and localization strings

This commit is contained in:
web@ppanel 2025-02-08 23:58:03 +07:00
parent 3a3d2236e2
commit 47f2c5853c
48 changed files with 749 additions and 293 deletions

View File

@ -33,8 +33,8 @@ export default function RegisterForm({
try {
const domain = email.split('@')[1];
const isValid =
!auth.email.email_enable_verify ||
auth.email?.email_domain_suffix_list.split('\n').includes(domain || '');
!auth.email.enable_verify ||
auth.email?.domain_suffix_list.split('\n').includes(domain || '');
return !isValid;
} catch (error) {
console.log('Error checking user:', error);
@ -52,7 +52,7 @@ export default function RegisterForm({
}),
password: z.string(),
repeat_password: z.string(),
code: auth.email.email_enable_verify ? z.string() : z.string().nullish(),
code: auth.email.enable_verify ? z.string() : z.string().nullish(),
invite: invite.forced_invite ? z.string() : z.string().nullish(),
cf_token:
verify.enable_register_verify && verify.turnstile_site_key
@ -120,7 +120,7 @@ export default function RegisterForm({
</FormItem>
)}
/>
{auth.email.email_enable_verify && (
{auth.email.enable_verify && (
<FormField
control={form.control}
name='code'

View File

@ -32,7 +32,7 @@ export default function ResetForm({
const formSchema = z.object({
email: z.string().email(t('email')),
password: z.string(),
code: auth?.email?.email_enable_verify ? z.string() : z.string().nullish(),
code: auth?.email?.enable_verify ? z.string() : z.string().nullish(),
cf_token:
verify.enable_register_verify && verify.turnstile_site_key
? z.string()
@ -72,7 +72,7 @@ export default function ResetForm({
)}
/>
{auth?.email?.email_enable_verify && (
{auth?.email?.enable_verify && (
<FormField
control={form.control}
name='code'

View File

@ -1,6 +1,6 @@
'use client';
import { getOAuthByPlatform, updateOAuthConfig } from '@/services/admin/system';
import { getAuthMethodConfig, updateAuthMethodConfig } from '@/services/admin/authMethod';
import { useQuery } from '@tanstack/react-query';
import { Label } from '@workspace/ui/components/label';
import { Switch } from '@workspace/ui/components/switch';
@ -14,21 +14,21 @@ export default function Page() {
const t = useTranslations('apple');
const { data, refetch } = useQuery({
queryKey: ['getOAuthByPlatform', 'apple'],
queryKey: ['getAuthMethodConfig', 'apple'],
queryFn: async () => {
const { data } = await getOAuthByPlatform({
platform: 'apple',
const { data } = await getAuthMethodConfig({
method: 'apple',
});
return data.data;
},
});
async function updateConfig(key: keyof API.UpdateOAuthConfig, value: unknown) {
async function updateConfig(key: keyof API.UpdataAuthMethodConfigRequest, value: unknown) {
try {
await updateOAuthConfig({
await updateAuthMethodConfig({
...data,
[key]: value,
} as API.UpdateOAuthConfig);
} as API.UpdataAuthMethodConfigRequest);
toast.success(t('saveSuccess'));
refetch();
} catch (error) {
@ -132,8 +132,13 @@ export default function Page() {
<TableCell className='text-right'>
<EnhancedInput
placeholder='https://your-domain.com/v1/auth/oauth/callback/apple'
value={data?.redirect}
onValueBlur={(value) => updateConfig('redirect', value)}
value={data?.config.redirect_url}
onValueBlur={(value) =>
updateConfig('config', {
...data?.config,
redirect_url: value,
})
}
/>
</TableCell>
</TableRow>

View File

@ -1,6 +1,10 @@
'use client';
import { getEmailSmtpConfig, testEmailSmtp, updateEmailSmtpConfig } from '@/services/admin/system';
import {
getAuthMethodConfig,
testEmailSend,
updateAuthMethodConfig,
} from '@/services/admin/authMethod';
import { useQuery } from '@tanstack/react-query';
import { Button } from '@workspace/ui/components/button';
import {
@ -23,14 +27,16 @@ import { toast } from 'sonner';
export default function Page() {
const t = useTranslations('email');
const ref = useRef<Partial<API.EmailSmtpConfig>>({});
const ref = useRef<Partial<API.AuthMethodConfig>>({});
const [email, setEmail] = useState<string>();
const { data, refetch, isFetching } = useQuery({
queryKey: ['getEmailSmtpConfig'],
queryKey: ['getAuthMethodConfig', 'email'],
queryFn: async () => {
const { data } = await getEmailSmtpConfig();
ref.current = data.data as API.EmailSmtpConfig;
const { data } = await getAuthMethodConfig({
method: 'email',
});
ref.current = data.data as API.AuthMethodConfig;
return data.data;
},
});
@ -38,10 +44,10 @@ export default function Page() {
async function updateConfig(key: string, value: unknown) {
if (data?.[key] === value) return;
try {
await updateEmailSmtpConfig({
await updateAuthMethodConfig({
...ref.current,
[key]: value,
} as API.EmailSmtpConfig);
} as API.UpdataAuthMethodConfigRequest);
toast.success(t('saveSuccess'));
refetch();
} catch (error) {
@ -59,94 +65,193 @@ export default function Page() {
<TabsContent value='basic'>
<Table>
<TableBody>
{[
{
key: 'email_enabled',
label: t('enable'),
description: t('enableDescription'),
component: 'switch',
},
{
key: 'enable_email_verify',
label: t('emailVerification'),
description: t('emailVerificationDescription'),
component: 'switch',
},
{
key: 'enable_email_domain_suffix',
label: t('emailSuffixWhitelist'),
description: t('emailSuffixWhitelistDescription'),
component: 'switch',
},
{
key: 'email_domain_suffix_list',
label: t('whitelistSuffixes'),
description: t('whitelistSuffixesDescription'),
component: 'textarea',
},
{
key: 'email_smtp_host',
label: t('smtpServerAddress'),
description: t('smtpServerAddressDescription'),
},
{
key: 'email_smtp_port',
label: t('smtpServerPort'),
description: t('smtpServerPortDescription'),
type: 'number',
},
{
key: 'email_smtp_ssl',
label: t('smtpEncryptionMethod'),
description: t('smtpEncryptionMethodDescription'),
component: 'switch',
},
{
key: 'email_smtp_user',
label: t('smtpAccount'),
description: t('smtpAccountDescription'),
},
{
key: 'email_smtp_pass',
label: t('smtpPassword'),
description: t('smtpPasswordDescription'),
type: 'password',
},
{
key: 'email_smtp_from',
label: t('senderAddress'),
description: t('senderAddressDescription'),
},
].map(({ key, label, description, type = 'text', component = 'input' }) => (
<TableRow key={key}>
<TableCell className={component === 'textarea' ? 'align-top' : undefined}>
<Label>{label}</Label>
<p className='text-muted-foreground text-xs'>{description}</p>
</TableCell>
<TableCell className='text-right'>
{component === 'input' ? (
<EnhancedInput
placeholder={t('inputPlaceholder')}
value={data?.[key]}
type={type}
onValueBlur={(value) => updateConfig(key, value)}
/>
) : component === 'switch' ? (
<Switch
checked={data?.[key]}
onCheckedChange={(checked) => updateConfig(key, checked)}
/>
) : (
<Textarea
className='h-32'
placeholder={t('whitelistSuffixesPlaceholder')}
defaultValue={data?.[key]}
onBlur={(e) => updateConfig(key, e.target.value)}
/>
)}
</TableCell>
</TableRow>
))}
<TableRow>
<TableCell>
<Label>{t('enable')}</Label>
<p className='text-muted-foreground text-xs'>{t('enableDescription')}</p>
</TableCell>
<TableCell className='text-right'>
<Switch
checked={data?.enabled}
onCheckedChange={(checked) => updateConfig('enabled', checked)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>{t('emailVerification')}</Label>
<p className='text-muted-foreground text-xs'>{t('emailVerificationDescription')}</p>
</TableCell>
<TableCell className='text-right'>
<Switch
checked={data?.config?.enable_verify}
onCheckedChange={(checked) =>
updateConfig('config', { ...data?.config, enable_verify: checked })
}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>{t('emailSuffixWhitelist')}</Label>
<p className='text-muted-foreground text-xs'>
{t('emailSuffixWhitelistDescription')}
</p>
</TableCell>
<TableCell className='text-right'>
<Switch
checked={data?.config?.enable_domain_suffix}
onCheckedChange={(checked) =>
updateConfig('config', { ...data?.config, enable_domain_suffix: checked })
}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell className='align-top'>
<Label>{t('whitelistSuffixes')}</Label>
<p className='text-muted-foreground text-xs'>{t('whitelistSuffixesDescription')}</p>
</TableCell>
<TableCell className='text-right'>
<Textarea
className='h-32'
placeholder={t('whitelistSuffixesPlaceholder')}
defaultValue={data?.config?.domain_suffix_list}
onBlur={(e) =>
updateConfig('config', { ...data?.config, domain_suffix_list: e.target.value })
}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>{t('smtpServerAddress')}</Label>
<p className='text-muted-foreground text-xs'>{t('smtpServerAddressDescription')}</p>
</TableCell>
<TableCell className='text-right'>
<EnhancedInput
placeholder={t('inputPlaceholder')}
value={data?.config?.platform_config?.host}
onValueBlur={(value) =>
updateConfig('config', {
...data?.config,
platform_config: {
...data?.platform_config,
host: value,
},
})
}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>{t('smtpServerPort')}</Label>
<p className='text-muted-foreground text-xs'>{t('smtpServerPortDescription')}</p>
</TableCell>
<TableCell className='text-right'>
<EnhancedInput
placeholder={t('inputPlaceholder')}
value={data?.config?.platform_config?.port}
type='number'
onValueBlur={(value) =>
updateConfig('config', {
...data?.config,
platform_config: {
...data?.platform_config,
port: value,
},
})
}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>{t('smtpEncryptionMethod')}</Label>
<p className='text-muted-foreground text-xs'>
{t('smtpEncryptionMethodDescription')}
</p>
</TableCell>
<TableCell className='text-right'>
<Switch
checked={data?.config?.platform_config?.ssl}
onCheckedChange={(checked) =>
updateConfig('config', {
...data?.config,
platform_config: {
...data?.platform_config,
ssl: checked,
},
})
}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>{t('smtpAccount')}</Label>
<p className='text-muted-foreground text-xs'>{t('smtpAccountDescription')}</p>
</TableCell>
<TableCell className='text-right'>
<EnhancedInput
placeholder={t('inputPlaceholder')}
value={data?.config?.platform_config?.user}
onValueBlur={(value) =>
updateConfig('config', {
...data?.config,
platform_config: {
...data?.platform_config,
user: value,
},
})
}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>{t('smtpPassword')}</Label>
<p className='text-muted-foreground text-xs'>{t('smtpPasswordDescription')}</p>
</TableCell>
<TableCell className='text-right'>
<EnhancedInput
placeholder={t('inputPlaceholder')}
value={data?.config?.platform_config?.pass}
type='password'
onValueBlur={(value) =>
updateConfig('config', {
...data?.config,
platform_config: {
...data?.platform_config,
pass: value,
},
})
}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>{t('senderAddress')}</Label>
<p className='text-muted-foreground text-xs'>{t('senderAddressDescription')}</p>
</TableCell>
<TableCell className='text-right'>
<EnhancedInput
placeholder={t('inputPlaceholder')}
value={data?.config?.platform_config?.from}
onValueBlur={(value) =>
updateConfig('config', {
...data?.config,
platform_config: {
...data?.platform_config,
from: value,
},
})
}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>{t('sendTestEmail')}</Label>
@ -164,7 +269,7 @@ export default function Page() {
onClick={async () => {
if (!email) return;
try {
await testEmailSmtp({ email });
await testEmailSend({ email });
toast.success(t('sendSuccess'));
} catch {
toast.error(t('sendFailure'));
@ -193,8 +298,13 @@ export default function Page() {
<CardContent>
<HTMLEditor
placeholder={t('inputPlaceholder')}
value={data?.[templateKey as keyof API.EmailSmtpConfig] as string}
onBlur={(value) => updateConfig(templateKey, value)}
value={data?.config?.[templateKey] as string}
onBlur={(value) =>
updateConfig('config', {
...data?.config,
[templateKey]: value,
})
}
/>
</CardContent>
</Card>

View File

@ -1,6 +1,6 @@
'use client';
import { getOAuthByPlatform, updateOAuthConfig } from '@/services/admin/system';
import { getAuthMethodConfig, updateAuthMethodConfig } from '@/services/admin/authMethod';
import { useQuery } from '@tanstack/react-query';
import { Label } from '@workspace/ui/components/label';
import { Switch } from '@workspace/ui/components/switch';
@ -13,21 +13,21 @@ export default function Page() {
const t = useTranslations('facebook');
const { data, refetch } = useQuery({
queryKey: ['getOAuthByPlatform', 'facebook'],
queryKey: ['getAuthMethodConfig', 'facebook'],
queryFn: async () => {
const { data } = await getOAuthByPlatform({
platform: 'facebook',
const { data } = await getAuthMethodConfig({
method: 'facebook',
});
return data.data;
},
});
async function updateConfig(key: keyof API.UpdateOAuthConfig, value: unknown) {
async function updateConfig(key: keyof API.UpdataAuthMethodConfigRequest, value: unknown) {
try {
await updateOAuthConfig({
await updateAuthMethodConfig({
...data,
[key]: value,
} as API.UpdateOAuthConfig);
} as API.UpdataAuthMethodConfigRequest);
toast.success(t('saveSuccess'));
refetch();
} catch (error) {
@ -94,8 +94,13 @@ export default function Page() {
<TableCell className='text-right'>
<EnhancedInput
placeholder='https://your-domain.com/v1/auth/oauth/callback/facebook'
value={data?.redirect}
onValueBlur={(value) => updateConfig('redirect', value)}
value={data?.config.redirect_url}
onValueBlur={(value) =>
updateConfig('config', {
...data?.config,
redirect_url: value,
})
}
/>
</TableCell>
</TableRow>

View File

@ -1,6 +1,6 @@
'use client';
import { getOAuthByPlatform, updateOAuthConfig } from '@/services/admin/system';
import { getAuthMethodConfig, updateAuthMethodConfig } from '@/services/admin/authMethod';
import { useQuery } from '@tanstack/react-query';
import { Label } from '@workspace/ui/components/label';
import { Switch } from '@workspace/ui/components/switch';
@ -13,21 +13,21 @@ export default function Page() {
const t = useTranslations('github');
const { data, refetch } = useQuery({
queryKey: ['getOAuthByPlatform', 'github'],
queryKey: ['getAuthMethodConfig', 'github'],
queryFn: async () => {
const { data } = await getOAuthByPlatform({
platform: 'github',
const { data } = await getAuthMethodConfig({
method: 'github',
});
return data.data;
},
});
async function updateConfig(key: keyof API.UpdateOAuthConfig, value: unknown) {
async function updateConfig(key: keyof API.UpdataAuthMethodConfigRequest, value: unknown) {
try {
await updateOAuthConfig({
await updateAuthMethodConfig({
...data,
[key]: value,
} as API.UpdateOAuthConfig);
} as API.UpdataAuthMethodConfigRequest);
toast.success(t('saveSuccess'));
refetch();
} catch (error) {
@ -93,8 +93,13 @@ export default function Page() {
<TableCell className='text-right'>
<EnhancedInput
placeholder='https://your-domain.com/v1/auth/oauth/callback/github'
value={data?.redirect}
onValueBlur={(value) => updateConfig('redirect', value)}
value={data?.config.redirect_url}
onValueBlur={(value) =>
updateConfig('config', {
...data?.config,
redirect_url: value,
})
}
/>
</TableCell>
</TableRow>

View File

@ -1,6 +1,6 @@
'use client';
import { getOAuthByPlatform, updateOAuthConfig } from '@/services/admin/system';
import { getAuthMethodConfig, updateAuthMethodConfig } from '@/services/admin/authMethod';
import { useQuery } from '@tanstack/react-query';
import { Label } from '@workspace/ui/components/label';
import { Switch } from '@workspace/ui/components/switch';
@ -13,21 +13,21 @@ export default function Page() {
const t = useTranslations('google');
const { data, refetch } = useQuery({
queryKey: ['getOAuthByPlatform', 'google'],
queryKey: ['getAuthMethodConfig', 'google'],
queryFn: async () => {
const { data } = await getOAuthByPlatform({
platform: 'google',
const { data } = await getAuthMethodConfig({
method: 'google',
});
return data.data;
},
});
async function updateConfig(key: keyof API.UpdateOAuthConfig, value: unknown) {
async function updateConfig(key: keyof API.UpdataAuthMethodConfigRequest, value: unknown) {
try {
await updateOAuthConfig({
await updateAuthMethodConfig({
...data,
[key]: value,
} as API.UpdateOAuthConfig);
} as API.UpdataAuthMethodConfigRequest);
toast.success(t('saveSuccess'));
refetch();
} catch (error) {
@ -94,8 +94,13 @@ export default function Page() {
<TableCell className='text-right'>
<EnhancedInput
placeholder='https://your-domain.com/v1/auth/oauth/callback/google'
value={data?.redirect}
onValueBlur={(value) => updateConfig('redirect', value)}
value={data?.config.redirect_url}
onValueBlur={(value) =>
updateConfig('config', {
...data?.config,
redirect_url: value,
})
}
/>
</TableCell>
</TableRow>

View File

@ -1,13 +1,13 @@
'use client';
import { ProTable, ProTableActions } from '@/components/pro-table';
import { getSmsList } from '@/services/admin/sms';
import {
getSmsConfig,
getAuthMethodConfig,
getSmsPlatform,
testSmsSend,
updateSmsConfig,
} from '@/services/admin/system';
updateAuthMethodConfig,
} from '@/services/admin/authMethod';
import { getSmsList } from '@/services/admin/sms';
import { useQuery } from '@tanstack/react-query';
import { Badge } from '@workspace/ui/components/badge';
import { Button } from '@workspace/ui/components/button';
@ -25,6 +25,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@workspace/ui/componen
import { Textarea } from '@workspace/ui/components/textarea';
import { AreaCodeSelect } from '@workspace/ui/custom-components/area-code-select';
import { EnhancedInput } from '@workspace/ui/custom-components/enhanced-input';
import TagInput from '@workspace/ui/custom-components/tag-input';
import { formatDate } from '@workspace/ui/utils';
import { useTranslations } from 'next-intl';
import Link from 'next/link';
@ -34,9 +35,11 @@ import { toast } from 'sonner';
export default function Page() {
const t = useTranslations('phone');
const { data, refetch, isFetching } = useQuery({
queryKey: ['getSmsConfig'],
queryKey: ['getAuthMethodConfig', 'mobile'],
queryFn: async () => {
const { data } = await getSmsConfig();
const { data } = await getAuthMethodConfig({
method: 'mobile',
});
return data.data;
},
});
@ -49,25 +52,27 @@ export default function Page() {
},
});
const selectedPlatform = platforms?.find((platform) => platform.platform === data?.sms_platform);
const selectedPlatform = platforms?.find(
(platform) => platform.platform === data?.config?.platform,
);
const { platform_url, platform_field_description: platformConfig } = selectedPlatform ?? {};
async function updateConfig(key: string, value: unknown) {
if (data?.[key] === value) return;
try {
await updateSmsConfig({
await updateAuthMethodConfig({
...data,
[key]: value,
} as API.SmsConfig);
} as API.UpdataAuthMethodConfigRequest);
toast.success(t('updateSuccess'));
refetch();
} catch (error) {
/* empty */
}
}
const [params, setParams] = useState<API.SendSmsRequest>({
const [params, setParams] = useState<API.TestSmsSendRequest>({
telephone: '',
content: t('testSmsContent'),
area_code: '1',
});
@ -88,8 +93,8 @@ export default function Page() {
</TableCell>
<TableCell className='text-right'>
<Switch
checked={data?.sms_enabled}
onCheckedChange={(checked) => updateConfig('sms_enabled', checked)}
checked={data?.enabled}
onCheckedChange={(checked) => updateConfig('enabled', checked)}
disabled={isFetching}
/>
</TableCell>
@ -103,8 +108,13 @@ export default function Page() {
<EnhancedInput
type='number'
min={0}
value={data?.sms_expire_time ?? 300}
onValueBlur={(value) => updateConfig('sms_expire_time', value)}
value={data?.config?.expire_time ?? 300}
onValueBlur={(value) =>
updateConfig('config', {
...data?.config,
expire_time: value,
})
}
suffix='S'
disabled={isFetching}
placeholder={t('placeholders.expireTime')}
@ -119,9 +129,14 @@ export default function Page() {
<TableCell className='text-right'>
<EnhancedInput
type='number'
value={data?.sms_interval ?? 60}
value={data?.config?.interval ?? 60}
min={0}
onValueBlur={(value) => updateConfig('sms_interval', value)}
onValueBlur={(value) =>
updateConfig('config', {
...data?.config,
interval: value,
})
}
suffix='S'
disabled={isFetching}
placeholder={t('placeholders.interval')}
@ -136,14 +151,48 @@ export default function Page() {
<TableCell className='text-right'>
<EnhancedInput
type='number'
value={data?.sms_limit ?? 20}
value={data?.config?.limit ?? 20}
min={0}
onValueBlur={(value) => updateConfig('sms_limit', value)}
onValueBlur={(value) =>
updateConfig('config', {
...data?.config,
limit: value,
})
}
disabled={isFetching}
placeholder={t('placeholders.limit')}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>{t('whitelistValidation')}</Label>
<p className='text-muted-foreground text-xs'>{t('whitelistValidationTip')}</p>
</TableCell>
<TableCell className='text-right'>
<Switch
defaultValue={data?.config?.enable_whitelist}
onCheckedChange={(checked) =>
updateConfig('config', { ...data?.config, enable_whitelist: checked })
}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>{t('whitelistAreaCode')}</Label>
<p className='text-muted-foreground text-xs'>{t('whitelistAreaCodeTip')}</p>
</TableCell>
<TableCell className='w-1/2 text-right'>
<TagInput
placeholder='1, 852, 886, 888'
value={data?.config?.whitelist || []}
onChange={(value) =>
updateConfig('config', { ...data?.config, whitelist: value })
}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>{t('platform')}</Label>
@ -151,8 +200,13 @@ export default function Page() {
</TableCell>
<TableCell className='flex items-center gap-1 text-right'>
<Select
value={data?.sms_platform}
onValueChange={(value) => updateConfig('sms_platform', value)}
value={data?.platform}
onValueChange={(value) =>
updateConfig('config', {
...data?.config,
platform: value,
})
}
disabled={isFetching}
>
<SelectTrigger>
@ -177,70 +231,128 @@ export default function Page() {
</TableRow>
<TableRow>
<TableCell>
<Label>Key</Label>
<Label>{t('accessLabel')}</Label>
<p className='text-muted-foreground text-xs'>
{t('platformConfigTip', { key: platformConfig?.sms_key })}
{t('platformConfigTip', { key: platformConfig?.access })}
</p>
</TableCell>
<TableCell className='text-right'>
<EnhancedInput
value={data?.sms_key ?? ''}
onValueBlur={(value) => updateConfig('sms_key', value)}
value={data?.config?.platform_config.access ?? ''}
onValueBlur={(value) =>
updateConfig('config', {
...data?.config,
platform_config: {
...data?.config?.platform_config,
access: value,
},
})
}
disabled={isFetching}
placeholder={t('platformConfigTip', { key: platformConfig?.sms_key })}
placeholder={t('platformConfigTip', { key: platformConfig?.access })}
/>
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Label>Secret</Label>
<p className='text-muted-foreground text-xs'>
{t('platformConfigTip', { key: platformConfig?.sms_secret })}
</p>
</TableCell>
<TableCell className='text-right'>
<EnhancedInput
value={data?.sms_secret ?? ''}
onValueBlur={(value) => updateConfig('sms_secret', value)}
disabled={isFetching}
type='password'
placeholder={t('platformConfigTip', { key: platformConfig?.sms_secret })}
/>
</TableCell>
</TableRow>
{platformConfig?.sms_template_code && (
{platformConfig?.endpoint && (
<TableRow>
<TableCell>
<Label>{t('templateCode')}</Label>
<Label>{t('endpointLabel')}</Label>
<p className='text-muted-foreground text-xs'>
{t('platformConfigTip', { key: platformConfig?.sms_template_code })}
{t('platformConfigTip', { key: platformConfig?.endpoint })}
</p>
</TableCell>
<TableCell className='text-right'>
<EnhancedInput
value={data?.sms_template_code ?? ''}
onValueBlur={(value) => updateConfig('sms_template_code', value)}
value={data?.config?.platform_config.endpoint ?? ''}
onValueBlur={(value) =>
updateConfig('config', {
...data?.config,
platform_config: {
...data?.config?.platform_config,
endpoint: value,
},
})
}
disabled={isFetching}
placeholder={t('platformConfigTip', { key: platformConfig?.sms_template_code })}
placeholder={t('platformConfigTip', { key: platformConfig?.endpoint })}
/>
</TableCell>
</TableRow>
)}
{platformConfig?.sms_template_param && (
<TableRow>
<TableCell>
<Label>{t('secretLabel')}</Label>
<p className='text-muted-foreground text-xs'>
{t('platformConfigTip', { key: platformConfig?.secret })}
</p>
</TableCell>
<TableCell className='text-right'>
<EnhancedInput
value={data?.config?.platform_config?.secret ?? ''}
onValueBlur={(value) =>
updateConfig('config', {
...data?.config,
platform_config: {
...data?.config?.platform_config,
secret: value,
},
})
}
disabled={isFetching}
type='password'
placeholder={t('platformConfigTip', { key: platformConfig?.secret })}
/>
</TableCell>
</TableRow>
{platformConfig?.template_code && (
<TableRow>
<TableCell>
<Label>{t('templateParam')}</Label>
<Label>{t('templateCodeLabel')}</Label>
<p className='text-muted-foreground text-xs'>
{t('platformConfigTip', { key: platformConfig?.sms_template_param })}
{t('platformConfigTip', { key: platformConfig?.template_code })}
</p>
</TableCell>
<TableCell className='text-right'>
<EnhancedInput
value={data?.sms_template_param ?? 'code'}
onValueBlur={(value) => updateConfig('sms_template_param', value)}
value={data?.config?.platform_config?.template_code ?? 'code'}
onValueBlur={(value) =>
updateConfig('config', {
...data?.config,
platform_config: {
...data?.config?.platform_config,
template_code: value,
},
})
}
disabled={isFetching}
placeholder={t('platformConfigTip', { key: platformConfig?.template_code })}
/>
</TableCell>
</TableRow>
)}
{platformConfig?.sign_name && (
<TableRow>
<TableCell>
<Label>{t('signNameLabel')}</Label>
<p className='text-muted-foreground text-xs'>
{t('platformConfigTip', { key: platformConfig?.sign_name })}
</p>
</TableCell>
<TableCell className='text-right'>
<EnhancedInput
value={data?.config?.platform_config?.sign_name ?? ''}
onValueBlur={(value) =>
updateConfig('config', {
...data?.config,
platform_config: {
...data?.config?.platform_config,
sign_name: value,
},
})
}
disabled={isFetching}
placeholder={t('platformConfigTip', {
key: platformConfig?.sms_template_param,
key: platformConfig?.sign_name,
})}
/>
</TableCell>
@ -250,15 +362,23 @@ export default function Page() {
<TableCell>
<Label>{t('template')}</Label>
<p className='text-muted-foreground text-xs'>
{t('templateTip', { code: platformConfig?.sms_template })}
{t('templateTip', { code: platformConfig?.code_variable })}
</p>
</TableCell>
<TableCell className='text-right'>
<Textarea
defaultValue={data?.sms_template ?? ''}
onBlur={(e) => updateConfig('sms_template', e.target.value)}
defaultValue={data?.platform_config?.template ?? ''}
onBlur={(e) =>
updateConfig('config', {
...data?.config,
platform_config: {
...data?.config?.platform_config,
template: e.target.value,
},
})
}
disabled={isFetching}
placeholder={t('placeholders.template', { code: platformConfig?.sms_template })}
placeholder={t('placeholders.template', { code: platformConfig?.code_variable })}
/>
</TableCell>
</TableRow>
@ -315,7 +435,7 @@ function LogsTable() {
const ref = useRef<ProTableActions>(null);
return (
<ProTable<API.Sms, { telephone: string }>
<ProTable<API.SMS, { telephone: string }>
action={ref}
header={{
title: t('SmsList'),

View File

@ -1,6 +1,6 @@
'use client';
import { getOAuthByPlatform, updateOAuthConfig } from '@/services/admin/system';
import { getAuthMethodConfig, updateAuthMethodConfig } from '@/services/admin/authMethod';
import { useQuery } from '@tanstack/react-query';
import { Label } from '@workspace/ui/components/label';
import { Switch } from '@workspace/ui/components/switch';
@ -13,21 +13,21 @@ export default function Page() {
const t = useTranslations('telegram');
const { data, refetch } = useQuery({
queryKey: ['getOAuthByPlatform', 'telegram'],
queryKey: ['getAuthMethodConfig', 'telegram'],
queryFn: async () => {
const { data } = await getOAuthByPlatform({
platform: 'telegram',
const { data } = await getAuthMethodConfig({
method: 'telegram',
});
return data.data;
},
});
async function updateConfig(key: keyof API.UpdateOAuthConfig, value: unknown) {
async function updateConfig(key: keyof API.UpdataAuthMethodConfigRequest, value: unknown) {
try {
await updateOAuthConfig({
await updateAuthMethodConfig({
...data,
[key]: value,
} as API.UpdateOAuthConfig);
} as API.UpdataAuthMethodConfigRequest);
toast.success(t('saveSuccess'));
refetch();
} catch (error) {
@ -94,8 +94,13 @@ export default function Page() {
<TableCell className='text-right'>
<EnhancedInput
placeholder='https://your-domain.com/v1/auth/oauth/callback/telegram'
value={data?.redirect}
onValueBlur={(value) => updateConfig('redirect', value)}
value={data?.config.redirect_url}
onValueBlur={(value) =>
updateConfig('config', {
...data?.config,
redirect_url: value,
})
}
/>
</TableCell>
</TableRow>

View File

@ -17,7 +17,7 @@ import { cn } from '@workspace/ui/lib/utils';
import { formatDate } from '@workspace/ui/utils';
import { UserDetail } from '../user/user-detail';
export default function Page(props: { userId?: string }) {
export default function Page(props: any) {
const t = useTranslations('order');
const statusOptions = [

View File

@ -5,7 +5,7 @@ import UserLoginHistory from './user-login-history';
import { UserProfileForm } from './user-profile';
import UserSubscription from './user-subscription';
export default async function Page({ params }: { params: Promise<{ id: string }> }) {
export default async function Page({ params }: { params: Promise<{ id: number }> }) {
const t = await getTranslations('user');
const { id } = await params;
return (

View File

@ -30,12 +30,14 @@ export default function UserSubscription({ userId }: { userId: number }) {
loading={loading}
userId={userId}
onSubmit={async (values) => {
setLoading(true);
await createUserSubscribe({
user_id: userId,
...values,
});
toast.success(t('createSuccess'));
ref.current?.refresh();
setLoading(false);
return true;
}}
/>
@ -122,6 +124,7 @@ export default function UserSubscription({ userId }: { userId: number }) {
userId={userId}
initialData={row}
onSubmit={async (values) => {
setLoading(true);
await updateUserSubscribe({
user_id: userId,
user_subscribe_id: row.id,
@ -129,6 +132,7 @@ export default function UserSubscription({ userId }: { userId: number }) {
});
toast.success(t('updateSuccess'));
ref.current?.refresh();
setLoading(false);
return true;
}}
/>,
@ -144,7 +148,7 @@ export default function UserSubscription({ userId }: { userId: number }) {
title={t('confirmDelete')}
description={t('deleteSubscriptionDescription')}
onConfirm={async () => {
console.log('删除订阅:', row.id);
console.log('Delete subscription:', row.id);
}}
cancelText={t('cancel')}
confirmText={t('confirm')}

View File

@ -16,23 +16,23 @@ export const useGlobalStore = create<GlobalStore>((set) => ({
site_logo: '',
},
verify: {
turnstile_site_key: '',
enable_login_verify: false,
enable_register_verify: false,
enable_reset_password_verify: false,
turnstile_site_key: '',
},
auth: {
sms: {
sms_enabled: false,
sms_limit: 0,
sms_interval: 0,
sms_expire_time: 0,
mobile: {
enable: false,
limit: 0,
interval: 0,
expire_time: 0,
},
email: {
email_enabled: false,
email_enable_verify: false,
email_enable_domain_suffix: false,
email_domain_suffix_list: '',
enable: false,
enable_verify: false,
enable_domain_suffix: false,
domain_suffix_list: '',
},
register: {
stop_register: false,
@ -42,31 +42,14 @@ export const useGlobalStore = create<GlobalStore>((set) => ({
ip_register_limit_duration: 0,
},
},
register: {
stop_register: false,
enable_email_verify: false,
enable_email_domain_suffix: false,
email_domain_suffix_list: '',
enable_trial: false,
enable_ip_register_limit: false,
ip_register_limit: 0,
ip_register_limit_duration: 0,
sms: {
sms_enabled: false,
sms_limit: 0,
sms_interval: 0,
sms_expire_time: 0,
},
},
invite: {
forced_invite: false,
referral_percentage: 0,
only_first_purchase: false,
},
currency: {
currency_unit: 'USD',
currency_symbol: '$',
access_key: '',
currency_unit: '',
currency_symbol: '',
},
subscribe: {
single_model: false,

View File

@ -1,11 +1,13 @@
{
"SmsList": "Seznam SMS záznamů",
"accessLabel": "Přístup",
"applyPlatform": "Použít platformu",
"areaCode": "Směrový kód",
"content": "Obsah",
"createdAt": "Čas odeslání",
"enable": "Povolit",
"enableTip": "Po povolení budou povoleny funkce registrace, přihlášení, připojení a odpojení mobilního telefonu",
"endpointLabel": "Koncový bod",
"expireTime": "Čas vypršení",
"expireTimeTip": "Doba platnosti ověřovacího kódu SMS (v sekundách)",
"interval": "Interval",
@ -24,18 +26,25 @@
"platformConfigTip": "Vyplňte prosím poskytnutou konfiguraci {key}",
"platformTip": "Vyberte prosím platformu pro SMS",
"search": "Vyhledat telefonní číslo",
"secretLabel": "Tajný klíč",
"sendFailed": "Odeslání se nezdařilo",
"sendSuccess": "Úspěšně odesláno",
"settings": "Nastavení",
"signNameLabel": "Název podpisu",
"status": "Stav",
"telephone": "Telefonní číslo",
"template": "Šablona SMS",
"templateCode": "Kód šablony",
"templateCodeLabel": "Kód šablony",
"templateParam": "Parametr šablony",
"templateTip": "Vyplňte prosím šablonu SMS, ponechte {code} uprostřed, jinak funkce SMS nebude fungovat",
"testSms": "Odeslat testovací SMS",
"testSmsContent": "Toto je testovací zpráva",
"testSmsPhone": "Zadejte telefonní číslo",
"testSmsTip": "Odeslat testovací SMS pro ověření vaší konfigurace",
"updateSuccess": "Aktualizace úspěšná"
"updateSuccess": "Aktualizace úspěšná",
"whitelistAreaCode": "Kód oblasti v bílém seznamu",
"whitelistAreaCodeTip": "Zadejte kódy oblastí v bílém seznamu, např. 1, 852, 886, 888",
"whitelistValidation": "Ověření bílého seznamu",
"whitelistValidationTip": "Pokud je povoleno, mohou SMS odesílat pouze kódy oblastí v bílém seznamu"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "SMS-Protokollliste",
"accessLabel": "Zugriff",
"applyPlatform": "Plattform anwenden",
"areaCode": "Vorwahl",
"content": "Inhalt",
"createdAt": "Sendezeit",
"enable": "Aktivieren",
"enableTip": "Nach der Aktivierung werden die Funktionen zur Registrierung, Anmeldung, Bindung und Entbindung von Mobiltelefonen aktiviert",
"endpointLabel": "Endpunkt",
"expireTime": "Ablaufzeit",
"expireTimeTip": "Gültigkeitsdauer des SMS-Bestätigungscodes (Sekunden)",
"interval": "Intervall",
@ -24,18 +26,25 @@
"platformConfigTip": "Bitte füllen Sie die bereitgestellte {key}-Konfiguration aus",
"platformTip": "Bitte wählen Sie die SMS-Plattform aus",
"search": "Telefonnummer suchen",
"secretLabel": "Geheimnis",
"sendFailed": "Senden fehlgeschlagen",
"sendSuccess": "Erfolgreich gesendet",
"settings": "Einstellungen",
"signNameLabel": "Signaturname",
"status": "Status",
"telephone": "Telefonnummer",
"template": "SMS-Vorlage",
"templateCode": "Vorlagen-Code",
"templateCodeLabel": "Vorlagen-Code",
"templateParam": "Vorlagenparameter",
"templateTip": "Bitte füllen Sie die SMS-Vorlage aus und lassen Sie {code} in der Mitte stehen, da sonst die SMS-Funktion nicht funktioniert.",
"testSms": "Test-SMS senden",
"testSmsContent": "Dies ist eine Testnachricht",
"testSmsPhone": "Telefonnummer eingeben",
"testSmsTip": "Senden Sie eine Test-SMS, um Ihre Konfiguration zu überprüfen",
"updateSuccess": "Aktualisierung erfolgreich"
"updateSuccess": "Aktualisierung erfolgreich",
"whitelistAreaCode": "Whitelist Bereichscode",
"whitelistAreaCodeTip": "Bitte geben Sie die Whitelist Bereichscodes ein, z.B. 1, 852, 886, 888",
"whitelistValidation": "Whitelist Überprüfung",
"whitelistValidationTip": "Wenn aktiviert, können nur Bereichscodes in der Whitelist SMS senden"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "SMS Log List",
"accessLabel": "Access",
"applyPlatform": "Apply Platform",
"areaCode": "Area Code",
"content": "Content",
"createdAt": "Send Time",
"enable": "Enable",
"enableTip": "After enabling, mobile phone registration, login, binding, and unbinding functions will be enabled",
"endpointLabel": "Endpoint",
"expireTime": "Expire Time",
"expireTimeTip": "SMS verification code validity period (seconds)",
"interval": "Interval",
@ -24,18 +26,25 @@
"platformConfigTip": "Please fill in the provided {key} configuration",
"platformTip": "Please select SMS platform",
"search": "Search phone number",
"secretLabel": "Secret",
"sendFailed": "Send Failed",
"sendSuccess": "Send Success",
"settings": "Settings",
"signNameLabel": "Sign Name",
"status": "Status",
"telephone": "Phone Number",
"template": "SMS Template",
"templateCode": "Template Code",
"templateCodeLabel": "Template Code",
"templateParam": "Template Parameter",
"templateTip": "Please fill in the SMS template, keep {code} in the middle, otherwise SMS function will not work",
"testSms": "Send Test SMS",
"testSmsContent": "This is a test message",
"testSmsPhone": "Enter phone number",
"testSmsTip": "Send a test SMS to verify your configuration",
"updateSuccess": "Update Success"
"updateSuccess": "Update Success",
"whitelistAreaCode": "Whitelist Area Code",
"whitelistAreaCodeTip": "Please enter whitelist area codes, e.g., 1, 852, 886, 888",
"whitelistValidation": "Whitelist Verification",
"whitelistValidationTip": "When enabled, only area codes in the whitelist can send SMS"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "Lista de Registro de SMS",
"accessLabel": "Acceso",
"applyPlatform": "Aplicar Plataforma",
"areaCode": "Código de Área",
"content": "Contenido",
"createdAt": "Hora de envío",
"enable": "Habilitar",
"enableTip": "Después de habilitar, se activarán las funciones de registro, inicio de sesión, vinculación y desvinculación del teléfono móvil",
"endpointLabel": "Punto final",
"expireTime": "Tiempo de Expiración",
"expireTimeTip": "Periodo de validez del código de verificación por SMS (segundos)",
"interval": "Intervalo",
@ -24,18 +26,25 @@
"platformConfigTip": "Por favor, complete la configuración proporcionada de {key}",
"platformTip": "Por favor, seleccione la plataforma de SMS",
"search": "Buscar número de teléfono",
"secretLabel": "Secreto",
"sendFailed": "Envío fallido",
"sendSuccess": "Envío exitoso",
"settings": "Configuración",
"signNameLabel": "Nombre de firma",
"status": "Estado",
"telephone": "Número de Teléfono",
"template": "Plantilla de SMS",
"templateCode": "Código de Plantilla",
"templateCodeLabel": "Código de plantilla",
"templateParam": "Parámetro de Plantilla",
"templateTip": "Por favor, complete la plantilla de SMS, mantenga {code} en el medio, de lo contrario, la función de SMS no funcionará",
"testSms": "Enviar SMS de prueba",
"testSmsContent": "Este es un mensaje de prueba",
"testSmsPhone": "Ingrese número de teléfono",
"testSmsTip": "Envía un SMS de prueba para verificar tu configuración",
"updateSuccess": "Actualización Exitosa"
"updateSuccess": "Actualización Exitosa",
"whitelistAreaCode": "Código de área en lista blanca",
"whitelistAreaCodeTip": "Por favor, introduce los códigos de área en la lista blanca, por ejemplo, 1, 852, 886, 888",
"whitelistValidation": "Verificación de lista blanca",
"whitelistValidationTip": "Cuando está habilitado, solo los códigos de área en la lista blanca pueden enviar SMS"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "Lista de Registro de SMS",
"accessLabel": "Acceso",
"applyPlatform": "Aplicar Plataforma",
"areaCode": "Código de Área",
"content": "Contenido",
"createdAt": "Hora de Envío",
"enable": "Habilitar",
"enableTip": "Después de habilitar, se activarán las funciones de registro, inicio de sesión, vinculación y desvinculación del teléfono móvil",
"endpointLabel": "Punto final",
"expireTime": "Tiempo de Expiración",
"expireTimeTip": "Periodo de validez del código de verificación por SMS (segundos)",
"interval": "Intervalo",
@ -24,18 +26,25 @@
"platformConfigTip": "Por favor, complete la configuración proporcionada de {key}",
"platformTip": "Por favor, seleccione la plataforma de SMS",
"search": "Buscar número de teléfono",
"secretLabel": "Secreto",
"sendFailed": "Envío Fallido",
"sendSuccess": "Envío Exitoso",
"settings": "Configuración",
"signNameLabel": "Nombre de firma",
"status": "Estado",
"telephone": "Número de Teléfono",
"template": "Plantilla de SMS",
"templateCode": "Código de Plantilla",
"templateCodeLabel": "Código de plantilla",
"templateParam": "Parámetro de Plantilla",
"templateTip": "Por favor, complete la plantilla de SMS, mantenga {code} en el medio, de lo contrario, la función de SMS no funcionará",
"testSms": "Enviar SMS de Prueba",
"testSmsContent": "Este es un mensaje de prueba",
"testSmsPhone": "Ingrese número de teléfono",
"testSmsTip": "Envía un SMS de prueba para verificar tu configuración",
"updateSuccess": "Actualización Exitosa"
"updateSuccess": "Actualización Exitosa",
"whitelistAreaCode": "Código de área en lista blanca",
"whitelistAreaCodeTip": "Por favor ingrese los códigos de área en la lista blanca, ej., 1, 852, 886, 888",
"whitelistValidation": "Verificación de lista blanca",
"whitelistValidationTip": "Cuando está habilitado, solo los códigos de área en la lista blanca pueden enviar SMS"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "لیست گزارش پیامک",
"accessLabel": "دسترسی",
"applyPlatform": "اعمال پلتفرم",
"areaCode": "کد منطقه",
"content": "محتوا",
"createdAt": "زمان ارسال",
"enable": "فعال کردن",
"enableTip": "پس از فعال‌سازی، عملکردهای ثبت‌نام، ورود، اتصال و قطع اتصال تلفن همراه فعال خواهند شد",
"endpointLabel": "نقطه پایانی",
"expireTime": "زمان انقضا",
"expireTimeTip": "مدت اعتبار کد تأیید پیامکی (ثانیه)",
"interval": "فاصله زمانی",
@ -24,18 +26,25 @@
"platformConfigTip": "لطفاً پیکربندی {key} ارائه شده را پر کنید",
"platformTip": "لطفاً پلتفرم پیامک را انتخاب کنید",
"search": "جستجوی شماره تلفن",
"secretLabel": "رمز",
"sendFailed": "ارسال ناموفق بود",
"sendSuccess": "ارسال موفقیت‌آمیز",
"settings": "تنظیمات",
"signNameLabel": "نام امضا",
"status": "وضعیت",
"telephone": "شماره تلفن",
"template": "قالب پیامک",
"templateCode": "کد الگو",
"templateCodeLabel": "کد الگو",
"templateParam": "پارامتر الگو",
"templateTip": "لطفاً قالب پیامک را پر کنید، {code} را در وسط نگه دارید، در غیر این صورت عملکرد پیامک کار نخواهد کرد",
"testSms": "ارسال پیامک آزمایشی",
"testSmsContent": "این یک پیام آزمایشی است",
"testSmsPhone": "شماره تلفن را وارد کنید",
"testSmsTip": "ارسال یک پیامک آزمایشی برای تأیید تنظیمات شما",
"updateSuccess": "به‌روزرسانی با موفقیت انجام شد"
"updateSuccess": "به‌روزرسانی با موفقیت انجام شد",
"whitelistAreaCode": "کد منطقه لیست سفید",
"whitelistAreaCodeTip": "لطفاً کدهای منطقه لیست سفید را وارد کنید، مثلاً 1، 852، 886، 888",
"whitelistValidation": "تأیید لیست سفید",
"whitelistValidationTip": "زمانی که فعال باشد، فقط کدهای منطقه در لیست سفید می‌توانند پیامک ارسال کنند"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "SMS-luettelolista",
"accessLabel": "Pääsy",
"applyPlatform": "Hae alustaa",
"areaCode": "Alueen koodi",
"content": "Sisältö",
"createdAt": "Lähetysaika",
"enable": "Ota käyttöön",
"enableTip": "Kun otat tämän käyttöön, matkapuhelimen rekisteröinti-, kirjautumis-, sitomis- ja purkutoiminnot otetaan käyttöön",
"endpointLabel": "Päätepiste",
"expireTime": "Vanhentumisaika",
"expireTimeTip": "Tekstiviestivarmennuskoodin voimassaoloaika (sekunteina)",
"interval": "Aikaväli",
@ -24,18 +26,25 @@
"platformConfigTip": "Täytä annettu {key} -määritys",
"platformTip": "Valitse SMS-alusta",
"search": "Hae puhelinnumeroa",
"secretLabel": "Salaisuus",
"sendFailed": "Lähetys epäonnistui",
"sendSuccess": "Lähetys onnistui",
"settings": "Asetukset",
"signNameLabel": "Allekirjoitusnimi",
"status": "Tila",
"telephone": "Puhelinnumero",
"template": "SMS-malli",
"templateCode": "Mallikoodi",
"templateCodeLabel": "Mallikoodi",
"templateParam": "Malliparametri",
"templateTip": "Täytä SMS-malli, pidä {code} keskellä, muuten SMS-toiminto ei toimi",
"testSms": "Lähetä testiviesti",
"testSmsContent": "Tämä on testiviesti",
"testSmsPhone": "Syötä puhelinnumero",
"testSmsTip": "Lähetä testiviesti varmistaaksesi asetuksesi",
"updateSuccess": "Päivitys onnistui"
"updateSuccess": "Päivitys onnistui",
"whitelistAreaCode": "Valkoisen listan aluekoodi",
"whitelistAreaCodeTip": "Syötä valkoisen listan aluekoodit, esim. 1, 852, 886, 888",
"whitelistValidation": "Valkoisen listan vahvistus",
"whitelistValidationTip": "Kun tämä on käytössä, vain valkoisen listan aluekoodit voivat lähettää SMS-viestejä"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "Liste des journaux SMS",
"accessLabel": "Accès",
"applyPlatform": "Plateforme d'application",
"areaCode": "Indicatif régional",
"content": "Contenu",
"createdAt": "Heure d'envoi",
"enable": "Activer",
"enableTip": "Après activation, les fonctions d'enregistrement, de connexion, de liaison et de déliaison par téléphone mobile seront activées",
"endpointLabel": "Point de terminaison",
"expireTime": "Date d'expiration",
"expireTimeTip": "Période de validité du code de vérification par SMS (secondes)",
"interval": "Intervalle",
@ -24,18 +26,25 @@
"platformConfigTip": "Veuillez remplir la configuration {key} fournie",
"platformTip": "Veuillez sélectionner la plateforme SMS",
"search": "Rechercher un numéro de téléphone",
"secretLabel": "Secret",
"sendFailed": "Échec de l'envoi",
"sendSuccess": "Envoi réussi",
"settings": "Paramètres",
"signNameLabel": "Nom de l'expéditeur",
"status": "Statut",
"telephone": "Numéro de téléphone",
"template": "Modèle SMS",
"templateCode": "Code du modèle",
"templateCodeLabel": "Code de modèle",
"templateParam": "Paramètre de Modèle",
"templateTip": "Veuillez remplir le modèle de SMS, gardez {code} au milieu, sinon la fonction SMS ne fonctionnera pas",
"testSms": "Envoyer un SMS de test",
"testSmsContent": "Ceci est un message de test",
"testSmsPhone": "Entrez le numéro de téléphone",
"testSmsTip": "Envoyez un SMS de test pour vérifier votre configuration",
"updateSuccess": "Mise à jour réussie"
"updateSuccess": "Mise à jour réussie",
"whitelistAreaCode": "Code de zone sur liste blanche",
"whitelistAreaCodeTip": "Veuillez entrer les codes de zone sur liste blanche, par exemple, 1, 852, 886, 888",
"whitelistValidation": "Vérification de la liste blanche",
"whitelistValidationTip": "Lorsqu'elle est activée, seuls les codes de zone figurant sur la liste blanche peuvent envoyer des SMS"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "एसएमएस लॉग सूची",
"accessLabel": "पहुँच",
"applyPlatform": "प्लेटफ़ॉर्म लागू करें",
"areaCode": "क्षेत्र कोड",
"content": "सामग्री",
"createdAt": "भेजने का समय",
"enable": "सक्षम करें",
"enableTip": "सक्षम करने के बाद, मोबाइल फोन पंजीकरण, लॉगिन, बाइंडिंग, और अनबाइंडिंग कार्यक्षमताएँ सक्षम हो जाएँगी",
"endpointLabel": "अंतिम बिंदु",
"expireTime": "समाप्ति समय",
"expireTimeTip": "एसएमएस सत्यापन कोड की वैधता अवधि (सेकंड)",
"interval": "अंतराल",
@ -24,18 +26,25 @@
"platformConfigTip": "कृपया दिए गए {key} कॉन्फ़िगरेशन को भरें",
"platformTip": "कृपया एसएमएस प्लेटफ़ॉर्म चुनें",
"search": "फ़ोन नंबर खोजें",
"secretLabel": "गुप्त",
"sendFailed": "भेजना विफल",
"sendSuccess": "सफलतापूर्वक भेजा गया",
"settings": "सेटिंग्स",
"signNameLabel": "साइन नाम",
"status": "स्थिति",
"telephone": "फ़ोन नंबर",
"template": "एसएमएस टेम्पलेट",
"templateCode": "टेम्पलेट कोड",
"templateCodeLabel": "टेम्पलेट कोड",
"templateParam": "टेम्पलेट पैरामीटर",
"templateTip": "कृपया एसएमएस टेम्पलेट भरें, {code} को बीच में रखें, अन्यथा एसएमएस कार्यक्षमता काम नहीं करेगी",
"testSms": "परीक्षण एसएमएस भेजें",
"testSmsContent": "यह एक परीक्षण संदेश है",
"testSmsPhone": "फ़ोन नंबर दर्ज करें",
"testSmsTip": "अपनी कॉन्फ़िगरेशन की पुष्टि करने के लिए एक परीक्षण एसएमएस भेजें",
"updateSuccess": "अद्यतन सफल"
"updateSuccess": "अद्यतन सफल",
"whitelistAreaCode": "व्हाइटलिस्ट क्षेत्र कोड",
"whitelistAreaCodeTip": "कृपया व्हाइटलिस्ट क्षेत्र कोड दर्ज करें, जैसे, 1, 852, 886, 888",
"whitelistValidation": "व्हाइटलिस्ट सत्यापन",
"whitelistValidationTip": "जब सक्षम किया जाता है, केवल व्हाइटलिस्ट में क्षेत्र कोड एसएमएस भेज सकते हैं"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "SMS naplólista",
"accessLabel": "Hozzáférés",
"applyPlatform": "Alkalmazási Platform",
"areaCode": "Körzetszám",
"content": "Tartalom",
"createdAt": "Küldés ideje",
"enable": "Engedélyez",
"enableTip": "A bekapcsolás után a mobiltelefon regisztráció, bejelentkezés, kötés és oldás funkciók elérhetővé válnak",
"endpointLabel": "Végpont",
"expireTime": "Lejárati idő",
"expireTimeTip": "Az SMS ellenőrző kód érvényességi ideje (másodpercben)",
"interval": "Intervallum",
@ -24,18 +26,25 @@
"platformConfigTip": "Kérjük, töltse ki a megadott {key} konfigurációt",
"platformTip": "Kérjük, válassza ki az SMS platformot",
"search": "Telefonszám keresése",
"secretLabel": "Titok",
"sendFailed": "Küldés sikertelen",
"sendSuccess": "Sikeres küldés",
"settings": "Beállítások",
"signNameLabel": "Aláírás Neve",
"status": "Állapot",
"telephone": "Telefonszám",
"template": "SMS sablon",
"templateCode": "Sablon kód",
"templateCodeLabel": "Sablon Kód",
"templateParam": "Sablon Paraméter",
"templateTip": "Kérjük, töltse ki az SMS sablont, tartsa meg a {code} elemet középen, különben az SMS funkció nem fog működni",
"testSms": "Teszt SMS küldése",
"testSmsContent": "Ez egy tesztüzenet",
"testSmsPhone": "Adja meg a telefonszámot",
"testSmsTip": "Küldjön egy teszt SMS-t a konfiguráció ellenőrzéséhez",
"updateSuccess": "Sikeres frissítés"
"updateSuccess": "Sikeres frissítés",
"whitelistAreaCode": "Fehérlista Területi Kód",
"whitelistAreaCodeTip": "Kérjük, adja meg a fehérlista területi kódokat, pl. 1, 852, 886, 888",
"whitelistValidation": "Fehérlista Ellenőrzés",
"whitelistValidationTip": "Ha engedélyezve van, csak a fehérlistán szereplő területi kódok küldhetnek SMS-t"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "SMSログリスト",
"accessLabel": "アクセス",
"applyPlatform": "プラットフォームを適用",
"areaCode": "市外局番",
"content": "コンテンツ",
"createdAt": "送信時間",
"enable": "有効にする",
"enableTip": "有効にすると、携帯電話の登録、ログイン、バインド、アンバインド機能が有効になります",
"endpointLabel": "エンドポイント",
"expireTime": "有効期限",
"expireTimeTip": "SMS認証コードの有効期間",
"interval": "間隔",
@ -24,18 +26,25 @@
"platformConfigTip": "指定された{key}の設定を入力してください",
"platformTip": "SMSプラットフォームを選択してください",
"search": "電話番号を検索",
"secretLabel": "シークレット",
"sendFailed": "送信に失敗しました",
"sendSuccess": "送信成功",
"settings": "設定",
"signNameLabel": "サイン名",
"status": "ステータス",
"telephone": "電話番号",
"template": "SMSテンプレート",
"templateCode": "テンプレートコード",
"templateCodeLabel": "テンプレートコード",
"templateParam": "テンプレートパラメータ",
"templateTip": "SMSテンプレートに記入してください。{code}を中央に保持しないと、SMS機能が動作しません。",
"testSms": "テストSMSを送信",
"testSmsContent": "これはテストメッセージです",
"testSmsPhone": "電話番号を入力してください",
"testSmsTip": "設定を確認するためにテストSMSを送信する",
"updateSuccess": "更新が成功しました"
"updateSuccess": "更新が成功しました",
"whitelistAreaCode": "ホワイトリストエリアコード",
"whitelistAreaCodeTip": "ホワイトリストエリアコードを入力してください。例1、852、886、888",
"whitelistValidation": "ホワイトリスト検証",
"whitelistValidationTip": "有効にすると、ホワイトリストにあるエリアコードのみがSMSを送信できます"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "SMS 로그 목록",
"accessLabel": "접근",
"applyPlatform": "플랫폼 적용",
"areaCode": "지역 코드",
"content": "콘텐츠",
"createdAt": "전송 시간",
"enable": "활성화",
"enableTip": "활성화 후, 휴대폰 등록, 로그인, 연결 및 연결 해제 기능이 활성화됩니다",
"endpointLabel": "엔드포인트",
"expireTime": "만료 시간",
"expireTimeTip": "SMS 인증 코드 유효 기간 (초)",
"interval": "간격",
@ -24,18 +26,25 @@
"platformConfigTip": "제공된 {key} 설정을 입력해 주세요",
"platformTip": "SMS 플랫폼을 선택하세요",
"search": "전화번호 검색",
"secretLabel": "비밀",
"sendFailed": "전송 실패",
"sendSuccess": "전송 성공",
"settings": "설정",
"signNameLabel": "서명 이름",
"status": "상태",
"telephone": "전화번호",
"template": "SMS 템플릿",
"templateCode": "템플릿 코드",
"templateCodeLabel": "템플릿 코드",
"templateParam": "템플릿 매개변수",
"templateTip": "SMS 템플릿을 작성해 주세요. {code}를 중간에 유지해야 SMS 기능이 작동합니다.",
"testSms": "테스트 SMS 보내기",
"testSmsContent": "이것은 테스트 메시지입니다",
"testSmsPhone": "전화번호를 입력하세요",
"testSmsTip": "구성을 확인하기 위해 테스트 SMS를 전송하세요",
"updateSuccess": "업데이트 성공"
"updateSuccess": "업데이트 성공",
"whitelistAreaCode": "허용된 지역 코드",
"whitelistAreaCodeTip": "허용된 지역 코드를 입력하세요. 예: 1, 852, 886, 888",
"whitelistValidation": "허용 목록 검증",
"whitelistValidationTip": "활성화되면, 허용 목록에 있는 지역 코드만 SMS를 보낼 수 있습니다."
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "SMS-loggliste",
"accessLabel": "Tilgang",
"applyPlatform": "Søk Plattform",
"areaCode": "Retningsnummer",
"content": "Innhold",
"createdAt": "Sendetid",
"enable": "Aktiver",
"enableTip": "Etter aktivering vil funksjonene for registrering, innlogging, binding og frakobling av mobiltelefon bli aktivert",
"endpointLabel": "Endepunkt",
"expireTime": "Utløpstid",
"expireTimeTip": "Gyldighetsperiode for SMS-bekreftelseskode (sekunder)",
"interval": "Intervall",
@ -24,18 +26,25 @@
"platformConfigTip": "Vennligst fyll inn den oppgitte {key} konfigurasjonen",
"platformTip": "Vennligst velg SMS-plattform",
"search": "Søk telefonnummer",
"secretLabel": "Hemmelighet",
"sendFailed": "Sending mislyktes",
"sendSuccess": "Sendt Vellykket",
"settings": "Innstillinger",
"signNameLabel": "Signaturnavn",
"status": "Status",
"telephone": "Telefonnummer",
"template": "SMS-mal",
"templateCode": "Malkode",
"templateCodeLabel": "Malekode",
"templateParam": "Malparameter",
"templateTip": "Vennligst fyll ut SMS-malen, behold {code} i midten, ellers vil ikke SMS-funksjonen fungere",
"testSms": "Send test-SMS",
"testSmsContent": "Dette er en testmelding",
"testSmsPhone": "Skriv inn telefonnummer",
"testSmsTip": "Send en test-SMS for å verifisere konfigurasjonen din",
"updateSuccess": "Oppdatering Vellykket"
"updateSuccess": "Oppdatering Vellykket",
"whitelistAreaCode": "Hviteliste områdekode",
"whitelistAreaCodeTip": "Vennligst skriv inn hviteliste områdekoder, f.eks. 1, 852, 886, 888",
"whitelistValidation": "Hviteliste verifisering",
"whitelistValidationTip": "Når aktivert, kan kun områdekoder i hvitelisten sende SMS"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "Lista dziennika SMS",
"accessLabel": "Dostęp",
"applyPlatform": "Zastosuj Platformę",
"areaCode": "Kod obszaru",
"content": "Treść",
"createdAt": "Czas wysłania",
"enable": "Włącz",
"enableTip": "Po włączeniu zostaną aktywowane funkcje rejestracji, logowania, wiązania i odwiązywania telefonu komórkowego",
"endpointLabel": "Punkt końcowy",
"expireTime": "Czas wygaśnięcia",
"expireTimeTip": "Okres ważności kodu weryfikacyjnego SMS (sekundy)",
"interval": "Interwał",
@ -24,18 +26,25 @@
"platformConfigTip": "Proszę wypełnić podaną konfigurację {key}",
"platformTip": "Proszę wybrać platformę SMS",
"search": "Wyszukaj numer telefonu",
"secretLabel": "Sekret",
"sendFailed": "Wysyłanie nie powiodło się",
"sendSuccess": "Wysłano pomyślnie",
"settings": "Ustawienia",
"signNameLabel": "Nazwa podpisu",
"status": "Status",
"telephone": "Numer telefonu",
"template": "Szablon SMS",
"templateCode": "Kod szablonu",
"templateCodeLabel": "Kod szablonu",
"templateParam": "Parametr Szablonu",
"templateTip": "Proszę wypełnić szablon SMS, zachowując {code} w środku, w przeciwnym razie funkcja SMS nie będzie działać",
"testSms": "Wyślij testowy SMS",
"testSmsContent": "To jest wiadomość testowa",
"testSmsPhone": "Wprowadź numer telefonu",
"testSmsTip": "Wyślij testowy SMS, aby zweryfikować swoją konfigurację",
"updateSuccess": "Aktualizacja zakończona pomyślnie"
"updateSuccess": "Aktualizacja zakończona pomyślnie",
"whitelistAreaCode": "Kod obszaru białej listy",
"whitelistAreaCodeTip": "Proszę wprowadzić kody obszarów białej listy, np. 1, 852, 886, 888",
"whitelistValidation": "Weryfikacja białej listy",
"whitelistValidationTip": "Po włączeniu, tylko kody obszarów na białej liście mogą wysyłać SMS"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "Lista de Registro de SMS",
"accessLabel": "Acesso",
"applyPlatform": "Aplicar Plataforma",
"areaCode": "Código de Área",
"content": "Conteúdo",
"createdAt": "Hora de Envio",
"enable": "Habilitar",
"enableTip": "Após a ativação, as funções de registro, login, vinculação e desvinculação de telefone celular serão ativadas",
"endpointLabel": "Endpoint",
"expireTime": "Tempo de Expiração",
"expireTimeTip": "Período de validade do código de verificação por SMS (segundos)",
"interval": "Intervalo",
@ -24,18 +26,25 @@
"platformConfigTip": "Por favor, preencha a configuração fornecida {key}",
"platformTip": "Por favor, selecione a plataforma de SMS",
"search": "Pesquisar número de telefone",
"secretLabel": "Segredo",
"sendFailed": "Envio Falhou",
"sendSuccess": "Envio bem-sucedido",
"settings": "Configurações",
"signNameLabel": "Nome da Assinatura",
"status": "Status",
"telephone": "Número de Telefone",
"template": "Modelo de SMS",
"templateCode": "Código do Modelo",
"templateCodeLabel": "Código do Modelo",
"templateParam": "Parâmetro de Modelo",
"templateTip": "Por favor, preencha o modelo de SMS, mantenha {code} no meio, caso contrário, a função de SMS não funcionará",
"testSms": "Enviar SMS de Teste",
"testSmsContent": "Esta é uma mensagem de teste",
"testSmsPhone": "Digite o número de telefone",
"testSmsTip": "Envie um SMS de teste para verificar sua configuração",
"updateSuccess": "Atualização bem-sucedida"
"updateSuccess": "Atualização bem-sucedida",
"whitelistAreaCode": "Código de Área da Lista Branca",
"whitelistAreaCodeTip": "Por favor, insira os códigos de área da lista branca, ex: 1, 852, 886, 888",
"whitelistValidation": "Verificação da Lista Branca",
"whitelistValidationTip": "Quando ativado, apenas os códigos de área na lista branca podem enviar SMS"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "Listă Jurnal SMS",
"accessLabel": "Acces",
"applyPlatform": "Aplică Platformă",
"areaCode": "Prefix telefonic",
"content": "Conținut",
"createdAt": "Ora trimiterii",
"enable": "Activează",
"enableTip": "După activare, funcțiile de înregistrare, autentificare, asociere și disociere a telefonului mobil vor fi activate",
"endpointLabel": "Punct de acces",
"expireTime": "Timp de expirare",
"expireTimeTip": "Perioada de valabilitate a codului de verificare prin SMS (secunde)",
"interval": "Interval",
@ -24,18 +26,25 @@
"platformConfigTip": "Vă rugăm să completați configurația {key} furnizată",
"platformTip": "Vă rugăm să selectați platforma SMS",
"search": "Caută număr de telefon",
"secretLabel": "Secret",
"sendFailed": "Trimitere eșuată",
"sendSuccess": "Trimitere reușită",
"settings": "Setări",
"signNameLabel": "Nume semnătură",
"status": "Stare",
"telephone": "Număr de telefon",
"template": "Șablon SMS",
"templateCode": "Cod Șablon",
"templateCodeLabel": "Cod șablon",
"templateParam": "Parametru Șablon",
"templateTip": "Vă rugăm să completați șablonul SMS, păstrați {code} în mijloc, altfel funcția SMS nu va funcționa",
"testSms": "Trimite SMS de test",
"testSmsContent": "Acesta este un mesaj de test",
"testSmsPhone": "Introduceți numărul de telefon",
"testSmsTip": "Trimite un SMS de test pentru a verifica configurația ta",
"updateSuccess": "Actualizare reușită"
"updateSuccess": "Actualizare reușită",
"whitelistAreaCode": "Coduri de zonă pe lista albă",
"whitelistAreaCodeTip": "Vă rugăm să introduceți codurile de zonă pe lista albă, de exemplu, 1, 852, 886, 888",
"whitelistValidation": "Verificare listă albă",
"whitelistValidationTip": "Când este activat, doar codurile de zonă din lista albă pot trimite SMS-uri"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "Список журнала SMS",
"accessLabel": "Доступ",
"applyPlatform": "Применить платформу",
"areaCode": "Код региона",
"content": "Содержание",
"createdAt": "Время отправки",
"enable": "Включить",
"enableTip": "После включения будут доступны функции регистрации, входа, привязки и отвязки мобильного телефона",
"endpointLabel": "Конечная точка",
"expireTime": "Время истечения",
"expireTimeTip": "Срок действия кода подтверждения по SMS (в секундах)",
"interval": "Интервал",
@ -24,18 +26,25 @@
"platformConfigTip": "Пожалуйста, заполните предоставленную конфигурацию {key}",
"platformTip": "Пожалуйста, выберите платформу SMS",
"search": "Поиск номера телефона",
"secretLabel": "Секрет",
"sendFailed": "Не удалось отправить",
"sendSuccess": "Успешно отправлено",
"settings": "Настройки",
"signNameLabel": "Имя подписи",
"status": "Статус",
"telephone": "Номер телефона",
"template": "Шаблон SMS",
"templateCode": "Код шаблона",
"templateCodeLabel": "Код шаблона",
"templateParam": "Параметр шаблона",
"templateTip": "Пожалуйста, заполните шаблон SMS, оставьте {code} в середине, иначе функция SMS не будет работать",
"testSms": "Отправить тестовое SMS",
"testSmsContent": "Это тестовое сообщение",
"testSmsPhone": "Введите номер телефона",
"testSmsTip": "Отправьте тестовое SMS, чтобы проверить вашу конфигурацию",
"updateSuccess": "Обновление успешно"
"updateSuccess": "Обновление успешно",
"whitelistAreaCode": "Код региона в белом списке",
"whitelistAreaCodeTip": "Пожалуйста, введите коды регионов в белом списке, например, 1, 852, 886, 888",
"whitelistValidation": "Проверка белого списка",
"whitelistValidationTip": "При включении только коды регионов из белого списка могут отправлять SMS"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "รายการบันทึก SMS",
"accessLabel": "การเข้าถึง",
"applyPlatform": "สมัครแพลตฟอร์ม",
"areaCode": "รหัสพื้นที่",
"content": "เนื้อหา",
"createdAt": "เวลาที่ส่ง",
"enable": "เปิดใช้งาน",
"enableTip": "หลังจากเปิดใช้งานแล้ว ฟังก์ชันการลงทะเบียน การเข้าสู่ระบบ การผูก และการยกเลิกการผูกโทรศัพท์มือถือจะถูกเปิดใช้งาน",
"endpointLabel": "จุดสิ้นสุด",
"expireTime": "เวลาหมดอายุ",
"expireTimeTip": "ระยะเวลาหมดอายุของรหัสยืนยันทาง SMS (วินาที)",
"interval": "ช่วงเวลา",
@ -24,18 +26,25 @@
"platformConfigTip": "กรุณากรอกการตั้งค่าที่ให้ไว้ {key}",
"platformTip": "กรุณาเลือกแพลตฟอร์ม SMS",
"search": "ค้นหาเบอร์โทรศัพท์",
"secretLabel": "ความลับ",
"sendFailed": "ส่งไม่สำเร็จ",
"sendSuccess": "ส่งสำเร็จ",
"settings": "การตั้งค่า",
"signNameLabel": "ชื่อผู้ลงนาม",
"status": "สถานะ",
"telephone": "หมายเลขโทรศัพท์",
"template": "เทมเพลต SMS",
"templateCode": "รหัสเทมเพลต",
"templateCodeLabel": "รหัสแม่แบบ",
"templateParam": "พารามิเตอร์แม่แบบ",
"templateTip": "กรุณากรอกเทมเพลต SMS โดยคง {code} ไว้ตรงกลาง มิฉะนั้นฟังก์ชัน SMS จะไม่ทำงาน",
"testSms": "ส่ง SMS ทดสอบ",
"testSmsContent": "นี่คือข้อความทดสอบ",
"testSmsPhone": "กรุณาใส่หมายเลขโทรศัพท์",
"testSmsTip": "ส่ง SMS ทดสอบเพื่อตรวจสอบการตั้งค่าของคุณ",
"updateSuccess": "อัปเดตสำเร็จ"
"updateSuccess": "อัปเดตสำเร็จ",
"whitelistAreaCode": "รหัสพื้นที่ในรายการอนุญาต",
"whitelistAreaCodeTip": "กรุณาใส่รหัสพื้นที่ในรายการอนุญาต เช่น 1, 852, 886, 888",
"whitelistValidation": "การตรวจสอบรายการอนุญาต",
"whitelistValidationTip": "เมื่อเปิดใช้งาน จะอนุญาตให้ส่ง SMS เฉพาะรหัสพื้นที่ในรายการอนุญาตเท่านั้น"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "SMS Günlük Listesi",
"accessLabel": "Erişim",
"applyPlatform": "Platforma Başvur",
"areaCode": "Alan Kodu",
"content": "İçerik",
"createdAt": "Gönderim Zamanı",
"enable": "Etkinleştir",
"enableTip": "Etkinleştirildikten sonra, cep telefonu kaydı, giriş, bağlama ve bağlantı kesme işlevleri etkinleştirilecektir",
"endpointLabel": "Uç Nokta",
"expireTime": "Sona Erme Süresi",
"expireTimeTip": "SMS doğrulama kodu geçerlilik süresi (saniye)",
"interval": "Aralık",
@ -24,18 +26,25 @@
"platformConfigTip": "Lütfen sağlanan {key} yapılandırmasını doldurun",
"platformTip": "Lütfen SMS platformunu seçin",
"search": "Telefon numarası ara",
"secretLabel": "Gizli Anahtar",
"sendFailed": "Gönderim Başarısız",
"sendSuccess": "Gönderim Başarılı",
"settings": "Ayarlar",
"signNameLabel": "İmza Adı",
"status": "Durum",
"telephone": "Telefon Numarası",
"template": "SMS Şablonu",
"templateCode": "Şablon Kodu",
"templateCodeLabel": "Şablon Kodu",
"templateParam": "Şablon Parametresi",
"templateTip": "Lütfen SMS şablonunu doldurun, {code} ortada kalacak şekilde, aksi takdirde SMS işlevi çalışmaz",
"testSms": "Test SMS Gönder",
"testSmsContent": "Bu bir test mesajıdır",
"testSmsPhone": "Telefon numarasını girin",
"testSmsTip": "Yapılandırmanızı doğrulamak için bir test SMS'i gönderin",
"updateSuccess": "Güncelleme Başarılı"
"updateSuccess": "Güncelleme Başarılı",
"whitelistAreaCode": "Beyaz Liste Alan Kodu",
"whitelistAreaCodeTip": "Lütfen beyaz liste alan kodlarını girin, örneğin, 1, 852, 886, 888",
"whitelistValidation": "Beyaz Liste Doğrulaması",
"whitelistValidationTip": "Etkinleştirildiğinde, yalnızca beyaz listedeki alan kodları SMS gönderebilir"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "Список журналу SMS",
"accessLabel": "Доступ",
"applyPlatform": "Застосувати платформу",
"areaCode": "Код регіону",
"content": "Зміст",
"createdAt": "Час відправлення",
"enable": "Увімкнути",
"enableTip": "Після увімкнення будуть доступні функції реєстрації, входу, прив'язки та відв'язки мобільного телефону",
"endpointLabel": "Кінцева точка",
"expireTime": "Час закінчення",
"expireTimeTip": "Термін дії коду перевірки SMS (секунди)",
"interval": "Інтервал",
@ -24,18 +26,25 @@
"platformConfigTip": "Будь ласка, заповніть надану конфігурацію {key}",
"platformTip": "Будь ласка, виберіть платформу SMS",
"search": "Пошук номера телефону",
"secretLabel": "Секрет",
"sendFailed": "Не вдалося надіслати",
"sendSuccess": "Відправлено успішно",
"settings": "Налаштування",
"signNameLabel": "Назва підпису",
"status": "Статус",
"telephone": "Номер телефону",
"template": "Шаблон SMS",
"templateCode": "Код шаблону",
"templateCodeLabel": "Код шаблону",
"templateParam": "Параметр Шаблону",
"templateTip": "Будь ласка, заповніть шаблон SMS, залиште {code} посередині, інакше функція SMS не працюватиме",
"testSms": "Надіслати тестове SMS",
"testSmsContent": "Це тестове повідомлення",
"testSmsPhone": "Введіть номер телефону",
"testSmsTip": "Надіслати тестове SMS, щоб перевірити вашу конфігурацію",
"updateSuccess": "Оновлення успішне"
"updateSuccess": "Оновлення успішне",
"whitelistAreaCode": "Код області білого списку",
"whitelistAreaCodeTip": "Будь ласка, введіть коди областей білого списку, наприклад, 1, 852, 886, 888",
"whitelistValidation": "Перевірка білого списку",
"whitelistValidationTip": "При увімкненні лише коди областей у білому списку можуть надсилати SMS"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "Danh sách nhật ký SMS",
"accessLabel": "Truy cập",
"applyPlatform": "Nền tảng ứng dụng",
"areaCode": "Mã vùng",
"content": "Nội dung",
"createdAt": "Thời gian gửi",
"enable": "Kích hoạt",
"enableTip": "Sau khi kích hoạt, các chức năng đăng ký, đăng nhập, liên kết và hủy liên kết điện thoại di động sẽ được kích hoạt",
"endpointLabel": "Điểm cuối",
"expireTime": "Thời Gian Hết Hạn",
"expireTimeTip": "Thời gian hiệu lực của mã xác minh SMS (giây)",
"interval": "Khoảng thời gian",
@ -24,18 +26,25 @@
"platformConfigTip": "Vui lòng điền vào cấu hình {key} được cung cấp",
"platformTip": "Vui lòng chọn nền tảng SMS",
"search": "Tìm số điện thoại",
"secretLabel": "Mật khẩu",
"sendFailed": "Gửi Thất Bại",
"sendSuccess": "Gửi thành công",
"settings": "Cài đặt",
"signNameLabel": "Tên ký hiệu",
"status": "Trạng thái",
"telephone": "Số điện thoại",
"template": "Mẫu SMS",
"templateCode": "Mã Mẫu",
"templateCodeLabel": "Mã mẫu",
"templateParam": "Tham số Mẫu",
"templateTip": "Vui lòng điền vào mẫu SMS, giữ {code} ở giữa, nếu không chức năng SMS sẽ không hoạt động",
"testSms": "Gửi SMS Thử",
"testSmsContent": "Đây là một tin nhắn thử nghiệm",
"testSmsPhone": "Nhập số điện thoại",
"testSmsTip": "Gửi một tin nhắn SMS thử nghiệm để xác minh cấu hình của bạn",
"updateSuccess": "Cập nhật thành công"
"updateSuccess": "Cập nhật thành công",
"whitelistAreaCode": "Mã khu vực trong danh sách trắng",
"whitelistAreaCodeTip": "Vui lòng nhập mã khu vực trong danh sách trắng, ví dụ: 1, 852, 886, 888",
"whitelistValidation": "Xác minh danh sách trắng",
"whitelistValidationTip": "Khi được kích hoạt, chỉ các mã khu vực trong danh sách trắng mới có thể gửi SMS"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "短信日志列表",
"accessLabel": "访问",
"applyPlatform": "申请平台",
"areaCode": "区号",
"content": "内容",
"createdAt": "发送时间",
"enable": "启用",
"enableTip": "启用后,将启用手机注册、登录、绑定和解绑功能",
"endpointLabel": "端点",
"expireTime": "过期时间",
"expireTimeTip": "短信验证码有效期(秒)",
"interval": "间隔",
@ -24,18 +26,25 @@
"platformConfigTip": "请填写提供的{key}配置",
"platformTip": "请选择短信平台",
"search": "搜索电话号码",
"secretLabel": "密钥",
"sendFailed": "发送失败",
"sendSuccess": "发送成功",
"settings": "设置",
"signNameLabel": "签名名称",
"status": "状态",
"telephone": "电话号码",
"template": "短信模板",
"templateCode": "模板代码",
"templateCodeLabel": "模板代码",
"templateParam": "模板参数",
"templateTip": "请填写短信模板,保持 {code} 在中间,否则短信功能将无法正常工作",
"testSms": "发送测试短信",
"testSmsContent": "这是一条测试消息",
"testSmsPhone": "输入电话号码",
"testSmsTip": "发送测试短信以验证您的配置",
"updateSuccess": "更新成功"
"updateSuccess": "更新成功",
"whitelistAreaCode": "白名单区号",
"whitelistAreaCodeTip": "请输入白名单区号例如1, 852, 886, 888",
"whitelistValidation": "白名单验证",
"whitelistValidationTip": "启用后,仅白名单中的区号可以发送短信"
}

View File

@ -1,11 +1,13 @@
{
"SmsList": "SMS 日誌列表",
"accessLabel": "訪問",
"applyPlatform": "申請平台",
"areaCode": "地區代碼",
"content": "內容",
"createdAt": "發送時間",
"enable": "啟用",
"enableTip": "啟用後,將啟用手機註冊、登入、綁定和解綁功能",
"endpointLabel": "端點",
"expireTime": "到期時間",
"expireTimeTip": "SMS 驗證碼有效期(秒)",
"interval": "間隔",
@ -24,18 +26,25 @@
"platformConfigTip": "請填寫提供的 {key} 配置",
"platformTip": "請選擇短信平台",
"search": "搜尋電話號碼",
"secretLabel": "密鑰",
"sendFailed": "發送失敗",
"sendSuccess": "發送成功",
"settings": "設定",
"signNameLabel": "簽名名稱",
"status": "狀態",
"telephone": "電話號碼",
"template": "短信範本",
"templateCode": "模板代碼",
"templateCodeLabel": "模板代碼",
"templateParam": "模板參數",
"templateTip": "請填寫短信模板,保持 {code} 在中間,否則短信功能將無法運作",
"testSms": "發送測試短信",
"testSmsContent": "這是一條測試訊息",
"testSmsPhone": "輸入電話號碼",
"testSmsTip": "發送測試短信以驗證您的配置",
"updateSuccess": "更新成功"
"updateSuccess": "更新成功",
"whitelistAreaCode": "白名單區域代碼",
"whitelistAreaCodeTip": "請輸入白名單區域代碼例如1, 852, 886, 888",
"whitelistValidation": "白名單驗證",
"whitelistValidationTip": "啟用後,只有白名單中的區域代碼可以發送短信"
}

View File

@ -66,7 +66,7 @@ declare namespace API {
};
type AuthConfig = {
sms: MobileAuthenticateConfig;
mobile: MobileAuthenticateConfig;
email: EmailAuthticateConfig;
register: RegisterConfig;
};
@ -1362,7 +1362,6 @@ declare namespace API {
expired_at: number;
upload: number;
download: number;
status: number;
};
type User = {

View File

@ -32,7 +32,6 @@ export async function appleLoginCallback(
return request<API.Response & { data?: any }>('/v1/auth/oauth/callback/apple', {
method: 'POST',
data: formData,
requestType: 'form',
...(options || {}),
});
}

View File

@ -64,7 +64,7 @@ declare namespace API {
};
type AuthConfig = {
sms: MobileAuthenticateConfig;
mobile: MobileAuthenticateConfig;
email: EmailAuthticateConfig;
register: RegisterConfig;
};

View File

@ -33,8 +33,8 @@ export default function RegisterForm({
try {
const domain = email.split('@')[1];
const isValid =
!auth.email.email_enable_verify ||
auth.email?.email_domain_suffix_list.split('\n').includes(domain || '');
!auth.email.enable_verify ||
auth.email?.domain_suffix_list.split('\n').includes(domain || '');
return !isValid;
} catch (error) {
console.log('Error checking user:', error);
@ -52,7 +52,7 @@ export default function RegisterForm({
}),
password: z.string(),
repeat_password: z.string(),
code: auth.email.email_enable_verify ? z.string() : z.string().nullish(),
code: auth.email.enable_verify ? z.string() : z.string().nullish(),
invite: invite.forced_invite ? z.string().min(1) : z.string().nullish(),
cf_token:
verify.enable_register_verify && verify.turnstile_site_key
@ -125,7 +125,7 @@ export default function RegisterForm({
</FormItem>
)}
/>
{auth.email.email_enable_verify && (
{auth.email.enable_verify && (
<FormField
control={form.control}
name='code'

View File

@ -32,7 +32,7 @@ export default function ResetForm({
const formSchema = z.object({
email: z.string().email(t('email')),
password: z.string(),
code: auth?.email?.email_enable_verify ? z.string() : z.string().nullish(),
code: auth?.email?.enable_verify ? z.string() : z.string().nullish(),
cf_token:
verify.enable_register_verify && verify.turnstile_site_key
? z.string()
@ -60,7 +60,7 @@ export default function ResetForm({
)}
/>
{auth?.email?.email_enable_verify && (
{auth?.email?.enable_verify && (
<FormField
control={form.control}
name='code'

View File

@ -35,7 +35,7 @@ export default function ResetForm({
telephone_area_code: z.string(),
telephone: z.string(),
password: z.string(),
code: auth?.email?.email_enable_verify ? z.string() : z.string().nullish(),
code: auth?.email?.enable_verify ? z.string() : z.string().nullish(),
cf_token:
verify.enable_register_verify && verify.turnstile_site_key
? z.string()

View File

@ -22,23 +22,23 @@ export const useGlobalStore = create<GlobalStore>((set, get) => ({
site_logo: '',
},
verify: {
turnstile_site_key: '',
enable_login_verify: false,
enable_register_verify: false,
enable_reset_password_verify: false,
turnstile_site_key: '',
},
auth: {
sms: {
sms_enabled: false,
sms_limit: 0,
sms_interval: 0,
sms_expire_time: 0,
mobile: {
enable: false,
limit: 0,
interval: 0,
expire_time: 0,
},
email: {
email_enabled: false,
email_enable_verify: false,
email_enable_domain_suffix: false,
email_domain_suffix_list: '',
enable: false,
enable_verify: false,
enable_domain_suffix: false,
domain_suffix_list: '',
},
register: {
stop_register: false,
@ -56,7 +56,6 @@ export const useGlobalStore = create<GlobalStore>((set, get) => ({
currency: {
currency_unit: 'USD',
currency_symbol: '$',
access_key: '',
},
subscribe: {
single_model: false,

View File

@ -47,7 +47,6 @@
"60002": "Kan for øyeblikket ikke bruke abonnementet, vennligst prøv igjen senere.",
"60003": "Et eksisterende abonnement er oppdaget. Vennligst avbryt det før du fortsetter.",
"60004": "Kan ikke slettes for øyeblikket da abonnementet har aktive brukere.",
"60005": "Abonnementet har nådd maks antall brukere.",
"60005": "Enkelt abonnementsmodus har overskredet brukergrensen.",
"70001": "Verifikasjonskoden er feil, vennligst skriv inn på nytt.",
"80001": "Oppgaven ble ikke vellykket lagt til i køen, vennligst prøv igjen senere.",

View File

@ -47,7 +47,6 @@
"60002": "Não é possível usar a assinatura no momento, por favor, tente novamente mais tarde.",
"60003": "Uma assinatura existente foi detectada. Cancele-a antes de prosseguir.",
"60004": "Não é possível excluir no momento, pois a assinatura possui usuários ativos.",
"60005": "A assinatura atingiu o número máximo de usuários.",
"60005": "O modo de assinatura única excedeu o limite de usuários.",
"70001": "O código de verificação está incorreto, por favor, digite novamente.",
"80001": "A tarefa não foi adicionada à fila com sucesso, por favor, tente novamente mais tarde.",

View File

@ -64,7 +64,7 @@ declare namespace API {
};
type AuthConfig = {
sms: MobileAuthenticateConfig;
mobile: MobileAuthenticateConfig;
email: EmailAuthticateConfig;
register: RegisterConfig;
};

View File

@ -58,7 +58,7 @@ declare namespace API {
};
type AuthConfig = {
sms: MobileAuthenticateConfig;
mobile: MobileAuthenticateConfig;
email: EmailAuthticateConfig;
register: RegisterConfig;
};

View File

@ -1,5 +1,6 @@
import { Badge } from '@workspace/ui/components/badge';
import { Input } from '@workspace/ui/components/input';
import { cn } from '@workspace/ui/lib/utils';
import { X } from 'lucide-react';
import React, { useEffect, useState } from 'react';
@ -8,9 +9,16 @@ interface TagInputProps {
onChange?: (tags: string[]) => void;
placeholder?: string;
separator?: string;
className?: string;
}
export function TagInput({ value = [], onChange, placeholder, separator = ',' }: TagInputProps) {
export function TagInput({
value = [],
onChange,
placeholder,
separator = ',',
className,
}: TagInputProps) {
const [inputValue, setInputValue] = useState('');
const [tags, setTags] = useState<string[]>(value);
@ -19,7 +27,6 @@ export function TagInput({ value = [], onChange, placeholder, separator = ',' }:
}, [value]);
function normalizeInput(input: string) {
// 将中文逗号替换为英文逗号
return input.replace(//g, ',');
}
@ -58,7 +65,12 @@ export function TagInput({ value = [], onChange, placeholder, separator = ',' }:
}
return (
<div className='border-input focus-within:ring-primary flex min-h-9 w-full flex-wrap items-center gap-2 rounded-md border bg-transparent p-2 shadow-sm transition-colors focus-within:ring-1'>
<div
className={cn(
'border-input focus-within:ring-primary flex min-h-9 w-full flex-wrap items-center gap-2 rounded-md border bg-transparent p-2 shadow-sm transition-colors focus-within:ring-1',
className,
)}
>
{tags.map((tag, index) => (
<Badge
key={tag}