feat(admin): 模型管理 - 统一财务统计并支持已有分组选择
This commit is contained in:
1 parent
b9d60f9807
commit
04cb438869
13 files changed
+522
-427
No files matched your search
@@ -115,33 +115,20 @@ test("channel model manager supports bounded atomic batch deletion", async () =>
|
||||
expect(component).toContain("批量删除");
|
||||
});
|
||||
|
||||
test("analytics keeps fixed range presets distinct and uses enabled channel models for pricing", async () => {
|
||||
test("analytics keeps range presets and uses order finances without a separate pricing editor", async () => {
|
||||
const source = compactSource(await Bun.file(new URL("../src/pages/admin/components/analytics-panel.tsx", import.meta.url)).text());
|
||||
|
||||
expect(source).toContain('type RangePreset = "7d" | "30d" | "60d"');
|
||||
expect(source).toContain('["60d", "60 天"]');
|
||||
expect(source).toContain('next.set("rangePreset", rangePreset)');
|
||||
expect(source).toContain("setRangePreset(undefined)");
|
||||
expect(source).toContain('placeholder={pricingModelOptions.length ? "选择已启用模型" : "暂无已启用模型"}');
|
||||
expect(source).toContain("onValuesChange={handlePricingValuesChange}");
|
||||
expect(source).toContain("onChange={handlePricingModelChange}");
|
||||
expect(source).toContain('hasOwnProperty.call(changedValues, "model")');
|
||||
expect(source).toContain('if (matchingChannels.length) form.setFieldValue("channelId", matchingChannels[0].id)');
|
||||
expect(source).toContain("const sourceChannels = channels.filter(");
|
||||
expect(source).toContain('Form.useWatch("channelId", form)');
|
||||
expect(source).toContain("pricingChannelId");
|
||||
expect(source).toContain("channel.id === pricingChannelId");
|
||||
expect(source).toContain('inputMode="decimal"');
|
||||
expect(source).toContain('className="admin-analytics-price-input"');
|
||||
expect(source).toContain('className="admin-analytics-price-field"');
|
||||
expect(source).toContain('rootClassName="admin-modal-root admin-analytics-pricing-modal"');
|
||||
expect(source).toContain("zIndex={1200}");
|
||||
expect(source).toContain("setPricingWorkspaceOpen(false)");
|
||||
expect(source).toContain("validator: validatePriceInput");
|
||||
expect(source).toContain("请输入非负价格,最多 6 位小数");
|
||||
expect(source).toContain("function formatPriceInput(micros: number)");
|
||||
expect(source).toContain("function toMicros(value?: string | number)");
|
||||
expect(source).not.toContain("<InputNumber");
|
||||
expect(source).not.toContain("模型价格配置");
|
||||
expect(source).not.toContain("listAdminModelPricings");
|
||||
expect(source).toContain("finance.revenueMicrocredits");
|
||||
expect(source).toContain("finance.profitMicrocredits");
|
||||
expect(source).toContain("finance.costedOrders < finance.settledOrders");
|
||||
expect(source).toContain("...analyticsFinanceColumns");
|
||||
expect(source).toContain("后端未返回完整财务统计");
|
||||
});
|
||||
|
||||
test("storage settings keep generic S3 controls and connection validation", async () => {
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { expect, test } from "bun:test";
|
||||
import type { AdminAnalytics, AnalyticsFinance } from "../src/services/api/auth";
|
||||
import { analyticsFinanceColumns } from "../src/pages/admin/components/analytics-finance";
|
||||
|
||||
function renderFinanceCells(finance?: AnalyticsFinance | null) {
|
||||
const row: AdminAnalytics["models"][number] = {
|
||||
model: "example", capability: "text", tasks: 1, requests: 1, uniqueUsers: 1,
|
||||
taskSuccessRate: 100, requestSuccessRate: 100, p50DurationMs: 100, p95DurationMs: 100,
|
||||
inputTokens: 10, outputTokens: 10, cachedTokens: 0, usageAvailable: true,
|
||||
mediaCount: 0, videoSeconds: 0, ...(finance === undefined ? {} : { finance }),
|
||||
};
|
||||
return analyticsFinanceColumns.map((column) => "render" in column ? column.render?.(undefined, row, 0) : undefined);
|
||||
}
|
||||
|
||||
test("model finance cells tolerate missing and null backend finance", () => {
|
||||
expect(renderFinanceCells()).toEqual(["--", "--", "--", "--"]);
|
||||
expect(renderFinanceCells(null)).toEqual(["--", "--", "--", "--"]);
|
||||
});
|
||||
|
||||
test("model finance cells preserve real zero values and unknown margins", () => {
|
||||
expect(renderFinanceCells({ settledOrders: 1, costedOrders: 1, revenueMicrocredits: 0, costMicrocredits: 0, profitMicrocredits: 0, profitMargin: null }))
|
||||
.toEqual(["0", "0", "0", "--"]);
|
||||
});
|
||||
|
||||
test("model finance cells show partial costs without inventing profits", () => {
|
||||
expect(renderFinanceCells({ settledOrders: 2, costedOrders: 1, revenueMicrocredits: 1500000, costMicrocredits: 250000, profitMicrocredits: null, profitMargin: null }))
|
||||
.toEqual(["1.5", "0.25(部分)", "--", "--"]);
|
||||
});
|
||||
|
||||
test("model finance cells display known losses", () => {
|
||||
expect(renderFinanceCells({ settledOrders: 1, costedOrders: 1, revenueMicrocredits: 1000000, costMicrocredits: 1500000, profitMicrocredits: -500000, profitMargin: -50 }))
|
||||
.toEqual(["1", "1.5", "-0.5", "-50.0%"]);
|
||||
});
|
||||
Reference in new issue
Block a user