fix: 修复代理编辑页面翻译问题和代理卡密生成页面
- 添加 admin.agents.create.saveBtn 和 admin.agents.editSuccess 翻译
- 修复代理卡密生成页面API路径错误,使用/agent/apps/{id}获取卡类
- 重构代理卡密生成页面样式,参考管理员后台卡密生成页面
- 添加代理卡密生成页面完整i18n国际化支持
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,189 +1,285 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Loader2 } from 'lucide-vue-next'
|
import { Loader2, Receipt, Settings2, Sparkles } from 'lucide-vue-next'
|
||||||
import { computed, onMounted, ref } from 'vue'
|
import { computed, onMounted, ref, watch } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { toast } from 'vue-sonner'
|
import { toast } from 'vue-sonner'
|
||||||
|
|
||||||
import { BasicPage } from '@/components/global-layout'
|
import { BasicPage } from '@/components/global-layout'
|
||||||
import api from '@/services/api'
|
import api from '@/services/api'
|
||||||
|
|
||||||
const { t } = useI18n()
|
|
||||||
const route = useRoute()
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
const loading = ref(false)
|
interface CardType {
|
||||||
const apps = ref<any[]>([])
|
id: number
|
||||||
const cardTypes = ref<any[]>([])
|
name: string
|
||||||
|
billing_type: string
|
||||||
|
price: number
|
||||||
|
value: number
|
||||||
|
duration_days: number
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Application {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const saving = ref(false)
|
||||||
|
const applications = ref<Application[]>([])
|
||||||
|
const cardTypes = ref<CardType[]>([])
|
||||||
|
|
||||||
const form = ref({
|
const form = ref({
|
||||||
app_id: route.query.app_id || '',
|
application_id: '',
|
||||||
card_type_id: route.query.card_type_id || '',
|
card_type_id: '',
|
||||||
quantity: 1,
|
count: 1,
|
||||||
})
|
})
|
||||||
|
|
||||||
const availableCardTypes = computed(() => {
|
async function fetchApplications() {
|
||||||
return cardTypes.value.filter(ct => ct.app_id === Number(form.value.app_id))
|
|
||||||
})
|
|
||||||
|
|
||||||
const totalPrice = computed(() => {
|
|
||||||
const ct = cardTypes.value.find(c => c.id === Number(form.value.card_type_id))
|
|
||||||
return ct ? ct.price * form.value.quantity : 0
|
|
||||||
})
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
try {
|
try {
|
||||||
const data = await api.get<any>('/agent/apps')
|
const data = await api.get<any>('/agent/apps')
|
||||||
if (Array.isArray(data)) {
|
if (Array.isArray(data)) {
|
||||||
apps.value = data
|
applications.value = data
|
||||||
} else if (data?.apps) {
|
} else if (data?.apps) {
|
||||||
apps.value = data.apps
|
applications.value = data.apps
|
||||||
} else if (data?.data) {
|
} else if (data?.data) {
|
||||||
apps.value = Array.isArray(data.data) ? data.data : []
|
applications.value = Array.isArray(data.data) ? data.data : []
|
||||||
} else {
|
} else {
|
||||||
apps.value = []
|
applications.value = []
|
||||||
}
|
|
||||||
|
|
||||||
if (apps.value.length > 0) {
|
|
||||||
const typesData = await api.get<any>('/agent/card-types')
|
|
||||||
if (Array.isArray(typesData)) {
|
|
||||||
cardTypes.value = typesData
|
|
||||||
} else if (typesData?.card_types) {
|
|
||||||
cardTypes.value = typesData.card_types
|
|
||||||
} else if (typesData?.data) {
|
|
||||||
cardTypes.value = Array.isArray(typesData.data) ? typesData.data : []
|
|
||||||
} else {
|
|
||||||
cardTypes.value = []
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error('Load data failed:', error)
|
console.error('获取应用列表失败:', error)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchCardTypes(appId: string) {
|
||||||
|
if (!appId) {
|
||||||
|
cardTypes.value = []
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const data = await api.get<{ app: any, cardTypes: CardType[] }>(`/agent/apps/${appId}`)
|
||||||
|
cardTypes.value = data?.cardTypes || []
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error('获取卡类列表失败:', error)
|
||||||
|
cardTypes.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => form.value.application_id, (appId) => {
|
||||||
|
form.value.card_type_id = ''
|
||||||
|
fetchCardTypes(appId)
|
||||||
|
})
|
||||||
|
|
||||||
|
const selectedCardType = computed(() => {
|
||||||
|
if (form.value.card_type_id) {
|
||||||
|
return cardTypes.value.find(ct => String(ct.id) === form.value.card_type_id)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
})
|
||||||
|
|
||||||
|
const totalCost = computed(() => {
|
||||||
|
if (selectedCardType.value) {
|
||||||
|
return selectedCardType.value.price * form.value.count
|
||||||
|
}
|
||||||
|
return 0
|
||||||
})
|
})
|
||||||
|
|
||||||
async function handleGenerate() {
|
async function handleGenerate() {
|
||||||
if (!form.value.app_id) {
|
if (!form.value.application_id) {
|
||||||
toast.error('请选择应用')
|
toast.error(t('agent.cards.create.selectAppFirst'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!form.value.card_type_id) {
|
if (!form.value.card_type_id) {
|
||||||
toast.error('请选择卡类')
|
toast.error(t('agent.cards.create.selectCardTypeFirst'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (form.value.quantity < 1 || form.value.quantity > 100) {
|
if (form.value.count < 1 || form.value.count > 100) {
|
||||||
toast.error('数量必须在1-100之间')
|
toast.error(t('agent.cards.create.countRange'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
loading.value = true
|
saving.value = true
|
||||||
try {
|
try {
|
||||||
const data = await api.post<{ codes: string[], cards: any[] }>('/agent/cards/generate', {
|
const data = await api.post<{ codes: string[], cards: any[] }>('/agent/cards/generate', {
|
||||||
app_id: Number(form.value.app_id),
|
app_id: Number(form.value.application_id),
|
||||||
card_type_id: Number(form.value.card_type_id),
|
card_type_id: Number(form.value.card_type_id),
|
||||||
quantity: form.value.quantity,
|
quantity: form.value.count,
|
||||||
})
|
})
|
||||||
|
toast.success(t('agent.cards.create.generateSuccess', { count: data.codes.length }))
|
||||||
toast.success(`成功生成 ${data.codes.length} 张卡密`)
|
|
||||||
|
|
||||||
const codesText = data.codes.join('\n')
|
const codesText = data.codes.join('\n')
|
||||||
await navigator.clipboard.writeText(codesText)
|
await navigator.clipboard.writeText(codesText)
|
||||||
toast.success('卡密已复制到剪贴板')
|
toast.success(t('agent.cards.create.copiedToClipboard'))
|
||||||
|
|
||||||
router.push('/agent/cards')
|
router.push('/agent/cards')
|
||||||
}
|
}
|
||||||
catch (error: any) {
|
catch (error: any) {
|
||||||
console.error('Generate cards failed:', error)
|
console.error('生成卡密失败:', error)
|
||||||
toast.error(error.message || '生成卡密失败')
|
toast.error(error.message || t('agent.cards.create.generateFailed'))
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
loading.value = false
|
saving.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
fetchApplications()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<BasicPage
|
<BasicPage
|
||||||
title="生成卡密"
|
:title="t('agent.cards.create.title')"
|
||||||
description="批量生成卡密"
|
:description="t('agent.cards.create.description')"
|
||||||
:breadcrumbs="[
|
:breadcrumbs="[
|
||||||
{ title: '卡密管理', href: '/agent/cards' },
|
{ title: t('agent.cards.title'), href: '/agent/cards' },
|
||||||
{ title: '生成卡密' },
|
{ title: t('agent.cards.create.title') },
|
||||||
]"
|
]"
|
||||||
sticky
|
sticky
|
||||||
>
|
>
|
||||||
<UiCard class="max-w-2xl">
|
<div class="space-y-6">
|
||||||
<UiCardHeader>
|
<div class="grid gap-6 lg:grid-cols-3">
|
||||||
<UiCardTitle>生成设置</UiCardTitle>
|
<div class="lg:col-span-2 space-y-6">
|
||||||
<UiCardDescription>
|
<UiCard>
|
||||||
选择应用和卡类,设置生成数量
|
<UiCardHeader>
|
||||||
</UiCardDescription>
|
<UiCardTitle class="flex items-center gap-2">
|
||||||
</UiCardHeader>
|
<Settings2 class="size-5" />
|
||||||
<UiCardContent class="space-y-6">
|
{{ t('agent.cards.create.config') }}
|
||||||
<div class="space-y-2">
|
</UiCardTitle>
|
||||||
<UiLabel>选择应用 <span class="text-destructive">*</span></UiLabel>
|
<UiCardDescription>{{ t('agent.cards.create.configDesc') }}</UiCardDescription>
|
||||||
<UiSelect v-model="form.app_id">
|
</UiCardHeader>
|
||||||
<UiSelectTrigger>
|
<UiCardContent class="space-y-6">
|
||||||
<UiSelectValue placeholder="请选择应用" />
|
<div class="space-y-2">
|
||||||
</UiSelectTrigger>
|
<UiLabel for="application">
|
||||||
<UiSelectContent>
|
{{ t('agent.cards.create.application') }}
|
||||||
<UiSelectItem v-for="app in apps" :key="app.id" :value="String(app.id)">
|
</UiLabel>
|
||||||
{{ app.name }}
|
<UiSelect v-model="form.application_id">
|
||||||
</UiSelectItem>
|
<UiSelectTrigger>
|
||||||
</UiSelectContent>
|
<UiSelectValue :placeholder="t('agent.cards.create.selectApplication')" />
|
||||||
</UiSelect>
|
</UiSelectTrigger>
|
||||||
|
<UiSelectContent>
|
||||||
|
<UiSelectItem v-for="app in applications" :key="app.id" :value="String(app.id)">
|
||||||
|
{{ app.name }}
|
||||||
|
</UiSelectItem>
|
||||||
|
</UiSelectContent>
|
||||||
|
</UiSelect>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="space-y-2">
|
||||||
|
<UiLabel for="cardType">
|
||||||
|
{{ t('agent.cards.create.cardType') }}
|
||||||
|
</UiLabel>
|
||||||
|
<UiSelect v-model="form.card_type_id" :disabled="!form.application_id">
|
||||||
|
<UiSelectTrigger>
|
||||||
|
<UiSelectValue :placeholder="t('agent.cards.create.selectCardType')" />
|
||||||
|
</UiSelectTrigger>
|
||||||
|
<UiSelectContent>
|
||||||
|
<UiSelectItem v-for="type in cardTypes" :key="type.id" :value="String(type.id)">
|
||||||
|
{{ type.name }}<template v-if="type.billing_type"> ({{ type.billing_type }})</template>
|
||||||
|
</UiSelectItem>
|
||||||
|
</UiSelectContent>
|
||||||
|
</UiSelect>
|
||||||
|
<p v-if="form.application_id && cardTypes.length === 0" class="text-xs text-muted-foreground">
|
||||||
|
{{ t('agent.cards.create.noCardType') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="space-y-2">
|
||||||
|
<UiLabel for="count">
|
||||||
|
{{ t('agent.cards.create.count') }}
|
||||||
|
</UiLabel>
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<UiNumberField v-model="form.count" :min="1" :max="100" class="flex-1 max-w-[200px]">
|
||||||
|
<UiNumberFieldContent>
|
||||||
|
<UiNumberFieldDecrement />
|
||||||
|
<UiNumberFieldInput />
|
||||||
|
<UiNumberFieldIncrement />
|
||||||
|
</UiNumberFieldContent>
|
||||||
|
</UiNumberField>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<UiButton variant="outline" size="sm" @click="form.count = 10">
|
||||||
|
10
|
||||||
|
</UiButton>
|
||||||
|
<UiButton variant="outline" size="sm" @click="form.count = 50">
|
||||||
|
50
|
||||||
|
</UiButton>
|
||||||
|
<UiButton variant="outline" size="sm" @click="form.count = 100">
|
||||||
|
100
|
||||||
|
</UiButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="text-xs text-muted-foreground">
|
||||||
|
{{ t('agent.cards.create.maxCount') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</UiCardContent>
|
||||||
|
</UiCard>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="form.app_id" class="space-y-2">
|
<div class="space-y-6">
|
||||||
<UiLabel>选择卡类 <span class="text-destructive">*</span></UiLabel>
|
<UiCard>
|
||||||
<UiSelect v-model="form.card_type_id">
|
<UiCardHeader>
|
||||||
<UiSelectTrigger>
|
<UiCardTitle class="flex items-center gap-2">
|
||||||
<UiSelectValue placeholder="请选择卡类" />
|
<Receipt class="size-5" />
|
||||||
</UiSelectTrigger>
|
{{ t('agent.cards.create.preview') }}
|
||||||
<UiSelectContent>
|
</UiCardTitle>
|
||||||
<UiSelectItem v-for="ct in availableCardTypes" :key="ct.id" :value="String(ct.id)">
|
</UiCardHeader>
|
||||||
{{ ct.name }} - {{ ct.duration_days }}天 - ¥{{ ct.price }}
|
<UiCardContent class="space-y-4">
|
||||||
</UiSelectItem>
|
<div class="space-y-3">
|
||||||
</UiSelectContent>
|
<div class="flex justify-between text-sm">
|
||||||
</UiSelect>
|
<span class="text-muted-foreground">{{ t('agent.cards.create.app') }}</span>
|
||||||
</div>
|
<span>{{ applications.find(a => String(a.id) === form.application_id)?.name || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between text-sm">
|
||||||
|
<span class="text-muted-foreground">{{ t('agent.cards.create.type') }}</span>
|
||||||
|
<span>{{ selectedCardType?.name || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between text-sm">
|
||||||
|
<span class="text-muted-foreground">{{ t('agent.cards.create.unitPrice') }}</span>
|
||||||
|
<span>¥{{ selectedCardType?.price?.toFixed(2) || '0.00' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between text-sm">
|
||||||
|
<span class="text-muted-foreground">{{ t('agent.cards.create.quantity') }}</span>
|
||||||
|
<span>{{ form.count }} {{ t('agent.cards.create.units') }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="border-t pt-3 mt-3">
|
||||||
|
<div class="flex justify-between items-center">
|
||||||
|
<span class="text-muted-foreground">{{ t('agent.cards.create.totalAmount') }}</span>
|
||||||
|
<span class="text-xl font-bold text-primary">¥{{ totalCost.toFixed(2) }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</UiCardContent>
|
||||||
|
</UiCard>
|
||||||
|
|
||||||
<div class="space-y-2">
|
<UiCard>
|
||||||
<UiLabel>生成数量 <span class="text-destructive">*</span></UiLabel>
|
<UiCardContent class="pt-6">
|
||||||
<UiInput
|
<div class="flex flex-col gap-3">
|
||||||
v-model.number="form.quantity"
|
<UiButton
|
||||||
type="number"
|
class="w-full"
|
||||||
:min="1"
|
size="lg"
|
||||||
:max="100"
|
:disabled="saving || !form.application_id || !form.card_type_id"
|
||||||
placeholder="请输入生成数量"
|
@click="handleGenerate"
|
||||||
/>
|
>
|
||||||
<p class="text-xs text-muted-foreground">
|
<Loader2 v-if="saving" class="mr-2 h-4 w-4 animate-spin" />
|
||||||
单次最多生成100张卡密
|
<Sparkles v-else class="mr-2 h-4 w-4" />
|
||||||
</p>
|
{{ t('agent.cards.create.generateNow') }}
|
||||||
|
</UiButton>
|
||||||
|
<UiButton
|
||||||
|
variant="outline"
|
||||||
|
class="w-full"
|
||||||
|
@click="router.back()"
|
||||||
|
>
|
||||||
|
{{ t('agent.cards.create.cancel') }}
|
||||||
|
</UiButton>
|
||||||
|
</div>
|
||||||
|
</UiCardContent>
|
||||||
|
</UiCard>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div v-if="totalPrice > 0" class="p-4 rounded-lg bg-muted/50">
|
</div>
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<span class="text-muted-foreground">预计费用</span>
|
|
||||||
<span class="text-xl font-bold">¥{{ totalPrice.toFixed(2) }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex gap-3">
|
|
||||||
<UiButton variant="outline" as-child>
|
|
||||||
<router-link to="/agent/cards">
|
|
||||||
取消
|
|
||||||
</router-link>
|
|
||||||
</UiButton>
|
|
||||||
<UiButton
|
|
||||||
:disabled="loading || !form.app_id || !form.card_type_id"
|
|
||||||
@click="handleGenerate"
|
|
||||||
>
|
|
||||||
<Loader2 v-if="loading" class="mr-2 h-4 w-4 animate-spin" />
|
|
||||||
{{ loading ? '生成中...' : '生成卡密' }}
|
|
||||||
</UiButton>
|
|
||||||
</div>
|
|
||||||
</UiCardContent>
|
|
||||||
</UiCard>
|
|
||||||
</BasicPage>
|
</BasicPage>
|
||||||
</template>
|
</template>
|
||||||
@@ -1322,8 +1322,11 @@
|
|||||||
"passwordMinLength": "Password must be at least 6 characters",
|
"passwordMinLength": "Password must be at least 6 characters",
|
||||||
"createSuccess": "Agent created successfully",
|
"createSuccess": "Agent created successfully",
|
||||||
"createFailed": "Failed to create agent",
|
"createFailed": "Failed to create agent",
|
||||||
"cancel": "Cancel"
|
"cancel": "Cancel",
|
||||||
|
"saveBtn": "Save Changes"
|
||||||
},
|
},
|
||||||
|
"editSuccess": "Agent updated successfully",
|
||||||
|
"editFailed": "Failed to update agent",
|
||||||
"enable": "Enable",
|
"enable": "Enable",
|
||||||
"disable": "Disable",
|
"disable": "Disable",
|
||||||
"deleteAgent": "Delete Agent",
|
"deleteAgent": "Delete Agent",
|
||||||
@@ -1341,7 +1344,8 @@
|
|||||||
"save": "Save",
|
"save": "Save",
|
||||||
"usernameHint": "Username cannot be changed",
|
"usernameHint": "Username cannot be changed",
|
||||||
"passwordPlaceholder": "Leave empty to keep current password",
|
"passwordPlaceholder": "Leave empty to keep current password",
|
||||||
"passwordHint": "Enter new password to change, leave empty to keep current"
|
"passwordHint": "Enter new password to change, leave empty to keep current",
|
||||||
|
"saveBtn": "Save Changes"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"announcements": {
|
"announcements": {
|
||||||
@@ -2857,7 +2861,27 @@
|
|||||||
"estimatedCost": "Estimated Cost",
|
"estimatedCost": "Estimated Cost",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"generating": "Generating...",
|
"generating": "Generating...",
|
||||||
"generateBtn": "Generate Cards"
|
"generateBtn": "Generate Cards",
|
||||||
|
"selectAppFirst": "Please select an application first",
|
||||||
|
"selectCardTypeFirst": "Please select a card type first",
|
||||||
|
"countRange": "Quantity must be between 1 and 100",
|
||||||
|
"config": "Generation Config",
|
||||||
|
"configDesc": "Select authorized application and available card type, set quantity",
|
||||||
|
"application": "Select Application",
|
||||||
|
"selectApplication": "Please select an application",
|
||||||
|
"cardType": "Select Card Type",
|
||||||
|
"selectCardType": "Please select a card type",
|
||||||
|
"noCardType": "No available card types for this application",
|
||||||
|
"count": "Quantity",
|
||||||
|
"maxCount": "Maximum 100 cards per generation",
|
||||||
|
"preview": "Generation Preview",
|
||||||
|
"app": "Application",
|
||||||
|
"type": "Card Type",
|
||||||
|
"unitPrice": "Unit Price",
|
||||||
|
"quantity": "Quantity",
|
||||||
|
"units": "cards",
|
||||||
|
"totalAmount": "Estimated Cost",
|
||||||
|
"generateNow": "Generate Now"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1280,8 +1280,23 @@
|
|||||||
"passwordMinLength": "密码长度至少6位",
|
"passwordMinLength": "密码长度至少6位",
|
||||||
"createSuccess": "创建代理成功",
|
"createSuccess": "创建代理成功",
|
||||||
"createFailed": "创建代理失败",
|
"createFailed": "创建代理失败",
|
||||||
"cancel": "取消"
|
"cancel": "取消",
|
||||||
|
"saveBtn": "保存修改"
|
||||||
},
|
},
|
||||||
|
"edit": {
|
||||||
|
"title": "编辑代理",
|
||||||
|
"description": "修改代理信息",
|
||||||
|
"fetchFailed": "获取代理信息失败",
|
||||||
|
"saveSuccess": "保存成功",
|
||||||
|
"saveFailed": "保存失败",
|
||||||
|
"save": "保存",
|
||||||
|
"usernameHint": "用户名不可修改",
|
||||||
|
"passwordPlaceholder": "留空则不修改密码",
|
||||||
|
"passwordHint": "输入新密码以修改,留空保持原密码",
|
||||||
|
"saveBtn": "保存修改"
|
||||||
|
},
|
||||||
|
"editSuccess": "更新代理成功",
|
||||||
|
"editFailed": "更新代理失败",
|
||||||
"enable": "启用",
|
"enable": "启用",
|
||||||
"disable": "禁用",
|
"disable": "禁用",
|
||||||
"deleteAgent": "删除代理",
|
"deleteAgent": "删除代理",
|
||||||
@@ -2847,7 +2862,27 @@
|
|||||||
"estimatedCost": "预计费用",
|
"estimatedCost": "预计费用",
|
||||||
"cancel": "取消",
|
"cancel": "取消",
|
||||||
"generating": "生成中...",
|
"generating": "生成中...",
|
||||||
"generateBtn": "生成卡密"
|
"generateBtn": "生成卡密",
|
||||||
|
"selectAppFirst": "请先选择应用",
|
||||||
|
"selectCardTypeFirst": "请先选择卡类",
|
||||||
|
"countRange": "生成数量需要在 1-100 之间",
|
||||||
|
"config": "生成配置",
|
||||||
|
"configDesc": "选择授权应用和可用卡类,设置生成数量",
|
||||||
|
"application": "选择应用",
|
||||||
|
"selectApplication": "请选择应用",
|
||||||
|
"cardType": "选择卡类",
|
||||||
|
"selectCardType": "请选择卡类",
|
||||||
|
"noCardType": "该应用暂无可用卡类",
|
||||||
|
"count": "生成数量",
|
||||||
|
"maxCount": "单次最多生成 100 张卡密",
|
||||||
|
"preview": "生成预览",
|
||||||
|
"app": "应用",
|
||||||
|
"type": "卡类",
|
||||||
|
"unitPrice": "单价",
|
||||||
|
"quantity": "数量",
|
||||||
|
"units": "张",
|
||||||
|
"totalAmount": "预计费用",
|
||||||
|
"generateNow": "立即生成"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user