From c0203df74a8da67761918bf9b85e7a71dd782fa1 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 25 八月 2026 14:11:55 +0800
Subject: [PATCH] pro 1.打开人力资源删除按钮
---
src/views/financialManagement/financialStatements/index.vue | 1065 +++++++++++++++++++++++++++++++++-------------------------
1 files changed, 603 insertions(+), 462 deletions(-)
diff --git a/src/views/financialManagement/financialStatements/index.vue b/src/views/financialManagement/financialStatements/index.vue
index e5f9b23..5dbce9b 100644
--- a/src/views/financialManagement/financialStatements/index.vue
+++ b/src/views/financialManagement/financialStatements/index.vue
@@ -1,507 +1,648 @@
- <template>
+<template>
<div style="padding: 20px;">
- <!-- 椤甸潰鏍囬鍜屾棩鏈熺瓫閫� -->
- <div class="w-full md:w-auto flex items-center gap-3" style="margin-bottom: 20px;">
- <el-date-picker
- v-model="dateRange"
- type="daterange"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- range-separator="鑷�"
- start-placeholder="寮�濮嬫棩鏈�"
- end-placeholder="缁撴潫鏃ユ湡"
- clearable
- @change="handleDateChange"
- class="w-full md:w-auto"
- style="margin-right: 30px;"
- />
-
- <el-button
- type="primary"
- icon="Refresh"
- @click="resetDateRange"
- size="default"
- >
+ <!-- 椤甸潰鏍囬鍜屾湀浠界瓫閫� -->
+ <div class="w-full md:w-auto flex items-center gap-3"
+ style="margin-bottom: 20px;">
+ <el-date-picker v-model="dateRange"
+ type="monthrange"
+ format="YYYY-MM"
+ value-format="YYYY-MM"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫湀浠�"
+ end-placeholder="缁撴潫鏈堜唤"
+ :disabled-date="disabledDate"
+ @change="handleDateChange"
+ class="w-full md:w-auto"
+ style="margin-right: 30px;" />
+ <el-button type="primary"
+ icon="Refresh"
+ @click="resetDateRange"
+ size="default">
閲嶇疆
</el-button>
</div>
-
<main class="container mx-auto px-4 pb-10">
<!-- 璐㈠姟鎸囨爣鍗$墖 -->
- <div class="grid-container">
- <!-- 鎬绘敹鍏� -->
- <el-card class="bg1">
- <p>鎬绘敹鍏�</p>
- <h3>
- 楼{{ pageInfo.totalIncome }}
- </h3>
- </el-card>
-
- <!-- 鏀跺叆绗旀暟 -->
- <el-card class="bg2">
- <p>鏀跺叆绗旀暟</p>
- <h3>
- {{ pageInfo.incomeNumber }}
- </h3>
- </el-card>
-
- <!-- 鎬绘敮鍑� -->
- <el-card class="bg3">
- <p>鎬绘敮鍑�</p>
- <h3>
- 楼{{ pageInfo.totalExpense }}
- </h3>
- </el-card>
-
- <!-- 鏀嚭绗旀暟 -->
- <el-card class="bg4">
- <p>鏀嚭绗旀暟</p>
- <h3>
- {{ pageInfo.expenseNumber }}
- </h3>
- </el-card>
-
- <!-- 鍑�鏀跺叆 -->
- <el-card class="bg5">
- <p>鍑�鏀跺叆</p>
- <h3>
- 楼{{ pageInfo.netRevenue }}
- </h3>
- </el-card>
+ <div class="stats-cards">
+ <div class="stat-card stat-card-blue">
+ <div class="stat-icon"><img src="@/assets/icons/png/walletBlue@2x.png"
+ alt="鎬昏惀鏀�" /></div>
+ <div class="stat-content">
+ <div class="stat-label">鎬昏惀鏀�</div>
+ <div class="stat-value">{{ formatMoney(pageInfo.totalIncome || 0) }}{{ Math.abs(pageInfo.totalIncome) < 10000 ? ' 鍏�' : '' }}</div>
+ </div>
+ </div>
+ <div class="stat-card stat-card-orange">
+ <div class="stat-icon"><img src="@/assets/icons/png/walletOrange@2x.png"
+ alt="鎬绘敮鍑�" /></div>
+ <div class="stat-content">
+ <div class="stat-label">鎬绘敮鍑�</div>
+ <div class="stat-value">{{ formatMoney(pageInfo.totalExpense || 0) }}{{ Math.abs(pageInfo.totalExpense) < 10000 ? ' 鍏�' : '' }}</div>
+ </div>
+ </div>
+ <div class="stat-card stat-card-green">
+ <div class="stat-icon"><img src="@/assets/icons/png/walletGreen@2x.png"
+ alt="搴旀敹璐︽" /></div>
+ <div class="stat-content">
+ <div class="stat-label">搴旀敹璐︽</div>
+ <div class="stat-value">{{ formatMoney(pageInfo.totalReceivable || 0) }}{{ Math.abs(pageInfo.totalReceivable) < 10000 ? ' 鍏�' : '' }}</div>
+ </div>
+ </div>
+ <div class="stat-card stat-card-red">
+ <div class="stat-icon"><img src="@/assets/icons/png/walletRed@2x.png"
+ alt="搴斾粯璐︽" /></div>
+ <div class="stat-content">
+ <div class="stat-label">搴斾粯璐︽</div>
+ <div class="stat-value">{{ formatMoney(pageInfo.totalPayable || 0) }}{{ Math.abs(pageInfo.totalPayable) < 10000 ? ' 鍏�' : '' }}</div>
+ </div>
+ </div>
+ <div class="stat-card stat-card-yellow">
+ <div class="stat-icon"><img src="@/assets/icons/png/walletYellow@2x.png"
+ alt="鍑�鍒╂鼎" /></div>
+ <div class="stat-content">
+ <div class="stat-label">鍑�鍒╂鼎</div>
+ <div class="stat-value">{{ formatMoney(pageInfo.netRevenue || 0) }}{{ Math.abs(pageInfo.netRevenue) < 10000 ? ' 鍏�' : '' }}</div>
+ </div>
+ </div>
</div>
-
- <!-- 鏀跺叆缁熻鍥捐〃 -->
- <div class="grid-layout">
- <el-card style="margin-bottom: 20px;">
- <h2 class="section-title">鏀跺叆缁熻(鍏�)</h2>
- <div class="echarts">
- <Echarts :legend="pieLegend0" :chartStyle="chartStylePie"
- :series="materialPieSeries0"
- :tooltip="pieTooltip" style="height: 260px;width: 35%;">
- <div class="chart-num">
- <span style="font-size: 22px;">鏀跺叆</span>
- <span style="font-size: 36px;
- font-weight: 500;
- font-family: 'MyCustomFont', sans-serif;">{{ pageInfo.totalIncome }}</span>
- </div>
- </Echarts>
- <Echarts ref="chart"
- :chartStyle="chartStyle"
- :grid="grid"
- :legend="lineLegend"
- :series="lineSeries0"
- :tooltip="tooltip"
- :xAxis="xAxis0"
- :yAxis="yAxis0"
- style="height: 260px;width: 64%;"></Echarts>
+ <!-- 鍥捐〃鍖哄煙 -->
+ <div class="charts-row">
+ <!-- 1. 鏀舵敮鏋勬垚鍒嗘瀽 (鍙岀幆褰㈠浘 + 鍑�鍒╀腑蹇�) -->
+ <el-card class="chart-card">
+ <template #header>
+ <div class="card-header">
+ <span class="header-title">鏀舵敮鏋勬垚鍙婂噣鍒╁垎鏋�</span>
+ <el-tooltip content="宸︿晶涓烘敹鍏ユ瀯鎴愶紝鍙充晶涓烘敮鍑烘瀯鎴愶紝涓棿灞曠ず鐩堜簭鍑�棰�"
+ placement="top">
+ <el-icon>
+ <QuestionFilled />
+ </el-icon>
+ </el-tooltip>
+ </div>
+ </template>
+ <div class="financial-overview-container">
+ <!-- 鏀跺叆灞曠ず (宸︿晶) -->
+ <div style="width:60%">
+ <div class="overview-item income"
+ style="margin-bottom: 20px;">
+ <div class="overview-box">
+ <div class="icon-circle">
+ <el-icon>
+ <TrendCharts />
+ </el-icon>
+ </div>
+ <div class="data-content">
+ <div class="label">鏈湡鎬绘敹鍏�</div>
+ <div class="value">{{ formatMoney(pageInfo.totalIncome) }}</div>
+ <div class="unit">RMB{{ Math.abs(pageInfo.totalIncome) < 10000 ? ' / 鍏�' : '' }}</div>
+ </div>
+ <div class="bg-decoration">INCOME</div>
+ </div>
+ </div>
+ <div class="overview-item expense">
+ <div class="overview-box">
+ <div class="icon-circle">
+ <el-icon>
+ <Sell />
+ </el-icon>
+ </div>
+ <div class="data-content">
+ <div class="label">鏈湡鎬绘敮鍑�</div>
+ <div class="value">{{ formatMoney(pageInfo.totalExpense) }}</div>
+ <div class="unit">RMB{{ Math.abs(pageInfo.totalExpense) < 10000 ? ' / 鍏�' : '' }}</div>
+ </div>
+ <div class="bg-decoration">EXPENSE</div>
+ </div>
+ </div>
+ </div>
+ <!-- 鍑�鍒╂鼎鏍稿績鎸囩ず (涓棿) -->
+ <div class="profit-indicator">
+ <div class="profit-gauge-wrapper">
+ <Echarts :chartStyle="chartStylePie"
+ :series="profitGaugeSeries"
+ :tooltip="gaugeTooltip"
+ style="height: 200px; width: 100%; max-width: 200px;">
+ </Echarts>
+ <div class="profit-center-text">
+ <div class="label">鍑�鍒╂鼎</div>
+ <div class="value"
+ :class="pageInfo.netRevenue >= 0 ? 'plus' : 'minus'">
+ {{ pageInfo.netRevenue >= 0 ? '+' : '' }}{{ formatMoney(pageInfo.netRevenue) }}
+ </div>
+ <div class="rate">鍒╂鼎鐜�: {{ pageInfo.totalIncome > 0 ? ((pageInfo.netRevenue / pageInfo.totalIncome) * 100).toFixed(1) : 0 }}%</div>
+ </div>
+ </div>
+ </div>
+ <!-- 鏀嚭灞曠ず (鍙充晶) -->
</div>
</el-card>
-
- <!-- 鏀嚭缁熻鍥捐〃 -->
- <el-card>
- <h2 class="section-title">鏀嚭缁熻(鍏�)</h2>
- <div class="echarts">
- <Echarts ref="chart"
- :legend="pieLegend1"
- :chartStyle="chartStylePie"
- :series="materialPieSeries1"
- :tooltip="pieTooltip"
- style="height: 260px;width: 35%;">
- <div class="chart-num">
- <span style="font-size: 22px;">鏀嚭</span>
- <span style="font-size: 36px;
- font-weight: 500;
- font-family: 'MyCustomFont', sans-serif;">{{ pageInfo.totalExpense }}</span>
- </div></Echarts>
- <Echarts ref="chart"
- :chartStyle="chartStyle"
- :grid="grid"
- :legend="lineLegend"
- :series="lineSeries1"
- :tooltip="tooltip"
- :xAxis="xAxis1"
- :yAxis="yAxis1"
- style="height: 260px;width: 64%;"></Echarts>
- </div>
+ <!-- 2. 搴旀敹/搴斾粯瀵瑰啿鍒嗘瀽 (鏌辩姸鍥�) -->
+ <el-card class="chart-card">
+ <template #header>
+ <div class="card-header">
+ <span class="header-title">搴旀敹/搴斾粯姒傝</span>
+ <el-tooltip content="瀵规瘮褰撳墠鍚勬湀浠界殑搴旀敹璐︽涓庡簲浠樿处娆�"
+ placement="top">
+ <el-icon>
+ <QuestionFilled />
+ </el-icon>
+ </el-tooltip>
+ </div>
+ </template>
+ <Echarts :chartStyle="chartStyle"
+ :grid="barGrid"
+ :legend="barLegend"
+ :series="barSeries"
+ :tooltip="barTooltip"
+ :xAxis="barXAxis"
+ :yAxis="barYAxis"
+ style="height: 270px; width: 100%;">
+ </Echarts>
</el-card>
</div>
+ <!-- 3. 璐㈠姟缁煎悎瓒嬪娍鍒嗘瀽 (鎶樼嚎鍥�) -->
+ <el-card class="trend-chart-card">
+ <template #header>
+ <div class="card-header">
+ <span class="header-title">璐㈠姟缁╂晥缁煎悎瓒嬪娍</span>
+ <el-tooltip content="灞曠ず鏀跺叆銆佹敮鍑哄強鍑�鍒╂鼎鐨勬湀搴﹀彉鍖栬秼鍔�"
+ placement="top">
+ <el-icon>
+ <QuestionFilled />
+ </el-icon>
+ </el-tooltip>
+ </div>
+ </template>
+ <Echarts :chartStyle="chartStyle"
+ :grid="trendGrid"
+ :legend="trendLegend"
+ :series="trendSeries"
+ :tooltip="trendTooltip"
+ :xAxis="trendXAxis"
+ :yAxis="trendYAxis"
+ style="height: 350px; width: 100%;">
+ </Echarts>
+ </el-card>
</main>
</div>
</template>
<script setup>
-import { ref, computed, onMounted, reactive } from 'vue';
-import 'element-plus/dist/index.css';
-import Echarts from "@/components/Echarts/echarts.vue";
-import { reportForms,reportIncome,reportExpense } from "@/api/financialManagement/financialStatements";
-import dayjs from "dayjs";
+ import {
+ ref,
+ computed,
+ onMounted,
+ reactive,
+ nextTick,
+ getCurrentInstance,
+ } from "vue";
+ import { QuestionFilled, TrendCharts, Sell } from "@element-plus/icons-vue";
+ import Echarts from "@/components/Echarts/echarts.vue";
+ import { accountStatementDetailsByMonth } from "@/api/financialManagement/financialStatements";
+ import dayjs from "dayjs";
-// 鏃ユ湡鑼冨洿
-const dateRange = ref(null);
-const chartStyle = {
- width: '100%',
- height: '100%', // 璁剧疆鍥捐〃瀹瑰櫒鐨勯珮搴�
- position:'relative',
-}
-const grid = {
- left: '3%',
- right: '4%',
- bottom: '3%',
- containLabel: true
-}
-const lineLegend = {
- show: false,
-}
-// 鎶樼嚎鍥炬彁绀烘
-const tooltip = reactive({
- trigger: 'axis',
- axisPointer: {
- type: 'line',
- lineStyle: { color: '#aaa' }
- },
- // 鑷畾涔夊唴瀹�
- formatter: function (params) {
- if (!params || !params.length) return ''
- const axisLabel = params[0].axisValueLabel || params[0].axisValue || ''
- const rows = params
- .map(p => {
- const colorDot = `<span style="display:inline-block;margin-right:6px;width:8px;height:8px;border-radius:50%;background:${p.color}"></span>`
- return `${colorDot}${p.seriesName}: ${p.value}`
- })
- .join('<br/>')
- return `<div>${axisLabel}</div><div>${rows}</div>`
- }
-})
-const months = ['1鏈�','2鏈�','3鏈�','4鏈�','5鏈�','6鏈�','7鏈�','8鏈�','9鏈�','10鏈�','11鏈�','12鏈�'];
-const lineSeries0 = ref([])
-const lineSeries1 = ref([])
+ const { proxy } = getCurrentInstance();
+ const dateRange = ref(null);
+ const pageInfo = reactive({
+ totalIncome: 0,
+ totalExpense: 0,
+ totalReceivable: 0,
+ totalPayable: 0,
+ netRevenue: 0,
+ });
-const xAxis0 = ref([
- {
- type: 'category',
- axisTick: { show: true, alignWithLabel: true },
- data: months,
- },
-]);
-const xAxis1 = ref([
- {
- type: 'category',
- axisTick: { show: true, alignWithLabel: true },
- data: months,
- },
-]);
-const yAxis0 = [
-{
- type: 'value',
- name: '鏀跺叆缁熻', // 宸︿晶y杞�
- position: 'left',
- min: 0,
- // 鍧愭爣杞村悕绉版牱寮�
- nameTextStyle: {
- color: '#000',
- fontSize: 14,
+ const chartStyle = { width: "100%", height: "100%", position: "relative" };
+ const chartStylePie = { width: "100%", height: "100%" };
+
+ const monthlyTrendList = ref([]);
+ const receivablePayableList = ref([]);
+
+ // --- 1. 鏀舵敮鏋勬垚鍒嗘瀽 (绠�鍖栫増閫昏緫) ---
+ const gaugeTooltip = { show: false };
+
+ const profitGaugeSeries = computed(() => {
+ const rate =
+ pageInfo.totalIncome > 0
+ ? (pageInfo.netRevenue / pageInfo.totalIncome) * 100
+ : 0;
+ return [
+ {
+ type: "gauge",
+ startAngle: 210,
+ endAngle: -30,
+ min: 0,
+ max: 100,
+ splitNumber: 10,
+ radius: "100%",
+ progress: {
+ show: true,
+ width: 14,
+ itemStyle: { color: pageInfo.netRevenue >= 0 ? "#10b981" : "#f43f5e" },
+ },
+ pointer: { show: false },
+ axisLine: { lineStyle: { width: 14, color: [[1, "#f1f5f9"]] } },
+ axisTick: { show: false },
+ splitLine: { show: false },
+ axisLabel: { show: false },
+ anchor: { show: false },
+ title: { show: false },
+ detail: { show: false },
+ data: [{ value: Math.max(0, Math.min(100, rate)) }],
+ },
+ ];
+ });
+
+ // --- 2. 搴旀敹/搴斾粯姒傝 (鏌辩姸鍥�) ---
+ const barGrid = { left: "3%", right: "4%", bottom: "3%", containLabel: true };
+ const barLegend = { top: "0", right: "center" };
+ const barXAxis = computed(() => [
+ {
+ type: "category",
+ data: receivablePayableList.value.map(item => item.month || ""),
+ axisTick: { alignWithLabel: true },
},
- }
-]
-
-const yAxis1 = [
-{
- type: 'value',
- name: '鏀嚭缁熻', // 宸︿晶y杞�
- position: 'left',
- min: 0,
- // 鍧愭爣杞村悕绉版牱寮�
- nameTextStyle: {
- color: '#000',
- fontSize: 14,
+ ]);
+ const barYAxis = [{ type: "value", name: "閲戦 (鍏�)" }];
+ const barTooltip = { trigger: "axis", axisPointer: { type: "shadow" } };
+ const barSeries = computed(() => [
+ {
+ name: "搴旀敹璐︽",
+ type: "bar",
+ barWidth: "30%",
+ data: receivablePayableList.value.map(item => item.receivable || 0),
+ itemStyle: { color: "#10b981" },
},
- }
-]
-
-const chartStylePie = {
- width: '100%',
- height: '100%' // 璁剧疆鍥捐〃瀹瑰櫒鐨勯珮搴�
-}
-const pieColors = ['#F04864','#FACC14', '#8543E0', '#1890FF', '#13C2C2','#2FC25B']; // 鍙牴鎹疄闄呰皟鏁�
-const pieData0 = ref([]);
-const pieData1 = ref([]);
-
-const pieLegend0 = computed(() => ({
- show: true,
- top: 'center',
- left: '60%',
- orient: 'vertical',
- icon: 'circle',
- data: pieData0.value.map(item => item.name),
- formatter: function(name) {
- const item = pieData0.value.find(i => i.name === name);
- if (!item) return name;
- return `${name} | ${item.percent} ${item.amount}`;
- },
- textStyle: {
- color: '#333',
- fontSize: 14,
- lineHeight: 26,
- }
-}));
-const pieLegend1 = computed(() => ({
- show: true,
- top: 'center',
- left: '60%',
- orient: 'vertical',
- icon: 'circle',
- data: pieData1.value.map(item => item.name),
- formatter: function(name) {
- const item = pieData1.value.find(i => i.name === name);
- if (!item) return name;
- return `${name} | ${item.percent} ${item.amount}`;
- },
- textStyle: {
- color: '#333',
- fontSize: 14,
- lineHeight: 26,
- }
-}));
-
-const materialPieSeries0 = computed(() => [
- {
- type: 'pie',
- radius: ['50%', '65%'],
- center: ['25%', '50%'],
- avoidLabelOverlap: false,
- itemStyle: {
- borderColor: '#fff',
- borderWidth: 2
+ {
+ name: "搴斾粯璐︽",
+ type: "bar",
+ barWidth: "30%",
+ data: receivablePayableList.value.map(item => item.payable || 0),
+ itemStyle: { color: "#ef4444" },
},
- label: {
- show: false
+ ]);
+
+ // --- 3. 璐㈠姟缁煎悎瓒嬪娍鍒嗘瀽 (鎶樼嚎鍥�) ---
+ const trendGrid = { left: "3%", right: "4%", bottom: "3%", containLabel: true };
+ const trendLegend = { top: "0", right: "center" };
+ const trendXAxis = computed(() => [
+ {
+ type: "category",
+ boundaryGap: false,
+ data: monthlyTrendList.value.map(item => item.month || ""),
},
- data: pieData0.value,
- color: pieColors
- }
-]);
-const materialPieSeries1 = computed(() => [
- {
- type: 'pie',
- radius: ['50%', '65%'],
- center: ['25%', '50%'],
- avoidLabelOverlap: false,
- itemStyle: {
- borderColor: '#fff',
- borderWidth: 2
+ ]);
+ const trendYAxis = [{ type: "value", name: "閲戦 (鍏�)" }];
+ const trendTooltip = { trigger: "axis" };
+ const trendSeries = computed(() => [
+ {
+ name: "鎬昏惀鏀�",
+ type: "line",
+ smooth: true,
+ data: monthlyTrendList.value.map(item => item.income || 0),
+ itemStyle: { color: "#4f46e5" },
+ areaStyle: { opacity: 0.1 },
},
- label: {
- show: false
+ {
+ name: "鎬绘敮鍑�",
+ type: "line",
+ smooth: true,
+ data: monthlyTrendList.value.map(item => item.expense || 0),
+ itemStyle: { color: "#f97316" },
},
- data: pieData1.value,
- color: pieColors
- }
-]);
-const pieTooltip = reactive({
- trigger: 'item',
- formatter: function(params) {
- // 妫�鏌ユ暟鎹槸鍚﹀瓨鍦�
- if (!params.data) return params.name;
- // 鎷兼帴瀹屾暣鍐呭
- return `
- <div>
- <div style="color:${params.color};font-size:16px;">鈼�</div>
- <div>${params.name}</div>
- <div>鍗犳瘮锛�${params.data.percent}</div>
- <div>閲戦锛�${params.data.amount}</div>
- </div>
- `;
- }
-})
+ {
+ name: "鍑�鍒╂鼎",
+ type: "line",
+ smooth: true,
+ data: monthlyTrendList.value.map(item => item.profit || 0),
+ lineStyle: { width: 4, type: "dashed" },
+ itemStyle: { color: "#10b981" },
+ },
+ ]);
+ // --- 鍏敤閫昏緫 ---
+ const formatMoney = val => {
+ return val;
+ };
-const pageInfo = ref({
-})
+ const handleDateChange = val => {
+ if (val) getData();
+ };
-const getData = async () => {
- if (!dateRange.value || !dateRange.value.length) {
- return;
- }
- try {
- const {code,data} = await reportForms({entryDateStart:dateRange.value[0], entryDateEnd:dateRange.value[1]});
- if(code === 200) {
- pageInfo.value = data
- pieData0.value = data.incomeType.map(item=>({
- name:item.typeName,
- value:item.account,
- percent:`${item.proportion*100}%`,
- amount:`楼${item.account}`
- }))
- pieData1.value = data.expenseType.map(item=>({
- name:item.typeName,
- value:item.account,
- percent:`${item.proportion*100}%`,
- amount:`楼${item.account}`
- }))
+ const resetDateRange = () => {
+ dateRange.value = [
+ dayjs().subtract(5, "month").format("YYYY-MM"),
+ dayjs().format("YYYY-MM"),
+ ];
+ getData();
+ };
+ const disabledDate = time => dayjs(time).isAfter(dayjs(), "month");
+
+ const getData = async () => {
+ if (!dateRange.value || dateRange.value.length !== 2) return;
+
+ const params = {
+ entryDateStart: dayjs(dateRange.value[0])
+ .startOf("month")
+ .format("YYYY-MM-DD"),
+ entryDateEnd: dayjs(dateRange.value[1]).endOf("month").format("YYYY-MM-DD"),
+ };
+
+ try {
+ const res = await accountStatementDetailsByMonth(params);
+ if (res.code === 200 && res.data) {
+ const data = res.data;
+ // 鏇存柊椤堕儴姹囨�诲崱鐗囨暟鎹�
+ pageInfo.totalIncome = data.totalIncome || 0;
+ pageInfo.totalExpense = data.totalExpense || 0;
+ pageInfo.totalReceivable = data.accountsReceivable || 0;
+ pageInfo.totalPayable = data.accountsPayable || 0;
+ pageInfo.netRevenue = data.netRevenue || 0;
+
+ // 鏇存柊鍥捐〃鏁版嵁
+ monthlyTrendList.value = data.monthlyTrendList || [];
+ receivablePayableList.value = data.receivablePayableList || [];
+ }
+ } catch (error) {
+ console.error("鑾峰彇璐㈠姟鎶ヨ〃鏁版嵁澶辫触锛�", error);
}
- } catch (error) {
- console.error('鑾峰彇璐㈠姟鎸囨爣鏁版嵁澶辫触锛�', error);
- }
- try{
- const {code,data} = await reportIncome();
- if(code==200){
- lineSeries0.value = data.map(item=>({
- name:item.typeName,
- type: 'line',
- data:item.account.map(item=>Number(item))
- }))
+ };
- }
- }catch (error) {
- console.error('鑾峰彇璐㈠姟鎸囨爣鏁版嵁澶辫触锛�', error);
- }
- try{
- const {code,data} = await reportExpense();
- if(code==200){
- lineSeries1.value = data.map(item=>({
- name:item.typeName,
- type: 'line',
- data:item.account.map(item=>Number(item))
- }))
-
- }
- }catch (error) {
- console.error('鑾峰彇璐㈠姟鎸囨爣鏁版嵁澶辫触锛�', error);
- }
-};
-
-
-// 鍒濆鍖�
-onMounted(() => {
- // 涓嶈缃粯璁ゆ棩鏈燂紝鐢辩敤鎴锋墜鍔ㄩ�夋嫨
-});
-
-// 澶勭悊鏃ユ湡鑼冨洿鍙樺寲
-const handleDateChange = (newRange) => {
- dateRange.value = newRange;
- if (newRange && newRange.length === 2) {
- getData()
- }
-};
-
-// 閲嶇疆鏃ユ湡鑼冨洿
-const resetDateRange = () => {
- dateRange.value = null;
-};
-
+ onMounted(() => {
+ resetDateRange();
+ });
</script>
<style scoped lang="scss">
-/* 鍩虹鏍峰紡琛ュ厖 */
-:root {
- --el-color-primary: #4f46e5;
-}
-.el-card{
- position: relative;
- border-radius: 12px;
- padding: 14px 10px 10px 10px;
- box-shadow: 0 2px 8px #eee;
- :deep(.el-card__body){
- padding: 10px 20px !important;
+ .stats-cards {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
+ gap: 20px;
+ margin-bottom: 24px;
}
- &.bg1{
- background: url(@/assets/icons/png/1.png) no-repeat 100% 100% !important;
- }
- &.bg2{
- background: url(@/assets/icons/png/2.png) no-repeat 100% 100% !important;
- }
- &.bg3{
- background: url(@/assets/icons/png/3.png) no-repeat 100% 100% !important;
- }
- &.bg4{
- background: url(@/assets/icons/png/4.png) no-repeat 100% 100% !important;
- }
- &.bg5{
- background: url(@/assets/icons/png/5.png) no-repeat 100% 100% !important;
- }
-}
-.grid-container {
- /* grid 瀹瑰櫒鍩虹鏍峰紡 */
- display: grid;
- gap: 1rem; /* gap-4 瀵瑰簲 1rem (16px) */
- margin-bottom: 2rem; /* mb-8 瀵瑰簲 2rem (32px) */
-
- p{
- font-size: 22px;
- margin-top: 0px;
- color: #fff;
+ .stat-card {
+ background: #fff;
+ border: 1px solid #edf2f7;
+ border-radius: 12px;
+ padding: 24px;
+ display: flex;
+ align-items: center;
+ gap: 16px;
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+
+ &:hover {
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
+ transform: translateY(-4px);
+ }
+
+ .stat-icon {
+ width: 56px;
+ height: 56px;
+ background: #f7fafc;
+ border-radius: 12px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ img {
+ width: 32px;
+ height: 32px;
+ }
+ }
+
+ .stat-content {
+ .stat-label {
+ font-size: 14px;
+ color: #718096;
+ margin-bottom: 4px;
+ }
+ .stat-value {
+ font-size: 20px;
+ font-weight: 700;
+ color: #2d3748;
+ }
+ }
}
- h3{
- font-size: 36px;
- font-weight: 500;
- font-family: 'MyCustomFont', sans-serif;
- margin: 10px 0;
- color: #fff;
+
+ .charts-row {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
+ gap: 24px;
+ margin-bottom: 24px;
}
-
-}
-/* 绉诲姩绔粯璁ゆ牱寮� (grid-cols-1) */
-.grid-container {
- grid-template-columns: repeat(1, minmax(0, 1fr));
-}
-
-/* 灏忓睆骞曞強浠ヤ笂 (sm:grid-cols-2) */
-@media (min-width: 640px) {
- .grid-container {
- grid-template-columns: repeat(2, minmax(0, 1fr));
+ @media (min-width: 1200px) {
+ .charts-row {
+ grid-template-columns: repeat(2, 1fr);
+ }
}
-}
-/* 澶у睆骞曞強浠ヤ笂 (lg:grid-cols-5) */
-@media (min-width: 1024px) {
- .grid-container {
- grid-template-columns: repeat(5, minmax(0, 1fr));
+ .chart-card,
+ .trend-chart-card {
+ border-radius: 16px;
+ border: none;
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);
+
+ .card-header {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ .header-title {
+ font-size: 16px;
+ font-weight: 600;
+ color: #1a202c;
+ }
+ .el-icon {
+ color: #a0aec0;
+ cursor: help;
+ }
+ }
}
-}
-/* 鍗$墖鎮仠鏁堟灉澧炲己 */
-.el-card:hover {
- transform: translateY(-2px);
-}
-.echarts{
- display: flex;
- justify-content: space-between;
-}
+ .financial-overview-container {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ flex-wrap: nowrap;
+ gap: 10px;
+ padding: 20px 0;
+ width: 100%;
+ overflow: hidden;
-/* 鍥捐〃瀹瑰櫒鏍峰紡 */
-.el-chart {
- width: 100%;
- height: 100%;
-}
-.section-title {
- position: relative;
- font-size: 18px;
- color: #333;
- padding-left: 10px;
- margin-bottom: 10px;
- font-weight: 700;
-}
+ .overview-item {
+ flex: 1;
+ min-width: 0; // 鍏佽鍦� flex 瀹瑰櫒涓缉鍐欙紝闃叉鍐呭鎾戝紑
+ display: flex;
+ justify-content: center;
-.section-title::before {
- position: absolute;
- left: 0;
- top: 0px;
- content: '';
- width: 4px;
- height: 18px;
- background-color: #002FA7;
- border-radius: 2px;
-}
-.chart-num{
- position: absolute;
- z-index: 3;
- top: 92px;
- left: 92px;
- display: flex;
- flex-direction: column;
- justify-content: center;
-}
+ .overview-box {
+ position: relative;
+ width: 100%;
+ max-width: 320px;
+ height: 110px;
+ background: #f8fafc;
+ border-radius: 12px;
+ padding: 12px 16px;
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ overflow: hidden;
+ transition: all 0.3s ease;
+
+ &:hover {
+ transform: translateY(-5px);
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
+ }
+
+ .icon-circle {
+ flex-shrink: 0;
+ width: 42px;
+ height: 42px;
+ border-radius: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 20px;
+ z-index: 2;
+ }
+
+ .data-content {
+ z-index: 2;
+ min-width: 0;
+ .label {
+ font-size: 13px;
+ color: #718096;
+ margin-bottom: 2px;
+ font-weight: 500;
+ white-space: nowrap;
+ }
+ .value {
+ font-size: 18px;
+ font-weight: 800;
+ color: #1a202c;
+ line-height: 1.2;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+ .unit {
+ font-size: 11px;
+ color: #a0aec0;
+ }
+ }
+
+ .bg-decoration {
+ position: absolute;
+ right: -5px;
+ bottom: -5px;
+ font-size: 32px;
+ font-weight: 950;
+ color: rgba(0, 0, 0, 0.03);
+ font-style: italic;
+ user-select: none;
+ z-index: 1;
+ }
+ }
+
+ &.income {
+ .icon-circle {
+ background: #eef2ff;
+ color: #4f46e5;
+ }
+ .overview-box {
+ border-left: 5px solid #4f46e5;
+ }
+ }
+
+ &.expense {
+ .icon-circle {
+ background: #fff7ed;
+ color: #f97316;
+ }
+ .overview-box {
+ border-left: 5px solid #f97316;
+ }
+ }
+ }
+
+ .profit-indicator {
+ flex: 0 40%; // 鍥哄畾瀹藉害锛屼笉鍙備笌寮规�х缉鏀句互淇濊瘉浠〃鐩樺畬鏁�
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ .profit-gauge-wrapper {
+ position: relative;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 100%;
+ // max-width: 180px;
+
+ .profit-center-text {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ text-align: center;
+ width: 100%;
+
+ .label {
+ font-size: 12px;
+ color: #718096;
+ font-weight: 500;
+ }
+
+ .value {
+ font-size: 20px;
+ font-weight: 800;
+ margin: 2px 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+
+ &.plus {
+ color: #10b981;
+ }
+
+ &.minus {
+ color: #f43f5e;
+ }
+ }
+
+ .rate {
+ font-size: 11px;
+ color: #a0aec0;
+ font-weight: 500;
+ }
+ }
+ }
+ }
+
+ // 閽堝闈炲父绐勭殑灞忓箷杩涜鏁翠綋缂╂斁
+ @media (max-width: 1400px) {
+ transform-origin: center;
+ // 濡傛灉瀹瑰櫒澶獎锛岄�氳繃缂╁皬鍐呴儴鍏冪礌鏉ラ�傚簲
+ // 杩欓噷涓嶄娇鐢� transform: scale 鍥犱负浼氬奖鍝嶅竷灞�娴侊紝鏀圭敤鍐呴儴灏哄寰皟
+ .overview-item .overview-box {
+ padding: 10px;
+ gap: 8px;
+ .value {
+ font-size: 16px;
+ }
+ .icon-circle {
+ width: 36px;
+ height: 36px;
+ font-size: 18px;
+ }
+ }
+ .profit-indicator {
+ flex: 0 40%;
+ .profit-gauge-wrapper .value {
+ font-size: 18px;
+ }
+ }
+ }
+ }
</style>
--
Gitblit v1.9.3