refactor: 简化授权管理添加/编辑页面为单卡类选择

- 移除卡类列表,改为单选卡类
- 选择代理 → 选择应用 → 选择卡类 → 设置价格
- 修复面包屑导航名称
- 优化预览卡片展示

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-09 19:28:06 +08:00
parent 802c36072c
commit aa5d3d126b
4 changed files with 211 additions and 304 deletions
+100 -144
View File
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { Check, CheckCircle, Eye, KeyRound, Loader2, Plus, Trash2 } from 'lucide-vue-next'
import { computed, onMounted, ref } from 'vue'
import { Check, Eye, KeyRound, Loader2 } from 'lucide-vue-next'
import { computed, onMounted, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRoute, useRouter } from 'vue-router'
import { toast } from 'vue-sonner'
@@ -29,13 +29,6 @@ interface CardType {
price: number
}
interface PermissionItem {
card_type_id: number
card_type_name: string
billing_type: string
price: number
}
const agentAppId = computed(() => route.params.id as string)
const loading = ref(true)
const saving = ref(false)
@@ -47,12 +40,11 @@ const cardTypes = ref<CardType[]>([])
const form = ref({
agent_id: '',
application_id: '',
card_type_id: '',
price: 0,
remark: '',
})
const selectedCardTypeId = ref<string>('')
const permissions = ref<PermissionItem[]>([])
const selectedAgent = computed(() => {
if (form.value.agent_id) {
return agents.value.find(a => String(a.id) === form.value.agent_id)
@@ -67,8 +59,11 @@ const selectedApplication = computed(() => {
return null
})
const availableCardTypes = computed(() => {
return cardTypes.value.filter(c => !permissions.value.some(p => p.card_type_id === c.id))
const selectedCardType = computed(() => {
if (form.value.card_type_id) {
return cardTypes.value.find(ct => String(ct.id) === form.value.card_type_id)
}
return null
})
async function fetchAgents() {
@@ -90,7 +85,10 @@ async function fetchApplications() {
}
async function fetchCardTypes(appId: string) {
if (!appId) return
if (!appId) {
cardTypes.value = []
return
}
try {
const data = await api.get<{ card_types: CardType[] }>(`/dev/card-types?application_id=${appId}`)
cardTypes.value = data?.card_types || []
@@ -115,15 +113,12 @@ async function fetchAgentApp() {
await fetchCardTypes(String(agentApp.application_id))
permissions.value = agentApp.card_types?.map((c: any) => {
const cardType = cardTypes.value.find(ct => ct.id === c.card_type_id)
return {
card_type_id: c.card_type_id,
card_type_name: cardType?.name || `卡类 #${c.card_type_id}`,
billing_type: cardType?.billing_type || '',
price: c.price || 0,
}
}) || []
// 取第一个卡类权限
if (agentApp.card_types && agentApp.card_types.length > 0) {
const firstCardType = agentApp.card_types[0]
form.value.card_type_id = String(firstCardType.card_type_id)
form.value.price = firstCardType.price || 0
}
}
}
catch (error) {
@@ -135,27 +130,11 @@ async function fetchAgentApp() {
}
}
function addPermission() {
if (!selectedCardTypeId.value) {
toast.error(t('admin.agentApps.createForm.selectCardType'))
return
watch(selectedCardType, (ct) => {
if (ct && !loading.value) {
form.value.price = ct.price
}
const cardType = cardTypes.value.find(ct => String(ct.id) === selectedCardTypeId.value)
if (!cardType) return
permissions.value.push({
card_type_id: cardType.id,
card_type_name: cardType.name,
billing_type: cardType.billing_type,
price: cardType.price,
})
selectedCardTypeId.value = ''
}
function removePermission(index: number) {
permissions.value.splice(index, 1)
}
})
async function handleSave() {
if (!form.value.agent_id) {
@@ -168,23 +147,21 @@ async function handleSave() {
return
}
if (permissions.value.length === 0) {
if (!form.value.card_type_id) {
toast.error(t('admin.agentApps.createForm.selectCardRequired'))
return
}
saving.value = true
try {
const cardTypesPayload = permissions.value.map(p => ({
card_type_id: p.card_type_id,
can_generate: true,
price: Number(p.price),
}))
await api.put(`/dev/agent-apps/${agentAppId.value}`, {
agent_id: Number(form.value.agent_id),
application_id: Number(form.value.application_id),
card_types: cardTypesPayload,
card_types: [{
card_type_id: Number(form.value.card_type_id),
can_generate: true,
price: Number(form.value.price),
}],
discount: 0,
remark: form.value.remark,
})
@@ -232,83 +209,73 @@ onMounted(() => {
<UiCardDescription>{{ t('admin.agentApps.createForm.authConfigDesc') }}</UiCardDescription>
</UiCardHeader>
<UiCardContent class="space-y-6">
<div class="space-y-2">
<UiLabel>{{ t('admin.agentApps.createForm.selectAgent') }} <span class="text-destructive">*</span></UiLabel>
<UiSelect v-model="form.agent_id" :disabled="saving">
<UiSelectTrigger>
<UiSelectValue :placeholder="t('admin.agentApps.createForm.selectAgentPlaceholder')" />
</UiSelectTrigger>
<UiSelectContent>
<UiSelectItem
v-for="agent in agents"
:key="agent.id"
:value="String(agent.id)"
>
{{ agent.username }}
</UiSelectItem>
</UiSelectContent>
</UiSelect>
</div>
<div class="space-y-2">
<UiLabel>{{ t('admin.agentApps.createForm.selectApp') }} <span class="text-destructive">*</span></UiLabel>
<UiSelect v-model="form.application_id" :disabled="saving" @update:model-value="fetchCardTypes($event)">
<UiSelectTrigger>
<UiSelectValue :placeholder="t('admin.agentApps.createForm.selectAppPlaceholder')" />
</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>{{ t('admin.agentApps.createForm.selectCardType') }} <span class="text-destructive">*</span></UiLabel>
<div class="flex gap-3">
<div class="flex-1">
<UiSelect v-model="selectedCardTypeId" :disabled="!form.application_id || saving">
<UiSelectTrigger>
<UiSelectValue :placeholder="t('admin.agentApps.createForm.selectCardTypePlaceholder')" />
</UiSelectTrigger>
<UiSelectContent>
<UiSelectItem v-for="ct in availableCardTypes" :key="ct.id" :value="String(ct.id)">
{{ ct.name }}<template v-if="ct.billing_type"> ({{ ct.billing_type }})</template>
</UiSelectItem>
</UiSelectContent>
</UiSelect>
</div>
<UiButton @click="addPermission" :disabled="!form.application_id || saving">
<Plus class="mr-1 h-4 w-4" />
{{ t('admin.agentApps.createForm.addCardType') }}
</UiButton>
<div class="grid gap-4 sm:grid-cols-2">
<div class="space-y-2">
<UiLabel>{{ t('admin.agentApps.createForm.selectAgent') }} <span class="text-destructive">*</span></UiLabel>
<UiSelect v-model="form.agent_id" :disabled="saving">
<UiSelectTrigger>
<UiSelectValue :placeholder="t('admin.agentApps.createForm.selectAgentPlaceholder')" />
</UiSelectTrigger>
<UiSelectContent>
<UiSelectItem
v-for="agent in agents"
:key="agent.id"
:value="String(agent.id)"
>
{{ agent.username }}
</UiSelectItem>
</UiSelectContent>
</UiSelect>
</div>
<div v-if="permissions.length > 0" class="border rounded-lg divide-y max-h-64 overflow-y-auto">
<div v-for="(p, index) in permissions" :key="p.card_type_id" class="flex items-center justify-between p-3 gap-4">
<div class="flex-1 min-w-0">
<div class="font-medium truncate">{{ p.card_type_name }}</div>
<div v-if="p.billing_type" class="text-sm text-muted-foreground">{{ p.billing_type }}</div>
</div>
<div class="flex items-center gap-2 shrink-0">
<div class="flex items-center gap-1">
<span class="text-muted-foreground">¥</span>
<UiInput class="w-20 text-right" v-model.number="p.price" :placeholder="t('admin.agentApps.createForm.pricePlaceholder')" />
</div>
<UiButton variant="ghost" size="icon" @click="removePermission(index)" :disabled="saving">
<Trash2 class="h-4 w-4 text-destructive" />
</UiButton>
</div>
<div class="space-y-2">
<UiLabel>{{ t('admin.agentApps.createForm.selectApp') }} <span class="text-destructive">*</span></UiLabel>
<UiSelect v-model="form.application_id" :disabled="saving" @update:model-value="fetchCardTypes($event)">
<UiSelectTrigger>
<UiSelectValue :placeholder="t('admin.agentApps.createForm.selectAppPlaceholder')" />
</UiSelectTrigger>
<UiSelectContent>
<UiSelectItem
v-for="app in applications"
:key="app.id"
:value="String(app.id)"
>
{{ app.name }}
</UiSelectItem>
</UiSelectContent>
</UiSelect>
</div>
</div>
<div class="grid gap-4 sm:grid-cols-2">
<div class="space-y-2">
<UiLabel>{{ t('admin.agentApps.createForm.selectCardType') }} <span class="text-destructive">*</span></UiLabel>
<UiSelect v-model="form.card_type_id" :disabled="!form.application_id || saving">
<UiSelectTrigger>
<UiSelectValue :placeholder="t('admin.agentApps.createForm.selectCardTypePlaceholder')" />
</UiSelectTrigger>
<UiSelectContent>
<UiSelectItem v-for="ct in cardTypes" :key="ct.id" :value="String(ct.id)">
{{ ct.name }}<template v-if="ct.billing_type"> ({{ ct.billing_type }})</template>
</UiSelectItem>
</UiSelectContent>
</UiSelect>
</div>
<div class="space-y-2">
<UiLabel for="price">{{ t('admin.agentApps.createForm.price') }} <span class="text-destructive">*</span></UiLabel>
<div class="relative">
<span class="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground">¥</span>
<UiInput
id="price"
v-model.number="form.price"
type="number"
class="pl-7"
:placeholder="t('admin.agentApps.createForm.pricePlaceholder')"
:disabled="saving"
/>
</div>
</div>
<p v-else class="text-sm text-muted-foreground text-center py-4">
{{ form.application_id ? t('admin.agentApps.createForm.noCardTypes') : t('admin.agentApps.createForm.selectAppFirst') }}
</p>
</div>
<div class="space-y-2">
@@ -344,29 +311,18 @@ onMounted(() => {
<span>{{ selectedApplication?.name || '-' }}</span>
</div>
<div class="flex justify-between text-sm">
<span class="text-muted-foreground">{{ t('admin.agentApps.createForm.previewCardTypes') }}</span>
<span>{{ t('admin.agentApps.createForm.cardCount', { count: permissions.length }) }}</span>
<span class="text-muted-foreground">{{ t('admin.agentApps.createForm.previewCardType') }}</span>
<span>{{ selectedCardType?.name || '-' }}</span>
</div>
<div class="flex justify-between text-sm">
<span class="text-muted-foreground">{{ t('admin.agentApps.createForm.previewPrice') }}</span>
<span>¥{{ form.price || 0 }}</span>
</div>
<div class="flex justify-between text-sm">
<span class="text-muted-foreground">{{ t('admin.agentApps.createForm.previewRemark') }}</span>
<span class="truncate max-w-[120px]">{{ form.remark || '-' }}</span>
</div>
</div>
<div v-if="permissions.length > 0" class="border-t pt-4 mt-4">
<p class="text-sm text-muted-foreground mb-2">
{{ t('admin.agentApps.createForm.cardTypeList') }}
</p>
<div class="rounded-lg bg-muted/50 p-3 space-y-2 max-h-[150px] overflow-auto">
<div v-for="p in permissions" :key="p.card_type_id" class="flex items-center justify-between text-sm">
<div class="flex items-center gap-2">
<CheckCircle class="size-4 text-green-600" />
<span>{{ p.card_type_name }}</span>
</div>
<span class="text-muted-foreground">¥{{ p.price }}</span>
</div>
</div>
</div>
</UiCardContent>
</UiCard>
@@ -376,7 +332,7 @@ onMounted(() => {
<UiButton
class="w-full"
size="lg"
:disabled="saving || !form.agent_id || !form.application_id || permissions.length === 0"
:disabled="saving || !form.agent_id || !form.application_id || !form.card_type_id"
@click="handleSave"
>
<Loader2 v-if="saving" class="mr-2 h-4 w-4 animate-spin" />
@@ -397,4 +353,4 @@ onMounted(() => {
</div>
</div>
</BasicPage>
</template>
</template>
+99 -134
View File
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { CheckCircle, Eye, KeyRound, Loader2, Plus, Rocket, Trash2 } from 'lucide-vue-next'
import { computed, onMounted, ref } from 'vue'
import { Eye, KeyRound, Loader2, Rocket } from 'lucide-vue-next'
import { computed, onMounted, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
import { toast } from 'vue-sonner'
@@ -28,13 +28,6 @@ interface CardType {
price: number
}
interface PermissionItem {
card_type_id: number
card_type_name: string
billing_type: string
price: number
}
const loading = ref(false)
const saving = ref(false)
const agents = ref<Agent[]>([])
@@ -44,12 +37,11 @@ const cardTypes = ref<CardType[]>([])
const form = ref({
agent_id: '',
application_id: '',
card_type_id: '',
price: 0,
remark: '',
})
const selectedCardTypeId = ref<string>('')
const permissions = ref<PermissionItem[]>([])
const selectedAgent = computed(() => {
if (form.value.agent_id) {
return agents.value.find(a => String(a.id) === form.value.agent_id)
@@ -64,8 +56,11 @@ const selectedApplication = computed(() => {
return null
})
const availableCardTypes = computed(() => {
return cardTypes.value.filter(c => !permissions.value.some(p => p.card_type_id === c.id))
const selectedCardType = computed(() => {
if (form.value.card_type_id) {
return cardTypes.value.find(ct => String(ct.id) === form.value.card_type_id)
}
return null
})
async function fetchAgents() {
@@ -93,37 +88,30 @@ async function fetchApplications() {
}
async function fetchCardTypes(appId: string) {
if (!appId) return
if (!appId) {
cardTypes.value = []
form.value.card_type_id = ''
form.value.price = 0
return
}
try {
const data = await api.get<{ card_types: CardType[] }>(`/dev/card-types?application_id=${appId}`)
cardTypes.value = data?.card_types || []
form.value.card_type_id = ''
form.value.price = 0
}
catch {
cardTypes.value = []
form.value.card_type_id = ''
form.value.price = 0
}
}
function addPermission() {
if (!selectedCardTypeId.value) {
toast.error(t('admin.agentApps.createForm.selectCardType'))
return
watch(selectedCardType, (ct) => {
if (ct) {
form.value.price = ct.price
}
const cardType = cardTypes.value.find(ct => String(ct.id) === selectedCardTypeId.value)
if (!cardType) return
permissions.value.push({
card_type_id: cardType.id,
card_type_name: cardType.name,
billing_type: cardType.billing_type,
price: cardType.price,
})
selectedCardTypeId.value = ''
}
function removePermission(index: number) {
permissions.value.splice(index, 1)
}
})
async function handleSave() {
if (!form.value.agent_id) {
@@ -136,23 +124,21 @@ async function handleSave() {
return
}
if (permissions.value.length === 0) {
if (!form.value.card_type_id) {
toast.error(t('admin.agentApps.createForm.selectCardRequired'))
return
}
saving.value = true
try {
const cardTypesPayload = permissions.value.map(p => ({
card_type_id: p.card_type_id,
can_generate: true,
price: Number(p.price),
}))
await api.post('/dev/agent-apps', {
agent_id: Number(form.value.agent_id),
application_id: Number(form.value.application_id),
card_types: cardTypesPayload,
card_types: [{
card_type_id: Number(form.value.card_type_id),
can_generate: true,
price: Number(form.value.price),
}],
discount: 0,
remark: form.value.remark,
})
@@ -195,83 +181,73 @@ onMounted(() => {
<UiCardDescription>{{ t('admin.agentApps.createForm.authConfigDesc') }}</UiCardDescription>
</UiCardHeader>
<UiCardContent class="space-y-6">
<div class="space-y-2">
<UiLabel>{{ t('admin.agentApps.createForm.selectAgent') }} <span class="text-destructive">*</span></UiLabel>
<UiSelect v-model="form.agent_id" :disabled="saving || loading">
<UiSelectTrigger>
<UiSelectValue :placeholder="t('admin.agentApps.createForm.selectAgentPlaceholder')" />
</UiSelectTrigger>
<UiSelectContent>
<UiSelectItem
v-for="agent in agents"
:key="agent.id"
:value="String(agent.id)"
>
{{ agent.username }}
</UiSelectItem>
</UiSelectContent>
</UiSelect>
</div>
<div class="space-y-2">
<UiLabel>{{ t('admin.agentApps.createForm.selectApp') }} <span class="text-destructive">*</span></UiLabel>
<UiSelect v-model="form.application_id" :disabled="saving || loading" @update:model-value="fetchCardTypes($event)">
<UiSelectTrigger>
<UiSelectValue :placeholder="t('admin.agentApps.createForm.selectAppPlaceholder')" />
</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>{{ t('admin.agentApps.createForm.selectCardType') }} <span class="text-destructive">*</span></UiLabel>
<div class="flex gap-3">
<div class="flex-1">
<UiSelect v-model="selectedCardTypeId" :disabled="!form.application_id || saving">
<UiSelectTrigger>
<UiSelectValue :placeholder="t('admin.agentApps.createForm.selectCardTypePlaceholder')" />
</UiSelectTrigger>
<UiSelectContent>
<UiSelectItem v-for="ct in availableCardTypes" :key="ct.id" :value="String(ct.id)">
{{ ct.name }}<template v-if="ct.billing_type"> ({{ ct.billing_type }})</template>
</UiSelectItem>
</UiSelectContent>
</UiSelect>
</div>
<UiButton @click="addPermission" :disabled="!form.application_id || saving">
<Plus class="mr-1 h-4 w-4" />
{{ t('admin.agentApps.createForm.addCardType') }}
</UiButton>
<div class="grid gap-4 sm:grid-cols-2">
<div class="space-y-2">
<UiLabel>{{ t('admin.agentApps.createForm.selectAgent') }} <span class="text-destructive">*</span></UiLabel>
<UiSelect v-model="form.agent_id" :disabled="saving || loading">
<UiSelectTrigger>
<UiSelectValue :placeholder="t('admin.agentApps.createForm.selectAgentPlaceholder')" />
</UiSelectTrigger>
<UiSelectContent>
<UiSelectItem
v-for="agent in agents"
:key="agent.id"
:value="String(agent.id)"
>
{{ agent.username }}
</UiSelectItem>
</UiSelectContent>
</UiSelect>
</div>
<div v-if="permissions.length > 0" class="border rounded-lg divide-y max-h-64 overflow-y-auto">
<div v-for="(p, index) in permissions" :key="p.card_type_id" class="flex items-center justify-between p-3 gap-4">
<div class="flex-1 min-w-0">
<div class="font-medium truncate">{{ p.card_type_name }}</div>
<div v-if="p.billing_type" class="text-sm text-muted-foreground">{{ p.billing_type }}</div>
</div>
<div class="flex items-center gap-2 shrink-0">
<div class="flex items-center gap-1">
<span class="text-muted-foreground">¥</span>
<UiInput class="w-20 text-right" v-model.number="p.price" :placeholder="t('admin.agentApps.createForm.pricePlaceholder')" />
</div>
<UiButton variant="ghost" size="icon" @click="removePermission(index)" :disabled="saving">
<Trash2 class="h-4 w-4 text-destructive" />
</UiButton>
</div>
<div class="space-y-2">
<UiLabel>{{ t('admin.agentApps.createForm.selectApp') }} <span class="text-destructive">*</span></UiLabel>
<UiSelect v-model="form.application_id" :disabled="saving || loading" @update:model-value="fetchCardTypes($event)">
<UiSelectTrigger>
<UiSelectValue :placeholder="t('admin.agentApps.createForm.selectAppPlaceholder')" />
</UiSelectTrigger>
<UiSelectContent>
<UiSelectItem
v-for="app in applications"
:key="app.id"
:value="String(app.id)"
>
{{ app.name }}
</UiSelectItem>
</UiSelectContent>
</UiSelect>
</div>
</div>
<div class="grid gap-4 sm:grid-cols-2">
<div class="space-y-2">
<UiLabel>{{ t('admin.agentApps.createForm.selectCardType') }} <span class="text-destructive">*</span></UiLabel>
<UiSelect v-model="form.card_type_id" :disabled="!form.application_id || saving">
<UiSelectTrigger>
<UiSelectValue :placeholder="t('admin.agentApps.createForm.selectCardTypePlaceholder')" />
</UiSelectTrigger>
<UiSelectContent>
<UiSelectItem v-for="ct in cardTypes" :key="ct.id" :value="String(ct.id)">
{{ ct.name }}<template v-if="ct.billing_type"> ({{ ct.billing_type }})</template>
</UiSelectItem>
</UiSelectContent>
</UiSelect>
</div>
<div class="space-y-2">
<UiLabel for="price">{{ t('admin.agentApps.createForm.price') }} <span class="text-destructive">*</span></UiLabel>
<div class="relative">
<span class="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground">¥</span>
<UiInput
id="price"
v-model.number="form.price"
type="number"
class="pl-7"
:placeholder="t('admin.agentApps.createForm.pricePlaceholder')"
:disabled="saving"
/>
</div>
</div>
<p v-else class="text-sm text-muted-foreground text-center py-4">
{{ form.application_id ? t('admin.agentApps.createForm.noCardTypes') : t('admin.agentApps.createForm.selectAppFirst') }}
</p>
</div>
<div class="space-y-2">
@@ -307,29 +283,18 @@ onMounted(() => {
<span>{{ selectedApplication?.name || '-' }}</span>
</div>
<div class="flex justify-between text-sm">
<span class="text-muted-foreground">{{ t('admin.agentApps.createForm.previewCardTypes') }}</span>
<span>{{ t('admin.agentApps.createForm.cardCount', { count: permissions.length }) }}</span>
<span class="text-muted-foreground">{{ t('admin.agentApps.createForm.previewCardType') }}</span>
<span>{{ selectedCardType?.name || '-' }}</span>
</div>
<div class="flex justify-between text-sm">
<span class="text-muted-foreground">{{ t('admin.agentApps.createForm.previewPrice') }}</span>
<span>¥{{ form.price || 0 }}</span>
</div>
<div class="flex justify-between text-sm">
<span class="text-muted-foreground">{{ t('admin.agentApps.createForm.previewRemark') }}</span>
<span class="truncate max-w-[120px]">{{ form.remark || '-' }}</span>
</div>
</div>
<div v-if="permissions.length > 0" class="border-t pt-4 mt-4">
<p class="text-sm text-muted-foreground mb-2">
{{ t('admin.agentApps.createForm.cardTypeList') }}
</p>
<div class="rounded-lg bg-muted/50 p-3 space-y-2 max-h-[150px] overflow-auto">
<div v-for="p in permissions" :key="p.card_type_id" class="flex items-center justify-between text-sm">
<div class="flex items-center gap-2">
<CheckCircle class="size-4 text-green-600" />
<span>{{ p.card_type_name }}</span>
</div>
<span class="text-muted-foreground">¥{{ p.price }}</span>
</div>
</div>
</div>
</UiCardContent>
</UiCard>
@@ -339,7 +304,7 @@ onMounted(() => {
<UiButton
class="w-full"
size="lg"
:disabled="saving || !form.agent_id || !form.application_id || permissions.length === 0"
:disabled="saving || !form.agent_id || !form.application_id || !form.card_type_id"
@click="handleSave"
>
<Loader2 v-if="saving" class="mr-2 h-4 w-4 animate-spin" />
+6 -13
View File
@@ -1706,32 +1706,26 @@
"remove": "Remove",
"createForm": {
"title": "Add Authorization",
"description": "Add new application authorization for agent",
"description": "Add application card type authorization for agent",
"editTitle": "Edit Authorization",
"editDescription": "Modify agent's application authorization configuration",
"editDescription": "Modify agent's application card type authorization",
"authConfig": "Authorization Configuration",
"authConfigDesc": "Select agent, application and configure card type permissions",
"authConfigDesc": "Select agent, application and card type",
"selectAgent": "Select Agent",
"selectAgentPlaceholder": "Please select an agent",
"selectApp": "Select Application",
"selectAppPlaceholder": "Please select an application",
"cardPermission": "Card Type Permissions",
"selectCardType": "Select Card Type",
"selectCardTypePlaceholder": "Please select a card type",
"addCardType": "Add",
"cardTypeList": "Authorized Card Types",
"cardTypeName": "Card Type Name",
"billingType": "Billing Type",
"price": "Price",
"pricePlaceholder": "Enter price",
"noCardTypes": "Please select card types to add to authorization list",
"selectAppFirst": "Please select an application first",
"remark": "Remark",
"remarkPlaceholder": "Enter remark (optional)",
"preview": "Preview",
"previewAgent": "Agent",
"previewApp": "Application",
"previewCardTypes": "Card Types",
"previewCardType": "Card Type",
"previewPrice": "Price",
"previewRemark": "Remark",
"confirmAuth": "Confirm Authorization",
"updateAuth": "Save Changes",
@@ -1742,8 +1736,7 @@
"fetchFailed": "Failed to fetch authorization information",
"selectAgentRequired": "Please select an agent",
"selectAppRequired": "Please select an application",
"selectCardRequired": "Please add at least one card type",
"cardCount": "{count} items"
"selectCardRequired": "Please select a card type"
}
},
"finance": {
+6 -13
View File
@@ -1695,32 +1695,26 @@
"remove": "移除",
"createForm": {
"title": "添加授权",
"description": "为代理添加新的应用授权",
"description": "为代理添加应用卡类授权",
"editTitle": "编辑授权",
"editDescription": "修改代理的应用授权配置",
"editDescription": "修改代理的应用卡类授权配置",
"authConfig": "授权配置",
"authConfigDesc": "选择代理、应用和配置卡类权限",
"authConfigDesc": "选择代理、应用和卡类",
"selectAgent": "选择代理",
"selectAgentPlaceholder": "请选择代理",
"selectApp": "选择应用",
"selectAppPlaceholder": "请选择应用",
"cardPermission": "卡类权限",
"selectCardType": "选择卡类",
"selectCardTypePlaceholder": "请选择卡类",
"addCardType": "添加",
"cardTypeList": "已授权卡类",
"cardTypeName": "卡类名称",
"billingType": "计费类型",
"price": "价格",
"pricePlaceholder": "输入价格",
"noCardTypes": "请选择卡类添加到授权列表",
"selectAppFirst": "请先选择应用",
"remark": "备注",
"remarkPlaceholder": "输入备注信息(可选)",
"preview": "预览",
"previewAgent": "代理",
"previewApp": "应用",
"previewCardTypes": "授权卡类",
"previewCardType": "卡类",
"previewPrice": "价格",
"previewRemark": "备注",
"confirmAuth": "确认授权",
"updateAuth": "保存修改",
@@ -1731,8 +1725,7 @@
"fetchFailed": "获取授权信息失败",
"selectAgentRequired": "请选择代理",
"selectAppRequired": "请选择应用",
"selectCardRequired": "请至少添加一个卡类",
"cardCount": "{count} 个"
"selectCardRequired": "请选择卡类"
}
},
"finance": {