From 4928db9a82b2409503c1f8de0cba0513d253e851 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期五, 08 八月 2025 11:45:11 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_ai' into dev_ai

---
 src/views/financialManagement/financialStatements/index.vue |  511 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 510 insertions(+), 1 deletions(-)

diff --git a/src/views/financialManagement/financialStatements/index.vue b/src/views/financialManagement/financialStatements/index.vue
index c272707..430fe6a 100644
--- a/src/views/financialManagement/financialStatements/index.vue
+++ b/src/views/financialManagement/financialStatements/index.vue
@@ -1,4 +1,513 @@
 <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="缁撴潫鏃ユ湡"
+        :default-value="[new Date(firstDayOfMonth), new Date()]"
+        @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>
+      
+      <!-- 鏀跺叆缁熻鍥捐〃 -->
+      <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>
+        </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>
+        </el-card>
+      </div>
+    </main>
+  </div>
 </template>
+
 <script setup>
-</script>
\ No newline at end of file
+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";
+
+// 鏃ユ湡鑼冨洿
+const dateRange = ref([]);
+const firstDayOfMonth = 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 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 yAxis1 = [
+{
+    type: 'value',
+    name: '鏀嚭缁熻', // 宸︿晶y杞�
+    position: 'left',
+    min: 0,
+    // 鍧愭爣杞村悕绉版牱寮�
+    nameTextStyle: {
+      color: '#000',
+      fontSize: 14,
+    },
+  }
+]
+
+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
+    },
+    label: {
+      show: false
+    },
+    data: pieData0.value,
+    color: pieColors
+  }
+]);
+const materialPieSeries1 = computed(() => [
+  {
+    type: 'pie',
+    radius: ['50%', '65%'],
+    center: ['25%', '50%'],
+    avoidLabelOverlap: false,
+    itemStyle: {
+      borderColor: '#fff',
+      borderWidth: 2
+    },
+    label: {
+      show: false
+    },
+    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>
+    `;
+  }
+})
+
+
+const pageInfo = ref({
+})
+
+const getData = async () => {
+  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}`
+      }))
+
+    }
+  } 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 today = new Date();
+  const firstDay = new Date(today.getFullYear(), today.getMonth(), 1);
+  firstDayOfMonth.value = firstDay;
+  dateRange.value = [dayjs(firstDay).format("YYYY-MM-DD"), dayjs(today).format("YYYY-MM-DD")];
+  getData()
+  
+});
+
+// 澶勭悊鏃ユ湡鑼冨洿鍙樺寲
+const handleDateChange = (newRange) => {
+  if (newRange && newRange.length === 2) {
+    dateRange.value = newRange;
+    getData()
+  }
+};
+
+// 閲嶇疆鏃ユ湡鑼冨洿
+const resetDateRange = () => {
+  const today = new Date();
+  const firstDay = new Date(today.getFullYear(), today.getMonth(), 1);
+  dateRange.value = [dayjs(firstDay).format("YYYY-MM-DD"), dayjs(today).format("YYYY-MM-DD")];
+  getData()
+};
+
+</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;
+  }
+  &.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;
+  }
+  h3{
+    font-size: 36px;
+    font-weight: 500;
+    font-family: 'MyCustomFont', sans-serif;
+    margin: 10px 0;
+    color: #fff;
+  }
+  
+}
+
+/* 绉诲姩绔粯璁ゆ牱寮� (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));
+  }
+}
+
+/* 澶у睆骞曞強浠ヤ笂 (lg:grid-cols-5) */
+@media (min-width: 1024px) {
+  .grid-container {
+    grid-template-columns: repeat(5, minmax(0, 1fr));
+  }
+}
+
+/* 鍗$墖鎮仠鏁堟灉澧炲己 */
+.el-card:hover {
+  transform: translateY(-2px);
+}
+.echarts{
+  display: flex;
+  justify-content: space-between;
+}
+
+/* 鍥捐〃瀹瑰櫒鏍峰紡 */
+.el-chart {
+  width: 100%;
+  height: 100%;
+}
+.section-title {
+	position: relative;
+	font-size: 18px;
+	color: #333;
+	padding-left: 10px;
+	margin-bottom: 10px;
+	font-weight: 700;
+}
+
+.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;
+}
+</style>

--
Gitblit v1.9.3