fix(web): 成员视图模型列与支付结构,范围 watch 勿误重置
This commit is contained in:
@@ -73,7 +73,7 @@ const columns = [
|
|||||||
{ title: "时间", key: "created_at", width: 150 },
|
{ title: "时间", key: "created_at", width: 150 },
|
||||||
{ title: "Key", key: "token_name", width: 120 },
|
{ title: "Key", key: "token_name", width: 120 },
|
||||||
{ title: "归属", key: "member_name", width: 110 },
|
{ title: "归属", key: "member_name", width: 110 },
|
||||||
{ title: "模型", key: "model_name", width: 110 },
|
{ title: "模型", key: "model_name", dataIndex: "model_name", width: 110 },
|
||||||
{ title: "类型", key: "type", width: 80 },
|
{ title: "类型", key: "type", width: 80 },
|
||||||
{ title: "来源", key: "source", width: 110 },
|
{ title: "来源", key: "source", width: 110 },
|
||||||
{ title: "用量", key: "usage", width: 140 },
|
{ title: "用量", key: "usage", width: 140 },
|
||||||
@@ -127,10 +127,13 @@ watch(
|
|||||||
() => route.query,
|
() => route.query,
|
||||||
() => syncFromRoute(),
|
() => syncFromRoute(),
|
||||||
);
|
);
|
||||||
watch([memberId, apiKeyId, billingSource, subscriptionId, typeFilter, range], () => {
|
watch(
|
||||||
|
[memberId, apiKeyId, billingSource, subscriptionId, typeFilter],
|
||||||
|
() => {
|
||||||
page.value = 1;
|
page.value = 1;
|
||||||
pushQuery();
|
pushQuery();
|
||||||
});
|
},
|
||||||
|
);
|
||||||
watch(page, () => pushQuery());
|
watch(page, () => pushQuery());
|
||||||
|
|
||||||
function sourceBadge(record: LogItem) {
|
function sourceBadge(record: LogItem) {
|
||||||
@@ -185,7 +188,16 @@ onUnmounted(() => {
|
|||||||
<PageHeader title="调用日志" subtitle="全池模型请求查询与筛选">
|
<PageHeader title="调用日志" subtitle="全池模型请求查询与筛选">
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<span class="call-logs__label">时间范围</span>
|
<span class="call-logs__label">时间范围</span>
|
||||||
<TimeRangePicker :model-value="range" @change="(v, k) => setRange(v, k)" />
|
<TimeRangePicker
|
||||||
|
:model-value="range"
|
||||||
|
@change="
|
||||||
|
(v, k) => {
|
||||||
|
setRange(v, k);
|
||||||
|
page = 1;
|
||||||
|
pushQuery();
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,11 @@
|
|||||||
/**
|
/**
|
||||||
* 成员视图单页(交互设计-成员视图):聚合 · 支付参数 · 我的 key · 日志徽章展开
|
* 成员视图单页(交互设计-成员视图):聚合 · 支付参数 · 我的 key · 日志徽章展开
|
||||||
*/
|
*/
|
||||||
import { computed, ref, watch } from "vue";
|
import { computed, h, onMounted, onUnmounted, ref, watch } from "vue";
|
||||||
import type { LogItem, PaymentItem } from "@new-api-key-usage/core";
|
import type { LogItem, PaymentItem } from "@new-api-key-usage/core";
|
||||||
|
import { Tooltip } from "antdv-next";
|
||||||
|
import { QuestionCircleOutlined } from "@antdv-next/icons";
|
||||||
|
import { useRoute, useRouter } from "vue-router";
|
||||||
import PageHeader from "@/components/common/page-header.vue";
|
import PageHeader from "@/components/common/page-header.vue";
|
||||||
import TimeRangePicker from "@/components/common/time-range-picker.vue";
|
import TimeRangePicker from "@/components/common/time-range-picker.vue";
|
||||||
import QuotaText from "@/components/common/quota-text.vue";
|
import QuotaText from "@/components/common/quota-text.vue";
|
||||||
@@ -13,6 +16,8 @@ import { useMemberLogs, useMemberOverview, useMemberMe } from "@/queries/member.
|
|||||||
import { formatDateTime, formatMinute, hoursSince } from "@/utils/time.ts";
|
import { formatDateTime, formatMinute, hoursSince } from "@/utils/time.ts";
|
||||||
import { formatInt } from "@/utils/format.ts";
|
import { formatInt } from "@/utils/format.ts";
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
const { range, setRange } = useLiveTimeRange("recent-30");
|
const { range, setRange } = useLiveTimeRange("recent-30");
|
||||||
const meQuery = useMemberMe();
|
const meQuery = useMemberMe();
|
||||||
const overviewQuery = useMemberOverview(() => range.value);
|
const overviewQuery = useMemberOverview(() => range.value);
|
||||||
@@ -55,22 +60,71 @@ const paymentBySub = computed(() => {
|
|||||||
|
|
||||||
const logs = computed(() => logsQuery.data.value?.items ?? []);
|
const logs = computed(() => logsQuery.data.value?.items ?? []);
|
||||||
const logTotal = computed(() => logsQuery.data.value?.total ?? 0);
|
const logTotal = computed(() => logsQuery.data.value?.total ?? 0);
|
||||||
|
|
||||||
const expandedRowKeys = ref<number[]>([]);
|
const expandedRowKeys = ref<number[]>([]);
|
||||||
|
|
||||||
|
function tipTitle(label: string, tip: string) {
|
||||||
|
return h("span", { class: "mv-col-title" }, [
|
||||||
|
label,
|
||||||
|
h(
|
||||||
|
Tooltip,
|
||||||
|
{ title: tip },
|
||||||
|
() =>
|
||||||
|
h(QuestionCircleOutlined, {
|
||||||
|
class: "mv-col-title__icon",
|
||||||
|
"aria-hidden": "true",
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
const logColumns = [
|
const logColumns = [
|
||||||
{ title: "时间", key: "created_at", width: 150 },
|
{ title: "时间", key: "created_at", width: 150 },
|
||||||
{ title: "Key", key: "token_name", width: 120 },
|
{ title: "Key", key: "token_name", dataIndex: "token_name", width: 120 },
|
||||||
{ title: "模型", key: "model_name", width: 120 },
|
{
|
||||||
|
title: "模型",
|
||||||
|
key: "model_name",
|
||||||
|
dataIndex: "model_name",
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
{ title: "来源", key: "source", width: 120 },
|
{ title: "来源", key: "source", width: 120 },
|
||||||
{ title: "用量", key: "usage", width: 150 },
|
{ title: "用量", key: "usage", width: 150 },
|
||||||
{ title: "Tokens", key: "tokens", width: 110 },
|
{
|
||||||
|
title: tipTitle("Tokens", "提示 tokens / 补全 tokens"),
|
||||||
|
key: "tokens",
|
||||||
|
width: 110,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
watch(range, () => {
|
function syncFromRoute() {
|
||||||
|
const from = route.query.from;
|
||||||
|
const to = route.query.to;
|
||||||
|
if (typeof from === "string" && from && typeof to === "string" && to) {
|
||||||
|
setRange({ from, to }, "fixed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pushRangeQuery() {
|
||||||
|
void router.replace({
|
||||||
|
path: "/member",
|
||||||
|
query: { from: range.value.from, to: range.value.to },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
syncFromRoute();
|
||||||
|
watch(
|
||||||
|
() => route.query,
|
||||||
|
() => syncFromRoute(),
|
||||||
|
);
|
||||||
|
|
||||||
|
function onRangeChange(
|
||||||
|
v: { from: string; to: string },
|
||||||
|
kind: "recent-7" | "recent-30" | "fixed",
|
||||||
|
) {
|
||||||
|
setRange(v, kind);
|
||||||
page.value = 1;
|
page.value = 1;
|
||||||
expandedRowKeys.value = [];
|
expandedRowKeys.value = [];
|
||||||
});
|
pushRangeQuery();
|
||||||
|
}
|
||||||
|
|
||||||
function isStalled(at: number | null | undefined): boolean {
|
function isStalled(at: number | null | undefined): boolean {
|
||||||
const h = hoursSince(at);
|
const h = hoursSince(at);
|
||||||
@@ -79,7 +133,11 @@ function isStalled(at: number | null | undefined): boolean {
|
|||||||
|
|
||||||
function sourceBadge(record: LogItem) {
|
function sourceBadge(record: LogItem) {
|
||||||
if (record.billing_source === "subscription" && record.subscription_id != null) {
|
if (record.billing_source === "subscription" && record.subscription_id != null) {
|
||||||
return { text: `订阅 #${record.subscription_id}`, kind: "sub" as const, id: record.subscription_id };
|
return {
|
||||||
|
text: `订阅 #${record.subscription_id}`,
|
||||||
|
kind: "sub" as const,
|
||||||
|
id: record.subscription_id,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if (record.billing_source === "wallet") {
|
if (record.billing_source === "wallet") {
|
||||||
return { text: "充值", kind: "wallet" as const, id: null };
|
return { text: "充值", kind: "wallet" as const, id: null };
|
||||||
@@ -95,30 +153,49 @@ function onBadge(record: LogItem) {
|
|||||||
else expandedRowKeys.value.push(record.id);
|
else expandedRowKeys.value.push(record.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function paymentText(p: PaymentItem | undefined): string {
|
|
||||||
if (!p) return "该订阅无登记信息";
|
|
||||||
const period =
|
|
||||||
p.kind === "subscription"
|
|
||||||
? `${formatDateTime(p.period_start)} ~ ${p.period_end == null ? "进行中" : formatDateTime(p.period_end)}`
|
|
||||||
: formatDateTime(p.paid_at);
|
|
||||||
return `${period} · 订阅 #${p.subscription_id ?? p.id} · 额度 ${formatInt(p.quota_granted)} ($${p.quota_usd}) · 金额 ${p.paid_amount}${p.remark ? ` · ${p.remark}` : ""}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function onRangeChange(v: { from: string; to: string }, kind: "recent-7" | "recent-30" | "fixed") {
|
|
||||||
setRange(v, kind);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onExpand(expanded: boolean, record: LogItem) {
|
function onExpand(expanded: boolean, record: LogItem) {
|
||||||
const i = expandedRowKeys.value.indexOf(record.id);
|
const i = expandedRowKeys.value.indexOf(record.id);
|
||||||
if (expanded && i < 0) expandedRowKeys.value.push(record.id);
|
if (expanded && i < 0) expandedRowKeys.value.push(record.id);
|
||||||
if (!expanded && i >= 0) expandedRowKeys.value.splice(i, 1);
|
if (!expanded && i >= 0) expandedRowKeys.value.splice(i, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 表体滚动,避免整页被明细撑高 */
|
||||||
|
const boxRef = ref<HTMLElement | null>(null);
|
||||||
|
const bodyY = ref(420);
|
||||||
|
const CHROME = 120;
|
||||||
|
function measure() {
|
||||||
|
const h = boxRef.value?.clientHeight ?? 0;
|
||||||
|
if (h > 0) bodyY.value = Math.max(220, h - CHROME);
|
||||||
|
}
|
||||||
|
let ro: ResizeObserver | null = null;
|
||||||
|
onMounted(() => {
|
||||||
|
measure();
|
||||||
|
if (typeof ResizeObserver !== "undefined" && boxRef.value) {
|
||||||
|
ro = new ResizeObserver(() => measure());
|
||||||
|
ro.observe(boxRef.value);
|
||||||
|
}
|
||||||
|
window.addEventListener("resize", measure);
|
||||||
|
});
|
||||||
|
onUnmounted(() => {
|
||||||
|
ro?.disconnect();
|
||||||
|
window.removeEventListener("resize", measure);
|
||||||
|
});
|
||||||
|
|
||||||
|
function periodText(p: PaymentItem): string {
|
||||||
|
if (p.kind !== "subscription") return formatDateTime(p.paid_at);
|
||||||
|
const end = p.period_end == null ? "进行中" : formatDateTime(p.period_end);
|
||||||
|
return `${formatDateTime(p.period_start)} ~ ${end}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function expandPayment(record: LogItem): PaymentItem | undefined {
|
||||||
|
return paymentBySub.value.get(sourceBadge(record).id ?? -1);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section>
|
<section class="mv">
|
||||||
<PageHeader
|
<PageHeader
|
||||||
:title="me?.name ? `${me.name}` : '我的用量'"
|
:title="me?.name ? me.name : '我的用量'"
|
||||||
subtitle="你在本池的名下用量"
|
subtitle="你在本池的名下用量"
|
||||||
>
|
>
|
||||||
<template #actions>
|
<template #actions>
|
||||||
@@ -136,13 +213,12 @@ function onExpand(expanded: boolean, record: LogItem) {
|
|||||||
active
|
active
|
||||||
:paragraph="{ rows: 4 }"
|
:paragraph="{ rows: 4 }"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<a-empty
|
<a-empty
|
||||||
v-else-if="keys.length === 0"
|
v-else-if="keys.length === 0"
|
||||||
description="作者尚未为你分配 key"
|
description="作者尚未为你分配 key"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<template v-else>
|
<div v-else class="mv-body">
|
||||||
<section class="mv-block">
|
<section class="mv-block">
|
||||||
<h2 class="mv-block__title">总用量</h2>
|
<h2 class="mv-block__title">总用量</h2>
|
||||||
<template v-if="usage && usage.count > 0">
|
<template v-if="usage && usage.count > 0">
|
||||||
@@ -160,27 +236,33 @@ function onExpand(expanded: boolean, record: LogItem) {
|
|||||||
<h2 class="mv-block__title">支付参数</h2>
|
<h2 class="mv-block__title">支付参数</h2>
|
||||||
<div v-if="payments.length === 0" class="mv-empty">暂无支付记录信息</div>
|
<div v-if="payments.length === 0" class="mv-empty">暂无支付记录信息</div>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div
|
<div v-for="p in payments" :key="p.id" class="mv-pay">
|
||||||
v-for="p in payments"
|
<div class="mv-pay__head">
|
||||||
:key="p.id"
|
|
||||||
class="mv-pay"
|
|
||||||
>
|
|
||||||
<a-tag :color="p.kind === 'subscription' ? 'blue' : 'gold'">
|
<a-tag :color="p.kind === 'subscription' ? 'blue' : 'gold'">
|
||||||
{{ p.kind === "subscription" ? "订阅" : "充值" }}
|
{{ p.kind === "subscription" ? "订阅" : "充值" }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
<template v-if="p.kind === 'subscription'">
|
<strong v-if="p.kind === 'subscription'">
|
||||||
<span>
|
订阅 #{{ p.subscription_id }}
|
||||||
{{ formatDateTime(p.period_start) }} ~
|
</strong>
|
||||||
{{ p.period_end == null ? "进行中" : formatDateTime(p.period_end) }}
|
</div>
|
||||||
· 订阅 #{{ p.subscription_id }}
|
<div class="mv-pay__grid">
|
||||||
</span>
|
<div class="mv-pay__row">
|
||||||
</template>
|
<span class="mv-pay__k">{{ p.kind === "subscription" ? "期间" : "支付时间" }}</span>
|
||||||
<template v-else>
|
<span>{{ periodText(p) }}</span>
|
||||||
<span>支付于 {{ formatDateTime(p.paid_at) }}</span>
|
</div>
|
||||||
</template>
|
<div class="mv-pay__row">
|
||||||
|
<span class="mv-pay__k">额度</span>
|
||||||
<QuotaText :quota="p.quota_granted" :quota-usd="p.quota_usd" />
|
<QuotaText :quota="p.quota_granted" :quota-usd="p.quota_usd" />
|
||||||
<span>金额 {{ p.paid_amount }}</span>
|
</div>
|
||||||
<span v-if="p.remark" class="mv-note">{{ p.remark }}</span>
|
<div class="mv-pay__row">
|
||||||
|
<span class="mv-pay__k">金额</span>
|
||||||
|
<span class="mv-num">{{ p.paid_amount }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="p.remark" class="mv-pay__row">
|
||||||
|
<span class="mv-pay__k">备注</span>
|
||||||
|
<span>{{ p.remark }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mv-note mv-foot">
|
<div class="mv-note mv-foot">
|
||||||
支付参数对成员完全公开;币种由成员与作者约定
|
支付参数对成员完全公开;币种由成员与作者约定
|
||||||
@@ -194,17 +276,20 @@ function onExpand(expanded: boolean, record: LogItem) {
|
|||||||
<div v-for="k in keys" :key="k.key_id" class="mv-key">
|
<div v-for="k in keys" :key="k.key_id" class="mv-key">
|
||||||
<strong>{{ k.token_name }}</strong>
|
<strong>{{ k.token_name }}</strong>
|
||||||
<span v-if="isStalled(k.log_synced_at)" class="mv-stall">
|
<span v-if="isStalled(k.log_synced_at)" class="mv-stall">
|
||||||
截止 {{ formatMinute(k.log_synced_at) }} 停滞
|
同步截止 {{ formatMinute(k.log_synced_at) }} · 停滞
|
||||||
|
</span>
|
||||||
|
<span v-else class="mv-note">
|
||||||
|
同步截止 {{ formatMinute(k.log_synced_at) }}
|
||||||
</span>
|
</span>
|
||||||
<span v-else class="mv-note">截止 {{ formatMinute(k.log_synced_at) }}</span>
|
|
||||||
<span>调用 {{ formatInt(k.usage.count) }} 次</span>
|
<span>调用 {{ formatInt(k.usage.count) }} 次</span>
|
||||||
<QuotaText :quota="k.usage.quota" :quota-usd="k.usage.quota_usd" />
|
<QuotaText :quota="k.usage.quota" :quota-usd="k.usage.quota_usd" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="mv-block">
|
<section class="mv-block mv-block--logs">
|
||||||
<h2 class="mv-block__title">日志明细</h2>
|
<h2 class="mv-block__title">日志明细</h2>
|
||||||
|
<div ref="boxRef" class="mv-logs">
|
||||||
<a-table
|
<a-table
|
||||||
:columns="logColumns"
|
:columns="logColumns"
|
||||||
:data-source="logs"
|
:data-source="logs"
|
||||||
@@ -222,9 +307,8 @@ function onExpand(expanded: boolean, record: LogItem) {
|
|||||||
},
|
},
|
||||||
}"
|
}"
|
||||||
size="middle"
|
size="middle"
|
||||||
:scroll="{ x: 800 }"
|
:scroll="{ x: 800, y: bodyY }"
|
||||||
:expanded-row-keys="expandedRowKeys"
|
:expanded-row-keys="expandedRowKeys"
|
||||||
:expand-column-width="24"
|
|
||||||
:expandable="{
|
:expandable="{
|
||||||
showExpandColumn: false,
|
showExpandColumn: false,
|
||||||
rowExpandable: (r: LogItem) => sourceBadge(r).kind === 'sub',
|
rowExpandable: (r: LogItem) => sourceBadge(r).kind === 'sub',
|
||||||
@@ -246,18 +330,11 @@ function onExpand(expanded: boolean, record: LogItem) {
|
|||||||
v-if="sourceBadge(record).kind === 'sub'"
|
v-if="sourceBadge(record).kind === 'sub'"
|
||||||
title="点击查看该订阅支付参数"
|
title="点击查看该订阅支付参数"
|
||||||
>
|
>
|
||||||
<a-tag
|
<a-tag color="blue" class="mv-badge" @click="onBadge(record)">
|
||||||
color="blue"
|
|
||||||
class="mv-badge"
|
|
||||||
@click="onBadge(record)"
|
|
||||||
>
|
|
||||||
{{ sourceBadge(record).text }}
|
{{ sourceBadge(record).text }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tag
|
<a-tag v-else-if="sourceBadge(record).kind === 'wallet'" color="gold">
|
||||||
v-else-if="sourceBadge(record).kind === 'wallet'"
|
|
||||||
color="gold"
|
|
||||||
>
|
|
||||||
充值
|
充值
|
||||||
</a-tag>
|
</a-tag>
|
||||||
<a-tag v-else>未关联</a-tag>
|
<a-tag v-else>未关联</a-tag>
|
||||||
@@ -265,24 +342,73 @@ function onExpand(expanded: boolean, record: LogItem) {
|
|||||||
</template>
|
</template>
|
||||||
<template #expandedRowRender="{ record }">
|
<template #expandedRowRender="{ record }">
|
||||||
<div class="mv-expand">
|
<div class="mv-expand">
|
||||||
{{ paymentText(paymentBySub.get(sourceBadge(record).id ?? -1)) }}
|
<template v-if="expandPayment(record)">
|
||||||
|
<div class="mv-expand__title">订阅支付参数</div>
|
||||||
|
<div class="mv-pay__grid">
|
||||||
|
<div class="mv-pay__row">
|
||||||
|
<span class="mv-pay__k">期间</span>
|
||||||
|
<span>{{ periodText(expandPayment(record)!) }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="mv-pay__row">
|
||||||
|
<span class="mv-pay__k">额度</span>
|
||||||
|
<QuotaText
|
||||||
|
:quota="expandPayment(record)!.quota_granted"
|
||||||
|
:quota-usd="expandPayment(record)!.quota_usd"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mv-pay__row">
|
||||||
|
<span class="mv-pay__k">金额</span>
|
||||||
|
<span class="mv-num">
|
||||||
|
{{ expandPayment(record)!.paid_amount }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="expandPayment(record)!.remark" class="mv-pay__row">
|
||||||
|
<span class="mv-pay__k">备注</span>
|
||||||
|
<span>{{ expandPayment(record)!.remark }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div v-else class="mv-empty">该订阅无登记信息</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.mv {
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.mv-range-label {
|
.mv-range-label {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
color: rgba(0, 0, 0, 0.65);
|
color: rgba(0, 0, 0, 0.65);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mv-body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.mv-block {
|
.mv-block {
|
||||||
margin-bottom: 24px;
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mv-block--logs {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 280px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mv-logs {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mv-block__title {
|
.mv-block__title {
|
||||||
@@ -315,16 +441,39 @@ function onExpand(expanded: boolean, record: LogItem) {
|
|||||||
color: rgba(0, 0, 0, 0.45);
|
color: rgba(0, 0, 0, 0.45);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mv-num {
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
|
||||||
.mv-pay {
|
.mv-pay {
|
||||||
display: flex;
|
padding: 12px 0;
|
||||||
flex-wrap: wrap;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px 12px;
|
|
||||||
padding: 10px 0;
|
|
||||||
border-bottom: 1px solid #f0f0f0;
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mv-pay__head {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mv-pay__grid {
|
||||||
|
display: grid;
|
||||||
|
gap: 4px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mv-pay__row {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mv-pay__k {
|
||||||
|
width: 56px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
color: rgba(0, 0, 0, 0.45);
|
||||||
|
}
|
||||||
|
|
||||||
.mv-keys {
|
.mv-keys {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
|
||||||
@@ -351,7 +500,25 @@ function onExpand(expanded: boolean, record: LogItem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mv-expand {
|
.mv-expand {
|
||||||
padding: 4px 8px;
|
padding: 8px 12px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mv-expand__title {
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mv-col-title {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mv-col-title__icon {
|
||||||
|
font-size: 12px;
|
||||||
|
color: rgba(0, 0, 0, 0.45);
|
||||||
|
cursor: help;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user