feat: 优化授权管理添加/编辑页面布局和样式
- 添加 i18n 国际化支持,新增 createForm 翻译 - 统一使用 KeyRound 图标作为授权配置标题 - 优化预览卡片,增加已授权卡类列表展示 - 添加 loading 状态和更完善的表单验证 - 统一使用 textarea 组件替代 UiTextarea - 与版本管理页面布局保持一致 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { Check, Eye, Info, Loader2, Plus, Trash2 } from 'lucide-vue-next'
|
||||
import { Check, CheckCircle, Eye, KeyRound, Loader2, Plus, Trash2 } from 'lucide-vue-next'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
@@ -37,7 +37,7 @@ interface PermissionItem {
|
||||
}
|
||||
|
||||
const agentAppId = computed(() => route.params.id as string)
|
||||
const loading = ref(false)
|
||||
const loading = ref(true)
|
||||
const saving = ref(false)
|
||||
|
||||
const agents = ref<Agent[]>([])
|
||||
@@ -128,7 +128,7 @@ async function fetchAgentApp() {
|
||||
}
|
||||
catch (error) {
|
||||
console.error('获取授权信息失败:', error)
|
||||
toast.error('获取授权信息失败')
|
||||
toast.error(t('admin.agentApps.createForm.fetchFailed'))
|
||||
}
|
||||
finally {
|
||||
loading.value = false
|
||||
@@ -137,7 +137,7 @@ async function fetchAgentApp() {
|
||||
|
||||
function addPermission() {
|
||||
if (!selectedCardTypeId.value) {
|
||||
toast.error('请选择卡类')
|
||||
toast.error(t('admin.agentApps.createForm.selectCardType'))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -159,17 +159,17 @@ function removePermission(index: number) {
|
||||
|
||||
async function handleSave() {
|
||||
if (!form.value.agent_id) {
|
||||
toast.error('请选择代理')
|
||||
toast.error(t('admin.agentApps.createForm.selectAgentRequired'))
|
||||
return
|
||||
}
|
||||
|
||||
if (!form.value.application_id) {
|
||||
toast.error('请选择应用')
|
||||
toast.error(t('admin.agentApps.createForm.selectAppRequired'))
|
||||
return
|
||||
}
|
||||
|
||||
if (permissions.value.length === 0) {
|
||||
toast.error('请至少添加一个卡类')
|
||||
toast.error(t('admin.agentApps.createForm.selectCardRequired'))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -188,11 +188,11 @@ async function handleSave() {
|
||||
discount: 0,
|
||||
remark: form.value.remark,
|
||||
})
|
||||
toast.success('授权更新成功')
|
||||
toast.success(t('admin.agentApps.createForm.updateSuccess'))
|
||||
router.push('/admin/agent-apps')
|
||||
}
|
||||
catch (error: any) {
|
||||
toast.error(error.message || '更新授权失败')
|
||||
toast.error(error.message || t('admin.agentApps.createForm.updateFailed'))
|
||||
}
|
||||
finally {
|
||||
saving.value = false
|
||||
@@ -208,11 +208,11 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<BasicPage
|
||||
title="编辑授权"
|
||||
description="修改代理的应用授权配置"
|
||||
:title="t('admin.agentApps.createForm.editTitle')"
|
||||
:description="t('admin.agentApps.createForm.editDescription')"
|
||||
:breadcrumbs="[
|
||||
{ title: '授权管理', href: '/admin/agent-apps' },
|
||||
{ title: '编辑授权' },
|
||||
{ title: t('nav.agentApps'), href: '/admin/agent-apps' },
|
||||
{ title: t('admin.agentApps.createForm.editTitle') },
|
||||
]"
|
||||
sticky
|
||||
>
|
||||
@@ -226,49 +226,55 @@ onMounted(() => {
|
||||
<UiCard>
|
||||
<UiCardHeader>
|
||||
<UiCardTitle class="flex items-center gap-2">
|
||||
<Info class="size-5" />
|
||||
授权信息
|
||||
<KeyRound class="size-5" />
|
||||
{{ t('admin.agentApps.createForm.authConfig') }}
|
||||
</UiCardTitle>
|
||||
<UiCardDescription>选择代理、应用和卡类</UiCardDescription>
|
||||
<UiCardDescription>{{ t('admin.agentApps.createForm.authConfigDesc') }}</UiCardDescription>
|
||||
</UiCardHeader>
|
||||
<UiCardContent class="space-y-6">
|
||||
<div class="grid gap-4 sm:grid-cols-2">
|
||||
<div class="space-y-2">
|
||||
<UiLabel>选择代理 <span class="text-destructive">*</span></UiLabel>
|
||||
<UiSelect v-model="form.agent_id">
|
||||
<UiSelectTrigger>
|
||||
<UiSelectValue placeholder="请选择代理" />
|
||||
</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>选择应用 <span class="text-destructive">*</span></UiLabel>
|
||||
<UiSelect v-model="form.application_id" @update:model-value="fetchCardTypes($event)">
|
||||
<UiSelectTrigger>
|
||||
<UiSelectValue placeholder="请选择应用" />
|
||||
</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.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-3">
|
||||
<UiLabel>卡类权限 <span class="text-destructive">*</span></UiLabel>
|
||||
<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.cardPermission') }} <span class="text-destructive">*</span></UiLabel>
|
||||
<div class="flex gap-3">
|
||||
<div class="flex-1">
|
||||
<UiSelect v-model="selectedCardTypeId" :disabled="!form.application_id">
|
||||
<UiSelect v-model="selectedCardTypeId" :disabled="!form.application_id || saving">
|
||||
<UiSelectTrigger>
|
||||
<UiSelectValue placeholder="选择卡类" />
|
||||
<UiSelectValue :placeholder="t('admin.agentApps.createForm.selectCardType')" />
|
||||
</UiSelectTrigger>
|
||||
<UiSelectContent>
|
||||
<UiSelectItem v-for="ct in availableCardTypes" :key="ct.id" :value="String(ct.id)">
|
||||
@@ -277,9 +283,9 @@ onMounted(() => {
|
||||
</UiSelectContent>
|
||||
</UiSelect>
|
||||
</div>
|
||||
<UiButton @click="addPermission" :disabled="!form.application_id">
|
||||
<UiButton @click="addPermission" :disabled="!form.application_id || saving">
|
||||
<Plus class="mr-1 h-4 w-4" />
|
||||
添加
|
||||
{{ t('admin.agentApps.createForm.addCardType') }}
|
||||
</UiButton>
|
||||
</div>
|
||||
|
||||
@@ -292,22 +298,28 @@ onMounted(() => {
|
||||
<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" />
|
||||
<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)">
|
||||
<UiButton variant="ghost" size="icon" @click="removePermission(index)" :disabled="saving">
|
||||
<Trash2 class="h-4 w-4 text-destructive" />
|
||||
</UiButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p v-else class="text-sm text-muted-foreground text-center py-4">
|
||||
{{ form.application_id ? '请选择卡类添加到授权列表' : '请先选择应用' }}
|
||||
{{ form.application_id ? t('admin.agentApps.createForm.noCardTypes') : t('admin.agentApps.createForm.selectAppFirst') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<UiLabel>备注</UiLabel>
|
||||
<UiTextarea v-model="form.remark" placeholder="输入备注信息(可选)" rows="2" />
|
||||
<UiLabel>{{ t('admin.agentApps.createForm.remark') }}</UiLabel>
|
||||
<textarea
|
||||
v-model="form.remark"
|
||||
class="flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
||||
:placeholder="t('admin.agentApps.createForm.remarkPlaceholder')"
|
||||
:disabled="saving"
|
||||
rows="2"
|
||||
/>
|
||||
</div>
|
||||
</UiCardContent>
|
||||
</UiCard>
|
||||
@@ -318,41 +330,65 @@ onMounted(() => {
|
||||
<UiCardHeader>
|
||||
<UiCardTitle class="flex items-center gap-2">
|
||||
<Eye class="size-5" />
|
||||
预览
|
||||
{{ t('admin.agentApps.createForm.preview') }}
|
||||
</UiCardTitle>
|
||||
</UiCardHeader>
|
||||
<UiCardContent class="space-y-4">
|
||||
<div class="space-y-3">
|
||||
<div class="flex justify-between text-sm">
|
||||
<span class="text-muted-foreground">代理</span>
|
||||
<span class="text-muted-foreground">{{ t('admin.agentApps.createForm.previewAgent') }}</span>
|
||||
<span>{{ selectedAgent?.username || '-' }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between text-sm">
|
||||
<span class="text-muted-foreground">应用</span>
|
||||
<span class="text-muted-foreground">{{ t('admin.agentApps.createForm.previewApp') }}</span>
|
||||
<span>{{ selectedApplication?.name || '-' }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between text-sm">
|
||||
<span class="text-muted-foreground">授权卡类</span>
|
||||
<span>{{ permissions.length }} 个</span>
|
||||
<span class="text-muted-foreground">{{ t('admin.agentApps.createForm.previewCardTypes') }}</span>
|
||||
<span>{{ t('admin.agentApps.createForm.cardCount', { count: permissions.length }) }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between text-sm">
|
||||
<span class="text-muted-foreground">备注</span>
|
||||
<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>
|
||||
|
||||
<UiCard>
|
||||
<UiCardContent class="pt-6">
|
||||
<div class="flex flex-col gap-3">
|
||||
<UiButton class="w-full" size="lg" :disabled="saving || !form.agent_id || !form.application_id || permissions.length === 0" @click="handleSave">
|
||||
<UiButton
|
||||
class="w-full"
|
||||
size="lg"
|
||||
:disabled="saving || !form.agent_id || !form.application_id || permissions.length === 0"
|
||||
@click="handleSave"
|
||||
>
|
||||
<Loader2 v-if="saving" class="mr-2 h-4 w-4 animate-spin" />
|
||||
<Check v-else class="mr-2 h-4 w-4" />
|
||||
保存修改
|
||||
{{ t('admin.agentApps.createForm.updateAuth') }}
|
||||
</UiButton>
|
||||
<UiButton variant="outline" class="w-full" @click="router.back()">
|
||||
取消
|
||||
<UiButton
|
||||
variant="outline"
|
||||
class="w-full"
|
||||
@click="router.back()"
|
||||
>
|
||||
{{ t('common.cancel') }}
|
||||
</UiButton>
|
||||
</div>
|
||||
</UiCardContent>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { Eye, Info, Loader2, Plus, Trash2 } from 'lucide-vue-next'
|
||||
import { CheckCircle, Eye, KeyRound, Loader2, Plus, Rocket, Trash2 } from 'lucide-vue-next'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRouter } from 'vue-router'
|
||||
@@ -35,6 +35,7 @@ interface PermissionItem {
|
||||
price: number
|
||||
}
|
||||
|
||||
const loading = ref(false)
|
||||
const saving = ref(false)
|
||||
const agents = ref<Agent[]>([])
|
||||
const applications = ref<Application[]>([])
|
||||
@@ -78,11 +79,17 @@ async function fetchAgents() {
|
||||
}
|
||||
|
||||
async function fetchApplications() {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await api.get<{ applications: Application[] }>('/dev/applications')
|
||||
applications.value = data?.applications || []
|
||||
}
|
||||
catch { /* ignore */ }
|
||||
catch (error) {
|
||||
console.error('获取应用列表失败:', error)
|
||||
}
|
||||
finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchCardTypes(appId: string) {
|
||||
@@ -98,7 +105,7 @@ async function fetchCardTypes(appId: string) {
|
||||
|
||||
function addPermission() {
|
||||
if (!selectedCardTypeId.value) {
|
||||
toast.error('请选择卡类')
|
||||
toast.error(t('admin.agentApps.createForm.selectCardType'))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -120,17 +127,17 @@ function removePermission(index: number) {
|
||||
|
||||
async function handleSave() {
|
||||
if (!form.value.agent_id) {
|
||||
toast.error('请选择代理')
|
||||
toast.error(t('admin.agentApps.createForm.selectAgentRequired'))
|
||||
return
|
||||
}
|
||||
|
||||
if (!form.value.application_id) {
|
||||
toast.error('请选择应用')
|
||||
toast.error(t('admin.agentApps.createForm.selectAppRequired'))
|
||||
return
|
||||
}
|
||||
|
||||
if (permissions.value.length === 0) {
|
||||
toast.error('请至少添加一个卡类')
|
||||
toast.error(t('admin.agentApps.createForm.selectCardRequired'))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -149,11 +156,11 @@ async function handleSave() {
|
||||
discount: 0,
|
||||
remark: form.value.remark,
|
||||
})
|
||||
toast.success('授权添加成功')
|
||||
toast.success(t('admin.agentApps.createForm.createSuccess'))
|
||||
router.push('/admin/agent-apps')
|
||||
}
|
||||
catch (error: any) {
|
||||
toast.error(error.message || '添加授权失败')
|
||||
toast.error(error.message || t('admin.agentApps.createForm.createFailed'))
|
||||
}
|
||||
finally {
|
||||
saving.value = false
|
||||
@@ -168,11 +175,11 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<BasicPage
|
||||
title="添加授权"
|
||||
description="为代理添加新的应用授权"
|
||||
:title="t('admin.agentApps.createForm.title')"
|
||||
:description="t('admin.agentApps.createForm.description')"
|
||||
:breadcrumbs="[
|
||||
{ title: '授权管理', href: '/admin/agent-apps' },
|
||||
{ title: '添加授权' },
|
||||
{ title: t('nav.agentApps'), href: '/admin/agent-apps' },
|
||||
{ title: t('admin.agentApps.createForm.title') },
|
||||
]"
|
||||
sticky
|
||||
>
|
||||
@@ -182,49 +189,55 @@ onMounted(() => {
|
||||
<UiCard>
|
||||
<UiCardHeader>
|
||||
<UiCardTitle class="flex items-center gap-2">
|
||||
<Info class="size-5" />
|
||||
授权信息
|
||||
<KeyRound class="size-5" />
|
||||
{{ t('admin.agentApps.createForm.authConfig') }}
|
||||
</UiCardTitle>
|
||||
<UiCardDescription>选择代理、应用和卡类</UiCardDescription>
|
||||
<UiCardDescription>{{ t('admin.agentApps.createForm.authConfigDesc') }}</UiCardDescription>
|
||||
</UiCardHeader>
|
||||
<UiCardContent class="space-y-6">
|
||||
<div class="grid gap-4 sm:grid-cols-2">
|
||||
<div class="space-y-2">
|
||||
<UiLabel>选择代理 <span class="text-destructive">*</span></UiLabel>
|
||||
<UiSelect v-model="form.agent_id">
|
||||
<UiSelectTrigger>
|
||||
<UiSelectValue placeholder="请选择代理" />
|
||||
</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>选择应用 <span class="text-destructive">*</span></UiLabel>
|
||||
<UiSelect v-model="form.application_id" @update:model-value="fetchCardTypes($event)">
|
||||
<UiSelectTrigger>
|
||||
<UiSelectValue placeholder="请选择应用" />
|
||||
</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.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-3">
|
||||
<UiLabel>卡类权限 <span class="text-destructive">*</span></UiLabel>
|
||||
<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.cardPermission') }} <span class="text-destructive">*</span></UiLabel>
|
||||
<div class="flex gap-3">
|
||||
<div class="flex-1">
|
||||
<UiSelect v-model="selectedCardTypeId" :disabled="!form.application_id">
|
||||
<UiSelect v-model="selectedCardTypeId" :disabled="!form.application_id || saving">
|
||||
<UiSelectTrigger>
|
||||
<UiSelectValue placeholder="选择卡类" />
|
||||
<UiSelectValue :placeholder="t('admin.agentApps.createForm.selectCardType')" />
|
||||
</UiSelectTrigger>
|
||||
<UiSelectContent>
|
||||
<UiSelectItem v-for="ct in availableCardTypes" :key="ct.id" :value="String(ct.id)">
|
||||
@@ -233,9 +246,9 @@ onMounted(() => {
|
||||
</UiSelectContent>
|
||||
</UiSelect>
|
||||
</div>
|
||||
<UiButton @click="addPermission" :disabled="!form.application_id">
|
||||
<UiButton @click="addPermission" :disabled="!form.application_id || saving">
|
||||
<Plus class="mr-1 h-4 w-4" />
|
||||
添加
|
||||
{{ t('admin.agentApps.createForm.addCardType') }}
|
||||
</UiButton>
|
||||
</div>
|
||||
|
||||
@@ -248,22 +261,28 @@ onMounted(() => {
|
||||
<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" />
|
||||
<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)">
|
||||
<UiButton variant="ghost" size="icon" @click="removePermission(index)" :disabled="saving">
|
||||
<Trash2 class="h-4 w-4 text-destructive" />
|
||||
</UiButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p v-else class="text-sm text-muted-foreground text-center py-4">
|
||||
{{ form.application_id ? '请选择卡类添加到授权列表' : '请先选择应用' }}
|
||||
{{ form.application_id ? t('admin.agentApps.createForm.noCardTypes') : t('admin.agentApps.createForm.selectAppFirst') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<UiLabel>备注</UiLabel>
|
||||
<UiTextarea v-model="form.remark" placeholder="输入备注信息(可选)" rows="2" />
|
||||
<UiLabel>{{ t('admin.agentApps.createForm.remark') }}</UiLabel>
|
||||
<textarea
|
||||
v-model="form.remark"
|
||||
class="flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
||||
:placeholder="t('admin.agentApps.createForm.remarkPlaceholder')"
|
||||
:disabled="saving"
|
||||
rows="2"
|
||||
/>
|
||||
</div>
|
||||
</UiCardContent>
|
||||
</UiCard>
|
||||
@@ -274,41 +293,65 @@ onMounted(() => {
|
||||
<UiCardHeader>
|
||||
<UiCardTitle class="flex items-center gap-2">
|
||||
<Eye class="size-5" />
|
||||
预览
|
||||
{{ t('admin.agentApps.createForm.preview') }}
|
||||
</UiCardTitle>
|
||||
</UiCardHeader>
|
||||
<UiCardContent class="space-y-4">
|
||||
<div class="space-y-3">
|
||||
<div class="flex justify-between text-sm">
|
||||
<span class="text-muted-foreground">代理</span>
|
||||
<span class="text-muted-foreground">{{ t('admin.agentApps.createForm.previewAgent') }}</span>
|
||||
<span>{{ selectedAgent?.username || '-' }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between text-sm">
|
||||
<span class="text-muted-foreground">应用</span>
|
||||
<span class="text-muted-foreground">{{ t('admin.agentApps.createForm.previewApp') }}</span>
|
||||
<span>{{ selectedApplication?.name || '-' }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between text-sm">
|
||||
<span class="text-muted-foreground">授权卡类</span>
|
||||
<span>{{ permissions.length }} 个</span>
|
||||
<span class="text-muted-foreground">{{ t('admin.agentApps.createForm.previewCardTypes') }}</span>
|
||||
<span>{{ t('admin.agentApps.createForm.cardCount', { count: permissions.length }) }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between text-sm">
|
||||
<span class="text-muted-foreground">备注</span>
|
||||
<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>
|
||||
|
||||
<UiCard>
|
||||
<UiCardContent class="pt-6">
|
||||
<div class="flex flex-col gap-3">
|
||||
<UiButton class="w-full" size="lg" :disabled="saving || !form.agent_id || !form.application_id || permissions.length === 0" @click="handleSave">
|
||||
<UiButton
|
||||
class="w-full"
|
||||
size="lg"
|
||||
:disabled="saving || !form.agent_id || !form.application_id || permissions.length === 0"
|
||||
@click="handleSave"
|
||||
>
|
||||
<Loader2 v-if="saving" class="mr-2 h-4 w-4 animate-spin" />
|
||||
<Plus v-else class="mr-2 h-4 w-4" />
|
||||
确认授权
|
||||
<Rocket v-else class="mr-2 h-4 w-4" />
|
||||
{{ t('admin.agentApps.createForm.confirmAuth') }}
|
||||
</UiButton>
|
||||
<UiButton variant="outline" class="w-full" @click="router.back()">
|
||||
取消
|
||||
<UiButton
|
||||
variant="outline"
|
||||
class="w-full"
|
||||
@click="router.back()"
|
||||
>
|
||||
{{ t('common.cancel') }}
|
||||
</UiButton>
|
||||
</div>
|
||||
</UiCardContent>
|
||||
@@ -317,4 +360,4 @@ onMounted(() => {
|
||||
</div>
|
||||
</div>
|
||||
</BasicPage>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@@ -1703,7 +1703,47 @@
|
||||
"my_request": "My Request"
|
||||
},
|
||||
"reject": "Reject",
|
||||
"remove": "Remove"
|
||||
"remove": "Remove",
|
||||
"createForm": {
|
||||
"title": "Add Authorization",
|
||||
"description": "Add new application authorization for agent",
|
||||
"editTitle": "Edit Authorization",
|
||||
"editDescription": "Modify agent's application authorization configuration",
|
||||
"authConfig": "Authorization Configuration",
|
||||
"authConfigDesc": "Select agent, application and configure card type permissions",
|
||||
"selectAgent": "Select Agent",
|
||||
"selectAgentPlaceholder": "Please select an agent",
|
||||
"selectApp": "Select Application",
|
||||
"selectAppPlaceholder": "Please select an application",
|
||||
"cardPermission": "Card Type Permissions",
|
||||
"selectCardType": "Select 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",
|
||||
"previewRemark": "Remark",
|
||||
"confirmAuth": "Confirm Authorization",
|
||||
"updateAuth": "Save Changes",
|
||||
"createSuccess": "Authorization added successfully",
|
||||
"createFailed": "Failed to add authorization",
|
||||
"updateSuccess": "Authorization updated successfully",
|
||||
"updateFailed": "Failed to update authorization",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"finance": {
|
||||
"title": "Finance Management",
|
||||
|
||||
@@ -1692,7 +1692,47 @@
|
||||
"my_request": "我的申请"
|
||||
},
|
||||
"reject": "拒绝",
|
||||
"remove": "移除"
|
||||
"remove": "移除",
|
||||
"createForm": {
|
||||
"title": "添加授权",
|
||||
"description": "为代理添加新的应用授权",
|
||||
"editTitle": "编辑授权",
|
||||
"editDescription": "修改代理的应用授权配置",
|
||||
"authConfig": "授权配置",
|
||||
"authConfigDesc": "选择代理、应用和配置卡类权限",
|
||||
"selectAgent": "选择代理",
|
||||
"selectAgentPlaceholder": "请选择代理",
|
||||
"selectApp": "选择应用",
|
||||
"selectAppPlaceholder": "请选择应用",
|
||||
"cardPermission": "卡类权限",
|
||||
"selectCardType": "选择卡类",
|
||||
"addCardType": "添加",
|
||||
"cardTypeList": "已授权卡类",
|
||||
"cardTypeName": "卡类名称",
|
||||
"billingType": "计费类型",
|
||||
"price": "价格",
|
||||
"pricePlaceholder": "输入价格",
|
||||
"noCardTypes": "请选择卡类添加到授权列表",
|
||||
"selectAppFirst": "请先选择应用",
|
||||
"remark": "备注",
|
||||
"remarkPlaceholder": "输入备注信息(可选)",
|
||||
"preview": "预览",
|
||||
"previewAgent": "代理",
|
||||
"previewApp": "应用",
|
||||
"previewCardTypes": "授权卡类",
|
||||
"previewRemark": "备注",
|
||||
"confirmAuth": "确认授权",
|
||||
"updateAuth": "保存修改",
|
||||
"createSuccess": "授权添加成功",
|
||||
"createFailed": "添加授权失败",
|
||||
"updateSuccess": "授权更新成功",
|
||||
"updateFailed": "更新授权失败",
|
||||
"fetchFailed": "获取授权信息失败",
|
||||
"selectAgentRequired": "请选择代理",
|
||||
"selectAppRequired": "请选择应用",
|
||||
"selectCardRequired": "请至少添加一个卡类",
|
||||
"cardCount": "{count} 个"
|
||||
}
|
||||
},
|
||||
"finance": {
|
||||
"title": "财务管理",
|
||||
|
||||
Reference in New Issue
Block a user