mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-09-24 16:05:44 +08:00
fix: clarify Grok media pricing controls
This commit is contained in:
@@ -841,6 +841,18 @@ export default {
|
||||
finalPricePreview: 'Final per-image price preview',
|
||||
notConfigured: 'Not configured'
|
||||
},
|
||||
mediaPricing: {
|
||||
title: 'Image / Video Generation Pricing',
|
||||
description:
|
||||
'Configure Grok image and video generation access plus base media prices. Leave empty to use default prices.',
|
||||
allowImageGeneration: 'Allow image and video generation for this group',
|
||||
independentMultiplier: 'Use independent media multiplier',
|
||||
imageMultiplier: 'Media multiplier',
|
||||
modeHint:
|
||||
'By default, Grok media billing uses media price × current effective group multiplier. Independent mode uses media price × media multiplier. One video generation is billed as one media unit.',
|
||||
finalPricePreview: 'Final per-media-unit price preview',
|
||||
notConfigured: 'Not configured'
|
||||
},
|
||||
peakRate: {
|
||||
enable: 'Enable peak rate multiplier',
|
||||
peakStart: 'Peak start',
|
||||
|
||||
@@ -919,6 +919,17 @@ export default {
|
||||
finalPricePreview: '最终单张价格预览',
|
||||
notConfigured: '未配置'
|
||||
},
|
||||
mediaPricing: {
|
||||
title: '图片/视频生成计费',
|
||||
description: '配置 Grok 图片和视频生成能力及媒体基础单价,留空则使用默认价格',
|
||||
allowImageGeneration: '允许当前分组生图和视频生成',
|
||||
independentMultiplier: '媒体倍率独立',
|
||||
imageMultiplier: '媒体独立倍率',
|
||||
modeHint:
|
||||
'默认关闭独立倍率时,Grok 媒体费用 = 媒体价格 × 当前分组有效倍率;开启独立倍率后,Grok 媒体费用 = 媒体价格 × 媒体独立倍率。一次视频生成按 1 个媒体单位计费。',
|
||||
finalPricePreview: '最终单次媒体价格预览',
|
||||
notConfigured: '未配置'
|
||||
},
|
||||
peakRate: {
|
||||
enable: '启用高峰倍率',
|
||||
peakStart: '高峰开始',
|
||||
|
||||
@@ -787,7 +787,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 图片生成计费配置 -->
|
||||
<!-- 图片/视频生成计费配置 -->
|
||||
<div
|
||||
v-if="supportsImagePricingPlatform(createForm.platform)"
|
||||
class="border-t pt-4"
|
||||
@@ -795,10 +795,10 @@
|
||||
<label
|
||||
class="block mb-2 font-medium text-gray-700 dark:text-gray-300"
|
||||
>
|
||||
{{ t("admin.groups.imagePricing.title") }}
|
||||
{{ t(imagePricingI18nKey(createForm.platform, "title")) }}
|
||||
</label>
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400 mb-3">
|
||||
{{ t("admin.groups.imagePricing.description") }}
|
||||
{{ t(imagePricingI18nKey(createForm.platform, "description")) }}
|
||||
</p>
|
||||
<div class="mb-4 grid grid-cols-1 gap-3 md:grid-cols-2">
|
||||
<label class="flex items-center gap-2 text-sm text-gray-700 dark:text-gray-300">
|
||||
@@ -807,7 +807,7 @@
|
||||
type="checkbox"
|
||||
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
|
||||
/>
|
||||
{{ t("admin.groups.imagePricing.allowImageGeneration") }}
|
||||
{{ t(imagePricingI18nKey(createForm.platform, "allowImageGeneration")) }}
|
||||
</label>
|
||||
<label class="flex items-center gap-2 text-sm text-gray-700 dark:text-gray-300">
|
||||
<input
|
||||
@@ -815,7 +815,7 @@
|
||||
type="checkbox"
|
||||
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
|
||||
/>
|
||||
{{ t("admin.groups.imagePricing.independentMultiplier") }}
|
||||
{{ t(imagePricingI18nKey(createForm.platform, "independentMultiplier")) }}
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
@@ -823,7 +823,7 @@
|
||||
class="mb-4"
|
||||
>
|
||||
<label class="input-label">{{
|
||||
t("admin.groups.imagePricing.imageMultiplier")
|
||||
t(imagePricingI18nKey(createForm.platform, "imageMultiplier"))
|
||||
}}</label>
|
||||
<input
|
||||
v-model.number="createForm.image_rate_multiplier"
|
||||
@@ -870,11 +870,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-3 text-xs text-gray-500 dark:text-gray-400">
|
||||
{{ t("admin.groups.imagePricing.modeHint") }}
|
||||
{{ t(imagePricingI18nKey(createForm.platform, "modeHint")) }}
|
||||
</p>
|
||||
<div class="mt-2 rounded-lg bg-gray-50 p-3 text-xs text-gray-700 dark:bg-gray-800 dark:text-gray-300">
|
||||
<div class="mb-1 font-medium">
|
||||
{{ t("admin.groups.imagePricing.finalPricePreview") }}
|
||||
{{ t(imagePricingI18nKey(createForm.platform, "finalPricePreview")) }}
|
||||
</div>
|
||||
<div class="grid grid-cols-3 gap-2">
|
||||
<div
|
||||
@@ -2174,7 +2174,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 图片生成计费配置 -->
|
||||
<!-- 图片/视频生成计费配置 -->
|
||||
<div
|
||||
v-if="supportsImagePricingPlatform(editForm.platform)"
|
||||
class="border-t pt-4"
|
||||
@@ -2182,10 +2182,10 @@
|
||||
<label
|
||||
class="block mb-2 font-medium text-gray-700 dark:text-gray-300"
|
||||
>
|
||||
{{ t("admin.groups.imagePricing.title") }}
|
||||
{{ t(imagePricingI18nKey(editForm.platform, "title")) }}
|
||||
</label>
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400 mb-3">
|
||||
{{ t("admin.groups.imagePricing.description") }}
|
||||
{{ t(imagePricingI18nKey(editForm.platform, "description")) }}
|
||||
</p>
|
||||
<div class="mb-4 grid grid-cols-1 gap-3 md:grid-cols-2">
|
||||
<label class="flex items-center gap-2 text-sm text-gray-700 dark:text-gray-300">
|
||||
@@ -2194,7 +2194,7 @@
|
||||
type="checkbox"
|
||||
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
|
||||
/>
|
||||
{{ t("admin.groups.imagePricing.allowImageGeneration") }}
|
||||
{{ t(imagePricingI18nKey(editForm.platform, "allowImageGeneration")) }}
|
||||
</label>
|
||||
<label class="flex items-center gap-2 text-sm text-gray-700 dark:text-gray-300">
|
||||
<input
|
||||
@@ -2202,7 +2202,7 @@
|
||||
type="checkbox"
|
||||
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
|
||||
/>
|
||||
{{ t("admin.groups.imagePricing.independentMultiplier") }}
|
||||
{{ t(imagePricingI18nKey(editForm.platform, "independentMultiplier")) }}
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
@@ -2210,7 +2210,7 @@
|
||||
class="mb-4"
|
||||
>
|
||||
<label class="input-label">{{
|
||||
t("admin.groups.imagePricing.imageMultiplier")
|
||||
t(imagePricingI18nKey(editForm.platform, "imageMultiplier"))
|
||||
}}</label>
|
||||
<input
|
||||
v-model.number="editForm.image_rate_multiplier"
|
||||
@@ -2257,11 +2257,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-3 text-xs text-gray-500 dark:text-gray-400">
|
||||
{{ t("admin.groups.imagePricing.modeHint") }}
|
||||
{{ t(imagePricingI18nKey(editForm.platform, "modeHint")) }}
|
||||
</p>
|
||||
<div class="mt-2 rounded-lg bg-gray-50 p-3 text-xs text-gray-700 dark:bg-gray-800 dark:text-gray-300">
|
||||
<div class="mb-1 font-medium">
|
||||
{{ t("admin.groups.imagePricing.finalPricePreview") }}
|
||||
{{ t(imagePricingI18nKey(editForm.platform, "finalPricePreview")) }}
|
||||
</div>
|
||||
<div class="grid grid-cols-3 gap-2">
|
||||
<div
|
||||
@@ -3312,7 +3312,10 @@ import {
|
||||
} from "./groupsModelsList";
|
||||
import { createModelsListCandidatesTracker } from "./groupsModelsListCandidates";
|
||||
import { normalizeSupportedModelScopesForPlatform } from "./groupsSupportedModelScopes";
|
||||
import { supportsImagePricingPlatform } from "./groupsImagePricing";
|
||||
import {
|
||||
imagePricingI18nKey,
|
||||
supportsImagePricingPlatform,
|
||||
} from "./groupsImagePricing";
|
||||
|
||||
const { t } = useI18n();
|
||||
const appStore = useAppStore();
|
||||
|
||||
@@ -2,6 +2,7 @@ import { describe, expect, it } from "vitest";
|
||||
|
||||
import {
|
||||
imagePricingPlatforms,
|
||||
imagePricingI18nKey,
|
||||
supportsImagePricingPlatform,
|
||||
} from "../groupsImagePricing";
|
||||
|
||||
@@ -14,4 +15,13 @@ describe("groups image pricing platform support", () => {
|
||||
it("keeps non-media group platforms out of the image pricing controls", () => {
|
||||
expect(supportsImagePricingPlatform("anthropic")).toBe(false);
|
||||
});
|
||||
|
||||
it("uses media pricing copy for Grok groups only", () => {
|
||||
expect(imagePricingI18nKey("grok", "title")).toBe(
|
||||
"admin.groups.mediaPricing.title",
|
||||
);
|
||||
expect(imagePricingI18nKey("openai", "title")).toBe(
|
||||
"admin.groups.imagePricing.title",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,3 +7,8 @@ export const imagePricingPlatforms = new Set([
|
||||
|
||||
export const supportsImagePricingPlatform = (platform: string): boolean =>
|
||||
imagePricingPlatforms.has(platform);
|
||||
|
||||
export const imagePricingI18nKey = (platform: string, key: string): string =>
|
||||
platform === "grok"
|
||||
? `admin.groups.mediaPricing.${key}`
|
||||
: `admin.groups.imagePricing.${key}`;
|
||||
|
||||
Reference in New Issue
Block a user