Match finance dashboard dark design
This commit is contained in:
+252
-247
@@ -72,7 +72,7 @@
|
|||||||
<div class="metrics-grid">
|
<div class="metrics-grid">
|
||||||
<div class="metric-card">
|
<div class="metric-card">
|
||||||
<div class="metric-head">
|
<div class="metric-head">
|
||||||
<span>总收入</span>
|
<span>网站收入 (USD)</span>
|
||||||
<span class="metric-icon income"><TrendingUp :size="18" /></span>
|
<span class="metric-icon income"><TrendingUp :size="18" /></span>
|
||||||
</div>
|
</div>
|
||||||
<strong>{{ formatAmount(summary.total_revenue) }}</strong>
|
<strong>{{ formatAmount(summary.total_revenue) }}</strong>
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="metric-card">
|
<div class="metric-card">
|
||||||
<div class="metric-head">
|
<div class="metric-head">
|
||||||
<span>总消费</span>
|
<span>上游消费 (USD)</span>
|
||||||
<span class="metric-icon cost"><ReceiptText :size="18" /></span>
|
<span class="metric-icon cost"><ReceiptText :size="18" /></span>
|
||||||
</div>
|
</div>
|
||||||
<strong>{{ formatAmount(summary.total_cost) }}</strong>
|
<strong>{{ formatAmount(summary.total_cost) }}</strong>
|
||||||
@@ -88,7 +88,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="metric-card">
|
<div class="metric-card">
|
||||||
<div class="metric-head">
|
<div class="metric-head">
|
||||||
<span>净收入</span>
|
<span>净收入 (USD)</span>
|
||||||
<span class="metric-icon net"><WalletCards :size="18" /></span>
|
<span class="metric-icon net"><WalletCards :size="18" /></span>
|
||||||
</div>
|
</div>
|
||||||
<strong :class="summary.net_income >= 0 ? 'positive' : 'negative'">
|
<strong :class="summary.net_income >= 0 ? 'positive' : 'negative'">
|
||||||
@@ -98,7 +98,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="metric-card">
|
<div class="metric-card">
|
||||||
<div class="metric-head">
|
<div class="metric-head">
|
||||||
<span>{{ summary.partial ? '部分汇总' : '失败项' }}</span>
|
<span>{{ summary.partial ? '部分汇总' : '失败项(项)' }}</span>
|
||||||
<span class="metric-icon risk"><BadgeAlert :size="18" /></span>
|
<span class="metric-icon risk"><BadgeAlert :size="18" /></span>
|
||||||
</div>
|
</div>
|
||||||
<strong :class="summary.failed_count > 0 || summary.partial ? 'negative' : ''">
|
<strong :class="summary.failed_count > 0 || summary.partial ? 'negative' : ''">
|
||||||
@@ -134,30 +134,14 @@
|
|||||||
<section class="dashboard-panel detail-panel">
|
<section class="dashboard-panel detail-panel">
|
||||||
<div class="panel-header detail-header">
|
<div class="panel-header detail-header">
|
||||||
<div>
|
<div>
|
||||||
<h2>收入 / 消费明细</h2>
|
<h2><span class="panel-dot amber" />网站收入明细</h2>
|
||||||
<p>{{ filteredWebsiteItems.length }} 个收入项,{{ filteredUpstreamItems.length }} 个消费项</p>
|
<p>{{ filteredWebsiteItems.length }} 个收入项</p>
|
||||||
</div>
|
|
||||||
<div class="table-tabs">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
:class="{ active: activeTable === 'websites' }"
|
|
||||||
@click="activeTable = 'websites'"
|
|
||||||
>
|
|
||||||
收入
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
:class="{ active: activeTable === 'upstreams' }"
|
|
||||||
@click="activeTable = 'upstreams'"
|
|
||||||
>
|
|
||||||
消费
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
<span class="success-pill">{{ filteredWebsiteItems.filter(i => i.status === 'success').length }}/{{ filteredWebsiteItems.length }} 成功</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="table-wrap">
|
<div class="table-wrap">
|
||||||
<el-table
|
<el-table
|
||||||
v-if="activeTable === 'websites'"
|
|
||||||
:data="filteredWebsiteItems"
|
:data="filteredWebsiteItems"
|
||||||
class="finance-table"
|
class="finance-table"
|
||||||
empty-text="暂无收入明细"
|
empty-text="暂无收入明细"
|
||||||
@@ -182,9 +166,20 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="dashboard-panel detail-panel">
|
||||||
|
<div class="panel-header detail-header">
|
||||||
|
<div>
|
||||||
|
<h2><span class="panel-dot amber" />上游消费明细</h2>
|
||||||
|
<p>{{ filteredUpstreamItems.length }} 个消费项</p>
|
||||||
|
</div>
|
||||||
|
<span class="success-pill">{{ filteredUpstreamItems.filter(i => i.status === 'success').length }}/{{ filteredUpstreamItems.length }} 成功</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="table-wrap">
|
||||||
<el-table
|
<el-table
|
||||||
v-else
|
|
||||||
:data="filteredUpstreamItems"
|
:data="filteredUpstreamItems"
|
||||||
class="finance-table"
|
class="finance-table"
|
||||||
empty-text="暂无消费明细"
|
empty-text="暂无消费明细"
|
||||||
@@ -398,9 +393,9 @@ interface CompareResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const periodOptions: Array<{ value: Period; label: string }> = [
|
const periodOptions: Array<{ value: Period; label: string }> = [
|
||||||
{ value: 'day', label: '日' },
|
{ value: 'day', label: '按日查询' },
|
||||||
{ value: 'week', label: '周' },
|
{ value: 'week', label: '按周查询' },
|
||||||
{ value: 'month', label: '月' },
|
{ value: 'month', label: '按月查询' },
|
||||||
]
|
]
|
||||||
|
|
||||||
const period = ref<Period>('day')
|
const period = ref<Period>('day')
|
||||||
@@ -411,7 +406,6 @@ const comparing = ref(false)
|
|||||||
const overwriting = ref(false)
|
const overwriting = ref(false)
|
||||||
const fetchError = ref<string | null>(null)
|
const fetchError = ref<string | null>(null)
|
||||||
const summary = ref<FinanceSummary | null>(null)
|
const summary = ref<FinanceSummary | null>(null)
|
||||||
const activeTable = ref<'websites' | 'upstreams'>('websites')
|
|
||||||
const compareDialogVisible = ref(false)
|
const compareDialogVisible = ref(false)
|
||||||
const compareResult = ref<CompareResponse | null>(null)
|
const compareResult = ref<CompareResponse | null>(null)
|
||||||
|
|
||||||
@@ -572,56 +566,56 @@ function renderTrendChart() {
|
|||||||
trendChart ??= echarts.init(trendChartRef.value)
|
trendChart ??= echarts.init(trendChartRef.value)
|
||||||
const labels = summary.value.chart.labels.map(label => label.slice(5))
|
const labels = summary.value.chart.labels.map(label => label.slice(5))
|
||||||
trendChart.setOption({
|
trendChart.setOption({
|
||||||
color: ['#22a884', '#f08a05'],
|
color: ['#f4a01f', '#ff4d4f'],
|
||||||
grid: { left: 10, right: 18, top: 28, bottom: 10, containLabel: true },
|
grid: { left: 10, right: 20, top: 34, bottom: 12, containLabel: true },
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
backgroundColor: '#ffffff',
|
backgroundColor: '#17110f',
|
||||||
borderColor: '#dbe4ef',
|
borderColor: 'rgba(245, 158, 11, 0.35)',
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
textStyle: { color: '#142033', fontSize: 12 },
|
textStyle: { color: '#f5ede5', fontSize: 12 },
|
||||||
valueFormatter: (value: number) => formatAmount(value),
|
valueFormatter: (value: number) => formatAmount(value),
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
top: 0,
|
top: 0,
|
||||||
right: 0,
|
left: 'center',
|
||||||
icon: 'circle',
|
icon: 'rect',
|
||||||
itemWidth: 9,
|
itemWidth: 32,
|
||||||
itemHeight: 9,
|
itemHeight: 8,
|
||||||
textStyle: { color: '#65758b', fontSize: 12, fontWeight: 600 },
|
textStyle: { color: '#8f7c6d', fontSize: 12, fontWeight: 700 },
|
||||||
data: ['收入', '消费'],
|
data: ['网站总收入 (USD)', '上游总消费 (USD)'],
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'category',
|
type: 'category',
|
||||||
boundaryGap: false,
|
boundaryGap: false,
|
||||||
data: labels,
|
data: labels,
|
||||||
axisLine: { lineStyle: { color: '#e8eef6' } },
|
axisLine: { lineStyle: { color: 'rgba(218, 183, 142, 0.14)' } },
|
||||||
axisTick: { show: false },
|
axisTick: { show: false },
|
||||||
axisLabel: { color: '#73839a', fontSize: 12 },
|
axisLabel: { color: '#74665b', fontSize: 12 },
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
axisLabel: { color: '#73839a', fontSize: 12, formatter: (value: number) => `$${value}` },
|
axisLabel: { color: '#74665b', fontSize: 12, formatter: (value: number) => `${value}` },
|
||||||
splitLine: { lineStyle: { color: '#edf2f7' } },
|
splitLine: { lineStyle: { color: 'rgba(218, 183, 142, 0.10)' } },
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: '收入',
|
name: '网站总收入 (USD)',
|
||||||
type: 'line',
|
type: 'line',
|
||||||
smooth: true,
|
smooth: true,
|
||||||
symbolSize: 7,
|
symbolSize: 7,
|
||||||
data: summary.value.chart.revenue,
|
data: summary.value.chart.revenue,
|
||||||
areaStyle: { color: 'rgba(34, 168, 132, 0.12)' },
|
areaStyle: { color: 'rgba(244, 160, 31, 0.18)' },
|
||||||
lineStyle: { width: 3 },
|
lineStyle: { width: 2.5 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '消费',
|
name: '上游总消费 (USD)',
|
||||||
type: 'line',
|
type: 'line',
|
||||||
smooth: true,
|
smooth: true,
|
||||||
symbolSize: 7,
|
symbolSize: 7,
|
||||||
data: summary.value.chart.cost,
|
data: summary.value.chart.cost,
|
||||||
areaStyle: { color: 'rgba(240, 138, 5, 0.11)' },
|
areaStyle: { color: 'rgba(255, 77, 79, 0.16)' },
|
||||||
lineStyle: { width: 3 },
|
lineStyle: { width: 2.5 },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
@@ -634,13 +628,13 @@ function renderShareChart() {
|
|||||||
.filter(item => item.amount > 0)
|
.filter(item => item.amount > 0)
|
||||||
.map(item => ({ name: item.name, value: Number(item.amount.toFixed(6)) }))
|
.map(item => ({ name: item.name, value: Number(item.amount.toFixed(6)) }))
|
||||||
shareChart.setOption({
|
shareChart.setOption({
|
||||||
color: ['#22a884', '#2f69e8', '#e87d04', '#9b42e8', '#dc4b4b', '#0b9bb0'],
|
color: ['#f4a01f', '#ff4d4f', '#3b82f6', '#10b981', '#a855f7', '#06b6d4'],
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'item',
|
trigger: 'item',
|
||||||
backgroundColor: '#ffffff',
|
backgroundColor: '#17110f',
|
||||||
borderColor: '#dbe4ef',
|
borderColor: 'rgba(245, 158, 11, 0.35)',
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
textStyle: { color: '#142033', fontSize: 12 },
|
textStyle: { color: '#f5ede5', fontSize: 12 },
|
||||||
formatter: (params: any) => `${params.name}<br/>${formatAmount(params.value)} (${params.percent}%)`,
|
formatter: (params: any) => `${params.name}<br/>${formatAmount(params.value)} (${params.percent}%)`,
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
@@ -649,20 +643,20 @@ function renderShareChart() {
|
|||||||
icon: 'circle',
|
icon: 'circle',
|
||||||
itemWidth: 9,
|
itemWidth: 9,
|
||||||
itemHeight: 9,
|
itemHeight: 9,
|
||||||
textStyle: { color: '#65758b', fontSize: 12, fontWeight: 600 },
|
textStyle: { color: '#a99583', fontSize: 12, fontWeight: 700 },
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: '上游消费',
|
name: '上游消费',
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
radius: ['52%', '72%'],
|
radius: ['48%', '70%'],
|
||||||
center: ['50%', '42%'],
|
center: ['50%', '42%'],
|
||||||
avoidLabelOverlap: true,
|
avoidLabelOverlap: true,
|
||||||
minAngle: 4,
|
minAngle: 4,
|
||||||
label: {
|
label: {
|
||||||
color: '#536276',
|
color: '#a99583',
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: 600,
|
fontWeight: 700,
|
||||||
formatter: '{b}\n{d}%',
|
formatter: '{b}\n{d}%',
|
||||||
},
|
},
|
||||||
labelLine: {
|
labelLine: {
|
||||||
@@ -671,10 +665,10 @@ function renderShareChart() {
|
|||||||
lineStyle: { width: 1.4 },
|
lineStyle: { width: 1.4 },
|
||||||
},
|
},
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
borderColor: '#fff',
|
borderColor: '#120d0b',
|
||||||
borderWidth: 3,
|
borderWidth: 3,
|
||||||
},
|
},
|
||||||
data: data.length ? data : [{ name: '暂无消费', value: 1, itemStyle: { color: '#e2e8f0' } }],
|
data: data.length ? data : [{ name: '暂无消费', value: 1, itemStyle: { color: '#2a201b' } }],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
@@ -772,18 +766,20 @@ onBeforeUnmount(() => {
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.finance-page {
|
.finance-page {
|
||||||
--finance-bg: #eef3f8;
|
--finance-bg: #0f0b09;
|
||||||
--finance-card: #ffffff;
|
--finance-panel: #15100e;
|
||||||
--finance-card-soft: #f8fafd;
|
--finance-panel-soft: #1b1411;
|
||||||
--finance-border: #dce5ef;
|
--finance-border: rgba(217, 139, 66, 0.16);
|
||||||
--finance-border-strong: #c7d3e1;
|
--finance-border-strong: rgba(245, 158, 11, 0.4);
|
||||||
--finance-text: #142033;
|
--finance-text: #f8efe6;
|
||||||
--finance-muted: #65758b;
|
--finance-muted: #a99787;
|
||||||
--finance-soft: #9aa8ba;
|
--finance-soft: #74675d;
|
||||||
--finance-green: #22a884;
|
--finance-card-text: #061329;
|
||||||
--finance-orange: #e87d04;
|
--finance-amber: #f59e0b;
|
||||||
--finance-blue: #2f69e8;
|
--finance-amber-soft: rgba(245, 158, 11, 0.16);
|
||||||
--finance-red: #ef5b61;
|
--finance-green: #10c985;
|
||||||
|
--finance-red: #ff4d4f;
|
||||||
|
--finance-blue: #3b82f6;
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
color: var(--finance-text);
|
color: var(--finance-text);
|
||||||
@@ -792,72 +788,60 @@ onBeforeUnmount(() => {
|
|||||||
|
|
||||||
.finance-shell {
|
.finance-shell {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 16px;
|
gap: 30px;
|
||||||
max-width: 1504px;
|
max-width: 1480px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 16px;
|
|
||||||
border: 1px solid rgba(221, 230, 240, 0.96);
|
|
||||||
border-radius: 18px;
|
|
||||||
background:
|
|
||||||
linear-gradient(180deg, rgba(255, 255, 255, 0.55), transparent 56px),
|
|
||||||
var(--finance-bg);
|
|
||||||
box-shadow:
|
|
||||||
0 24px 70px rgba(10, 16, 28, 0.28),
|
|
||||||
inset 0 1px 0 rgba(255, 255, 255, 0.86);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.finance-topbar,
|
.finance-topbar,
|
||||||
.dashboard-panel,
|
.dashboard-panel,
|
||||||
.metric-card,
|
|
||||||
.loading-panel,
|
.loading-panel,
|
||||||
.empty-state {
|
.empty-state {
|
||||||
background: var(--finance-card);
|
background:
|
||||||
|
linear-gradient(180deg, rgba(255, 244, 232, 0.025), transparent 42%),
|
||||||
|
var(--finance-panel);
|
||||||
border: 1px solid var(--finance-border);
|
border: 1px solid var(--finance-border);
|
||||||
border-radius: 8px;
|
border-radius: 16px;
|
||||||
box-shadow: 0 8px 20px rgba(30, 43, 62, 0.045);
|
box-shadow: inset 0 1px 0 rgba(255, 244, 232, 0.035);
|
||||||
}
|
}
|
||||||
|
|
||||||
.finance-topbar {
|
.finance-topbar {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 12px;
|
gap: 16px;
|
||||||
min-height: 66px;
|
min-height: 96px;
|
||||||
padding: 12px;
|
padding: 20px 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.period-tabs,
|
.period-tabs {
|
||||||
.table-tabs {
|
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: 8px;
|
||||||
padding: 4px;
|
padding: 6px;
|
||||||
border-radius: 8px;
|
border: 1px solid rgba(217, 139, 66, 0.12);
|
||||||
background: #e7edf5;
|
border-radius: 12px;
|
||||||
border: 1px solid var(--finance-border);
|
background: rgba(8, 6, 5, 0.72);
|
||||||
box-shadow: inset 0 1px 2px rgba(20, 32, 51, 0.04);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.period-tab,
|
.period-tab {
|
||||||
.table-tabs button {
|
min-width: 128px;
|
||||||
min-width: 54px;
|
height: 42px;
|
||||||
height: 34px;
|
|
||||||
padding: 0 18px;
|
padding: 0 18px;
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: 6px;
|
border-radius: 9px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: var(--finance-muted);
|
color: #a99583;
|
||||||
font-weight: 700;
|
font-weight: 800;
|
||||||
line-height: 34px;
|
line-height: 42px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background-color 180ms ease, color 180ms ease, box-shadow 180ms ease;
|
transition: background-color 180ms ease, color 180ms ease, box-shadow 180ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.period-tab.active,
|
.period-tab.active {
|
||||||
.table-tabs button.active {
|
color: #2a1708;
|
||||||
color: var(--finance-text);
|
background: linear-gradient(135deg, #f3a321, #f59e0b);
|
||||||
background: #fff;
|
box-shadow: 0 10px 24px rgba(245, 158, 11, 0.22);
|
||||||
box-shadow: 0 1px 4px rgba(20, 32, 51, 0.13);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar-actions {
|
.toolbar-actions {
|
||||||
@@ -865,62 +849,66 @@ onBeforeUnmount(() => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 9px;
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-input {
|
.search-input {
|
||||||
width: 232px;
|
width: 310px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.date-picker {
|
.date-picker {
|
||||||
width: 190px;
|
width: 230px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-button {
|
.icon-button {
|
||||||
min-height: 38px;
|
min-height: 42px;
|
||||||
padding-inline: 15px;
|
padding-inline: 18px;
|
||||||
border-radius: 8px;
|
border-radius: 12px;
|
||||||
font-weight: 700;
|
font-weight: 800;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-button :deep(svg) {
|
.icon-button :deep(svg) {
|
||||||
margin-right: 6px;
|
margin-right: 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.compare-button {
|
.compare-button {
|
||||||
color: #fff6ec;
|
color: #1d1108;
|
||||||
box-shadow: 0 8px 18px rgba(232, 125, 4, 0.24);
|
box-shadow: 0 12px 26px rgba(245, 158, 11, 0.22);
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-alert {
|
.page-alert {
|
||||||
border-radius: 8px;
|
border-radius: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.metrics-grid {
|
.metrics-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
gap: 14px;
|
gap: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric-card {
|
.metric-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: 120px;
|
min-height: 166px;
|
||||||
padding: 17px 18px 16px;
|
padding: 28px 30px 24px;
|
||||||
display: grid;
|
display: grid;
|
||||||
align-content: space-between;
|
align-content: space-between;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
background: #fffdf9;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.72);
|
||||||
|
border-radius: 16px;
|
||||||
|
box-shadow: 0 18px 38px rgba(0, 0, 0, 0.16);
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric-card::after {
|
.metric-card::after {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 24px;
|
right: 30px;
|
||||||
bottom: 18px;
|
bottom: 25px;
|
||||||
width: 38px;
|
width: 48px;
|
||||||
height: 38px;
|
height: 48px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: radial-gradient(circle, rgba(232, 125, 4, 0.13), transparent 68%);
|
background: radial-gradient(circle, rgba(245, 158, 11, 0.18), transparent 68%);
|
||||||
filter: blur(2px);
|
filter: blur(2px);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
@@ -930,52 +918,52 @@ onBeforeUnmount(() => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
color: var(--finance-muted);
|
color: #42516a;
|
||||||
font-size: 12px;
|
font-size: 14px;
|
||||||
font-weight: 700;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric-icon {
|
.metric-icon {
|
||||||
width: 31px;
|
width: 36px;
|
||||||
height: 31px;
|
height: 36px;
|
||||||
display: inline-grid;
|
display: inline-grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border-radius: 8px;
|
border-radius: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric-icon.income {
|
.metric-icon.income {
|
||||||
color: var(--finance-green);
|
color: #d98b00;
|
||||||
background: rgba(31, 157, 122, 0.1);
|
background: rgba(245, 158, 11, 0.14);
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric-icon.cost {
|
.metric-icon.cost {
|
||||||
color: var(--finance-orange);
|
color: var(--finance-red);
|
||||||
background: rgba(217, 119, 6, 0.12);
|
background: rgba(255, 77, 79, 0.10);
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric-icon.net {
|
.metric-icon.net {
|
||||||
color: var(--finance-blue);
|
color: var(--finance-green);
|
||||||
background: rgba(37, 99, 235, 0.1);
|
background: rgba(16, 201, 133, 0.11);
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric-icon.risk {
|
.metric-icon.risk {
|
||||||
color: var(--finance-red);
|
color: #6f7480;
|
||||||
background: rgba(220, 38, 38, 0.1);
|
background: #f4f4f6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric-card strong {
|
.metric-card strong {
|
||||||
color: var(--finance-text);
|
color: var(--finance-card-text);
|
||||||
font-family: "JetBrains Mono", Consolas, monospace;
|
font-family: "JetBrains Mono", Consolas, monospace;
|
||||||
font-size: 30px;
|
font-size: 32px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
line-height: 1.12;
|
line-height: 1.08;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric-card small {
|
.metric-card small {
|
||||||
color: var(--finance-muted);
|
color: #7a8597;
|
||||||
font-size: 12px;
|
font-size: 13px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -989,12 +977,12 @@ onBeforeUnmount(() => {
|
|||||||
|
|
||||||
.chart-grid {
|
.chart-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(0, 1.74fr) minmax(340px, 0.82fr);
|
grid-template-columns: minmax(0, 2.1fr) minmax(340px, 1fr);
|
||||||
gap: 14px;
|
gap: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-panel {
|
.dashboard-panel {
|
||||||
padding: 18px;
|
padding: 28px 30px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1002,33 +990,50 @@ onBeforeUnmount(() => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 14px;
|
gap: 16px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-header h2 {
|
.panel-header h2 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
color: var(--finance-text);
|
color: var(--finance-text);
|
||||||
font-size: 17px;
|
font-size: 18px;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
font-weight: 800;
|
font-weight: 900;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-header p {
|
.panel-header p {
|
||||||
margin: 5px 0 0;
|
margin: 9px 0 0;
|
||||||
color: var(--finance-muted);
|
color: #817166;
|
||||||
font-size: 12px;
|
font-size: 13px;
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-chip {
|
.panel-dot {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
vertical-align: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-dot.amber {
|
||||||
|
background: var(--finance-amber);
|
||||||
|
box-shadow: 0 0 16px rgba(245, 158, 11, 0.42);
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-chip,
|
||||||
|
.success-pill {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
padding: 5px 9px;
|
min-height: 26px;
|
||||||
|
padding: 4px 10px;
|
||||||
|
border: 1px solid rgba(16, 201, 133, 0.22);
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #eef3f8;
|
background: rgba(16, 201, 133, 0.12);
|
||||||
color: var(--finance-muted);
|
color: var(--finance-green);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 700;
|
font-weight: 900;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chart {
|
.chart {
|
||||||
@@ -1036,23 +1041,23 @@ onBeforeUnmount(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.trend-chart {
|
.trend-chart {
|
||||||
height: 314px;
|
height: 280px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-chart {
|
.share-chart {
|
||||||
height: 314px;
|
height: 280px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-header {
|
.detail-header {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
padding-bottom: 18px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
border-bottom: 1px solid rgba(217, 139, 66, 0.14);
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-wrap {
|
.table-wrap {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
border: 1px solid var(--finance-border);
|
|
||||||
border-radius: 8px;
|
|
||||||
background: #fff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.finance-table {
|
.finance-table {
|
||||||
@@ -1070,26 +1075,26 @@ onBeforeUnmount(() => {
|
|||||||
.amount.income,
|
.amount.income,
|
||||||
.diff-new {
|
.diff-new {
|
||||||
color: var(--finance-green);
|
color: var(--finance-green);
|
||||||
font-weight: 800;
|
font-weight: 900;
|
||||||
}
|
}
|
||||||
|
|
||||||
.amount.cost {
|
.amount.cost {
|
||||||
color: var(--finance-orange);
|
color: var(--finance-amber);
|
||||||
font-weight: 800;
|
font-weight: 900;
|
||||||
}
|
}
|
||||||
|
|
||||||
.diff-old {
|
.diff-old,
|
||||||
|
.error-text {
|
||||||
color: var(--finance-red);
|
color: var(--finance-red);
|
||||||
}
|
}
|
||||||
|
|
||||||
.error-text {
|
.error-text {
|
||||||
color: var(--finance-red);
|
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
.muted-text {
|
.muted-text {
|
||||||
color: var(--finance-soft);
|
color: #72645a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-state,
|
.empty-state,
|
||||||
@@ -1110,8 +1115,8 @@ onBeforeUnmount(() => {
|
|||||||
.compare-card {
|
.compare-card {
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
border: 1px solid var(--finance-border);
|
border: 1px solid var(--finance-border);
|
||||||
border-radius: 8px;
|
border-radius: 12px;
|
||||||
background: #fff;
|
background: var(--finance-panel-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
.compare-card h3,
|
.compare-card h3,
|
||||||
@@ -1149,123 +1154,126 @@ onBeforeUnmount(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.finance-page :deep(.el-input__wrapper) {
|
.finance-page :deep(.el-input__wrapper) {
|
||||||
min-height: 38px;
|
min-height: 42px;
|
||||||
border-radius: 8px;
|
border-radius: 12px;
|
||||||
background: #fff;
|
background: rgba(6, 5, 4, 0.72) !important;
|
||||||
box-shadow: 0 0 0 1px #e7dde5 inset !important;
|
box-shadow: 0 0 0 1px rgba(217, 139, 66, 0.22) inset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.finance-page :deep(.el-input__wrapper:hover),
|
.finance-page :deep(.el-input__wrapper:hover),
|
||||||
.finance-page :deep(.el-input__wrapper.is-focus) {
|
.finance-page :deep(.el-input__wrapper.is-focus) {
|
||||||
box-shadow: 0 0 0 1px var(--finance-border-strong) inset, 0 0 0 3px rgba(232, 125, 4, 0.06) !important;
|
box-shadow: 0 0 0 1px rgba(245, 158, 11, 0.52) inset, 0 0 0 3px rgba(245, 158, 11, 0.08) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.finance-page :deep(.el-input__inner) {
|
.finance-page :deep(.el-input__inner) {
|
||||||
color: var(--finance-text) !important;
|
color: var(--finance-text) !important;
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
.finance-page :deep(.el-input__inner::placeholder),
|
.finance-page :deep(.el-input__inner::placeholder),
|
||||||
.finance-page :deep(.el-input__prefix) {
|
.finance-page :deep(.el-input__prefix),
|
||||||
color: var(--finance-soft);
|
.finance-page :deep(.el-input__suffix) {
|
||||||
|
color: #75675d;
|
||||||
}
|
}
|
||||||
|
|
||||||
.finance-page :deep(.el-button--primary) {
|
.finance-page :deep(.el-button--primary) {
|
||||||
--el-button-bg-color: #ee9b45;
|
--el-button-bg-color: #f59e0b;
|
||||||
--el-button-border-color: #ee9b45;
|
--el-button-border-color: #f59e0b;
|
||||||
--el-button-hover-bg-color: #f0a85a;
|
--el-button-hover-bg-color: #f7ad2d;
|
||||||
--el-button-hover-border-color: #f0a85a;
|
--el-button-hover-border-color: #f7ad2d;
|
||||||
--el-button-active-bg-color: #e2862c;
|
--el-button-active-bg-color: #df8704;
|
||||||
--el-button-active-border-color: #e2862c;
|
--el-button-active-border-color: #df8704;
|
||||||
|
--el-button-text-color: #211205;
|
||||||
transform: none;
|
transform: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.finance-page :deep(.el-button:not(.el-button--primary)) {
|
.finance-page :deep(.el-button:not(.el-button--primary)) {
|
||||||
--el-button-bg-color: #fff;
|
--el-button-bg-color: rgba(255, 255, 255, 0.08);
|
||||||
--el-button-border-color: var(--finance-border);
|
--el-button-border-color: rgba(255, 255, 255, 0.18);
|
||||||
--el-button-text-color: var(--finance-text);
|
--el-button-text-color: #f5ede5;
|
||||||
--el-button-hover-bg-color: #f8fafc;
|
--el-button-hover-bg-color: rgba(255, 255, 255, 0.13);
|
||||||
--el-button-hover-border-color: var(--finance-border-strong);
|
--el-button-hover-border-color: rgba(255, 255, 255, 0.28);
|
||||||
--el-button-hover-text-color: var(--finance-text);
|
--el-button-hover-text-color: #ffffff;
|
||||||
transform: none;
|
transform: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.finance-page :deep(.el-table) {
|
.finance-page :deep(.el-table) {
|
||||||
--el-table-bg-color: #fff;
|
--el-table-bg-color: transparent;
|
||||||
--el-table-tr-bg-color: #fff;
|
--el-table-tr-bg-color: transparent;
|
||||||
--el-table-header-bg-color: #f8fafc;
|
--el-table-header-bg-color: rgba(255, 244, 232, 0.02);
|
||||||
--el-table-header-text-color: #475569;
|
--el-table-header-text-color: #83756b;
|
||||||
--el-table-text-color: var(--finance-text);
|
--el-table-text-color: var(--finance-text);
|
||||||
--el-table-row-hover-bg-color: #f8fafc;
|
--el-table-row-hover-bg-color: rgba(255, 244, 232, 0.025);
|
||||||
--el-table-border-color: var(--finance-border);
|
--el-table-border-color: rgba(217, 139, 66, 0.12);
|
||||||
border-radius: 8px;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.finance-page :deep(.el-table th.el-table__cell) {
|
.finance-page :deep(.el-table th.el-table__cell) {
|
||||||
background: #f8fafc;
|
background: rgba(255, 244, 232, 0.025);
|
||||||
color: #506179;
|
color: #83756b;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 800;
|
font-weight: 900;
|
||||||
}
|
}
|
||||||
|
|
||||||
.finance-page :deep(.el-table td.el-table__cell) {
|
.finance-page :deep(.el-table td.el-table__cell) {
|
||||||
border-bottom-color: #eef2f7;
|
border-bottom-color: rgba(217, 139, 66, 0.10);
|
||||||
padding-top: 13px;
|
padding-top: 17px;
|
||||||
padding-bottom: 13px;
|
padding-bottom: 17px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.finance-page :deep(.el-table__inner-wrapper::before),
|
.finance-page :deep(.el-table__inner-wrapper::before),
|
||||||
.finance-page :deep(.el-table__border-left-patch) {
|
.finance-page :deep(.el-table__border-left-patch) {
|
||||||
background: var(--finance-border);
|
background: rgba(217, 139, 66, 0.12);
|
||||||
}
|
}
|
||||||
|
|
||||||
.finance-page :deep(.el-tag) {
|
.finance-page :deep(.el-tag) {
|
||||||
border-radius: 4px;
|
border-radius: 999px;
|
||||||
font-weight: 800;
|
font-weight: 900;
|
||||||
padding-inline: 8px;
|
padding-inline: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.finance-page :deep(.el-tag--success) {
|
.finance-page :deep(.el-tag--success) {
|
||||||
--el-tag-bg-color: #edf9e9;
|
--el-tag-bg-color: rgba(16, 201, 133, 0.12);
|
||||||
--el-tag-border-color: #edf9e9;
|
--el-tag-border-color: rgba(16, 201, 133, 0.22);
|
||||||
--el-tag-text-color: #42aa35;
|
--el-tag-text-color: var(--finance-green);
|
||||||
}
|
}
|
||||||
|
|
||||||
.finance-page :deep(.el-tag--primary) {
|
.finance-page :deep(.el-tag--primary) {
|
||||||
--el-tag-bg-color: #e9f3ff;
|
--el-tag-bg-color: rgba(59, 130, 246, 0.14);
|
||||||
--el-tag-border-color: #e9f3ff;
|
--el-tag-border-color: rgba(59, 130, 246, 0.28);
|
||||||
--el-tag-text-color: #4d9cff;
|
--el-tag-text-color: #4ea1ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.finance-page :deep(.el-tag--warning) {
|
.finance-page :deep(.el-tag--warning) {
|
||||||
--el-tag-bg-color: #fff4e2;
|
--el-tag-bg-color: rgba(245, 158, 11, 0.12);
|
||||||
--el-tag-border-color: #fff4e2;
|
--el-tag-border-color: rgba(245, 158, 11, 0.28);
|
||||||
--el-tag-text-color: #e3912d;
|
--el-tag-text-color: var(--finance-amber);
|
||||||
}
|
}
|
||||||
|
|
||||||
.finance-page :deep(.el-tag--danger) {
|
.finance-page :deep(.el-tag--danger) {
|
||||||
--el-tag-bg-color: #fff0f0;
|
--el-tag-bg-color: rgba(255, 77, 79, 0.12);
|
||||||
--el-tag-border-color: #fff0f0;
|
--el-tag-border-color: rgba(255, 77, 79, 0.24);
|
||||||
--el-tag-text-color: var(--finance-red);
|
--el-tag-text-color: var(--finance-red);
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.finance-compare-dialog) {
|
:global(.finance-compare-dialog) {
|
||||||
--el-dialog-bg-color: #fff;
|
--el-dialog-bg-color: #15100e;
|
||||||
--el-text-color-primary: #0f172a;
|
--el-text-color-primary: #f8efe6;
|
||||||
--el-text-color-regular: #0f172a;
|
--el-text-color-regular: #f8efe6;
|
||||||
border-radius: 8px;
|
border: 1px solid rgba(217, 139, 66, 0.16);
|
||||||
|
border-radius: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.finance-compare-dialog .el-dialog__body) {
|
:global(.finance-compare-dialog .el-dialog__body) {
|
||||||
color: #0f172a;
|
color: #f8efe6;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.finance-compare-dialog .el-table) {
|
:global(.finance-compare-dialog .el-table) {
|
||||||
--el-table-bg-color: #fff;
|
--el-table-bg-color: transparent;
|
||||||
--el-table-tr-bg-color: #fff;
|
--el-table-tr-bg-color: transparent;
|
||||||
--el-table-header-bg-color: #f8fafc;
|
--el-table-header-bg-color: rgba(255, 244, 232, 0.02);
|
||||||
--el-table-text-color: #0f172a;
|
--el-table-text-color: #f8efe6;
|
||||||
--el-table-border-color: #e2e8f0;
|
--el-table-border-color: rgba(217, 139, 66, 0.12);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1180px) {
|
@media (max-width: 1180px) {
|
||||||
@@ -1280,13 +1288,13 @@ onBeforeUnmount(() => {
|
|||||||
|
|
||||||
@media (max-width: 760px) {
|
@media (max-width: 760px) {
|
||||||
.finance-shell {
|
.finance-shell {
|
||||||
padding: 12px;
|
gap: 16px;
|
||||||
gap: 12px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.finance-topbar {
|
.finance-topbar {
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.period-tabs,
|
.period-tabs,
|
||||||
@@ -1297,8 +1305,13 @@ onBeforeUnmount(() => {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.period-tabs {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
.period-tab {
|
.period-tab {
|
||||||
flex: 1;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar-actions {
|
.toolbar-actions {
|
||||||
@@ -1311,7 +1324,7 @@ onBeforeUnmount(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.metric-card strong {
|
.metric-card strong {
|
||||||
font-size: 26px;
|
font-size: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-header,
|
.panel-header,
|
||||||
@@ -1321,14 +1334,6 @@ onBeforeUnmount(() => {
|
|||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-tabs {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-tabs button {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.finance-compare-dialog) {
|
:global(.finance-compare-dialog) {
|
||||||
width: calc(100vw - 24px) !important;
|
width: calc(100vw - 24px) !important;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user