feat: require compliance confirmation for paid features
Gate payment, redemption, subscription, and invitation reward flows behind an audited compliance acknowledgement.
This commit is contained in:
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
Copyright (C) 2023-2026 QuantumNous
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
For commercial licensing, please contact support@quantumnous.com
|
||||
*/
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { cn } from '@/lib/utils'
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from '@/components/ui/alert-dialog'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Checkbox } from '@/components/ui/checkbox'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
|
||||
type RequiredTextPart = {
|
||||
type: 'input' | 'static'
|
||||
text: string
|
||||
placeholder?: string
|
||||
}
|
||||
|
||||
type NormalizedRequiredTextPart = RequiredTextPart & {
|
||||
inputIndex?: number
|
||||
}
|
||||
|
||||
type RiskAcknowledgementDialogProps = {
|
||||
open: boolean
|
||||
onOpenChange: (open: boolean) => void
|
||||
title: string
|
||||
description?: React.ReactNode
|
||||
items?: string[]
|
||||
checklist?: string[]
|
||||
requiredText?: string
|
||||
requiredTextParts?: RequiredTextPart[]
|
||||
inputPrompt?: string
|
||||
inputPlaceholder?: string
|
||||
mismatchHint?: string
|
||||
confirmText?: string
|
||||
cancelText?: string
|
||||
destructive?: boolean
|
||||
isLoading?: boolean
|
||||
onConfirm: () => void
|
||||
className?: string
|
||||
}
|
||||
|
||||
export function RiskAcknowledgementDialog({
|
||||
open,
|
||||
onOpenChange,
|
||||
title,
|
||||
description,
|
||||
items = [],
|
||||
checklist = [],
|
||||
requiredText = '',
|
||||
requiredTextParts = [],
|
||||
inputPrompt,
|
||||
inputPlaceholder,
|
||||
mismatchHint,
|
||||
confirmText,
|
||||
cancelText,
|
||||
destructive = true,
|
||||
isLoading = false,
|
||||
onConfirm,
|
||||
className,
|
||||
}: RiskAcknowledgementDialogProps) {
|
||||
const { t } = useTranslation()
|
||||
const [checkedItems, setCheckedItems] = useState<boolean[]>([])
|
||||
const [typedText, setTypedText] = useState('')
|
||||
const [typedTextParts, setTypedTextParts] = useState<string[]>([])
|
||||
|
||||
const normalizedRequiredTextParts = useMemo<
|
||||
NormalizedRequiredTextPart[]
|
||||
>(() => {
|
||||
let inputIndex = 0
|
||||
return requiredTextParts.map((part) => {
|
||||
if (part.type === 'input') {
|
||||
const normalizedPart = { ...part, inputIndex }
|
||||
inputIndex += 1
|
||||
return normalizedPart
|
||||
}
|
||||
return part
|
||||
})
|
||||
}, [requiredTextParts])
|
||||
|
||||
const requiredTextInputCount = useMemo(
|
||||
() =>
|
||||
normalizedRequiredTextParts.filter((part) => part.type === 'input')
|
||||
.length,
|
||||
[normalizedRequiredTextParts]
|
||||
)
|
||||
const hasSegmentedRequiredText = requiredTextInputCount > 0
|
||||
const requiredTextToDisplay = hasSegmentedRequiredText
|
||||
? normalizedRequiredTextParts.map((part) => part.text).join('')
|
||||
: requiredText
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) return
|
||||
setCheckedItems(Array(checklist.length).fill(false))
|
||||
setTypedText('')
|
||||
setTypedTextParts(Array(requiredTextInputCount).fill(''))
|
||||
}, [open, checklist.length, requiredTextInputCount])
|
||||
|
||||
const allChecked = useMemo(() => {
|
||||
if (checklist.length === 0) return true
|
||||
return (
|
||||
checkedItems.length === checklist.length &&
|
||||
checkedItems.every((checked) => checked)
|
||||
)
|
||||
}, [checkedItems, checklist.length])
|
||||
|
||||
const typedMatched = useMemo(() => {
|
||||
if (hasSegmentedRequiredText) {
|
||||
return normalizedRequiredTextParts.every((part) => {
|
||||
if (part.type === 'static') return true
|
||||
return typedTextParts[part.inputIndex ?? 0]?.trim() === part.text.trim()
|
||||
})
|
||||
}
|
||||
if (!requiredText) return true
|
||||
return typedText.trim() === requiredText.trim()
|
||||
}, [
|
||||
hasSegmentedRequiredText,
|
||||
normalizedRequiredTextParts,
|
||||
requiredText,
|
||||
typedText,
|
||||
typedTextParts,
|
||||
])
|
||||
const hasTypedRequiredText = hasSegmentedRequiredText
|
||||
? typedTextParts.some((part) => part.trim() !== '')
|
||||
: typedText.length > 0
|
||||
|
||||
const canConfirm = allChecked && typedMatched && !isLoading
|
||||
|
||||
const handleChecklistChange = (index: number, checked: boolean) => {
|
||||
setCheckedItems((previous) => {
|
||||
const next = [...previous]
|
||||
next[index] = checked
|
||||
return next
|
||||
})
|
||||
}
|
||||
|
||||
const handleTextPartChange = (index: number, value: string) => {
|
||||
setTypedTextParts((previous) => {
|
||||
const next = [...previous]
|
||||
next[index] = value
|
||||
return next
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<AlertDialog open={open} onOpenChange={onOpenChange}>
|
||||
<AlertDialogContent
|
||||
className={cn(
|
||||
'flex max-h-[min(88dvh,760px)] w-[calc(100vw-1.5rem)] !max-w-[44rem] grid-rows-none flex-col gap-0 overflow-hidden !p-0 sm:w-[min(44rem,calc(100vw-3rem))]',
|
||||
className
|
||||
)}
|
||||
>
|
||||
<AlertDialogHeader className='shrink-0 px-4 pt-4 pb-3 text-left sm:px-6 sm:pt-6'>
|
||||
<AlertDialogTitle>{title}</AlertDialogTitle>
|
||||
{description ? (
|
||||
<AlertDialogDescription
|
||||
render={<div />}
|
||||
className='mt-1 text-left leading-5'
|
||||
>
|
||||
{description}
|
||||
</AlertDialogDescription>
|
||||
) : null}
|
||||
</AlertDialogHeader>
|
||||
|
||||
<div className='min-h-0 flex-1 space-y-4 overflow-y-auto px-4 pb-4 sm:px-6'>
|
||||
{items.length > 0 ? (
|
||||
<ol className='border-border/70 bg-muted/30 text-foreground list-decimal space-y-2 rounded-lg border px-4 py-3 pl-8 text-sm leading-6 sm:px-5 sm:py-4 sm:pl-9'>
|
||||
{items.map((item) => (
|
||||
<li key={item}>{item}</li>
|
||||
))}
|
||||
</ol>
|
||||
) : null}
|
||||
|
||||
{checklist.length > 0 ? (
|
||||
<div className='border-border/70 bg-muted/30 space-y-3 rounded-lg border p-3 sm:p-4'>
|
||||
{checklist.map((item, index) => {
|
||||
const id = `risk-acknowledgement-${index}`
|
||||
return (
|
||||
<div key={item} className='flex items-start gap-3'>
|
||||
<Checkbox
|
||||
id={id}
|
||||
checked={checkedItems[index] ?? false}
|
||||
onCheckedChange={(checked) =>
|
||||
handleChecklistChange(index, checked === true)
|
||||
}
|
||||
className='mt-0.5'
|
||||
/>
|
||||
<Label
|
||||
htmlFor={id}
|
||||
className='text-muted-foreground text-sm leading-5 font-normal'
|
||||
>
|
||||
{item}
|
||||
</Label>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{requiredTextToDisplay ? (
|
||||
<div className='border-destructive/30 bg-destructive/5 space-y-3 rounded-lg border p-3 sm:p-4'>
|
||||
<Label className='text-sm font-medium'>
|
||||
{inputPrompt ?? t('Please type the following text to confirm:')}
|
||||
</Label>
|
||||
<div className='bg-background border-border rounded-md border px-3 py-2 font-mono text-sm break-all'>
|
||||
{requiredTextToDisplay}
|
||||
</div>
|
||||
{hasSegmentedRequiredText ? (
|
||||
<div className='flex flex-wrap items-center gap-2'>
|
||||
{normalizedRequiredTextParts.map((part, index) =>
|
||||
part.type === 'static' ? (
|
||||
<span
|
||||
key={`static-${index}`}
|
||||
className='text-muted-foreground bg-background/70 border-border rounded-md border px-2 py-1.5 font-mono text-sm select-none'
|
||||
>
|
||||
{part.text}
|
||||
</span>
|
||||
) : (
|
||||
<Input
|
||||
key={`input-${index}`}
|
||||
value={typedTextParts[part.inputIndex ?? 0] ?? ''}
|
||||
onChange={(event) =>
|
||||
handleTextPartChange(
|
||||
part.inputIndex ?? 0,
|
||||
event.target.value
|
||||
)
|
||||
}
|
||||
placeholder={
|
||||
part.placeholder ??
|
||||
part.text ??
|
||||
inputPlaceholder ??
|
||||
t('Type the confirmation text here')
|
||||
}
|
||||
autoFocus={open && part.inputIndex === 0}
|
||||
onCopy={(event) => event.preventDefault()}
|
||||
onCut={(event) => event.preventDefault()}
|
||||
onPaste={(event) => event.preventDefault()}
|
||||
onDrop={(event) => event.preventDefault()}
|
||||
aria-invalid={hasTypedRequiredText && !typedMatched}
|
||||
className='w-full font-mono sm:w-64'
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<Input
|
||||
value={typedText}
|
||||
onChange={(event) => setTypedText(event.target.value)}
|
||||
placeholder={
|
||||
inputPlaceholder ?? t('Type the confirmation text here')
|
||||
}
|
||||
autoFocus={open}
|
||||
onCopy={(event) => event.preventDefault()}
|
||||
onCut={(event) => event.preventDefault()}
|
||||
onPaste={(event) => event.preventDefault()}
|
||||
onDrop={(event) => event.preventDefault()}
|
||||
aria-invalid={hasTypedRequiredText && !typedMatched}
|
||||
/>
|
||||
)}
|
||||
{hasTypedRequiredText && !typedMatched ? (
|
||||
<p className='text-destructive text-xs'>
|
||||
{mismatchHint ??
|
||||
t('The entered text does not match the required text.')}
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<AlertDialogFooter className='mx-0 mb-0 shrink-0 rounded-b-xl border-t p-3 sm:p-4'>
|
||||
<AlertDialogCancel disabled={isLoading}>
|
||||
{cancelText ?? t('Cancel')}
|
||||
</AlertDialogCancel>
|
||||
<Button
|
||||
variant={destructive ? 'destructive' : 'default'}
|
||||
disabled={!canConfirm}
|
||||
onClick={onConfirm}
|
||||
>
|
||||
{confirmText ?? t('Confirm')}
|
||||
</Button>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
)
|
||||
}
|
||||
+3
-1
@@ -35,7 +35,7 @@ interface DataTableRowActionsProps {
|
||||
|
||||
export function DataTableRowActions({ row }: DataTableRowActionsProps) {
|
||||
const { t } = useTranslation()
|
||||
const { setOpen, setCurrentRow } = useSubscriptions()
|
||||
const { setOpen, setCurrentRow, complianceConfirmed } = useSubscriptions()
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
@@ -46,6 +46,7 @@ export function DataTableRowActions({ row }: DataTableRowActionsProps) {
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align='end'>
|
||||
<DropdownMenuItem
|
||||
disabled={!complianceConfirmed}
|
||||
onClick={() => {
|
||||
setCurrentRow(row.original)
|
||||
setOpen('update')
|
||||
@@ -55,6 +56,7 @@ export function DataTableRowActions({ row }: DataTableRowActionsProps) {
|
||||
{t('Edit')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
disabled={!complianceConfirmed}
|
||||
onClick={() => {
|
||||
setCurrentRow(row.original)
|
||||
setOpen('toggle-status')
|
||||
|
||||
+6
-2
@@ -23,10 +23,14 @@ import { useSubscriptions } from './subscriptions-provider'
|
||||
|
||||
export function SubscriptionsPrimaryButtons() {
|
||||
const { t } = useTranslation()
|
||||
const { setOpen } = useSubscriptions()
|
||||
const { setOpen, complianceConfirmed } = useSubscriptions()
|
||||
return (
|
||||
<div className='flex gap-2'>
|
||||
<Button size='sm' onClick={() => setOpen('create')}>
|
||||
<Button
|
||||
size='sm'
|
||||
onClick={() => setOpen('create')}
|
||||
disabled={!complianceConfirmed}
|
||||
>
|
||||
<Plus className='h-4 w-4' />
|
||||
{t('Create Plan')}
|
||||
</Button>
|
||||
|
||||
@@ -18,8 +18,14 @@ For commercial licensing, please contact support@quantumnous.com
|
||||
*/
|
||||
import React, { useState } from 'react'
|
||||
import useDialogState from '@/hooks/use-dialog'
|
||||
import {
|
||||
getOptionValue,
|
||||
useSystemOptions,
|
||||
} from '@/features/system-settings/hooks/use-system-options'
|
||||
import { type PlanRecord, type SubscriptionsDialogType } from '../types'
|
||||
|
||||
const CURRENT_COMPLIANCE_TERMS_VERSION = 'v1'
|
||||
|
||||
type SubscriptionsContextType = {
|
||||
open: SubscriptionsDialogType | null
|
||||
setOpen: (str: SubscriptionsDialogType | null) => void
|
||||
@@ -27,6 +33,7 @@ type SubscriptionsContextType = {
|
||||
setCurrentRow: React.Dispatch<React.SetStateAction<PlanRecord | null>>
|
||||
refreshTrigger: number
|
||||
triggerRefresh: () => void
|
||||
complianceConfirmed: boolean
|
||||
}
|
||||
|
||||
const SubscriptionsContext =
|
||||
@@ -40,6 +47,15 @@ export function SubscriptionsProvider({
|
||||
const [open, setOpen] = useDialogState<SubscriptionsDialogType>(null)
|
||||
const [currentRow, setCurrentRow] = useState<PlanRecord | null>(null)
|
||||
const [refreshTrigger, setRefreshTrigger] = useState(0)
|
||||
const { data } = useSystemOptions()
|
||||
const complianceOptions = getOptionValue(data?.data, {
|
||||
'payment_setting.compliance_confirmed': false,
|
||||
'payment_setting.compliance_terms_version': '',
|
||||
})
|
||||
const complianceConfirmed =
|
||||
complianceOptions['payment_setting.compliance_confirmed'] &&
|
||||
complianceOptions['payment_setting.compliance_terms_version'] ===
|
||||
CURRENT_COMPLIANCE_TERMS_VERSION
|
||||
|
||||
const triggerRefresh = () => setRefreshTrigger((prev) => prev + 1)
|
||||
|
||||
@@ -52,6 +68,7 @@ export function SubscriptionsProvider({
|
||||
setCurrentRow,
|
||||
refreshTrigger,
|
||||
triggerRefresh,
|
||||
complianceConfirmed,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
+25
-3
@@ -22,13 +22,18 @@ import { Alert, AlertDescription } from '@/components/ui/alert'
|
||||
import { SectionPageLayout } from '@/components/layout'
|
||||
import { SubscriptionsDialogs } from './components/subscriptions-dialogs'
|
||||
import { SubscriptionsPrimaryButtons } from './components/subscriptions-primary-buttons'
|
||||
import { SubscriptionsProvider } from './components/subscriptions-provider'
|
||||
import {
|
||||
SubscriptionsProvider,
|
||||
useSubscriptions,
|
||||
} from './components/subscriptions-provider'
|
||||
import { SubscriptionsTable } from './components/subscriptions-table'
|
||||
|
||||
export function Subscriptions() {
|
||||
function SubscriptionsContent() {
|
||||
const { t } = useTranslation()
|
||||
const { complianceConfirmed } = useSubscriptions()
|
||||
|
||||
return (
|
||||
<SubscriptionsProvider>
|
||||
<>
|
||||
<SectionPageLayout>
|
||||
<SectionPageLayout.Title>
|
||||
{t('Subscription Management')}
|
||||
@@ -50,11 +55,28 @@ export function Subscriptions() {
|
||||
</div>
|
||||
</SectionPageLayout.Actions>
|
||||
<SectionPageLayout.Content>
|
||||
{!complianceConfirmed ? (
|
||||
<Alert variant='destructive' className='mb-4'>
|
||||
<AlertDescription>
|
||||
{t(
|
||||
'Subscription plan creation and changes are locked until the administrator confirms compliance terms in Payment Gateway settings.'
|
||||
)}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
) : null}
|
||||
<SubscriptionsTable />
|
||||
</SectionPageLayout.Content>
|
||||
</SectionPageLayout>
|
||||
|
||||
<SubscriptionsDialogs />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export function Subscriptions() {
|
||||
return (
|
||||
<SubscriptionsProvider>
|
||||
<SubscriptionsContent />
|
||||
</SubscriptionsProvider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ For commercial licensing, please contact support@quantumnous.com
|
||||
*/
|
||||
import { api } from '@/lib/api'
|
||||
import type {
|
||||
ConfirmPaymentComplianceResponse,
|
||||
DeleteLogsResponse,
|
||||
FetchUpstreamRatiosRequest,
|
||||
SystemOptionsResponse,
|
||||
@@ -37,6 +38,14 @@ export async function updateSystemOption(request: UpdateOptionRequest) {
|
||||
return res.data
|
||||
}
|
||||
|
||||
export async function confirmPaymentCompliance() {
|
||||
const res = await api.post<ConfirmPaymentComplianceResponse>(
|
||||
'/api/option/payment_compliance',
|
||||
{ confirmed: true }
|
||||
)
|
||||
return res.data
|
||||
}
|
||||
|
||||
export async function deleteLogsBefore(targetTimestamp: number) {
|
||||
const res = await api.delete<DeleteLogsResponse>('/api/log/', {
|
||||
params: { target_timestamp: targetTimestamp },
|
||||
|
||||
@@ -66,6 +66,11 @@ const defaultBillingSettings: BillingSettings = {
|
||||
PayMethods: '',
|
||||
'payment_setting.amount_options': '',
|
||||
'payment_setting.amount_discount': '',
|
||||
'payment_setting.compliance_confirmed': false,
|
||||
'payment_setting.compliance_terms_version': '',
|
||||
'payment_setting.compliance_confirmed_at': 0,
|
||||
'payment_setting.compliance_confirmed_by': 0,
|
||||
'payment_setting.compliance_confirmed_ip': '',
|
||||
StripeApiSecret: '',
|
||||
StripeWebhookSecret: '',
|
||||
StripePriceId: '',
|
||||
|
||||
@@ -71,6 +71,10 @@ const BILLING_SECTIONS = [
|
||||
settings['quota_setting.enable_free_model_pre_consume'],
|
||||
},
|
||||
}}
|
||||
complianceConfirmed={
|
||||
(settings['payment_setting.compliance_confirmed'] ?? false) &&
|
||||
settings['payment_setting.compliance_terms_version'] === 'v1'
|
||||
}
|
||||
/>
|
||||
),
|
||||
},
|
||||
@@ -187,6 +191,13 @@ const BILLING_SECTIONS = [
|
||||
WaffoPancakeUnitPrice: settings.WaffoPancakeUnitPrice ?? 1,
|
||||
WaffoPancakeMinTopUp: settings.WaffoPancakeMinTopUp ?? 1,
|
||||
}}
|
||||
complianceDefaults={{
|
||||
confirmed: settings['payment_setting.compliance_confirmed'] ?? false,
|
||||
termsVersion:
|
||||
settings['payment_setting.compliance_terms_version'] ?? '',
|
||||
confirmedAt: settings['payment_setting.compliance_confirmed_at'] ?? 0,
|
||||
confirmedBy: settings['payment_setting.compliance_confirmed_by'] ?? 0,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
|
||||
@@ -21,6 +21,7 @@ import * as z from 'zod'
|
||||
import type { Resolver } from 'react-hook-form'
|
||||
import { zodResolver } from '@hookform/resolvers/zod'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Alert, AlertDescription } from '@/components/ui/alert'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
Form,
|
||||
@@ -57,10 +58,12 @@ type QuotaFormValues = z.infer<typeof quotaSchema>
|
||||
|
||||
type QuotaSettingsSectionProps = {
|
||||
defaultValues: QuotaFormValues
|
||||
complianceConfirmed?: boolean
|
||||
}
|
||||
|
||||
export function QuotaSettingsSection({
|
||||
defaultValues,
|
||||
complianceConfirmed = true,
|
||||
}: QuotaSettingsSectionProps) {
|
||||
const { t } = useTranslation()
|
||||
const updateOption = useUpdateOption()
|
||||
@@ -97,6 +100,16 @@ export function QuotaSettingsSection({
|
||||
>
|
||||
<FormNavigationGuard when={isDirty} />
|
||||
|
||||
{!complianceConfirmed ? (
|
||||
<Alert variant='destructive'>
|
||||
<AlertDescription>
|
||||
{t(
|
||||
'Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.'
|
||||
)}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
) : null}
|
||||
|
||||
<Form {...form}>
|
||||
<form onSubmit={handleSubmit} className='space-y-6'>
|
||||
<FormDirtyIndicator isDirty={isDirty} />
|
||||
|
||||
+166
-2
@@ -20,8 +20,17 @@ import * as React from 'react'
|
||||
import * as z from 'zod'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { zodResolver } from '@hookform/resolvers/zod'
|
||||
import { Code2, Eye } from 'lucide-react'
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import { Code2, Eye, ShieldAlert } from 'lucide-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { toast } from 'sonner'
|
||||
import { cn } from '@/lib/utils'
|
||||
import {
|
||||
Alert,
|
||||
AlertAction,
|
||||
AlertDescription,
|
||||
AlertTitle,
|
||||
} from '@/components/ui/alert'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
Form,
|
||||
@@ -36,6 +45,8 @@ import { Input } from '@/components/ui/input'
|
||||
import { Separator } from '@/components/ui/separator'
|
||||
import { Switch } from '@/components/ui/switch'
|
||||
import { Textarea } from '@/components/ui/textarea'
|
||||
import { RiskAcknowledgementDialog } from '@/components/risk-acknowledgement-dialog'
|
||||
import { confirmPaymentCompliance } from '../api'
|
||||
import { SettingsSection } from '../components/settings-section'
|
||||
import { useUpdateOption } from '../hooks/use-update-option'
|
||||
import { AmountDiscountVisualEditor } from './amount-discount-visual-editor'
|
||||
@@ -125,18 +136,30 @@ const paymentSchema = z.object({
|
||||
|
||||
type PaymentFormValues = z.infer<typeof paymentSchema>
|
||||
|
||||
const CURRENT_COMPLIANCE_TERMS_VERSION = 'v1'
|
||||
|
||||
type PaymentComplianceDefaults = {
|
||||
confirmed: boolean
|
||||
termsVersion: string
|
||||
confirmedAt: number
|
||||
confirmedBy: number
|
||||
}
|
||||
|
||||
type PaymentSettingsSectionProps = {
|
||||
defaultValues: PaymentFormValues
|
||||
waffoDefaultValues: WaffoSettingsValues
|
||||
waffoPancakeDefaultValues: WaffoPancakeSettingsValues
|
||||
complianceDefaults: PaymentComplianceDefaults
|
||||
}
|
||||
|
||||
export function PaymentSettingsSection({
|
||||
defaultValues,
|
||||
waffoDefaultValues,
|
||||
waffoPancakeDefaultValues,
|
||||
complianceDefaults,
|
||||
}: PaymentSettingsSectionProps) {
|
||||
const { t } = useTranslation()
|
||||
const queryClient = useQueryClient()
|
||||
const updateOption = useUpdateOption()
|
||||
const initialRef = React.useRef(defaultValues)
|
||||
const defaultsSignature = React.useMemo(
|
||||
@@ -151,6 +174,81 @@ export function PaymentSettingsSection({
|
||||
React.useState(true)
|
||||
const [creemProductsVisualMode, setCreemProductsVisualMode] =
|
||||
React.useState(true)
|
||||
const [showComplianceDialog, setShowComplianceDialog] = React.useState(false)
|
||||
|
||||
const complianceStatements = React.useMemo(
|
||||
() => [
|
||||
t(
|
||||
'You have legally obtained authorization for the connected model APIs, accounts, keys, and quotas.'
|
||||
),
|
||||
t(
|
||||
'You commit to using upstream APIs, accounts, keys, quotas, and service capabilities only within the scope of lawful authorization obtained from upstream service providers, model service providers, or relevant rights holders, and will not conduct unauthorized resale, trafficking, distribution, or other non-compliant commercialization.'
|
||||
),
|
||||
t(
|
||||
'If you provide generative AI services to the public in mainland China, you will fulfill legal obligations including filing, security assessment, content safety, complaint handling, generated content labeling, log retention, and personal information protection.'
|
||||
),
|
||||
t(
|
||||
'You commit not to use this system to implement, assist with, or indirectly implement acts that violate applicable laws and regulations, regulatory requirements, platform rules, public interests, or the lawful rights and interests of third parties.'
|
||||
),
|
||||
t(
|
||||
'You understand and independently bear legal responsibility arising from deployment, operation, and charging behavior.'
|
||||
),
|
||||
t(
|
||||
'You understand this compliance reminder is only for risk notice and does not constitute legal advice, a compliance review conclusion, or a guarantee of the legality of your use of this system; you should consult professional legal or compliance advisors based on your actual business scenario.'
|
||||
),
|
||||
],
|
||||
[t]
|
||||
)
|
||||
|
||||
const complianceRequiredText = t(
|
||||
'I have read and understood the above compliance reminder, acknowledge the related legal risks, and confirm that I bear legal responsibility arising from deployment, operation, and charging behavior.'
|
||||
)
|
||||
const complianceRequiredTextParts = React.useMemo(
|
||||
() => [
|
||||
{
|
||||
type: 'input' as const,
|
||||
text: t('I have read and understood the above compliance reminder'),
|
||||
},
|
||||
{ type: 'static' as const, text: t(',') },
|
||||
{
|
||||
type: 'input' as const,
|
||||
text: t('acknowledge the related legal risks'),
|
||||
},
|
||||
{ type: 'static' as const, text: t(',and ') },
|
||||
{
|
||||
type: 'input' as const,
|
||||
text: t(
|
||||
'confirm that I bear legal responsibility arising from deployment'
|
||||
),
|
||||
},
|
||||
{ type: 'static' as const, text: t('、') },
|
||||
{
|
||||
type: 'input' as const,
|
||||
text: t('operation and charging behavior'),
|
||||
},
|
||||
],
|
||||
[t]
|
||||
)
|
||||
|
||||
const complianceConfirmed =
|
||||
complianceDefaults.confirmed &&
|
||||
complianceDefaults.termsVersion === CURRENT_COMPLIANCE_TERMS_VERSION
|
||||
|
||||
const confirmComplianceMutation = useMutation({
|
||||
mutationFn: confirmPaymentCompliance,
|
||||
onSuccess: (data) => {
|
||||
if (data.success) {
|
||||
toast.success(t('Compliance confirmed successfully'))
|
||||
setShowComplianceDialog(false)
|
||||
queryClient.invalidateQueries({ queryKey: ['system-options'] })
|
||||
} else {
|
||||
toast.error(data.message || t('Failed to confirm compliance'))
|
||||
}
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
toast.error(error.message || t('Failed to confirm compliance'))
|
||||
},
|
||||
})
|
||||
|
||||
const form = useForm({
|
||||
resolver: zodResolver(paymentSchema),
|
||||
@@ -562,11 +660,77 @@ export function PaymentSettingsSection({
|
||||
'Configure recharge pricing and payment gateway integrations'
|
||||
)}
|
||||
>
|
||||
{!complianceConfirmed ? (
|
||||
<Alert variant='destructive' className='mb-6'>
|
||||
<ShieldAlert className='h-4 w-4' />
|
||||
<AlertTitle>{t('Compliance confirmation required')}</AlertTitle>
|
||||
<AlertDescription>
|
||||
<div className='space-y-3'>
|
||||
<p>
|
||||
{t(
|
||||
'Payment, redemption codes, subscription plans, and invitation rewards are locked until the root administrator confirms the compliance terms.'
|
||||
)}
|
||||
</p>
|
||||
<ol className='list-decimal space-y-1 pl-5'>
|
||||
{complianceStatements.map((statement) => (
|
||||
<li key={statement}>{statement}</li>
|
||||
))}
|
||||
</ol>
|
||||
</div>
|
||||
</AlertDescription>
|
||||
<AlertAction>
|
||||
<Button
|
||||
type='button'
|
||||
size='sm'
|
||||
variant='destructive'
|
||||
onClick={() => setShowComplianceDialog(true)}
|
||||
>
|
||||
{t('Confirm compliance')}
|
||||
</Button>
|
||||
</AlertAction>
|
||||
</Alert>
|
||||
) : (
|
||||
<Alert className='mb-6'>
|
||||
<AlertTitle>{t('Compliance confirmed')}</AlertTitle>
|
||||
<AlertDescription>
|
||||
{t('Confirmed at {{time}} by user #{{userId}}', {
|
||||
time: complianceDefaults.confirmedAt
|
||||
? new Date(
|
||||
complianceDefaults.confirmedAt * 1000
|
||||
).toLocaleString()
|
||||
: '-',
|
||||
userId: complianceDefaults.confirmedBy || '-',
|
||||
})}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<RiskAcknowledgementDialog
|
||||
open={showComplianceDialog}
|
||||
onOpenChange={setShowComplianceDialog}
|
||||
title={t('Confirm compliance terms')}
|
||||
description={t(
|
||||
'This confirmation unlocks payment, redemption code, subscription plan, and invitation reward features. Please read the statements carefully.'
|
||||
)}
|
||||
items={complianceStatements}
|
||||
requiredText={complianceRequiredText}
|
||||
requiredTextParts={complianceRequiredTextParts}
|
||||
inputPrompt={t('Please type the following text to confirm:')}
|
||||
inputPlaceholder={t('Type the confirmation text here')}
|
||||
mismatchHint={t('The entered text does not match the required text.')}
|
||||
confirmText={t('Confirm and enable')}
|
||||
isLoading={confirmComplianceMutation.isPending}
|
||||
onConfirm={() => confirmComplianceMutation.mutate()}
|
||||
/>
|
||||
|
||||
{/* eslint-disable react-hooks/refs */}
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className='space-y-8'
|
||||
className={cn(
|
||||
'space-y-8',
|
||||
!complianceConfirmed && 'pointer-events-none opacity-40'
|
||||
)}
|
||||
data-no-autosubmit='true'
|
||||
>
|
||||
<div className='space-y-4'>
|
||||
|
||||
@@ -39,6 +39,17 @@ export type UpdateOptionResponse = {
|
||||
message: string
|
||||
}
|
||||
|
||||
export type ConfirmPaymentComplianceResponse = {
|
||||
success: boolean
|
||||
message: string
|
||||
data?: {
|
||||
confirmed: boolean
|
||||
terms_version: string
|
||||
confirmed_at: number
|
||||
confirmed_by: number
|
||||
}
|
||||
}
|
||||
|
||||
export type DeleteLogsResponse = {
|
||||
success: boolean
|
||||
message: string
|
||||
@@ -215,6 +226,11 @@ export type BillingSettings = {
|
||||
PayMethods: string
|
||||
'payment_setting.amount_options': string
|
||||
'payment_setting.amount_discount': string
|
||||
'payment_setting.compliance_confirmed': boolean
|
||||
'payment_setting.compliance_terms_version': string
|
||||
'payment_setting.compliance_confirmed_at': number
|
||||
'payment_setting.compliance_confirmed_by': number
|
||||
'payment_setting.compliance_confirmed_ip': string
|
||||
StripeApiSecret: string
|
||||
StripeWebhookSecret: string
|
||||
StripePriceId: string
|
||||
|
||||
@@ -30,6 +30,7 @@ interface AffiliateRewardsCardProps {
|
||||
user: UserWalletData | null
|
||||
affiliateLink: string
|
||||
onTransfer: () => void
|
||||
complianceConfirmed?: boolean
|
||||
loading?: boolean
|
||||
}
|
||||
|
||||
@@ -37,6 +38,7 @@ export function AffiliateRewardsCard({
|
||||
user,
|
||||
affiliateLink,
|
||||
onTransfer,
|
||||
complianceConfirmed = true,
|
||||
loading,
|
||||
}: AffiliateRewardsCardProps) {
|
||||
const { t } = useTranslation()
|
||||
@@ -110,6 +112,7 @@ export function AffiliateRewardsCard({
|
||||
{hasRewards && (
|
||||
<Button
|
||||
onClick={onTransfer}
|
||||
disabled={!complianceConfirmed}
|
||||
className='h-9 shrink-0 px-3'
|
||||
size='sm'
|
||||
>
|
||||
@@ -117,6 +120,13 @@ export function AffiliateRewardsCard({
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
{!complianceConfirmed ? (
|
||||
<p className='text-muted-foreground text-xs lg:col-span-3'>
|
||||
{t(
|
||||
'Referral reward transfer is disabled until the administrator confirms compliance terms.'
|
||||
)}
|
||||
</p>
|
||||
) : null}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
|
||||
@@ -135,6 +135,7 @@ export function RechargeFormCard({
|
||||
const hasWaffoPaymentMethods =
|
||||
Array.isArray(waffoPayMethods) && waffoPayMethods.length > 0
|
||||
const minTopup = getMinTopupAmount(topupInfo)
|
||||
const redemptionEnabled = topupInfo?.enable_redemption !== false
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
@@ -445,49 +446,59 @@ export function RechargeFormCard({
|
||||
)}
|
||||
|
||||
{/* Redemption Code Section */}
|
||||
<div className='space-y-2.5 border-t pt-4 sm:space-y-3 sm:pt-6'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Gift className='text-muted-foreground h-4 w-4' />
|
||||
<Label
|
||||
htmlFor='redemption-code'
|
||||
className='text-muted-foreground text-xs font-medium tracking-wider uppercase'
|
||||
>
|
||||
{t('Have a Code?')}
|
||||
</Label>
|
||||
</div>
|
||||
<div className='grid grid-cols-[minmax(0,1fr)_auto] gap-2'>
|
||||
<Input
|
||||
id='redemption-code'
|
||||
value={redemptionCode}
|
||||
onChange={(e) => onRedemptionCodeChange(e.target.value)}
|
||||
placeholder={t('Enter your redemption code')}
|
||||
className='h-9 min-w-0'
|
||||
/>
|
||||
<Button
|
||||
onClick={onRedeem}
|
||||
disabled={redeeming}
|
||||
variant='outline'
|
||||
className='h-9 px-4'
|
||||
>
|
||||
{redeeming && <Loader2 className='mr-2 h-4 w-4 animate-spin' />}
|
||||
{t('Redeem')}
|
||||
</Button>
|
||||
</div>
|
||||
{topupLink && (
|
||||
<p className='text-muted-foreground text-xs'>
|
||||
{t('Need a redemption code?')}{' '}
|
||||
<a
|
||||
href={topupLink}
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
className='inline-flex items-center gap-1 underline-offset-4 hover:underline'
|
||||
{redemptionEnabled ? (
|
||||
<div className='space-y-2.5 border-t pt-4 sm:space-y-3 sm:pt-6'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Gift className='text-muted-foreground h-4 w-4' />
|
||||
<Label
|
||||
htmlFor='redemption-code'
|
||||
className='text-muted-foreground text-xs font-medium tracking-wider uppercase'
|
||||
>
|
||||
{t('Get one here')}
|
||||
<ExternalLink className='h-3 w-3' />
|
||||
</a>
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
{t('Have a Code?')}
|
||||
</Label>
|
||||
</div>
|
||||
<div className='grid grid-cols-[minmax(0,1fr)_auto] gap-2'>
|
||||
<Input
|
||||
id='redemption-code'
|
||||
value={redemptionCode}
|
||||
onChange={(e) => onRedemptionCodeChange(e.target.value)}
|
||||
placeholder={t('Enter your redemption code')}
|
||||
className='h-9 min-w-0'
|
||||
/>
|
||||
<Button
|
||||
onClick={onRedeem}
|
||||
disabled={redeeming}
|
||||
variant='outline'
|
||||
className='h-9 px-4'
|
||||
>
|
||||
{redeeming && <Loader2 className='mr-2 h-4 w-4 animate-spin' />}
|
||||
{t('Redeem')}
|
||||
</Button>
|
||||
</div>
|
||||
{topupLink && (
|
||||
<p className='text-muted-foreground text-xs'>
|
||||
{t('Need a redemption code?')}{' '}
|
||||
<a
|
||||
href={topupLink}
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
className='inline-flex items-center gap-1 underline-offset-4 hover:underline'
|
||||
>
|
||||
{t('Get one here')}
|
||||
<ExternalLink className='h-3 w-3' />
|
||||
</a>
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<Alert className='border-t'>
|
||||
<AlertDescription>
|
||||
{t(
|
||||
'Redemption codes are disabled until the administrator confirms compliance terms.'
|
||||
)}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
</TitledCard>
|
||||
)
|
||||
}
|
||||
|
||||
+3
@@ -319,6 +319,9 @@ export function Wallet(props: WalletProps) {
|
||||
user={user}
|
||||
affiliateLink={affiliateLink}
|
||||
onTransfer={() => setTransferDialogOpen(true)}
|
||||
complianceConfirmed={
|
||||
topupInfo?.payment_compliance_confirmed !== false
|
||||
}
|
||||
loading={affiliateLoading}
|
||||
/>
|
||||
</div>
|
||||
|
||||
+6
@@ -145,6 +145,12 @@ export interface TopupInfo {
|
||||
enable_waffo_pancake_topup?: boolean
|
||||
/** Minimum topup amount for Waffo Pancake */
|
||||
waffo_pancake_min_topup?: number
|
||||
/** Whether redemption code usage is enabled */
|
||||
enable_redemption?: boolean
|
||||
/** Whether compliance confirmation has been completed */
|
||||
payment_compliance_confirmed?: boolean
|
||||
/** Current compliance terms version */
|
||||
payment_compliance_terms_version?: string
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Vendored
+33
-2
@@ -1756,7 +1756,7 @@
|
||||
"footer.columns.related.links.oneApi": "One API",
|
||||
"footer.columns.related.title": "Related Projects",
|
||||
"footer.defaultCopyright": "All rights reserved.",
|
||||
"footer.new\u0061pi.projectAttributionSuffix": "All rights reserved. Designed and developed by the project contributors.",
|
||||
"footer.newapi.projectAttributionSuffix": "All rights reserved. Designed and developed by the project contributors.",
|
||||
"For channels added after May 10, 2025, no need to remove \".\" from model names during deployment": "For channels added after May 10, 2025, no need to remove \".\" from model names during deployment",
|
||||
"For private deployments, format: https://fastgpt.run/api/openapi": "For private deployments, format: https://fastgpt.run/api/openapi",
|
||||
"Force a syntactically valid JSON response": "Force a syntactically valid JSON response",
|
||||
@@ -4423,6 +4423,37 @@
|
||||
"Zero retention": "Zero retention",
|
||||
"Zhipu": "Zhipu",
|
||||
"Zhipu V4": "Zhipu V4",
|
||||
"Zoom": "Zoom"
|
||||
"Zoom": "Zoom",
|
||||
"You have legally obtained authorization for the connected model APIs, accounts, keys, and quotas.": "You have legally obtained authorization for the connected model APIs, accounts, keys, and quotas.",
|
||||
"You commit to using upstream APIs, accounts, keys, quotas, and service capabilities only within the scope of lawful authorization obtained from upstream service providers, model service providers, or relevant rights holders, and will not conduct unauthorized resale, trafficking, distribution, or other non-compliant commercialization.": "You commit to using upstream APIs, accounts, keys, quotas, and service capabilities only within the scope of lawful authorization obtained from upstream service providers, model service providers, or relevant rights holders, and will not conduct unauthorized resale, trafficking, distribution, or other non-compliant commercialization.",
|
||||
"If you provide generative AI services to the public in mainland China, you will fulfill legal obligations including filing, security assessment, content safety, complaint handling, generated content labeling, log retention, and personal information protection.": "If you provide generative AI services to the public in mainland China, you will fulfill legal obligations including filing, security assessment, content safety, complaint handling, generated content labeling, log retention, and personal information protection.",
|
||||
"You commit not to use this system to implement, assist with, or indirectly implement acts that violate applicable laws and regulations, regulatory requirements, platform rules, public interests, or the lawful rights and interests of third parties.": "You commit not to use this system to implement, assist with, or indirectly implement acts that violate applicable laws and regulations, regulatory requirements, platform rules, public interests, or the lawful rights and interests of third parties.",
|
||||
"You understand and independently bear legal responsibility arising from deployment, operation, and charging behavior.": "You understand and independently bear legal responsibility arising from deployment, operation, and charging behavior.",
|
||||
"You understand this compliance reminder is only for risk notice and does not constitute legal advice, a compliance review conclusion, or a guarantee of the legality of your use of this system; you should consult professional legal or compliance advisors based on your actual business scenario.": "You understand this compliance reminder is only for risk notice and does not constitute legal advice, a compliance review conclusion, or a guarantee of the legality of your use of this system; you should consult professional legal or compliance advisors based on your actual business scenario.",
|
||||
"I have read and understood the above compliance reminder, acknowledge the related legal risks, and confirm that I bear legal responsibility arising from deployment, operation, and charging behavior.": "I have read and understood the above compliance reminder, acknowledge the related legal risks, and confirm that I bear legal responsibility arising from deployment, operation, and charging behavior.",
|
||||
"Please type the following text to confirm:": "Please type the following text to confirm:",
|
||||
"Type the confirmation text here": "Type the confirmation text here",
|
||||
"The entered text does not match the required text.": "The entered text does not match the required text.",
|
||||
"Compliance confirmation required": "Compliance confirmation required",
|
||||
"Payment, redemption codes, subscription plans, and invitation rewards are locked until the root administrator confirms the compliance terms.": "Payment, redemption codes, subscription plans, and invitation rewards are locked until the root administrator confirms the compliance terms.",
|
||||
"Confirm compliance": "Confirm compliance",
|
||||
"Compliance confirmed": "Compliance confirmed",
|
||||
"Confirmed at {{time}} by user #{{userId}}": "Confirmed at {{time}} by user #{{userId}}",
|
||||
"Confirm compliance terms": "Confirm compliance terms",
|
||||
"This confirmation unlocks payment, redemption code, subscription plan, and invitation reward features. Please read the statements carefully.": "This confirmation unlocks payment, redemption code, subscription plan, and invitation reward features. Please read the statements carefully.",
|
||||
"Confirm and enable": "Confirm and enable",
|
||||
"Compliance confirmed successfully": "Compliance confirmed successfully",
|
||||
"Failed to confirm compliance": "Failed to confirm compliance",
|
||||
"Redemption codes are disabled until the administrator confirms compliance terms.": "Redemption codes are disabled until the administrator confirms compliance terms.",
|
||||
"Subscription plan creation and changes are locked until the administrator confirms compliance terms in Payment Gateway settings.": "Subscription plan creation and changes are locked until the administrator confirms compliance terms in Payment Gateway settings.",
|
||||
"Referral reward transfer is disabled until the administrator confirms compliance terms.": "Referral reward transfer is disabled until the administrator confirms compliance terms.",
|
||||
"Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.": "Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.",
|
||||
"I have read and understood the above compliance reminder": "I have read and understood the above compliance reminder",
|
||||
"acknowledge the related legal risks": "acknowledge the related legal risks",
|
||||
"confirm that I bear legal responsibility arising from deployment": "confirm that I bear legal responsibility arising from deployment",
|
||||
"operation and charging behavior": "operation and charging behavior",
|
||||
",": ", ",
|
||||
",and ": ", and ",
|
||||
"、": ", "
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+33
-2
@@ -1756,7 +1756,7 @@
|
||||
"footer.columns.related.links.oneApi": "One API",
|
||||
"footer.columns.related.title": "Projets liés",
|
||||
"footer.defaultCopyright": "Tous droits réservés.",
|
||||
"footer.new\u0061pi.projectAttributionSuffix": "Tous droits réservés. Conçu et développé par les contributeurs du projet.",
|
||||
"footer.newapi.projectAttributionSuffix": "Tous droits réservés. Conçu et développé par les contributeurs du projet.",
|
||||
"For channels added after May 10, 2025, no need to remove \".\" from model names during deployment": "Pour les canaux ajoutés après le 10 mai 2025, pas besoin de supprimer \".\" des noms de modèles lors du déploiement",
|
||||
"For private deployments, format: https://fastgpt.run/api/openapi": "Pour les déploiements privés, format : https://fastgpt.run/api/openapi",
|
||||
"Force a syntactically valid JSON response": "Imposer une réponse JSON syntaxiquement valide",
|
||||
@@ -4423,6 +4423,37 @@
|
||||
"Zero retention": "Aucune rétention",
|
||||
"Zhipu": "Zhipu",
|
||||
"Zhipu V4": "Zhipu V4",
|
||||
"Zoom": "Zoom"
|
||||
"Zoom": "Zoom",
|
||||
"You have legally obtained authorization for the connected model APIs, accounts, keys, and quotas.": "You have legally obtained authorization for the connected model APIs, accounts, keys, and quotas.",
|
||||
"You commit to using upstream APIs, accounts, keys, quotas, and service capabilities only within the scope of lawful authorization obtained from upstream service providers, model service providers, or relevant rights holders, and will not conduct unauthorized resale, trafficking, distribution, or other non-compliant commercialization.": "You commit to using upstream APIs, accounts, keys, quotas, and service capabilities only within the scope of lawful authorization obtained from upstream service providers, model service providers, or relevant rights holders, and will not conduct unauthorized resale, trafficking, distribution, or other non-compliant commercialization.",
|
||||
"If you provide generative AI services to the public in mainland China, you will fulfill legal obligations including filing, security assessment, content safety, complaint handling, generated content labeling, log retention, and personal information protection.": "If you provide generative AI services to the public in mainland China, you will fulfill legal obligations including filing, security assessment, content safety, complaint handling, generated content labeling, log retention, and personal information protection.",
|
||||
"You commit not to use this system to implement, assist with, or indirectly implement acts that violate applicable laws and regulations, regulatory requirements, platform rules, public interests, or the lawful rights and interests of third parties.": "You commit not to use this system to implement, assist with, or indirectly implement acts that violate applicable laws and regulations, regulatory requirements, platform rules, public interests, or the lawful rights and interests of third parties.",
|
||||
"You understand and independently bear legal responsibility arising from deployment, operation, and charging behavior.": "You understand and independently bear legal responsibility arising from deployment, operation, and charging behavior.",
|
||||
"You understand this compliance reminder is only for risk notice and does not constitute legal advice, a compliance review conclusion, or a guarantee of the legality of your use of this system; you should consult professional legal or compliance advisors based on your actual business scenario.": "You understand this compliance reminder is only for risk notice and does not constitute legal advice, a compliance review conclusion, or a guarantee of the legality of your use of this system; you should consult professional legal or compliance advisors based on your actual business scenario.",
|
||||
"I have read and understood the above compliance reminder, acknowledge the related legal risks, and confirm that I bear legal responsibility arising from deployment, operation, and charging behavior.": "I have read and understood the above compliance reminder, acknowledge the related legal risks, and confirm that I bear legal responsibility arising from deployment, operation, and charging behavior.",
|
||||
"Please type the following text to confirm:": "Please type the following text to confirm:",
|
||||
"Type the confirmation text here": "Type the confirmation text here",
|
||||
"The entered text does not match the required text.": "The entered text does not match the required text.",
|
||||
"Compliance confirmation required": "Compliance confirmation required",
|
||||
"Payment, redemption codes, subscription plans, and invitation rewards are locked until the root administrator confirms the compliance terms.": "Payment, redemption codes, subscription plans, and invitation rewards are locked until the root administrator confirms the compliance terms.",
|
||||
"Confirm compliance": "Confirm compliance",
|
||||
"Compliance confirmed": "Compliance confirmed",
|
||||
"Confirmed at {{time}} by user #{{userId}}": "Confirmed at {{time}} by user #{{userId}}",
|
||||
"Confirm compliance terms": "Confirm compliance terms",
|
||||
"This confirmation unlocks payment, redemption code, subscription plan, and invitation reward features. Please read the statements carefully.": "This confirmation unlocks payment, redemption code, subscription plan, and invitation reward features. Please read the statements carefully.",
|
||||
"Confirm and enable": "Confirm and enable",
|
||||
"Compliance confirmed successfully": "Compliance confirmed successfully",
|
||||
"Failed to confirm compliance": "Failed to confirm compliance",
|
||||
"Redemption codes are disabled until the administrator confirms compliance terms.": "Redemption codes are disabled until the administrator confirms compliance terms.",
|
||||
"Subscription plan creation and changes are locked until the administrator confirms compliance terms in Payment Gateway settings.": "Subscription plan creation and changes are locked until the administrator confirms compliance terms in Payment Gateway settings.",
|
||||
"Referral reward transfer is disabled until the administrator confirms compliance terms.": "Referral reward transfer is disabled until the administrator confirms compliance terms.",
|
||||
"Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.": "Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.",
|
||||
"I have read and understood the above compliance reminder": "I have read and understood the above compliance reminder",
|
||||
"acknowledge the related legal risks": "acknowledge the related legal risks",
|
||||
"confirm that I bear legal responsibility arising from deployment": "confirm that I bear legal responsibility arising from deployment",
|
||||
"operation and charging behavior": "operation and charging behavior",
|
||||
",": ", ",
|
||||
",and ": ", and ",
|
||||
"、": ", "
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+33
-2
@@ -1756,7 +1756,7 @@
|
||||
"footer.columns.related.links.oneApi": "1つのAPI",
|
||||
"footer.columns.related.title": "関連プロジェクト",
|
||||
"footer.defaultCopyright": "すべての権利を留保します。",
|
||||
"footer.new\u0061pi.projectAttributionSuffix": "すべての権利を留保します。プロジェクトコントリビューターにより設計・開発されています。",
|
||||
"footer.newapi.projectAttributionSuffix": "すべての権利を留保します。プロジェクトコントリビューターにより設計・開発されています。",
|
||||
"For channels added after May 10, 2025, no need to remove \".\" from model names during deployment": "2025 年 5 月 10 日以降に追加されたチャネルの場合、デプロイ時にモデル名から「.」を削除する必要はありません",
|
||||
"For private deployments, format: https://fastgpt.run/api/openapi": "プライベートデプロイメントの場合、形式: https://fastgpt.run/api/openapi",
|
||||
"Force a syntactically valid JSON response": "構文的に有効な JSON 応答を強制",
|
||||
@@ -4423,6 +4423,37 @@
|
||||
"Zero retention": "データ保持なし",
|
||||
"Zhipu": "Zhipu",
|
||||
"Zhipu V4": "Zhipu V 4",
|
||||
"Zoom": "ズーム"
|
||||
"Zoom": "ズーム",
|
||||
"You have legally obtained authorization for the connected model APIs, accounts, keys, and quotas.": "You have legally obtained authorization for the connected model APIs, accounts, keys, and quotas.",
|
||||
"You commit to using upstream APIs, accounts, keys, quotas, and service capabilities only within the scope of lawful authorization obtained from upstream service providers, model service providers, or relevant rights holders, and will not conduct unauthorized resale, trafficking, distribution, or other non-compliant commercialization.": "You commit to using upstream APIs, accounts, keys, quotas, and service capabilities only within the scope of lawful authorization obtained from upstream service providers, model service providers, or relevant rights holders, and will not conduct unauthorized resale, trafficking, distribution, or other non-compliant commercialization.",
|
||||
"If you provide generative AI services to the public in mainland China, you will fulfill legal obligations including filing, security assessment, content safety, complaint handling, generated content labeling, log retention, and personal information protection.": "If you provide generative AI services to the public in mainland China, you will fulfill legal obligations including filing, security assessment, content safety, complaint handling, generated content labeling, log retention, and personal information protection.",
|
||||
"You commit not to use this system to implement, assist with, or indirectly implement acts that violate applicable laws and regulations, regulatory requirements, platform rules, public interests, or the lawful rights and interests of third parties.": "You commit not to use this system to implement, assist with, or indirectly implement acts that violate applicable laws and regulations, regulatory requirements, platform rules, public interests, or the lawful rights and interests of third parties.",
|
||||
"You understand and independently bear legal responsibility arising from deployment, operation, and charging behavior.": "You understand and independently bear legal responsibility arising from deployment, operation, and charging behavior.",
|
||||
"You understand this compliance reminder is only for risk notice and does not constitute legal advice, a compliance review conclusion, or a guarantee of the legality of your use of this system; you should consult professional legal or compliance advisors based on your actual business scenario.": "You understand this compliance reminder is only for risk notice and does not constitute legal advice, a compliance review conclusion, or a guarantee of the legality of your use of this system; you should consult professional legal or compliance advisors based on your actual business scenario.",
|
||||
"I have read and understood the above compliance reminder, acknowledge the related legal risks, and confirm that I bear legal responsibility arising from deployment, operation, and charging behavior.": "I have read and understood the above compliance reminder, acknowledge the related legal risks, and confirm that I bear legal responsibility arising from deployment, operation, and charging behavior.",
|
||||
"Please type the following text to confirm:": "Please type the following text to confirm:",
|
||||
"Type the confirmation text here": "Type the confirmation text here",
|
||||
"The entered text does not match the required text.": "The entered text does not match the required text.",
|
||||
"Compliance confirmation required": "Compliance confirmation required",
|
||||
"Payment, redemption codes, subscription plans, and invitation rewards are locked until the root administrator confirms the compliance terms.": "Payment, redemption codes, subscription plans, and invitation rewards are locked until the root administrator confirms the compliance terms.",
|
||||
"Confirm compliance": "Confirm compliance",
|
||||
"Compliance confirmed": "Compliance confirmed",
|
||||
"Confirmed at {{time}} by user #{{userId}}": "Confirmed at {{time}} by user #{{userId}}",
|
||||
"Confirm compliance terms": "Confirm compliance terms",
|
||||
"This confirmation unlocks payment, redemption code, subscription plan, and invitation reward features. Please read the statements carefully.": "This confirmation unlocks payment, redemption code, subscription plan, and invitation reward features. Please read the statements carefully.",
|
||||
"Confirm and enable": "Confirm and enable",
|
||||
"Compliance confirmed successfully": "Compliance confirmed successfully",
|
||||
"Failed to confirm compliance": "Failed to confirm compliance",
|
||||
"Redemption codes are disabled until the administrator confirms compliance terms.": "Redemption codes are disabled until the administrator confirms compliance terms.",
|
||||
"Subscription plan creation and changes are locked until the administrator confirms compliance terms in Payment Gateway settings.": "Subscription plan creation and changes are locked until the administrator confirms compliance terms in Payment Gateway settings.",
|
||||
"Referral reward transfer is disabled until the administrator confirms compliance terms.": "Referral reward transfer is disabled until the administrator confirms compliance terms.",
|
||||
"Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.": "Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.",
|
||||
"I have read and understood the above compliance reminder": "I have read and understood the above compliance reminder",
|
||||
"acknowledge the related legal risks": "acknowledge the related legal risks",
|
||||
"confirm that I bear legal responsibility arising from deployment": "confirm that I bear legal responsibility arising from deployment",
|
||||
"operation and charging behavior": "operation and charging behavior",
|
||||
",": ", ",
|
||||
",and ": ", and ",
|
||||
"、": ", "
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+33
-2
@@ -1756,7 +1756,7 @@
|
||||
"footer.columns.related.links.oneApi": "Один API",
|
||||
"footer.columns.related.title": "Связанные проекты",
|
||||
"footer.defaultCopyright": "Все права защищены.",
|
||||
"footer.new\u0061pi.projectAttributionSuffix": "Все права защищены. Разработано участниками проекта.",
|
||||
"footer.newapi.projectAttributionSuffix": "Все права защищены. Разработано участниками проекта.",
|
||||
"For channels added after May 10, 2025, no need to remove \".\" from model names during deployment": "Для каналов, добавленных после 10 мая 2025 г., не нужно удалять \".\" из имён моделей при развёртывании",
|
||||
"For private deployments, format: https://fastgpt.run/api/openapi": "Для частных развертываний, формат: https://fastgpt.run/api/openapi",
|
||||
"Force a syntactically valid JSON response": "Принудительно возвращать синтаксически корректный JSON",
|
||||
@@ -4423,6 +4423,37 @@
|
||||
"Zero retention": "Без хранения данных",
|
||||
"Zhipu": "Zhipu",
|
||||
"Zhipu V4": "Zhipu V4",
|
||||
"Zoom": "Zoom"
|
||||
"Zoom": "Zoom",
|
||||
"You have legally obtained authorization for the connected model APIs, accounts, keys, and quotas.": "You have legally obtained authorization for the connected model APIs, accounts, keys, and quotas.",
|
||||
"You commit to using upstream APIs, accounts, keys, quotas, and service capabilities only within the scope of lawful authorization obtained from upstream service providers, model service providers, or relevant rights holders, and will not conduct unauthorized resale, trafficking, distribution, or other non-compliant commercialization.": "You commit to using upstream APIs, accounts, keys, quotas, and service capabilities only within the scope of lawful authorization obtained from upstream service providers, model service providers, or relevant rights holders, and will not conduct unauthorized resale, trafficking, distribution, or other non-compliant commercialization.",
|
||||
"If you provide generative AI services to the public in mainland China, you will fulfill legal obligations including filing, security assessment, content safety, complaint handling, generated content labeling, log retention, and personal information protection.": "If you provide generative AI services to the public in mainland China, you will fulfill legal obligations including filing, security assessment, content safety, complaint handling, generated content labeling, log retention, and personal information protection.",
|
||||
"You commit not to use this system to implement, assist with, or indirectly implement acts that violate applicable laws and regulations, regulatory requirements, platform rules, public interests, or the lawful rights and interests of third parties.": "You commit not to use this system to implement, assist with, or indirectly implement acts that violate applicable laws and regulations, regulatory requirements, platform rules, public interests, or the lawful rights and interests of third parties.",
|
||||
"You understand and independently bear legal responsibility arising from deployment, operation, and charging behavior.": "You understand and independently bear legal responsibility arising from deployment, operation, and charging behavior.",
|
||||
"You understand this compliance reminder is only for risk notice and does not constitute legal advice, a compliance review conclusion, or a guarantee of the legality of your use of this system; you should consult professional legal or compliance advisors based on your actual business scenario.": "You understand this compliance reminder is only for risk notice and does not constitute legal advice, a compliance review conclusion, or a guarantee of the legality of your use of this system; you should consult professional legal or compliance advisors based on your actual business scenario.",
|
||||
"I have read and understood the above compliance reminder, acknowledge the related legal risks, and confirm that I bear legal responsibility arising from deployment, operation, and charging behavior.": "I have read and understood the above compliance reminder, acknowledge the related legal risks, and confirm that I bear legal responsibility arising from deployment, operation, and charging behavior.",
|
||||
"Please type the following text to confirm:": "Please type the following text to confirm:",
|
||||
"Type the confirmation text here": "Type the confirmation text here",
|
||||
"The entered text does not match the required text.": "The entered text does not match the required text.",
|
||||
"Compliance confirmation required": "Compliance confirmation required",
|
||||
"Payment, redemption codes, subscription plans, and invitation rewards are locked until the root administrator confirms the compliance terms.": "Payment, redemption codes, subscription plans, and invitation rewards are locked until the root administrator confirms the compliance terms.",
|
||||
"Confirm compliance": "Confirm compliance",
|
||||
"Compliance confirmed": "Compliance confirmed",
|
||||
"Confirmed at {{time}} by user #{{userId}}": "Confirmed at {{time}} by user #{{userId}}",
|
||||
"Confirm compliance terms": "Confirm compliance terms",
|
||||
"This confirmation unlocks payment, redemption code, subscription plan, and invitation reward features. Please read the statements carefully.": "This confirmation unlocks payment, redemption code, subscription plan, and invitation reward features. Please read the statements carefully.",
|
||||
"Confirm and enable": "Confirm and enable",
|
||||
"Compliance confirmed successfully": "Compliance confirmed successfully",
|
||||
"Failed to confirm compliance": "Failed to confirm compliance",
|
||||
"Redemption codes are disabled until the administrator confirms compliance terms.": "Redemption codes are disabled until the administrator confirms compliance terms.",
|
||||
"Subscription plan creation and changes are locked until the administrator confirms compliance terms in Payment Gateway settings.": "Subscription plan creation and changes are locked until the administrator confirms compliance terms in Payment Gateway settings.",
|
||||
"Referral reward transfer is disabled until the administrator confirms compliance terms.": "Referral reward transfer is disabled until the administrator confirms compliance terms.",
|
||||
"Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.": "Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.",
|
||||
"I have read and understood the above compliance reminder": "I have read and understood the above compliance reminder",
|
||||
"acknowledge the related legal risks": "acknowledge the related legal risks",
|
||||
"confirm that I bear legal responsibility arising from deployment": "confirm that I bear legal responsibility arising from deployment",
|
||||
"operation and charging behavior": "operation and charging behavior",
|
||||
",": ", ",
|
||||
",and ": ", and ",
|
||||
"、": ", "
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+33
-2
@@ -1756,7 +1756,7 @@
|
||||
"footer.columns.related.links.oneApi": "One API",
|
||||
"footer.columns.related.title": "Các Dự Án Liên Quan",
|
||||
"footer.defaultCopyright": "Bản quyền được bảo lưu.",
|
||||
"footer.new\u0061pi.projectAttributionSuffix": "Bản quyền được bảo lưu. Được thiết kế và phát triển bởi các cộng tác viên dự án.",
|
||||
"footer.newapi.projectAttributionSuffix": "Bản quyền được bảo lưu. Được thiết kế và phát triển bởi các cộng tác viên dự án.",
|
||||
"For channels added after May 10, 2025, no need to remove \".\" from model names during deployment": "Đối với các kênh được thêm sau ngày 10 tháng 5 năm 2025, không cần loại bỏ \".\" khỏi tên mô hình trong quá trình triển khai",
|
||||
"For private deployments, format: https://fastgpt.run/api/openapi": "Đối với các triển khai riêng tư, định dạng: https://fastgpt.run/api/openapi",
|
||||
"Force a syntactically valid JSON response": "Buộc phản hồi JSON hợp lệ về cú pháp",
|
||||
@@ -4423,6 +4423,37 @@
|
||||
"Zero retention": "Không lưu dữ liệu",
|
||||
"Zhipu": "Zhipu",
|
||||
"Zhipu V4": "Zhipu V4",
|
||||
"Zoom": "Zoom"
|
||||
"Zoom": "Zoom",
|
||||
"You have legally obtained authorization for the connected model APIs, accounts, keys, and quotas.": "You have legally obtained authorization for the connected model APIs, accounts, keys, and quotas.",
|
||||
"You commit to using upstream APIs, accounts, keys, quotas, and service capabilities only within the scope of lawful authorization obtained from upstream service providers, model service providers, or relevant rights holders, and will not conduct unauthorized resale, trafficking, distribution, or other non-compliant commercialization.": "You commit to using upstream APIs, accounts, keys, quotas, and service capabilities only within the scope of lawful authorization obtained from upstream service providers, model service providers, or relevant rights holders, and will not conduct unauthorized resale, trafficking, distribution, or other non-compliant commercialization.",
|
||||
"If you provide generative AI services to the public in mainland China, you will fulfill legal obligations including filing, security assessment, content safety, complaint handling, generated content labeling, log retention, and personal information protection.": "If you provide generative AI services to the public in mainland China, you will fulfill legal obligations including filing, security assessment, content safety, complaint handling, generated content labeling, log retention, and personal information protection.",
|
||||
"You commit not to use this system to implement, assist with, or indirectly implement acts that violate applicable laws and regulations, regulatory requirements, platform rules, public interests, or the lawful rights and interests of third parties.": "You commit not to use this system to implement, assist with, or indirectly implement acts that violate applicable laws and regulations, regulatory requirements, platform rules, public interests, or the lawful rights and interests of third parties.",
|
||||
"You understand and independently bear legal responsibility arising from deployment, operation, and charging behavior.": "You understand and independently bear legal responsibility arising from deployment, operation, and charging behavior.",
|
||||
"You understand this compliance reminder is only for risk notice and does not constitute legal advice, a compliance review conclusion, or a guarantee of the legality of your use of this system; you should consult professional legal or compliance advisors based on your actual business scenario.": "You understand this compliance reminder is only for risk notice and does not constitute legal advice, a compliance review conclusion, or a guarantee of the legality of your use of this system; you should consult professional legal or compliance advisors based on your actual business scenario.",
|
||||
"I have read and understood the above compliance reminder, acknowledge the related legal risks, and confirm that I bear legal responsibility arising from deployment, operation, and charging behavior.": "I have read and understood the above compliance reminder, acknowledge the related legal risks, and confirm that I bear legal responsibility arising from deployment, operation, and charging behavior.",
|
||||
"Please type the following text to confirm:": "Please type the following text to confirm:",
|
||||
"Type the confirmation text here": "Type the confirmation text here",
|
||||
"The entered text does not match the required text.": "The entered text does not match the required text.",
|
||||
"Compliance confirmation required": "Compliance confirmation required",
|
||||
"Payment, redemption codes, subscription plans, and invitation rewards are locked until the root administrator confirms the compliance terms.": "Payment, redemption codes, subscription plans, and invitation rewards are locked until the root administrator confirms the compliance terms.",
|
||||
"Confirm compliance": "Confirm compliance",
|
||||
"Compliance confirmed": "Compliance confirmed",
|
||||
"Confirmed at {{time}} by user #{{userId}}": "Confirmed at {{time}} by user #{{userId}}",
|
||||
"Confirm compliance terms": "Confirm compliance terms",
|
||||
"This confirmation unlocks payment, redemption code, subscription plan, and invitation reward features. Please read the statements carefully.": "This confirmation unlocks payment, redemption code, subscription plan, and invitation reward features. Please read the statements carefully.",
|
||||
"Confirm and enable": "Confirm and enable",
|
||||
"Compliance confirmed successfully": "Compliance confirmed successfully",
|
||||
"Failed to confirm compliance": "Failed to confirm compliance",
|
||||
"Redemption codes are disabled until the administrator confirms compliance terms.": "Redemption codes are disabled until the administrator confirms compliance terms.",
|
||||
"Subscription plan creation and changes are locked until the administrator confirms compliance terms in Payment Gateway settings.": "Subscription plan creation and changes are locked until the administrator confirms compliance terms in Payment Gateway settings.",
|
||||
"Referral reward transfer is disabled until the administrator confirms compliance terms.": "Referral reward transfer is disabled until the administrator confirms compliance terms.",
|
||||
"Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.": "Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.",
|
||||
"I have read and understood the above compliance reminder": "I have read and understood the above compliance reminder",
|
||||
"acknowledge the related legal risks": "acknowledge the related legal risks",
|
||||
"confirm that I bear legal responsibility arising from deployment": "confirm that I bear legal responsibility arising from deployment",
|
||||
"operation and charging behavior": "operation and charging behavior",
|
||||
",": ", ",
|
||||
",and ": ", and ",
|
||||
"、": ", "
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+33
-2
@@ -1756,7 +1756,7 @@
|
||||
"footer.columns.related.links.oneApi": "One API",
|
||||
"footer.columns.related.title": "相关项目",
|
||||
"footer.defaultCopyright": "版权所有。",
|
||||
"footer.new\u0061pi.projectAttributionSuffix": "版权所有,由项目贡献者设计与开发。",
|
||||
"footer.newapi.projectAttributionSuffix": "版权所有,由项目贡献者设计与开发。",
|
||||
"For channels added after May 10, 2025, no need to remove \".\" from model names during deployment": "对于 2025 年 5 月 10 日之后添加的渠道,在部署时无需从模型名称中移除 \".\"",
|
||||
"For private deployments, format: https://fastgpt.run/api/openapi": "对于私有部署,格式为:https://fastgpt.run/api/openapi",
|
||||
"Force a syntactically valid JSON response": "强制返回语法合法的 JSON",
|
||||
@@ -4423,6 +4423,37 @@
|
||||
"Zero retention": "零数据保留",
|
||||
"Zhipu": "智谱",
|
||||
"Zhipu V4": "智谱 V4",
|
||||
"Zoom": "缩放"
|
||||
"Zoom": "缩放",
|
||||
"You have legally obtained authorization for the connected model APIs, accounts, keys, and quotas.": "你已合法取得所接入模型 API、账号、密钥和额度的授权。",
|
||||
"You commit to using upstream APIs, accounts, keys, quotas, and service capabilities only within the scope of lawful authorization obtained from upstream service providers, model service providers, or relevant rights holders, and will not conduct unauthorized resale, trafficking, distribution, or other non-compliant commercialization.": "你承诺仅在已取得上游服务商、模型服务提供方或相关权利方合法授权的范围内使用其 API、账号、密钥、额度及服务能力,不进行未经授权的转售、倒卖、分销或其他违规商业化使用。",
|
||||
"If you provide generative AI services to the public in mainland China, you will fulfill legal obligations including filing, security assessment, content safety, complaint handling, generated content labeling, log retention, and personal information protection.": "如向中华人民共和国境内公众提供生成式人工智能服务,你将依法履行备案登记、安全评估、内容安全、投诉举报、生成合成内容标识、日志留存、个人信息保护等合规义务。",
|
||||
"You commit not to use this system to implement, assist with, or indirectly implement acts that violate applicable laws and regulations, regulatory requirements, platform rules, public interests, or the lawful rights and interests of third parties.": "你承诺不会利用本系统实施、协助实施或变相实施违反适用法律法规、监管要求、平台规则、社会公共利益或第三方合法权益的行为。",
|
||||
"You understand and independently bear legal responsibility arising from deployment, operation, and charging behavior.": "你理解并自行承担部署、运营和收费行为产生的法律责任。",
|
||||
"You understand this compliance reminder is only for risk notice and does not constitute legal advice, a compliance review conclusion, or a guarantee of the legality of your use of this system; you should consult professional legal or compliance advisors based on your actual business scenario.": "你理解本合规提醒仅用于风险提示,不构成法律意见、合规审查结论或对你使用本系统行为合法性的保证;你应根据实际业务场景自行咨询专业法律或合规顾问。",
|
||||
"I have read and understood the above compliance reminder, acknowledge the related legal risks, and confirm that I bear legal responsibility arising from deployment, operation, and charging behavior.": "我已阅读并理解上述合规提醒,知悉相关法律风险,并确认自行承担部署、运营和收费行为产生的法律责任",
|
||||
"Please type the following text to confirm:": "请输入以下文字以确认:",
|
||||
"Type the confirmation text here": "请输入确认文案",
|
||||
"The entered text does not match the required text.": "输入内容与要求文案不一致。",
|
||||
"Compliance confirmation required": "需要确认合规声明",
|
||||
"Payment, redemption codes, subscription plans, and invitation rewards are locked until the root administrator confirms the compliance terms.": "确认前,支付、兑换码、订阅计划和邀请返利功能将保持锁定。",
|
||||
"Confirm compliance": "确认合规声明",
|
||||
"Compliance confirmed": "合规声明已确认",
|
||||
"Confirmed at {{time}} by user #{{userId}}": "确认时间:{{time}},确认用户:#{{userId}}",
|
||||
"Confirm compliance terms": "确认合规声明",
|
||||
"This confirmation unlocks payment, redemption code, subscription plan, and invitation reward features. Please read the statements carefully.": "该操作将启用支付、兑换码、订阅计划和邀请返利相关功能。请仔细阅读并确认以下声明。",
|
||||
"Confirm and enable": "确认并启用",
|
||||
"Compliance confirmed successfully": "合规声明确认成功",
|
||||
"Failed to confirm compliance": "确认失败",
|
||||
"Redemption codes are disabled until the administrator confirms compliance terms.": "兑换码功能已禁用,管理员需先确认合规声明。",
|
||||
"Subscription plan creation and changes are locked until the administrator confirms compliance terms in Payment Gateway settings.": "订阅套餐创建和变更已锁定,管理员需先在支付设置中确认合规声明。",
|
||||
"Referral reward transfer is disabled until the administrator confirms compliance terms.": "邀请奖励划转已禁用,管理员需先确认合规声明。",
|
||||
"Non-zero invitation rewards require compliance confirmation in Payment Gateway settings.": "设置非零邀请奖励额度前,需要先在支付设置中确认合规声明。",
|
||||
"I have read and understood the above compliance reminder": "我已阅读并理解上述合规提醒",
|
||||
"acknowledge the related legal risks": "知悉相关法律风险",
|
||||
"confirm that I bear legal responsibility arising from deployment": "并确认自行承担部署",
|
||||
"operation and charging behavior": "运营和收费行为产生的法律责任",
|
||||
",": ",",
|
||||
",and ": ",",
|
||||
"、": "、"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user