Browse Source

fix:token计费获取 兜底

version/2.1.0
WIN-UGQIHHLSKBB\EDY 1 month ago
parent
commit
96d13df700
  1. BIN
      src/assets/images/subscribe_banner3.png
  2. 2
      src/layouts/Layout/Layout.tsx
  3. 35
      src/layouts/globalPromptPanel/globalPromptPanel.tsx
  4. 47
      src/layouts/globalPromptPanel/utils.ts
  5. 4
      vite.config.mts

BIN
src/assets/images/subscribe_banner3.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 622 KiB

After

Width:  |  Height:  |  Size: 637 KiB

2
src/layouts/Layout/Layout.tsx

@ -666,7 +666,7 @@ export function Layout({ children }: LayoutProps) {
</section> </section>
<button type="button" className="layoutShell__avatarMemberRow" onClick={() => navigate(ROUTES.SUBSCRIBE)}> <button type="button" className="layoutShell__avatarMemberRow" onClick={() => navigate(ROUTES.SUBSCRIBE)}>
<span className="layoutShell__avatarMemberLabel">{Number(user?.memberLevel) > 0 ? "VIP" : memberLevelMap[0]} </span> <span className="layoutShell__avatarMemberLabel">{Number(user?.memberLevel) > 0 ? "VIP" : t(memberLevelMap[0])} </span>
<span className="layoutShell__avatarMemberAction">{t("layout.userMenu.openMembership")}</span> <span className="layoutShell__avatarMemberAction">{t("layout.userMenu.openMembership")}</span>
<img className="layoutShell__avatarChevron" src={new URL("@/assets/images/ic_arrow_right_purple.png", import.meta.url).href} /> <img className="layoutShell__avatarChevron" src={new URL("@/assets/images/ic_arrow_right_purple.png", import.meta.url).href} />
</button> </button>

35
src/layouts/globalPromptPanel/globalPromptPanel.tsx

@ -46,6 +46,8 @@ import { useHorizontalWheelScroll } from "./useHorizontalWheelScroll";
import { import {
OTHER_CATEGORY, OTHER_CATEGORY,
buildPreferredParamValues, buildPreferredParamValues,
buildComposerTaskParamPayload,
buildSeedanceVideoPricePayload,
buildSelectedParamsFromTaskInfo, buildSelectedParamsFromTaskInfo,
buildGenTaskModelPayload, buildGenTaskModelPayload,
collectTaskInfoMedia, collectTaskInfoMedia,
@ -135,12 +137,11 @@ function useGenerateCost(params: {
activeModelItem: AiModelItem | null; activeModelItem: AiModelItem | null;
selectedParamValues: Record<string, string | number>; selectedParamValues: Record<string, string | number>;
activeTaskSubType: number | null; activeTaskSubType: number | null;
ratioSizePreview: AspectRatioItem | null;
inputVideoDurationSeconds: number; inputVideoDurationSeconds: number;
isActionMimicTask: boolean; isActionMimicTask: boolean;
selectedActionMimicItem: ActionMimicSelectedItem | null; selectedActionMimicItem: ActionMimicSelectedItem | null;
}) { }) {
const { activeModelItem, selectedParamValues, activeTaskSubType, ratioSizePreview, inputVideoDurationSeconds, isActionMimicTask, selectedActionMimicItem } = params; const { activeModelItem, selectedParamValues, activeTaskSubType, inputVideoDurationSeconds, isActionMimicTask, selectedActionMimicItem } = params;
const [generateCost, setGenerateCost] = useState<number>(0); const [generateCost, setGenerateCost] = useState<number>(0);
const debounceTimerRef = useRef<number | null>(null); const debounceTimerRef = useRef<number | null>(null);
const requestSeqRef = useRef(0); const requestSeqRef = useRef(0);
@ -161,22 +162,27 @@ function useGenerateCost(params: {
return; return;
} }
const modelParamFields = getComposerParamFieldsForModel(activeModelItem);
const resolvedParamValues = buildComposerTaskParamPayload(modelParamFields, selectedParamValues);
// token计费 从服务端拿积分 // token计费 从服务端拿积分
if (activeModelItem?.billingMethod === 2) { if (activeModelItem?.billingMethod === 2) {
if (!Object.keys(selectedParamValues).length) return; const seedanceParams = buildSeedanceVideoPricePayload(modelParamFields, selectedParamValues);
if (!seedanceParams) {
if (!cancelled) setGenerateCost(0);
return;
}
const currentSeq = ++requestSeqRef.current; const currentSeq = ++requestSeqRef.current;
const res: any = await getAiModelPrice({ const res: any = await getAiModelPrice({
modelName: activeModelItem?.aiModelCodeAlias, modelName: activeModelItem?.aiModelCodeAlias,
estimationType: "seedance_video", estimationType: "seedance_video",
seedanceVideo: { seedanceVideo: {
input_video_duration_seconds: inputVideoDurationSeconds, input_video_duration_seconds: inputVideoDurationSeconds,
output_video_duration_seconds: selectedParamValues.duration, ...seedanceParams,
resolution: selectedParamValues.resolution,
aspect_ratio: selectedParamValues.ratio,
}, },
}); });
const points = res?.data?.estimated_points ?? 0; const points = res?.data?.estimated_points ?? 0;
const batchSize = Number(selectedParamValues.batchSize ?? 1); const batchSize = Number(resolvedParamValues.batchSize ?? 1);
if (!cancelled && currentSeq === requestSeqRef.current) { if (!cancelled && currentSeq === requestSeqRef.current) {
setGenerateCost(Math.ceil(points * batchSize)); setGenerateCost(Math.ceil(points * batchSize));
} }
@ -198,8 +204,7 @@ function useGenerateCost(params: {
aiModelCode: activeModelItem?.code, aiModelCode: activeModelItem?.code,
aiModelCodeAlias: activeModelItem?.aiModelCodeAlias, aiModelCodeAlias: activeModelItem?.aiModelCodeAlias,
type: getTaskSubTypeRow(activeTaskSubType)?.type, type: getTaskSubTypeRow(activeTaskSubType)?.type,
...selectedParamValues, ...resolvedParamValues,
...dimensionPayloadFromPreview(selectedParamValues.resolution, ratioSizePreview),
}); });
const taskPrice = Number(res?.data?.taskPrice ?? 0); const taskPrice = Number(res?.data?.taskPrice ?? 0);
if (!cancelled && currentSeq === requestSeqRef.current) { if (!cancelled && currentSeq === requestSeqRef.current) {
@ -224,7 +229,7 @@ function useGenerateCost(params: {
debounceTimerRef.current = null; debounceTimerRef.current = null;
} }
}; };
}, [activeModelItem, activeTaskSubType, inputVideoDurationSeconds, isActionMimicTask, ratioSizePreview, selectedActionMimicItem, selectedParamValues]); }, [activeModelItem, activeTaskSubType, inputVideoDurationSeconds, isActionMimicTask, selectedActionMimicItem, selectedParamValues]);
return generateCost; return generateCost;
} }
@ -865,8 +870,9 @@ export function GlobalPromptPanel({
const applyAiModelsList = useCallback((list: AiModelItem[]) => { const applyAiModelsList = useCallback((list: AiModelItem[]) => {
setAiModels(list); setAiModels(list);
setActiveModelItem(list[0] ?? null); const firstModel = list[0] ?? null;
setSelectedParamValues({}); setActiveModelItem(firstModel);
setSelectedParamValues(buildPreferredParamValues(getComposerParamFieldsForModel(firstModel), {}));
}, []); }, []);
/** 拉模型并写状态;制作同款可选择只取列表不落地,避免中间态覆盖。 */ /** 拉模型并写状态;制作同款可选择只取列表不落地,避免中间态覆盖。 */
@ -1241,7 +1247,6 @@ export function GlobalPromptPanel({
activeModelItem, activeModelItem,
selectedParamValues, selectedParamValues,
activeTaskSubType, activeTaskSubType,
ratioSizePreview,
inputVideoDurationSeconds, inputVideoDurationSeconds,
isActionMimicTask, isActionMimicTask,
selectedActionMimicItem, selectedActionMimicItem,
@ -1754,7 +1759,9 @@ export function GlobalPromptPanel({
onClick={() => { onClick={() => {
setActiveModelItem(item); setActiveModelItem(item);
setModelMenuOpen(false); setModelMenuOpen(false);
setSelectedParamValues({}); setSelectedParamValues(
buildPreferredParamValues(getComposerParamFieldsForModel(item), {}),
);
}} }}
> >
<img <img

47
src/layouts/globalPromptPanel/utils.ts

@ -792,6 +792,53 @@ export function buildPreferredParamValues(fields: ComposerParamField[], prev: Re
return next; return next;
} }
/**
* Token Seedance
* `buildPreferredParamValues` field key
* null
*/
export function buildSeedanceVideoPricePayload(
fields: ComposerParamField[],
selected: Record<string, string | number>,
): {
output_video_duration_seconds: string | number;
resolution: string | number;
aspect_ratio: string;
} | null {
const params = buildPreferredParamValues(fields, selected);
const durationField = fields.find((field) => {
const key = field.key.trim().toLowerCase();
return key === "duration" || key === "output_video_duration_seconds";
});
const resolutionField = fields.find(
(field) =>
field.key.toLowerCase().includes("resolution") ||
(field.name ?? "").toLowerCase().includes("resolution"),
);
const ratioField = fields.find((field) => isRatioField(field.key, field.name));
const duration = durationField != null ? params[durationField.key] : params.duration;
const resolution = resolutionField != null ? params[resolutionField.key] : params.resolution;
const aspectRatio = ratioField != null ? params[ratioField.key] : params.ratio;
if (
duration == null ||
duration === "" ||
resolution == null ||
resolution === "" ||
aspectRatio == null ||
aspectRatio === ""
) {
return null;
}
return {
output_video_duration_seconds: duration,
resolution,
aspect_ratio: String(aspectRatio),
};
}
/** /**
* width/height `ratio` * width/height `ratio`
*/ */

4
vite.config.mts

@ -39,9 +39,9 @@ export default defineConfig(({ mode }) => {
proxy: isDev proxy: isDev
? { ? {
"/api_client": { "/api_client": {
// target: "http://192.168.77.111:8080/", target: "http://192.168.77.111:8080/",
// target: "https://wwwtest.popi.art/", // target: "https://wwwtest.popi.art/",
target: "https://www.popi.art/", // target: "https://www.popi.art/",
secure: false, secure: false,
changeOrigin: true, changeOrigin: true,
}, },

Loading…
Cancel
Save