| | |
| | | <div style="padding: 20px;"> |
| | | <!-- 页面标题和筛选条件 --> |
| | | <div class="w-full md:w-auto flex items-center gap-3" style="margin-bottom: 20px;"> |
| | | <el-button |
| | | type="primary" |
| | | icon="Refresh" |
| | | @click="resetFilters" |
| | | size="default" |
| | | > |
| | | 查询 |
| | | </el-button> |
| | | <el-form :inline="true"> |
| | | <el-form-item label="年份"> |
| | | <el-date-picker |
| | | v-model="selectedYear" |
| | | type="year" |
| | | placeholder="请选择年份" |
| | | format="YYYY" |
| | | value-format="YYYY" |
| | | clearable |
| | | @change="fetchData()" |
| | | style="width: 200px" |
| | | :disabled-date="(date) => date.getFullYear() > new Date().getFullYear()" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | icon="Refresh" |
| | | @click="resetFilters" |
| | | size="default" |
| | | > |
| | | 重置 |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | |
| | | <main class="container mx-auto px-4 pb-10"> |
| | |
| | | <el-card class="bg3"> |
| | | <p>资产原值</p> |
| | | <h3> |
| | | ¥{{ assetInfo.totalOriginalValue }} |
| | | ¥{{ formatCurrency(assetInfo.totalOriginalValue) }} |
| | | </h3> |
| | | </el-card> |
| | | |
| | |
| | | <el-card class="bg4"> |
| | | <p>累计折旧</p> |
| | | <h3> |
| | | ¥{{ assetInfo.totalDepreciation }} |
| | | ¥{{ formatCurrency(assetInfo.totalDepreciation) }} |
| | | </h3> |
| | | </el-card> |
| | | |
| | |
| | | <el-card class="bg5"> |
| | | <p>净值</p> |
| | | <h3> |
| | | ¥{{ assetInfo.totalNetValue }} |
| | | ¥{{ formatCurrency(assetInfo.totalNetValue) }} |
| | | </h3> |
| | | </el-card> |
| | | <!-- 负债 --> |
| | | <el-card class="bg2"> |
| | | <p>负债</p> |
| | | <h3> |
| | | ¥{{ formatCurrency(assetInfo.debt) }} |
| | | </h3> |
| | | </el-card> |
| | | <!-- 库存资产 --> |
| | | <el-card class="bg3"> |
| | | <p>库存资产</p> |
| | | <h3> |
| | | ¥{{ formatCurrency(assetInfo.inventoryValue) }} |
| | | </h3> |
| | | </el-card> |
| | | </div> |
| | |
| | | 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;">{{ assetInfo.totalEquipment }}</span> |
| | | <span style="font-size: 36px; font-weight: 500; font-family: 'MyCustomFont', sans-serif;">{{ deviceTypeTotalCount }}</span> |
| | | </div> |
| | | </Echarts> |
| | | <Echarts |
| | |
| | | style="width: 100%" |
| | | :header-cell-style="{ background: '#f5f7fa', color: '#606266' }" |
| | | > |
| | | <el-table-column prop="id" label="资产编号" width="120" /> |
| | | <el-table-column prop="deviceName" label="设备名称" width="250" /> |
| | | <el-table-column prop="deviceModel" label="型号规格" min-width="150" /> |
| | | <el-table-column prop="supplierName" label="供应商" min-width="120" /> |
| | |
| | | <el-table-column prop="number" label="数量" width="120" /> |
| | | <el-table-column prop="originalValue" label="原值(元)" width="120"> |
| | | <template #default="{ row }"> |
| | | ¥{{ formatCurrency(row.taxIncludingPriceTotal) }} |
| | | {{ formatCurrency(row.taxIncludingPriceTotal) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="depreciation" label="累计折旧(元)" width="140"> |
| | | <template #default="{ row }"> |
| | | ¥{{ formatCurrency(row.taxIncludingPriceTotal-row.unTaxIncludingPriceTotal) }} |
| | | {{ formatCurrency(row.deprAmount) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="netValue" label="净值(元)" width="120"> |
| | | <template #default="{ row }"> |
| | | ¥{{ formatCurrency(row.unTaxIncludingPriceTotal) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="status" label="状态" width="100"> |
| | | <template #default="{ row }"> |
| | | <el-tag |
| | | :type="getStatusTagType(row.status)" |
| | | size="small" |
| | | > |
| | | {{ row.status }} |
| | | </el-tag> |
| | | {{ formatCurrency(row.netValue) }} |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | import 'element-plus/dist/index.css'; |
| | | import Echarts from "@/components/Echarts/echarts.vue"; |
| | | import { getLedgerPage } from "@/api/equipmentManagement/ledger"; |
| | | import { getAccountingTotal, getDeviceTypeDistribution, getCalculateDepreciation } from "@/api/financialManagement/accounting"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | // 筛选条件 |
| | | const dateRange = ref(null); |
| | | const equipmentType = ref(''); |
| | | const selectedYear = ref(dayjs().format('YYYY')); // 默认当前年份 |
| | | |
| | | |
| | | // 固定资产信息 |
| | | const assetInfo = ref({ |
| | | totalEquipment: 0, |
| | | totalOriginalValue: 0, |
| | | totalDepreciation: 0, |
| | | totalNetValue: 0 |
| | | totalEquipment: 0, // deviceTotal |
| | | totalOriginalValue: 0, // deviceAmount |
| | | totalDepreciation: 0, // deprAmount |
| | | totalNetValue: 0, // netValue |
| | | debt: 0, // 负债 |
| | | inventoryValue: 0 // 库存资产 |
| | | }); |
| | | |
| | | // 设备类型总数(用于图表显示) |
| | | const deviceTypeTotalCount = ref(0); |
| | | |
| | | // 设备列表 |
| | | const equipmentList = ref([]); |
| | |
| | | const fetchData = async () => { |
| | | try { |
| | | // 获取固定资产汇总信息 |
| | | const assetInfoRes = await getAssetInfo({ |
| | | const assetInfoRes = await getAccountingTotal({ |
| | | startDate: dateRange.value ? dateRange.value[0] : null, |
| | | endDate: dateRange.value ? dateRange.value[1] : null, |
| | | equipmentType: equipmentType.value |
| | | equipmentType: equipmentType.value, |
| | | year: selectedYear.value |
| | | }); |
| | | |
| | | if (assetInfoRes.code === 200) { |
| | | assetInfo.value = assetInfoRes.data; |
| | | // 映射后端字段到前端字段 |
| | | const data = assetInfoRes.data; |
| | | assetInfo.value = { |
| | | totalEquipment: data.deviceTotal || 0, // 设备总数 |
| | | totalOriginalValue: data.deviceAmount || 0, // 资产原值 |
| | | totalDepreciation: data.deprAmount || 0, // 累计折旧 |
| | | totalNetValue: data.netValue || 0, // 净值 |
| | | debt: data.debt || 0, // 负债 |
| | | inventoryValue: data.inventoryValue || 0 // 库存资产 |
| | | }; |
| | | } |
| | | |
| | | // 获取设备列表 |
| | | const equipmentListRes = await getLedgerPage({ |
| | | current: pagination.value.currentPage, |
| | | size: pagination.value.pageSize, |
| | | // 获取设备类型分布数据(饼图和折线图) |
| | | const distributionRes = await getDeviceTypeDistribution({ |
| | | startDate: dateRange.value ? dateRange.value[0] : null, |
| | | endDate: dateRange.value ? dateRange.value[1] : null, |
| | | equipmentType: equipmentType.value |
| | | equipmentType: equipmentType.value, |
| | | year: selectedYear.value |
| | | }); |
| | | |
| | | if (equipmentListRes.code === 200) { |
| | | equipmentList.value = equipmentListRes.data.records; |
| | | pagination.value.total = equipmentListRes.data.total; |
| | | |
| | | // 根据 equipmentList 按 deviceName 进行分类统计 |
| | | const deviceNameMap = {}; |
| | | equipmentList.value.forEach(item => { |
| | | const deviceName = item.deviceName; |
| | | if (!deviceNameMap[deviceName]) { |
| | | deviceNameMap[deviceName] = { |
| | | name: deviceName, |
| | | count: 0, |
| | | totalValue: 0 |
| | | }; |
| | | } |
| | | deviceNameMap[deviceName].count += item.number || 1; // 假设 number 为设备数量 |
| | | deviceNameMap[deviceName].totalValue += item.taxIncludingPriceTotal || 0; // 累加含税总价 |
| | | }); |
| | | |
| | | // 转换为 typeDistributionData 格式 |
| | | typeDistributionData.value = Object.values(deviceNameMap).map(item => ({ |
| | | name: item.name, |
| | | value: item.count, |
| | | count: item.count, |
| | | amount: `¥${formatCurrency(item.totalValue)}` |
| | | })); |
| | | if (distributionRes.code === 200) { |
| | | const data = distributionRes.data; |
| | | |
| | | // 更新设备类型总数 |
| | | deviceTypeTotalCount.value = data.totalCount || 0; |
| | | |
| | | // 转换饼图数据格式 |
| | | if (data.details && data.details.length > 0) { |
| | | typeDistributionData.value = data.details.map(item => ({ |
| | | name: item.type || '', |
| | | value: Number(item.count || 0), |
| | | count: Number(item.count || 0), |
| | | amount: `¥${formatCurrency(item.amount || 0)}` |
| | | })); |
| | | } else if (data.categories && data.categories.length > 0) { |
| | | // 如果没有 details,使用 categories、countData 和 amountData 构建 |
| | | typeDistributionData.value = data.categories.map((category, index) => ({ |
| | | name: category, |
| | | value: Number(data.countData[index] || 0), |
| | | count: Number(data.countData[index] || 0), |
| | | amount: `¥${formatCurrency(data.amountData[index] || 0)}` |
| | | })); |
| | | } else { |
| | | typeDistributionData.value = []; |
| | | } |
| | | |
| | | // 更新x轴数据 |
| | | xAxis.value[0].data = typeDistributionData.value.map(item => item.name); |
| | | xAxis.value[0].data = data.categories || typeDistributionData.value.map(item => item.name); |
| | | |
| | | // 构建折线图数据 |
| | | typeDistributionLineSeries.value = [ |
| | | { |
| | | name: '设备数量', |
| | | type: 'line', |
| | | data: typeDistributionData.value.map(item => item.count) |
| | | data: data.countData || typeDistributionData.value.map(item => item.count) |
| | | } |
| | | ]; |
| | | } |
| | | |
| | | // 获取设备列表(折旧计算数据) |
| | | const equipmentListRes = await getCalculateDepreciation({ |
| | | current: pagination.value.currentPage, |
| | | size: pagination.value.pageSize, |
| | | startDate: dateRange.value ? dateRange.value[0] : null, |
| | | endDate: dateRange.value ? dateRange.value[1] : null, |
| | | equipmentType: equipmentType.value, |
| | | year: selectedYear.value |
| | | }); |
| | | |
| | | if (equipmentListRes.code === 200) { |
| | | // 如果返回的是分页数据 |
| | | if (equipmentListRes.data.records) { |
| | | equipmentList.value = equipmentListRes.data.records; |
| | | pagination.value.total = equipmentListRes.data.total; |
| | | } else if (Array.isArray(equipmentListRes.data)) { |
| | | // 如果返回的是数组 |
| | | equipmentList.value = equipmentListRes.data; |
| | | pagination.value.total = equipmentListRes.data.length; |
| | | } else { |
| | | equipmentList.value = []; |
| | | pagination.value.total = 0; |
| | | } |
| | | } |
| | | } catch (error) { |
| | | console.error('获取固定资产数据失败:', error); |
| | |
| | | const resetFilters = () => { |
| | | dateRange.value = null; |
| | | equipmentType.value = ''; |
| | | selectedYear.value = dayjs().format('YYYY'); // 重置为当前年份 |
| | | fetchData(); |
| | | }; |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | /* 大屏幕及以上 (lg:grid-cols-5) */ |
| | | /* 大屏幕及以上 (lg:grid-cols-6) */ |
| | | @media (min-width: 1024px) { |
| | | .grid-container { |
| | | grid-template-columns: repeat(5, minmax(0, 1fr)); |
| | | grid-template-columns: repeat(6, minmax(0, 1fr)); |
| | | } |
| | | } |
| | | |