improve(channel):调整渠道编辑表单
This commit is contained in:
1 parent
a9f5e08889
commit
07369f2f30
4 files changed
+102
-50
No files matched your search
@@ -30,6 +30,7 @@ type ChannelItem struct {
|
||||
Status string `json:"status"`
|
||||
Priority int `json:"priority"`
|
||||
Weight int `json:"weight"`
|
||||
MaxConcurrency int `json:"max_concurrency"`
|
||||
Tier string `json:"tier"`
|
||||
StrictCapacity bool `json:"strict_capacity"`
|
||||
TestModel string `json:"test_model"`
|
||||
@@ -52,6 +53,7 @@ type ChannelCreateReq struct {
|
||||
ApiKey string `json:"api_key" v:"required#请输入 API Key" dc:"API Key"`
|
||||
Priority int `json:"priority" d:"0" dc:"优先级"`
|
||||
Weight int `json:"weight" d:"100" v:"between:0,100" dc:"权重"`
|
||||
MaxConcurrency int `json:"max_concurrency" d:"100" v:"min:0" dc:"最大并发请求数(0=按上游 429 水位自动估算)"`
|
||||
Tier string `json:"tier" d:"primary" v:"in:primary,secondary,reserve" dc:"调度层级:primary=首选 secondary=备用 reserve=保底"`
|
||||
StrictCapacity bool `json:"strict_capacity" d:"false" dc:"严格容量:Redis 故障时实例级保守限额(fail-closed),用于高成本渠道"`
|
||||
TestModel string `json:"test_model" dc:"测试模型名"`
|
||||
@@ -78,6 +80,7 @@ type ChannelUpdateReq struct {
|
||||
ApiKey *string `json:"api_key" dc:"更新 API Key(留空不更新)"`
|
||||
Priority int `json:"priority" dc:"优先级"`
|
||||
Weight int `json:"weight" dc:"权重"`
|
||||
MaxConcurrency *int `json:"max_concurrency" v:"min:0" dc:"最大并发请求数(0=按上游 429 水位自动估算,留空不更新)"`
|
||||
TestModel string `json:"test_model" dc:"测试模型名"`
|
||||
Remark string `json:"remark" dc:"备注"`
|
||||
Status string `json:"status" v:"in:active,disabled,testing" dc:"状态"`
|
||||
@@ -112,6 +115,7 @@ type ChannelDetailRes struct {
|
||||
Status string `json:"status"`
|
||||
Priority int `json:"priority"`
|
||||
Weight int `json:"weight"`
|
||||
MaxConcurrency int `json:"max_concurrency"`
|
||||
Tier string `json:"tier"`
|
||||
StrictCapacity bool `json:"strict_capacity"`
|
||||
TestModel string `json:"test_model"`
|
||||
|
||||
@@ -68,6 +68,7 @@ func (s *sAdmin) ListChannels(ctx context.Context, req *v1.ChannelListReq) (*v1.
|
||||
Status string `json:"status"`
|
||||
Priority int `json:"priority"`
|
||||
Weight int `json:"weight"`
|
||||
MaxConcurrency int `json:"max_concurrency"`
|
||||
Tier string `json:"tier"`
|
||||
StrictCapacity bool `json:"strict_capacity"`
|
||||
TestModel string `json:"test_model"`
|
||||
@@ -81,7 +82,7 @@ func (s *sAdmin) ListChannels(ctx context.Context, req *v1.ChannelListReq) (*v1.
|
||||
Settings string `json:"settings"`
|
||||
}
|
||||
|
||||
err := query.Fields("chn_channels.id, chn_channels.name, chn_channels.type, chn_channels.base_url, chn_channels.status, chn_channels.priority, chn_channels.weight, chn_channels.tier, chn_channels.strict_capacity, chn_channels.test_model, chn_channels.remark, chn_channels.is_vip, chn_channels.sharing_threshold, chn_channels.preemption_threshold, chn_channels.borrowing_cooldown_seconds, chn_channels.created_at, h.health_score, chn_channels.settings").
|
||||
err := query.Fields("chn_channels.id, chn_channels.name, chn_channels.type, chn_channels.base_url, chn_channels.status, chn_channels.priority, chn_channels.weight, chn_channels.max_concurrency, chn_channels.tier, chn_channels.strict_capacity, chn_channels.test_model, chn_channels.remark, chn_channels.is_vip, chn_channels.sharing_threshold, chn_channels.preemption_threshold, chn_channels.borrowing_cooldown_seconds, chn_channels.created_at, h.health_score, chn_channels.settings").
|
||||
// 列表默认按 id 倒序:新建渠道排在最前,便于运营查看最新配置。
|
||||
// 注意分页场景下排序必须在 DB 层完成,前端只在当前页排序会导致跨页错乱。
|
||||
OrderDesc("chn_channels.id").
|
||||
@@ -109,6 +110,7 @@ func (s *sAdmin) ListChannels(ctx context.Context, req *v1.ChannelListReq) (*v1.
|
||||
Status: ch.Status,
|
||||
Priority: ch.Priority,
|
||||
Weight: ch.Weight,
|
||||
MaxConcurrency: ch.MaxConcurrency,
|
||||
Tier: ch.Tier,
|
||||
StrictCapacity: ch.StrictCapacity,
|
||||
TestModel: ch.TestModel,
|
||||
@@ -141,6 +143,7 @@ func (s *sAdmin) CloneChannel(ctx context.Context, req *v1.ChannelCloneReq) (*v1
|
||||
BaseURL string `json:"base_url"`
|
||||
Priority int `json:"priority"`
|
||||
Weight int `json:"weight"`
|
||||
MaxConcurrency int `json:"max_concurrency"`
|
||||
TestModel string `json:"test_model"`
|
||||
Remark string `json:"remark"`
|
||||
Settings string `json:"settings"`
|
||||
@@ -150,7 +153,7 @@ func (s *sAdmin) CloneChannel(ctx context.Context, req *v1.ChannelCloneReq) (*v1
|
||||
BorrowingCooldownSeconds int `json:"borrowing_cooldown_seconds"`
|
||||
}
|
||||
err := dao.ChnChannels.Ctx(ctx).
|
||||
Fields("id, name, type, base_url, priority, weight, test_model, remark, settings, is_vip, sharing_threshold, preemption_threshold, borrowing_cooldown_seconds").
|
||||
Fields("id, name, type, base_url, priority, weight, max_concurrency, test_model, remark, settings, is_vip, sharing_threshold, preemption_threshold, borrowing_cooldown_seconds").
|
||||
Where("id", req.ID).
|
||||
Scan(&src)
|
||||
if err != nil {
|
||||
@@ -184,6 +187,7 @@ func (s *sAdmin) CloneChannel(ctx context.Context, req *v1.ChannelCloneReq) (*v1
|
||||
Status: "active",
|
||||
Priority: src.Priority,
|
||||
Weight: src.Weight,
|
||||
MaxConcurrency: src.MaxConcurrency,
|
||||
TestModel: src.TestModel,
|
||||
Remark: src.Remark,
|
||||
Settings: src.Settings,
|
||||
@@ -265,6 +269,7 @@ func (s *sAdmin) CreateChannel(ctx context.Context, req *v1.ChannelCreateReq) (*
|
||||
Status: "active",
|
||||
Priority: req.Priority,
|
||||
Weight: req.Weight,
|
||||
MaxConcurrency: req.MaxConcurrency,
|
||||
Tier: tier,
|
||||
StrictCapacity: req.StrictCapacity,
|
||||
TestModel: req.TestModel,
|
||||
@@ -317,6 +322,9 @@ func (s *sAdmin) UpdateChannel(ctx context.Context, req *v1.ChannelUpdateReq) (*
|
||||
}
|
||||
data.Priority = req.Priority
|
||||
data.Weight = req.Weight
|
||||
if req.MaxConcurrency != nil {
|
||||
data.MaxConcurrency = *req.MaxConcurrency
|
||||
}
|
||||
if req.TestModel != "" {
|
||||
data.TestModel = req.TestModel
|
||||
}
|
||||
@@ -426,6 +434,7 @@ func (s *sAdmin) GetChannelDetail(ctx context.Context, req *v1.ChannelDetailReq)
|
||||
Status string `json:"status"`
|
||||
Priority int `json:"priority"`
|
||||
Weight int `json:"weight"`
|
||||
MaxConcurrency int `json:"max_concurrency"`
|
||||
Tier string `json:"tier"`
|
||||
StrictCapacity bool `json:"strict_capacity"`
|
||||
TestModel string `json:"test_model"`
|
||||
@@ -442,7 +451,7 @@ func (s *sAdmin) GetChannelDetail(ctx context.Context, req *v1.ChannelDetailReq)
|
||||
|
||||
err := dao.ChnChannels.Ctx(ctx).
|
||||
LeftJoin("chn_health_scores h ON chn_channels.id = h.channel_id").
|
||||
Fields("chn_channels.id, chn_channels.name, chn_channels.type, chn_channels.base_url, chn_channels.status, chn_channels.priority, chn_channels.weight, chn_channels.tier, chn_channels.strict_capacity, chn_channels.test_model, chn_channels.remark, chn_channels.is_vip, chn_channels.settings, chn_channels.sharing_threshold, chn_channels.preemption_threshold, chn_channels.borrowing_cooldown_seconds, chn_channels.created_at, chn_channels.updated_at, h.health_score").
|
||||
Fields("chn_channels.id, chn_channels.name, chn_channels.type, chn_channels.base_url, chn_channels.status, chn_channels.priority, chn_channels.weight, chn_channels.max_concurrency, chn_channels.tier, chn_channels.strict_capacity, chn_channels.test_model, chn_channels.remark, chn_channels.is_vip, chn_channels.settings, chn_channels.sharing_threshold, chn_channels.preemption_threshold, chn_channels.borrowing_cooldown_seconds, chn_channels.created_at, chn_channels.updated_at, h.health_score").
|
||||
Where("chn_channels.id", req.ID).
|
||||
Scan(&ch)
|
||||
if err != nil {
|
||||
@@ -486,6 +495,7 @@ func (s *sAdmin) GetChannelDetail(ctx context.Context, req *v1.ChannelDetailReq)
|
||||
Status: ch.Status,
|
||||
Priority: ch.Priority,
|
||||
Weight: ch.Weight,
|
||||
MaxConcurrency: ch.MaxConcurrency,
|
||||
Tier: ch.Tier,
|
||||
StrictCapacity: ch.StrictCapacity,
|
||||
TestModel: ch.TestModel,
|
||||
|
||||
@@ -58,6 +58,7 @@ const editForm = reactive({
|
||||
base_url: '',
|
||||
priority: 0,
|
||||
weight: 100,
|
||||
max_concurrency: 100,
|
||||
tier: 'primary',
|
||||
strict_capacity: false,
|
||||
test_model: '',
|
||||
@@ -78,6 +79,7 @@ function openEditModal() {
|
||||
base_url: detail.value.base_url || '',
|
||||
priority: detail.value.priority || 0,
|
||||
weight: detail.value.weight || 100,
|
||||
max_concurrency: detail.value.max_concurrency ?? 100,
|
||||
tier: detail.value.tier || 'primary',
|
||||
strict_capacity: detail.value.strict_capacity || false,
|
||||
test_model: detail.value.test_model || '',
|
||||
@@ -511,6 +513,10 @@ function formatHeaders(headers: Record<string, string>): string {
|
||||
</ADescriptionsItem>
|
||||
<ADescriptionsItem label="优先级">{{ detail.priority }}</ADescriptionsItem>
|
||||
<ADescriptionsItem label="权重">{{ detail.weight }}</ADescriptionsItem>
|
||||
<ADescriptionsItem label="最大并发">
|
||||
<span v-if="detail.max_concurrency > 0">{{ detail.max_concurrency }}</span>
|
||||
<span v-else style="color: #94a3b8">自动</span>
|
||||
</ADescriptionsItem>
|
||||
<ADescriptionsItem label="调度层级">
|
||||
<ATag :color="tierTagColor[detail.tier] || 'gray'" size="small">{{ tierLabel[detail.tier] || detail.tier || '-' }}</ATag>
|
||||
</ADescriptionsItem>
|
||||
@@ -731,41 +737,50 @@ function formatHeaders(headers: Record<string, string>): string {
|
||||
</template>
|
||||
</AFormItem>
|
||||
|
||||
<!-- 调度与状态 -->
|
||||
<div class="form-group-title">调度与状态</div>
|
||||
<!-- 调度与容量 -->
|
||||
<div class="form-group-title">调度与容量</div>
|
||||
<ARow :gutter="16">
|
||||
<ACol :span="8">
|
||||
<ACol :span="12">
|
||||
<AFormItem label="调度层级">
|
||||
<ASelect v-model="editForm.tier" :options="tierOptions" />
|
||||
<template #extra><span class="field-help">三档固定层级,替代旧版数值优先级</span></template>
|
||||
</AFormItem>
|
||||
</ACol>
|
||||
<ACol :span="8">
|
||||
<ACol :span="12">
|
||||
<AFormItem label="权重">
|
||||
<AInputNumber v-model="editForm.weight" :min="0" :max="100" class="w-full" />
|
||||
<template #extra><span class="field-help">同层级内按权重比例分配</span></template>
|
||||
</AFormItem>
|
||||
</ACol>
|
||||
<ACol :span="8">
|
||||
</ARow>
|
||||
<ARow :gutter="16">
|
||||
<ACol :span="12">
|
||||
<AFormItem label="最大并发">
|
||||
<AInputNumber v-model="editForm.max_concurrency" :min="0" class="w-full" />
|
||||
<template #extra><span class="field-help">0 = 自动估算(按上游 429 水位动态调整)</span></template>
|
||||
</AFormItem>
|
||||
</ACol>
|
||||
<ACol :span="12">
|
||||
<AFormItem label="严格容量">
|
||||
<ASwitch v-model="editForm.strict_capacity" />
|
||||
<template #extra><span class="field-help">Redis 故障时按保守限额拒绝新请求(高成本渠道)</span></template>
|
||||
</AFormItem>
|
||||
</ACol>
|
||||
</ARow>
|
||||
<ARow :gutter="16">
|
||||
<ACol :span="12">
|
||||
<AFormItem label="状态">
|
||||
<ASelect v-model="editForm.status" :options="[{ label: '启用', value: 'active' }, { label: '禁用', value: 'disabled' }, { label: '测试中', value: 'testing' }]" />
|
||||
</AFormItem>
|
||||
</ACol>
|
||||
</ARow>
|
||||
|
||||
<!-- 功能与测试 -->
|
||||
<div class="form-group-title">功能与测试</div>
|
||||
<ARow :gutter="16">
|
||||
<ACol :span="12">
|
||||
<AFormItem label="测试模型"><AInput v-model="editForm.test_model" /></AFormItem>
|
||||
</ACol>
|
||||
<ACol :span="6">
|
||||
<AFormItem label="使用代理"><ASwitch v-model="editForm.use_proxy" /></AFormItem>
|
||||
</ACol>
|
||||
<ACol :span="6">
|
||||
<AFormItem label="严格容量">
|
||||
<ASwitch v-model="editForm.strict_capacity" />
|
||||
<template #extra><span class="field-help">Redis 故障时按保守限额拒绝新请求(高成本渠道)</span></template>
|
||||
</ARow>
|
||||
<ARow :gutter="16">
|
||||
<ACol :span="12">
|
||||
<AFormItem label="使用代理">
|
||||
<ASwitch v-model="editForm.use_proxy" />
|
||||
</AFormItem>
|
||||
</ACol>
|
||||
</ARow>
|
||||
@@ -775,16 +790,18 @@ function formatHeaders(headers: Record<string, string>): string {
|
||||
<ACollapse :bordered="false">
|
||||
<ACollapseItem header="VIP 设置" key="vip" :header-style="{ fontSize: '13px' }">
|
||||
<ARow :gutter="16">
|
||||
<ACol :span="6">
|
||||
<ACol :span="12">
|
||||
<AFormItem label="VIP 渠道"><ASwitch v-model="editForm.is_vip" /></AFormItem>
|
||||
</ACol>
|
||||
<ACol v-if="editForm.is_vip" :span="6">
|
||||
<ACol v-if="editForm.is_vip" :span="12">
|
||||
<AFormItem label="共享阈值"><AInputNumber v-model="editForm.sharing_threshold" :min="0" :max="100" class="w-full" /></AFormItem>
|
||||
</ACol>
|
||||
<ACol v-if="editForm.is_vip" :span="6">
|
||||
</ARow>
|
||||
<ARow v-if="editForm.is_vip" :gutter="16">
|
||||
<ACol :span="12">
|
||||
<AFormItem label="抢占阈值"><AInputNumber v-model="editForm.preemption_threshold" :min="0" :max="100" class="w-full" /></AFormItem>
|
||||
</ACol>
|
||||
<ACol v-if="editForm.is_vip" :span="6">
|
||||
<ACol :span="12">
|
||||
<AFormItem label="借用冷却(秒)"><AInputNumber v-model="editForm.borrowing_cooldown_seconds" :min="0" class="w-full" /></AFormItem>
|
||||
</ACol>
|
||||
</ARow>
|
||||
|
||||
@@ -175,10 +175,10 @@ const providerDefaultURLs: Record<number, string> = {
|
||||
35: 'https://api.openai.com',
|
||||
}
|
||||
|
||||
const form = reactive({ name: '', type: 1, base_url: '', api_key: '', priority: 0, weight: 100, tier: 'primary', strict_capacity: false, test_model: '', remark: '', status: 'active', is_vip: false, use_proxy: false, sharing_threshold: null as number | null, preemption_threshold: null as number | null, borrowing_cooldown_seconds: null as number | null })
|
||||
const form = reactive({ name: '', type: 1, base_url: '', api_key: '', priority: 0, weight: 100, max_concurrency: 100, tier: 'primary', strict_capacity: false, test_model: '', remark: '', status: 'active', is_vip: false, use_proxy: false, sharing_threshold: null as number | null, preemption_threshold: null as number | null, borrowing_cooldown_seconds: null as number | null })
|
||||
|
||||
function openCreate() {
|
||||
Object.assign(form, { name: '', type: 1, base_url: '', api_key: '', priority: 0, weight: 100, tier: 'primary', strict_capacity: false, test_model: '', remark: '', status: 'active', is_vip: false, use_proxy: false, sharing_threshold: null, preemption_threshold: null, borrowing_cooldown_seconds: null })
|
||||
Object.assign(form, { name: '', type: 1, base_url: '', api_key: '', priority: 0, weight: 100, max_concurrency: 100, tier: 'primary', strict_capacity: false, test_model: '', remark: '', status: 'active', is_vip: false, use_proxy: false, sharing_threshold: null, preemption_threshold: null, borrowing_cooldown_seconds: null })
|
||||
showModal.value = true
|
||||
}
|
||||
|
||||
@@ -372,7 +372,8 @@ const { exporting, exportFile } = useExport({
|
||||
<!-- Create Channel Modal -->
|
||||
<AModal v-model:visible="showModal" title="创建渠道" :width="640" :mask-closable="false" :on-before-ok="handleSubmit" :ok-loading="formLoading">
|
||||
<AForm ref="formRef" :model="form" :rules="formRules" :auto-label-width="true" layout="vertical">
|
||||
<!-- 基本信息 -->
|
||||
<!-- 基础信息 -->
|
||||
<div class="form-group-title">基础信息</div>
|
||||
<ARow :gutter="16">
|
||||
<ACol :span="12">
|
||||
<AFormItem field="name" label="渠道名称" required><AInput v-model="form.name" placeholder="例如:OpenAI 主力" /></AFormItem>
|
||||
@@ -392,40 +393,51 @@ const { exporting, exportFile } = useExport({
|
||||
<AFormItem field="api_key" label="API Key" required>
|
||||
<AInput v-model="form.api_key" type="textarea" :auto-size="{ minRows: 2, maxRows: 4 }" placeholder="sk-xxxx..." />
|
||||
</AFormItem>
|
||||
<!-- 调度 & 状态 -->
|
||||
<!-- 调度与容量 -->
|
||||
<div class="form-group-title">调度与容量</div>
|
||||
<ARow :gutter="16">
|
||||
<ACol :span="8">
|
||||
<ACol :span="12">
|
||||
<AFormItem label="调度层级">
|
||||
<ASelect v-model="form.tier" :options="tierOptions" />
|
||||
<template #extra><span class="field-help">三档固定层级,替代旧版数值优先级</span></template>
|
||||
</AFormItem>
|
||||
</ACol>
|
||||
<ACol :span="8">
|
||||
<ACol :span="12">
|
||||
<AFormItem label="权重">
|
||||
<AInputNumber v-model="form.weight" :min="0" :max="100" class="w-full" />
|
||||
<template #extra><span class="field-help">同层级内按权重比例分配</span></template>
|
||||
</AFormItem>
|
||||
</ACol>
|
||||
<ACol :span="8">
|
||||
<AFormItem label="状态">
|
||||
<ASelect v-model="form.status" :options="[{ label: '启用', value: 'active' }, { label: '禁用', value: 'disabled' }, { label: '测试中', value: 'testing' }]" />
|
||||
</ARow>
|
||||
<ARow :gutter="16">
|
||||
<ACol :span="12">
|
||||
<AFormItem label="最大并发">
|
||||
<AInputNumber v-model="form.max_concurrency" :min="0" class="w-full" />
|
||||
<template #extra><span class="field-help">0 = 自动估算(按上游 429 水位动态调整)</span></template>
|
||||
</AFormItem>
|
||||
</ACol>
|
||||
<ACol :span="12">
|
||||
<AFormItem label="严格容量">
|
||||
<ASwitch v-model="form.strict_capacity" />
|
||||
<template #extra><span class="field-help">Redis 故障时保守限流(高成本渠道)</span></template>
|
||||
</AFormItem>
|
||||
</ACol>
|
||||
</ARow>
|
||||
<ARow :gutter="16">
|
||||
<ACol :span="8">
|
||||
<AFormItem label="测试模型"><AInput v-model="form.test_model" placeholder="gpt-4o-mini" /></AFormItem>
|
||||
</ACol>
|
||||
<ACol :span="8">
|
||||
<AFormItem label="使用代理">
|
||||
<ASwitch v-model="form.use_proxy" />
|
||||
<template #extra><span style="color:var(--color-text-3);font-size:12px">需先在系统设置中配置代理</span></template>
|
||||
<ACol :span="12">
|
||||
<AFormItem label="状态">
|
||||
<ASelect v-model="form.status" :options="[{ label: '启用', value: 'active' }, { label: '禁用', value: 'disabled' }, { label: '测试中', value: 'testing' }]" />
|
||||
</AFormItem>
|
||||
</ACol>
|
||||
<ACol :span="8">
|
||||
<AFormItem label="严格容量">
|
||||
<ASwitch v-model="form.strict_capacity" />
|
||||
<template #extra><span style="color:var(--color-text-3);font-size:12px">Redis 故障时保守限流(高成本渠道)</span></template>
|
||||
<ACol :span="12">
|
||||
<AFormItem label="测试模型"><AInput v-model="form.test_model" placeholder="gpt-4o-mini" /></AFormItem>
|
||||
</ACol>
|
||||
</ARow>
|
||||
<ARow :gutter="16">
|
||||
<ACol :span="12">
|
||||
<AFormItem label="使用代理">
|
||||
<ASwitch v-model="form.use_proxy" />
|
||||
<template #extra><span class="field-help">需先在系统设置中配置代理</span></template>
|
||||
</AFormItem>
|
||||
</ACol>
|
||||
</ARow>
|
||||
@@ -434,18 +446,18 @@ const { exporting, exportFile } = useExport({
|
||||
<ACollapse :bordered="false" :default-active-key="form.is_vip ? ['vip'] : []">
|
||||
<ACollapseItem header="VIP 设置" key="vip" :header-style="{ fontSize: '13px' }">
|
||||
<ARow :gutter="16">
|
||||
<ACol :span="8">
|
||||
<ACol :span="12">
|
||||
<AFormItem label="VIP 渠道"><ASwitch v-model="form.is_vip" /></AFormItem>
|
||||
</ACol>
|
||||
<ACol v-if="form.is_vip" :span="8">
|
||||
<ACol v-if="form.is_vip" :span="12">
|
||||
<AFormItem label="共享阈值"><AInputNumber v-model="form.sharing_threshold" :min="0" :max="100" placeholder="共享健康分阈值" class="w-full" /></AFormItem>
|
||||
</ACol>
|
||||
<ACol v-if="form.is_vip" :span="8">
|
||||
<AFormItem label="抢占阈值"><AInputNumber v-model="form.preemption_threshold" :min="0" :max="100" placeholder="抢占优先级阈值" class="w-full" /></AFormItem>
|
||||
</ACol>
|
||||
</ARow>
|
||||
<ARow v-if="form.is_vip" :gutter="16">
|
||||
<ACol :span="8">
|
||||
<ACol :span="12">
|
||||
<AFormItem label="抢占阈值"><AInputNumber v-model="form.preemption_threshold" :min="0" :max="100" placeholder="抢占优先级阈值" class="w-full" /></AFormItem>
|
||||
</ACol>
|
||||
<ACol :span="12">
|
||||
<AFormItem label="借用冷却(秒)"><AInputNumber v-model="form.borrowing_cooldown_seconds" :min="0" placeholder="非VIP冷却时间" class="w-full" /></AFormItem>
|
||||
</ACol>
|
||||
</ARow>
|
||||
@@ -586,4 +598,13 @@ const { exporting, exportFile } = useExport({
|
||||
color: var(--color-text-3);
|
||||
font-size: 12px;
|
||||
}
|
||||
.form-group-title {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: var(--color-text-2);
|
||||
margin: 12px 0 12px;
|
||||
padding-left: 8px;
|
||||
border-left: 3px solid #165dff;
|
||||
line-height: 1.2;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user