@@ -74,7 +74,7 @@ function toggleWeekday(index: number) {
async function handleCreate ( ) {
if ( ! formData . value . name . trim ( ) ) {
toast . error ( t ( 'developer .applications.appNameRequired' ) )
toast . error ( t ( 'admin .applications.appNameRequired' ) )
return
}
@@ -120,16 +120,16 @@ async function handleCreate() {
const data = await response . json ( )
if ( data . code === 200 ) {
toast . success ( t ( 'developer .applications.createSuccess' ) )
router . push ( '/developer /applications' )
toast . success ( t ( 'admin .applications.createSuccess' ) )
router . push ( '/admin /applications' )
}
else {
toast . error ( data . message || t ( 'developer .applications.createFailed' ) )
toast . error ( data . message || t ( 'admin .applications.createFailed' ) )
}
}
catch ( error ) {
console . error ( '创建应用失败:' , error )
toast . error ( t ( 'developer .applications.createFailed' ) )
toast . error ( t ( 'admin .applications.createFailed' ) )
}
finally {
loading . value = false
@@ -139,31 +139,31 @@ async function handleCreate() {
< template >
< BasicPage
:title = "t('developer .applications.createApp')"
:description = "t('developer .applications.createAppDesc')"
:title = "t('admin .applications.createApp')"
:description = "t('admin .applications.createAppDesc')"
: breadcrumbs = "[
{ title: t('developer .applications.title'), href: '/developer /applications' },
{ title: t('developer .applications.createApp') },
{ title: t('admin .applications.title'), href: '/admin /applications' },
{ title: t('admin .applications.createApp') },
]"
sticky
>
< div class = "space-y-6" >
< UiCard >
< UiCardHeader >
< UiCardTitle > { { t ( 'developer .applications.basicInfo' ) } } < / UiCardTitle >
< UiCardDescription > { { t ( 'developer .applications.basicInfoDesc' ) } } < / UiCardDescription >
< UiCardTitle > { { t ( 'admin .applications.basicInfo' ) } } < / UiCardTitle >
< UiCardDescription > { { t ( 'admin .applications.basicInfoDesc' ) } } < / UiCardDescription >
< / UiCardHeader >
< UiCardContent class = "space-y-4" >
< div class = "grid grid-cols-1 md:grid-cols-2 gap-4" >
< div class = "space-y-2" >
< UiLabel for = "name" >
{ { t ( 'developer .applications.appName' ) } } *
{ { t ( 'admin .applications.appName' ) } } *
< / UiLabel >
< UiInput id = "name" v-model = "formData.name" :placeholder="t('developer .applications.appNamePlaceholder')" / >
< UiInput id = "name" v-model = "formData.name" :placeholder="t('admin .applications.appNamePlaceholder')" / >
< / div >
< div class = "space-y-2" >
< UiLabel > { { t ( 'developer .applications.appIcon' ) } } < / UiLabel >
< UiLabel > { { t ( 'admin .applications.appIcon' ) } } < / UiLabel >
< div class = "flex items-center gap-4" >
< div v-if = "formData.iconPreview" class="relative group" >
< img
@@ -185,7 +185,7 @@ async function handleCreate() {
class = "flex items-center justify-center h-12 px-4 border-2 border-dashed rounded-lg cursor-pointer hover:bg-accent/50 transition-colors"
>
< Icon icon = "lucide:upload" class = "w-4 h-4 mr-2 text-muted-foreground" / >
< span class = "text-sm text-muted-foreground" > { { formData . iconPreview ? t ( 'developer .applications.change' ) : t ( 'developer .applications.upload' ) } } < / span >
< span class = "text-sm text-muted-foreground" > { { formData . iconPreview ? t ( 'admin .applications.change' ) : t ( 'admin .applications.upload' ) } } < / span >
< input
id = "appIcon"
type = "file"
@@ -200,17 +200,17 @@ async function handleCreate() {
< div class = "space-y-2" >
< UiLabel for = "description" >
{ { t ( 'developer .applications.appDescription' ) } }
{ { t ( 'admin .applications.appDescription' ) } }
< / UiLabel >
< UiTextarea id = "description" v-model = "formData.description" :placeholder="t('developer .applications.appDescriptionPlaceholder')" rows="3" / >
< UiTextarea id = "description" v-model = "formData.description" :placeholder="t('admin .applications.appDescriptionPlaceholder')" rows="3" / >
< / div >
< / UiCardContent >
< / UiCard >
< UiCard >
< UiCardHeader >
< UiCardTitle > { { t ( 'developer .applications.operationMode' ) } } < / UiCardTitle >
< UiCardDescription > { { t ( 'developer .applications.operationModeDesc' ) } } < / UiCardDescription >
< UiCardTitle > { { t ( 'admin .applications.operationMode' ) } } < / UiCardTitle >
< UiCardDescription > { { t ( 'admin .applications.operationModeDesc' ) } } < / UiCardDescription >
< / UiCardHeader >
< UiCardContent >
< UiRadioGroup v-model = "formData.billing_type" class="grid grid-cols-1 md:grid-cols-2 gap-4" >
@@ -222,10 +222,10 @@ async function handleCreate() {
< UiRadioGroupItem value = "free" class = "mt-0.5" / >
< div >
< p class = "font-medium" >
{ { t ( 'developer .applications.freeMode' ) } }
{ { t ( 'admin .applications.freeMode' ) } }
< / p >
< p class = "text-sm text-muted-foreground" >
{ { t ( 'developer .applications.freeModeDesc' ) } }
{ { t ( 'admin .applications.freeModeDesc' ) } }
< / p >
< / div >
< / div >
@@ -238,10 +238,10 @@ async function handleCreate() {
< UiRadioGroupItem value = "subscription" class = "mt-0.5" / >
< div >
< p class = "font-medium" >
{ { t ( 'developer .applications.subscriptionMode' ) } }
{ { t ( 'admin .applications.subscriptionMode' ) } }
< / p >
< p class = "text-sm text-muted-foreground" >
{ { t ( 'developer .applications.subscriptionModeDesc' ) } }
{ { t ( 'admin .applications.subscriptionModeDesc' ) } }
< / p >
< / div >
< / div >
@@ -254,10 +254,10 @@ async function handleCreate() {
< UiRadioGroupItem value = "time" class = "mt-0.5" / >
< div >
< p class = "font-medium" >
{ { t ( 'developer .applications.timeMode' ) } }
{ { t ( 'admin .applications.timeMode' ) } }
< / p >
< p class = "text-sm text-muted-foreground" >
{ { t ( 'developer .applications.timeModeDesc' ) } }
{ { t ( 'admin .applications.timeModeDesc' ) } }
< / p >
< / div >
< / div >
@@ -270,10 +270,10 @@ async function handleCreate() {
< UiRadioGroupItem value = "count" class = "mt-0.5" / >
< div >
< p class = "font-medium" >
{ { t ( 'developer .applications.countMode' ) } }
{ { t ( 'admin .applications.countMode' ) } }
< / p >
< p class = "text-sm text-muted-foreground" >
{ { t ( 'developer .applications.countModeDesc' ) } }
{ { t ( 'admin .applications.countModeDesc' ) } }
< / p >
< / div >
< / div >
@@ -282,30 +282,30 @@ async function handleCreate() {
< div v-if = "formData.billing_type !== 'free'" class="mt-4 pt-4 border-t space-y-4" >
< div class = "grid grid-cols-1 md:grid-cols-2 gap-4" >
< div class = "space-y-2" >
< UiLabel > { { t ( 'developer .applications.deductionCycle' ) } } < / UiLabel >
< UiLabel > { { t ( 'admin .applications.deductionCycle' ) } } < / UiLabel >
< UiSelect v-model = "formData.deduction_cycle" >
< UiSelectTrigger >
< UiSelectValue :placeholder = "t('developer .applications.selectDeductionCycle')" / >
< UiSelectValue :placeholder = "t('admin .applications.selectDeductionCycle')" / >
< / UiSelectTrigger >
< UiSelectContent >
< UiSelectItem value = "per_use" >
{ { t ( 'developer .applications.perUse' ) } }
{ { t ( 'admin .applications.perUse' ) } }
< / UiSelectItem >
< UiSelectItem value = "per_minute" >
{ { t ( 'developer .applications.perMinute' ) } }
{ { t ( 'admin .applications.perMinute' ) } }
< / UiSelectItem >
< UiSelectItem value = "per_hour" >
{ { t ( 'developer .applications.perHour' ) } }
{ { t ( 'admin .applications.perHour' ) } }
< / UiSelectItem >
< UiSelectItem value = "per_day" >
{ { t ( 'developer .applications.perDay' ) } }
{ { t ( 'admin .applications.perDay' ) } }
< / UiSelectItem >
< / UiSelectContent >
< / UiSelect >
< / div >
< div class = "space-y-2" >
< UiLabel > { { t ( 'developer .applications.deductionAmount' ) } } < / UiLabel >
< UiLabel > { { t ( 'admin .applications.deductionAmount' ) } } < / UiLabel >
< UiNumberField v-model = "formData.deduction_amount" :min="0" :step="0.01" >
< UiNumberFieldContent >
< UiNumberFieldDecrement / >
@@ -321,8 +321,8 @@ async function handleCreate() {
< UiCard >
< UiCardHeader >
< UiCardTitle > { { t ( 'developer .applications.loginPolicy' ) } } < / UiCardTitle >
< UiCardDescription > { { t ( 'developer .applications.loginPolicyDesc' ) } } < / UiCardDescription >
< UiCardTitle > { { t ( 'admin .applications.loginPolicy' ) } } < / UiCardTitle >
< UiCardDescription > { { t ( 'admin .applications.loginPolicyDesc' ) } } < / UiCardDescription >
< / UiCardHeader >
< UiCardContent >
< UiRadioGroup v-model = "formData.login_policy" class="grid grid-cols-1 md:grid-cols-3 gap-4" >
@@ -334,10 +334,10 @@ async function handleCreate() {
< UiRadioGroupItem value = "loose" class = "mt-0.5" / >
< div >
< p class = "font-medium" >
{ { t ( 'developer .applications.looseMode' ) } }
{ { t ( 'admin .applications.looseMode' ) } }
< / p >
< p class = "text-sm text-muted-foreground" >
{ { t ( 'developer .applications.looseModeDesc' ) } }
{ { t ( 'admin .applications.looseModeDesc' ) } }
< / p >
< / div >
< / div >
@@ -350,10 +350,10 @@ async function handleCreate() {
< UiRadioGroupItem value = "strict" class = "mt-0.5" / >
< div >
< p class = "font-medium" >
{ { t ( 'developer .applications.strictMode' ) } }
{ { t ( 'admin .applications.strictMode' ) } }
< / p >
< p class = "text-sm text-muted-foreground" >
{ { t ( 'developer .applications.strictModeDesc' ) } }
{ { t ( 'admin .applications.strictModeDesc' ) } }
< / p >
< / div >
< / div >
@@ -366,10 +366,10 @@ async function handleCreate() {
< UiRadioGroupItem value = "hybrid" class = "mt-0.5" / >
< div >
< p class = "font-medium" >
{ { t ( 'developer .applications.hybridMode' ) } }
{ { t ( 'admin .applications.hybridMode' ) } }
< / p >
< p class = "text-sm text-muted-foreground" >
{ { t ( 'developer .applications.hybridModeDesc' ) } }
{ { t ( 'admin .applications.hybridModeDesc' ) } }
< / p >
< / div >
< / div >
@@ -379,14 +379,14 @@ async function handleCreate() {
< UiCard >
< UiCardHeader >
< UiCardTitle > { { t ( 'developer .applications.trialSettings' ) } } < / UiCardTitle >
< UiCardDescription > { { t ( 'developer .applications.trialSettings' ) } } < / UiCardDescription >
< UiCardTitle > { { t ( 'admin .applications.trialSettings' ) } } < / UiCardTitle >
< UiCardDescription > { { t ( 'admin .applications.trialSettings' ) } } < / UiCardDescription >
< / UiCardHeader >
< UiCardContent class = "space-y-4" >
< div class = "flex items-center justify-between" >
< div >
< p class = "font-medium" >
{ { t ( 'developer .applications.enableTrial' ) } }
{ { t ( 'admin .applications.enableTrial' ) } }
< / p >
< p class = "text-sm text-muted-foreground" >
新用户注册后自动获得试用权益
@@ -397,7 +397,7 @@ async function handleCreate() {
< div v-if = "formData.enable_trial" class="space-y-4 pt-4 border-t" >
< div class = "space-y-2" >
< UiLabel > { { t ( 'developer .applications.trialBalance' ) } } < / UiLabel >
< UiLabel > { { t ( 'admin .applications.trialBalance' ) } } < / UiLabel >
< UiNumberField
v-model = "formData.trial_balance"
:min = "0"
@@ -420,14 +420,14 @@ async function handleCreate() {
< UiCard >
< UiCardHeader >
< UiCardTitle > { { t ( 'developer .applications.freePeriodSettings' ) } } < / UiCardTitle >
< UiCardDescription > { { t ( 'developer .applications.freePeriodSettings' ) } } < / UiCardDescription >
< UiCardTitle > { { t ( 'admin .applications.freePeriodSettings' ) } } < / UiCardTitle >
< UiCardDescription > { { t ( 'admin .applications.freePeriodSettings' ) } } < / UiCardDescription >
< / UiCardHeader >
< UiCardContent class = "space-y-4" >
< div class = "flex items-center justify-between" >
< div >
< p class = "font-medium" >
{ { t ( 'developer .applications.enableFreePeriod' ) } }
{ { t ( 'admin .applications.enableFreePeriod' ) } }
< / p >
< p class = "text-sm text-muted-foreground" >
在设定的时间段内 , 所有用户可免费使用
@@ -438,7 +438,7 @@ async function handleCreate() {
< div v-if = "formData.enable_free_period" class="space-y-4 pt-4 border-t" >
< div class = "space-y-2" >
< UiLabel > { { t ( 'developer .applications.periodType' ) } } < / UiLabel >
< UiLabel > { { t ( 'admin .applications.periodType' ) } } < / UiLabel >
< UiRadioGroup v-model = "formData.free_period_type" class="grid grid-cols-1 md:grid-cols-2 gap-4" >
< div
class = "flex items-start gap-3 p-4 rounded-lg border cursor-pointer transition-colors"
@@ -448,7 +448,7 @@ async function handleCreate() {
< UiRadioGroupItem value = "range" class = "mt-0.5" / >
< div >
< p class = "font-medium" >
{ { t ( 'developer .applications.dateRange' ) } }
{ { t ( 'admin .applications.dateRange' ) } }
< / p >
< p class = "text-sm text-muted-foreground" >
指定开始和结束日期时间
@@ -464,7 +464,7 @@ async function handleCreate() {
< UiRadioGroupItem value = "weekly" class = "mt-0.5" / >
< div >
< p class = "font-medium" >
{ { t ( 'developer .applications.weekly' ) } }
{ { t ( 'admin .applications.weekly' ) } }
< / p >
< p class = "text-sm text-muted-foreground" >
每周固定日期和时间段
@@ -476,18 +476,18 @@ async function handleCreate() {
< div v-if = "formData.free_period_type === 'range'" class="grid grid-cols-1 md:grid-cols-2 gap-4" >
< div class = "space-y-2" >
< UiLabel > { { t ( 'developer .applications.startTime' ) } } < / UiLabel >
< UiDatePickerDateTimePicker v-model = "formData.free_period_start" :placeholder="t('developer .applications.startTime')" / >
< UiLabel > { { t ( 'admin .applications.startTime' ) } } < / UiLabel >
< UiDatePickerDateTimePicker v-model = "formData.free_period_start" :placeholder="t('admin .applications.startTime')" / >
< / div >
< div class = "space-y-2" >
< UiLabel > { { t ( 'developer .applications.endTime' ) } } < / UiLabel >
< UiDatePickerDateTimePicker v-model = "formData.free_period_end" :placeholder="t('developer .applications.endTime')" / >
< UiLabel > { { t ( 'admin .applications.endTime' ) } } < / UiLabel >
< UiDatePickerDateTimePicker v-model = "formData.free_period_end" :placeholder="t('admin .applications.endTime')" / >
< / div >
< / div >
< div v-if = "formData.free_period_type === 'weekly'" class="space-y-4" >
< div class = "space-y-2" >
< UiLabel > { { t ( 'developer .applications.weekdays' ) } } < / UiLabel >
< UiLabel > { { t ( 'admin .applications.weekdays' ) } } < / UiLabel >
< div class = "flex flex-wrap gap-2" >
< template v-for = "(day, index) in ['周一', '周二', '周三', '周四', '周五', '周六', '周日']" :key="index" >
< UiButton
@@ -507,15 +507,15 @@ async function handleCreate() {
< div class = "grid grid-cols-1 md:grid-cols-2 gap-4" >
< div class = "space-y-2" >
< UiLabel > { { t ( 'developer .applications.startTime' ) } } < / UiLabel >
< UiDatePickerTimePicker v-model = "formData.free_period_start_time" :placeholder="t('developer .applications.startTime')" / >
< UiLabel > { { t ( 'admin .applications.startTime' ) } } < / UiLabel >
< UiDatePickerTimePicker v-model = "formData.free_period_start_time" :placeholder="t('admin .applications.startTime')" / >
< p class = "text-xs text-muted-foreground" >
每天免费开始时间
< / p >
< / div >
< div class = "space-y-2" >
< UiLabel > { { t ( 'developer .applications.endTime' ) } } < / UiLabel >
< UiDatePickerTimePicker v-model = "formData.free_period_end_time" :placeholder="t('developer .applications.endTime')" / >
< UiLabel > { { t ( 'admin .applications.endTime' ) } } < / UiLabel >
< UiDatePickerTimePicker v-model = "formData.free_period_end_time" :placeholder="t('admin .applications.endTime')" / >
< p class = "text-xs text-muted-foreground" >
每天免费结束时间
< / p >
@@ -528,29 +528,29 @@ async function handleCreate() {
< UiCard >
< UiCardHeader >
< UiCardTitle > { { t ( 'developer .applications.securitySettings' ) } } < / UiCardTitle >
< UiCardDescription > { { t ( 'developer .applications.securitySettingsDesc' ) } } < / UiCardDescription >
< UiCardTitle > { { t ( 'admin .applications.securitySettings' ) } } < / UiCardTitle >
< UiCardDescription > { { t ( 'admin .applications.securitySettingsDesc' ) } } < / UiCardDescription >
< / UiCardHeader >
< UiCardContent class = "space-y-4" >
< div class = "grid grid-cols-1 md:grid-cols-2 gap-4" >
< div class = "space-y-2" >
< UiLabel > { { t ( 'developer .applications.encryptionType' ) } } < / UiLabel >
< UiLabel > { { t ( 'admin .applications.encryptionType' ) } } < / UiLabel >
< UiSelect v-model = "formData.encrypt_type" >
< UiSelectTrigger >
< UiSelectValue :placeholder = "t('developer .applications.encryptionType')" / >
< UiSelectValue :placeholder = "t('admin .applications.encryptionType')" / >
< / UiSelectTrigger >
< UiSelectContent >
< UiSelectItem value = "none" >
{ { t ( 'developer .applications.noEncryption' ) } }
{ { t ( 'admin .applications.noEncryption' ) } }
< / UiSelectItem >
< UiSelectItem value = "aes" >
{ { t ( 'developer .applications.aesEncryption' ) } }
{ { t ( 'admin .applications.aesEncryption' ) } }
< / UiSelectItem >
< UiSelectItem value = "rsa" >
{ { t ( 'developer .applications.rsaEncryption' ) } }
{ { t ( 'admin .applications.rsaEncryption' ) } }
< / UiSelectItem >
< UiSelectItem value = "rc4" >
{ { t ( 'developer .applications.rc4Encryption' ) } }
{ { t ( 'admin .applications.rc4Encryption' ) } }
< / UiSelectItem >
< / UiSelectContent >
< / UiSelect >
@@ -563,7 +563,7 @@ async function handleCreate() {
< / div >
< div class = "space-y-2" >
< UiLabel > { { t ( 'developer .applications.secretKey' ) } } < / UiLabel >
< UiLabel > { { t ( 'admin .applications.secretKey' ) } } < / UiLabel >
< div class = "relative" >
< UiInput
v-model = "formData.secret_key"
@@ -591,14 +591,14 @@ async function handleCreate() {
< UiCard >
< UiCardHeader >
< UiCardTitle > { { t ( 'developer .applications.deviceBind' ) } } < / UiCardTitle >
< UiCardTitle > { { t ( 'admin .applications.deviceBind' ) } } < / UiCardTitle >
< UiCardDescription > 控制用户登录时是否需要绑定设备 < / UiCardDescription >
< / UiCardHeader >
< UiCardContent class = "space-y-4" >
< div class = "flex items-center justify-between" >
< div >
< p class = "font-medium" >
{ { t ( 'developer .applications.deviceBind' ) } }
{ { t ( 'admin .applications.deviceBind' ) } }
< / p >
< p class = "text-sm text-muted-foreground" >
启用后 , 用户登录时需要绑定设备 , 可限制同时登录的设备数量
@@ -611,7 +611,7 @@ async function handleCreate() {
</div>
<div v-if=" formData . bind _type === 'device' " class=" space - y - 2 pt - 4 border - t ">
<UiLabel>{{ t('developer .applications.maxDevices') }}</UiLabel>
<UiLabel>{{ t('admin .applications.maxDevices') }}</UiLabel>
<UiNumberField v-model=" formData . max _devices " :min=" 1 " :max=" 10 ">
<UiNumberFieldContent>
<UiNumberFieldDecrement />
@@ -627,7 +627,7 @@ async function handleCreate() {
<div class=" flex items - center justify - between pt - 4 border - t ">
<div>
<p class=" font - medium ">
{{ t('developer .applications.allowMultiOpen') }}
{{ t('admin .applications.allowMultiOpen') }}
</p>
<p class=" text - sm text - muted - foreground ">
允许同一账号在同一设备上同时运行多个实例
@@ -639,12 +639,12 @@ async function handleCreate() {
</UiCard>
<div class=" flex justify - end gap - 3 ">
<UiButton variant=" outline " @click=" router . push ( '/developer /applications' ) ">
<UiButton variant=" outline " @click=" router . push ( '/admin /applications' ) ">
取消
</UiButton>
<UiButton :disabled=" loading " @click=" handleCreate ">
<Icon v-if=" loading " icon=" lucide : loader - 2 " class=" mr - 2 h - 4 w - 4 animate - spin " / >
{ { t ( 'developer .applications.createApp' ) } }
{ { t ( 'admin .applications.createApp' ) } }
< / UiButton >
< / div >
< / div >