新增待办信息
@@ -134,13 +134,13 @@ public class vDate {
|
||||
return switch (cycleType) {
|
||||
case "D" ->
|
||||
// 日:最近30天,格式 yyyy-MM-dd
|
||||
baseDate.minusDays(7).format(DAY_FORMATTER);
|
||||
baseDate.minusDays(14).format(DAY_FORMATTER);
|
||||
case "M" ->
|
||||
// 月:最近6个月,格式 yyyy-MM
|
||||
baseDate.minusMonths(6).format(MONTH_FORMATTER);
|
||||
baseDate.minusMonths(12).format(MONTH_FORMATTER);
|
||||
case "Q" ->
|
||||
// 季度:最近3年,格式 yyyy-Qx
|
||||
getQuarterCycleCode(baseDate.minusYears(2));
|
||||
getQuarterCycleCode(baseDate.minusYears(3));
|
||||
case "Y" ->
|
||||
// 年:最近6年,格式 yyyy
|
||||
String.valueOf(baseDate.minusYears(6).getYear());
|
||||
|
||||
BIN
web-vue/packages/assets/images/bigview.png
Normal file
|
After Width: | Height: | Size: 5.3 MiB |
@@ -5,34 +5,64 @@
|
||||
总金额:<span class="amount-value">{{ totalAmountText }}</span> 元
|
||||
</div>
|
||||
</template>
|
||||
<div ref="chartDom" style="width: 100%; height: 300px;"></div>
|
||||
<div class="layout-container">
|
||||
<div class="left-panel">
|
||||
<div class="stat-card">
|
||||
<span class="stat-title">本月收入</span>
|
||||
<div class="stat-content">
|
||||
<Icon icon="icons/erp-income.png" size="36"/>
|
||||
<span class="stat-value">{{ thisIncome }} 元</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span class="stat-title">本月支出</span>
|
||||
<div class="stat-content">
|
||||
<Icon icon="icons/erp-expense.png" size="36"/>
|
||||
<span class="stat-value">{{ thisExpense }} 元</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span class="stat-title">消费占比</span>
|
||||
<div class="stat-content">
|
||||
<Icon icon="icons/erp-share.png" size="36"/>
|
||||
<span class="stat-value">{{ thisShare }} %</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-panel">
|
||||
<div ref="chartDom" class="chart-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, computed } from 'vue';
|
||||
import { Card } from 'ant-design-vue';
|
||||
import { Icon } from '@jeesite/core/components/Icon';
|
||||
import { ErpAccount, erpAccountListAll } from '@jeesite/erp/api/erp/account';
|
||||
import { ErpIncExpRatio, erpIncExpRatioListAll } from '@jeesite/erp/api/erp/incExpRatio';
|
||||
import * as echarts from 'echarts';
|
||||
import type { ECharts, EChartsOption, LegendSelectedChangedParams } from 'echarts';
|
||||
import type { ECharts, EChartsOption } from 'echarts';
|
||||
|
||||
const listAccount = ref<ErpAccount[]>([]);
|
||||
const chartDom = ref<HTMLDivElement | null>(null);
|
||||
let myChart: ECharts | null = null;
|
||||
|
||||
// 核心修复1:新增「是否全取消」的标记 + 维护所有图例名称的集合
|
||||
const allLegendNames = ref<Set<string>>(new Set()); // 存储所有账户名称(图例名)
|
||||
const selectedLegends = ref<Set<string>>(new Set()); // 选中的图例
|
||||
const isAllUnselected = ref(false); // 标记是否所有图例都被取消选中
|
||||
const thisIncome = ref(0);
|
||||
const thisExpense = ref(0);
|
||||
const thisShare = ref(0);
|
||||
|
||||
// 修复后的总金额计算逻辑
|
||||
// 核心标记:是否全取消 + 维护所有图例名称的集合
|
||||
const allLegendNames = ref<Set<string>>(new Set());
|
||||
const selectedLegends = ref<Set<string>>(new Set());
|
||||
const isAllUnselected = ref(false);
|
||||
|
||||
// 总金额计算逻辑
|
||||
const totalAmountText = computed(() => {
|
||||
// 1. 所有图例都取消选中时,显示 0 元
|
||||
if (isAllUnselected.value) {
|
||||
return '0.00';
|
||||
}
|
||||
|
||||
// 2. 初始状态(全选):显示全部总金额
|
||||
if (selectedLegends.value.size === 0 && !isAllUnselected.value) {
|
||||
const total = listAccount.value.reduce(
|
||||
(sum, item) => sum + (Number(item.currentBalance) || 0),
|
||||
@@ -41,7 +71,6 @@ const totalAmountText = computed(() => {
|
||||
return total.toFixed(2);
|
||||
}
|
||||
|
||||
// 3. 部分选中:显示选中账户的合计
|
||||
const total = listAccount.value
|
||||
.filter(item => selectedLegends.value.has(item.accountName || '未知账户'))
|
||||
.reduce((sum, item) => sum + (Number(item.currentBalance) || 0), 0);
|
||||
@@ -53,6 +82,7 @@ const formatPercent = (value: number) => {
|
||||
return `${value.toFixed(1)}%`;
|
||||
};
|
||||
|
||||
// 优化颜色生成逻辑,增加颜色复用规则
|
||||
const generateRandomColors = (count: number): string[] => {
|
||||
const colorLibrary = [
|
||||
'#1890ff', '#52c41a', '#f5a623', '#fa8c16', '#722ed1', '#eb2f96',
|
||||
@@ -61,20 +91,37 @@ const generateRandomColors = (count: number): string[] => {
|
||||
];
|
||||
|
||||
if (count <= colorLibrary.length) {
|
||||
const shuffled = [...colorLibrary].sort(() => 0.5 - Math.random());
|
||||
return shuffled.slice(0, count);
|
||||
return colorLibrary.slice(0, count);
|
||||
}
|
||||
|
||||
const colors: string[] = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
const colors: string[] = [...colorLibrary];
|
||||
while (colors.length < count) {
|
||||
const hue = Math.floor(Math.random() * 360);
|
||||
const saturation = 70 + Math.floor(Math.random() * 20);
|
||||
const lightness = 45 + Math.floor(Math.random() * 15);
|
||||
colors.push(`hsl(${hue}, ${saturation}%, ${lightness}%)`);
|
||||
colors.push(`hsl(${hue}, 75%, 55%)`);
|
||||
}
|
||||
return colors;
|
||||
};
|
||||
|
||||
const getThisData = async() => {
|
||||
try {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = now.getMonth() + 1;
|
||||
const formattedMonth = month.toString().padStart(2, '0');
|
||||
const currentMonthStr = `${year}-${formattedMonth}`;
|
||||
const params = {
|
||||
cycleType: 'M',
|
||||
statDate: currentMonthStr ,
|
||||
}
|
||||
const result = await erpIncExpRatioListAll(params);
|
||||
thisIncome.value = result[0]?.incomeAmount || 0;
|
||||
thisExpense.value = result[0]?.expenseAmount || 0;
|
||||
thisShare.value = result[0]?.expenseRatio || 0;
|
||||
} catch (error) {
|
||||
console.error('获取数据失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
const fetchList = async () => {
|
||||
try {
|
||||
const result = await erpAccountListAll();
|
||||
@@ -85,21 +132,18 @@ const fetchList = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 核心修复2:重构图例选中事件处理逻辑
|
||||
const handleLegendSelect = (params: LegendSelectedChangedParams) => {
|
||||
// 图例选中事件处理
|
||||
const handleLegendSelect = (params: any) => {
|
||||
const { name, selected } = params;
|
||||
|
||||
// 1. 更新选中集合
|
||||
if (selected[name]) {
|
||||
selectedLegends.value.add(name);
|
||||
} else {
|
||||
selectedLegends.value.delete(name);
|
||||
}
|
||||
|
||||
// 2. 判断是否所有图例都被取消选中
|
||||
isAllUnselected.value = selectedLegends.value.size === 0 && allLegendNames.value.size > 0;
|
||||
|
||||
// 3. 强制更新图表(确保饼图和总金额同步)
|
||||
// 同步更新图表数据
|
||||
myChart?.setOption({
|
||||
series: [
|
||||
{
|
||||
@@ -113,6 +157,7 @@ const handleLegendSelect = (params: LegendSelectedChangedParams) => {
|
||||
});
|
||||
};
|
||||
|
||||
// 初始化图表(适配新布局)
|
||||
const initChart = () => {
|
||||
if (!chartDom.value || listAccount.value.length === 0) return;
|
||||
|
||||
@@ -130,9 +175,7 @@ const initChart = () => {
|
||||
const validData = pieData.filter(item => item.value > 0);
|
||||
const colors = generateRandomColors(validData.length);
|
||||
|
||||
// 核心修复3:初始化所有图例名称集合
|
||||
allLegendNames.value = new Set(validData.map(item => item.name));
|
||||
|
||||
const total = validData.reduce((sum, item) => sum + item.value, 0);
|
||||
|
||||
const option: EChartsOption = {
|
||||
@@ -206,10 +249,9 @@ const initChart = () => {
|
||||
};
|
||||
|
||||
myChart.setOption(option);
|
||||
|
||||
myChart.on('legendselectchanged', handleLegendSelect);
|
||||
|
||||
// 初始化选中状态:全选 + 标记非全取消
|
||||
// 初始化选中状态
|
||||
selectedLegends.value = new Set(validData.map(item => item.name));
|
||||
isAllUnselected.value = false;
|
||||
};
|
||||
@@ -220,7 +262,11 @@ const resizeChart = () => {
|
||||
|
||||
onMounted(async () => {
|
||||
await fetchList();
|
||||
initChart();
|
||||
await getThisData();
|
||||
// 增加微延迟确保DOM渲染完成
|
||||
setTimeout(() => {
|
||||
initChart();
|
||||
}, 100);
|
||||
window.addEventListener('resize', resizeChart);
|
||||
});
|
||||
|
||||
@@ -254,6 +300,106 @@ onUnmounted(() => {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 核心布局样式 */
|
||||
.layout-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
gap: 16px;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
/* 左侧20%面板 - 精简版 */
|
||||
.left-panel {
|
||||
width: 15%;
|
||||
height: 100%;
|
||||
border-radius: 8px;
|
||||
padding: 8px;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px; /* 缩小卡片间距 */
|
||||
}
|
||||
|
||||
/* 统计卡片样式 - 更小尺寸 */
|
||||
.stat-card {
|
||||
background-color: #f0f7ff; /* 淡蓝色背景 */
|
||||
border-radius: 6px;
|
||||
padding: 10px 8px; /* 缩小内边距 */
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #e6f4ff;
|
||||
}
|
||||
|
||||
/* 统计标题 - 简化为span */
|
||||
.stat-title {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
margin-bottom: 8px; /* 缩小间距 */
|
||||
text-align: left;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
/* 统计内容(图标+金额)- 关键优化 */
|
||||
.stat-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between; /* 改为两端对齐 */
|
||||
width: 100%; /* 确保占满容器宽度 */
|
||||
padding: 0 4px; /* 增加左右内边距 */
|
||||
}
|
||||
|
||||
/* 图标容器 - 确保图标靠左对齐 */
|
||||
:deep(.stat-content .icon) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
flex-shrink: 0; /* 防止图标被压缩 */
|
||||
}
|
||||
|
||||
/* 统计数值 - 确保数字靠右对齐 */
|
||||
.stat-value {
|
||||
font-size: 12px; /* 缩小字体 */
|
||||
font-weight: 600;
|
||||
color: #1890ff;
|
||||
white-space: nowrap;
|
||||
text-align: right; /* 文字右对齐 */
|
||||
flex-shrink: 0; /* 防止数字被压缩 */
|
||||
}
|
||||
|
||||
/* 右侧80%图表面板 */
|
||||
.right-panel {
|
||||
width: 85%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* 滚动条样式优化 */
|
||||
:deep(.left-panel::-webkit-scrollbar) {
|
||||
width: 4px; /* 缩小滚动条 */
|
||||
}
|
||||
|
||||
:deep(.left-panel::-webkit-scrollbar-thumb) {
|
||||
background: #d9d9d9;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
:deep(.left-panel::-webkit-scrollbar-track) {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 图表样式优化 */
|
||||
:deep(.ant-card .echarts-legend-item) {
|
||||
margin: 0 8px !important;
|
||||
padding: 0 5px;
|
||||
@@ -278,4 +424,40 @@ onUnmounted(() => {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 响应式适配 */
|
||||
@media (max-width: 768px) {
|
||||
.layout-container {
|
||||
flex-direction: column;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.left-panel, .right-panel {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.left-panel {
|
||||
flex-direction: row;
|
||||
height: 140px; /* 缩小高度 */
|
||||
overflow-x: auto;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
min-width: 120px; /* 缩小最小宽度 */
|
||||
flex: none;
|
||||
padding: 8px 6px;
|
||||
}
|
||||
|
||||
.right-panel {
|
||||
height: 300px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
/* 移动端保持图标左、数字右对齐 */
|
||||
.stat-content {
|
||||
justify-content: space-between;
|
||||
padding: 0 2px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,69 +1,137 @@
|
||||
<template>
|
||||
<PageWrapper class="dashboard-container">
|
||||
<template #extra>
|
||||
<BasicForm
|
||||
:labelWidth="100"
|
||||
:schemas="schemaForm.schemas"
|
||||
style="width: 245px;"
|
||||
/>
|
||||
</template>
|
||||
<div class="top-header-section">
|
||||
<div class="header-icon-wrapper">
|
||||
<img :src="headerImg" class="header-img" />
|
||||
</div>
|
||||
<BasicForm
|
||||
:labelWidth="100"
|
||||
:schemas="schemaForm.schemas"
|
||||
class="search-form"
|
||||
/>
|
||||
</div>
|
||||
<div class="two-column-layout">
|
||||
<ChartPie />
|
||||
<ChartLineRatio :formParams="FormValues" />
|
||||
<ChartLineRatio :formParams="FormValues" />
|
||||
</div>
|
||||
<div class="two-column-layout">
|
||||
<ChartBarCycle :formParams="FormValues" />
|
||||
<ChartBarAccount :formParams="FormValues" />
|
||||
</div>
|
||||
<ChartLineType :formParams="FormValues" />
|
||||
<div class="two-column-layout">
|
||||
<ChartLineExp :formParams="FormValues" />
|
||||
<ChartLineInc :formParams="FormValues" />
|
||||
</div>
|
||||
<ChartLineType :formParams="FormValues" />
|
||||
<div class="two-column-layout">
|
||||
<ChartLineExp :formParams="FormValues" />
|
||||
<ChartLineInc :formParams="FormValues" />
|
||||
</div>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
import { Card } from 'ant-design-vue';
|
||||
import { BasicForm, FormSchema, FormProps } from '@jeesite/core/components/Form';
|
||||
import { PageWrapper } from '@jeesite/core/components/Page';
|
||||
import ChartPie from './components/ChartPie.vue';
|
||||
import ChartLineExp from './components/ChartLineExp.vue';
|
||||
import ChartLineInc from './components/ChartLineInc.vue';
|
||||
import ChartBarCycle from './components/ChartBarCycle.vue';
|
||||
import ChartBarAccount from './components/ChartBarAccount.vue';
|
||||
import ChartLineType from './components/ChartLineType.vue';
|
||||
import ChartLineRatio from './components/ChartLineRatio.vue';
|
||||
|
||||
const FormValues = ref<Record<string, any>>({
|
||||
cycleType: 'M'
|
||||
});
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
import { Card } from 'ant-design-vue';
|
||||
import { Icon } from '@jeesite/core/components/Icon';
|
||||
import { BasicForm, FormSchema, FormProps } from '@jeesite/core/components/Form';
|
||||
import { PageWrapper } from '@jeesite/core/components/Page';
|
||||
import ChartPie from './components/ChartPie.vue';
|
||||
import ChartLineExp from './components/ChartLineExp.vue';
|
||||
import ChartLineInc from './components/ChartLineInc.vue';
|
||||
import ChartBarCycle from './components/ChartBarCycle.vue';
|
||||
import ChartBarAccount from './components/ChartBarAccount.vue';
|
||||
import ChartLineType from './components/ChartLineType.vue';
|
||||
import ChartLineRatio from './components/ChartLineRatio.vue';
|
||||
|
||||
const schemaForm: FormProps = {
|
||||
baseColProps: { md: 8, lg: 6 },
|
||||
labelWidth: 90,
|
||||
schemas: [
|
||||
{
|
||||
label: '周期',
|
||||
field: 'cycleType',
|
||||
defaultValue: 'M',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
dictType: 'report_cycle',
|
||||
allowClear: true,
|
||||
onChange: (value: string) => {
|
||||
FormValues.value.cycleType = value || '';
|
||||
}
|
||||
},
|
||||
colProps: { md: 24, lg: 24 },
|
||||
},
|
||||
],
|
||||
};
|
||||
import headerImg from '@jeesite/assets/images/bigview.png';
|
||||
|
||||
const FormValues = ref<Record<string, any>>({
|
||||
cycleType: 'M'
|
||||
});
|
||||
|
||||
const schemaForm: FormProps = {
|
||||
baseColProps: { md: 8, lg: 6 },
|
||||
labelWidth: 90,
|
||||
schemas: [
|
||||
{
|
||||
label: '周期',
|
||||
field: 'cycleType',
|
||||
defaultValue: 'M',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
dictType: 'report_cycle',
|
||||
allowClear: true,
|
||||
onChange: (value: string) => {
|
||||
FormValues.value.cycleType = value || '';
|
||||
}
|
||||
},
|
||||
colProps: { md: 24, lg: 24 },
|
||||
},
|
||||
],
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dashboard-container {
|
||||
padding: 0 8px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.top-header-section {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 16px 20px;
|
||||
width: 100%;
|
||||
background-color: #e6f7ff;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.03);
|
||||
border: 1px solid #bde5ff;
|
||||
}
|
||||
|
||||
/* 优化:图标容器样式 */
|
||||
.header-icon-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px; /* 图标与文本间距 */
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
/* 核心优化:限制图片尺寸 */
|
||||
.header-img {
|
||||
width: 60px; /* 固定宽度 */
|
||||
height: 30px; /* 固定高度 */
|
||||
object-fit: contain; /* 保持图片比例,不拉伸 */
|
||||
flex-shrink: 0; /* 防止被压缩 */
|
||||
border-radius: 4px; /* 轻微圆角,更美观 */
|
||||
}
|
||||
|
||||
/* 优化:图标核心样式 */
|
||||
.dashboard-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
vertical-align: middle;
|
||||
transition: transform 0.2s ease, filter 0.2s ease;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* hover效果 */
|
||||
.header-icon-wrapper:hover .header-img {
|
||||
transform: scale(1.05);
|
||||
filter: brightness(1.1);
|
||||
}
|
||||
|
||||
/* 图标文本样式 */
|
||||
.icon-text {
|
||||
color: #1890ff;
|
||||
margin-left: 4px;
|
||||
white-space: nowrap; /* 防止文本换行 */
|
||||
}
|
||||
|
||||
/* 右侧表单样式 */
|
||||
.search-form {
|
||||
width: 245px;
|
||||
}
|
||||
|
||||
.two-column-layout {
|
||||
@@ -71,6 +139,7 @@
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: 12px; /* 增加图表区域间距 */
|
||||
}
|
||||
|
||||
.chart-line-wrapper {
|
||||
@@ -79,12 +148,39 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* 响应式适配(可选) */
|
||||
/* 响应式适配优化 */
|
||||
@media (max-width: 768px) {
|
||||
.two-column-layout {
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
margin-bottom: 4px; /* 移动端也保持紧凑 */
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.top-header-section {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
.search-form {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* 移动端图片适配 */
|
||||
.header-img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.header-icon-wrapper {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
/* 额外优化:防止图片溢出 */
|
||||
:deep(.header-img) {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
</style>
|
||||
BIN
web-vue/web/public/resource/img/icons/erp-add.png
Normal file
|
After Width: | Height: | Size: 6.6 MiB |
BIN
web-vue/web/public/resource/img/icons/erp-bigview.png
Normal file
|
After Width: | Height: | Size: 5.3 MiB |
BIN
web-vue/web/public/resource/img/icons/erp-bigview2.png
Normal file
|
After Width: | Height: | Size: 9.6 MiB |
BIN
web-vue/web/public/resource/img/icons/erp-expense.png
Normal file
|
After Width: | Height: | Size: 3.8 MiB |
BIN
web-vue/web/public/resource/img/icons/erp-income.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
web-vue/web/public/resource/img/icons/erp-share.png
Normal file
|
After Width: | Height: | Size: 230 KiB |
BIN
web-vue/web/public/resource/img/icons/erp-view.png
Normal file
|
After Width: | Height: | Size: 276 KiB |