fix: 🧩 图标显示问题;增加收入和支出合计显示
This commit is contained in:
parent
2a75ff30e0
commit
476d4677a5
|
@ -20,7 +20,7 @@ VITE_BASE_API_RETRY=5
|
|||
VITE_BASE_API_RETRY_DELAY=3000
|
||||
|
||||
# 是否在打包时使用cdn替换本地库 替换 true 不替换 false
|
||||
VITE_CDN=true
|
||||
VITE_CDN=false
|
||||
|
||||
# 是否启用gzip压缩或brotli压缩(分两种情况,删除原始文件和不删除原始文件)
|
||||
# 压缩时不删除原始文件的配置:gzip、brotli、both(同时开启 gzip 与 brotli 压缩)、none(不开启压缩,默认)
|
||||
|
|
|
@ -3,6 +3,16 @@ import type { BaseResult, ResultTable } from '@/api/service/types';
|
|||
|
||||
/** 账单信息---获取账单信息列表 */
|
||||
export const fetchGetBillList = (data: any) => {
|
||||
data = {
|
||||
userId: data.userId,
|
||||
amount: data.amount,
|
||||
type: data.type,
|
||||
description: data.description,
|
||||
startDate: data.startDate,
|
||||
endDate: data.endDate,
|
||||
pageSize: data.pageSize,
|
||||
currentPage: data.currentPage,
|
||||
};
|
||||
return http.request<BaseResult<ResultTable>>('get', `bill/getBillList/${data.currentPage}/${data.pageSize}`, { params: data });
|
||||
};
|
||||
|
||||
|
|
|
@ -3,13 +3,21 @@ import type { BaseResult, ResultTable } from '@/api/service/types';
|
|||
|
||||
/** 账单信息---获取账单信息列表 */
|
||||
export const fetchGetUserBillList = (data: any) => {
|
||||
// 删除这个请求参数
|
||||
delete data.date;
|
||||
data = {
|
||||
amount: data.amount,
|
||||
type: data.type,
|
||||
description: data.description,
|
||||
startDate: data.startDate,
|
||||
endDate: data.endDate,
|
||||
pageSize: data.pageSize,
|
||||
currentPage: data.currentPage,
|
||||
};
|
||||
return http.request<BaseResult<ResultTable>>('get', `bill/noManage/getUserBillList/${data.currentPage}/${data.pageSize}`, { params: data });
|
||||
};
|
||||
|
||||
/** 账单信息---账单收入和支出 */
|
||||
export const fetchGetExpendOrIncome = (data: any) => {
|
||||
data = { userId: data.userId, type: data.type, startDate: data.startDate, endDate: data.endDate };
|
||||
return http.request<BaseResult<object>>('get', 'bill/noManage/getExpendOrIncome', { params: data });
|
||||
};
|
||||
|
||||
|
|
|
@ -1,166 +0,0 @@
|
|||
<script lang="tsx" setup>
|
||||
import { useRenderIcon } from '@/components/CommonIcon/src/hooks';
|
||||
import PureTable from '@pureadmin/table';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import { ElTag, ElText } from 'element-plus';
|
||||
import { onMounted, reactive, ref, watch } from 'vue';
|
||||
import { fetchGetUserBillList } from '@/api/v1/financial/user/billUser';
|
||||
import Empty from './empty.svg?component';
|
||||
|
||||
const props = defineProps({
|
||||
financialType: { type: Number as PropType<any>, default: undefined },
|
||||
startDate: { type: String as PropType<any>, default: undefined },
|
||||
endDate: { type: String as PropType<any>, default: undefined },
|
||||
});
|
||||
|
||||
const columns: TableColumnList = [
|
||||
{ type: 'index', index: (index: number) => index + 1, label: '序号', width: 60 },
|
||||
// 金额
|
||||
{
|
||||
label: $t('amount'),
|
||||
prop: 'amount',
|
||||
sortable: true,
|
||||
formatter({ type, amount }) {
|
||||
return type === -1 ? (
|
||||
<ElText size={'large'} type={'danger'} style={{ fontWeight: 800 }}>
|
||||
- {amount}¥
|
||||
</ElText>
|
||||
) : (
|
||||
<ElText size={'large'} type={'success'} style={{ fontWeight: 800 }}>
|
||||
+ {amount}¥
|
||||
</ElText>
|
||||
);
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
// 类别
|
||||
{
|
||||
label: $t('categoryName'),
|
||||
prop: 'categoryName',
|
||||
width: 150,
|
||||
formatter({ categoryName }) {
|
||||
return <ElTag effect={'plain'}>{categoryName}</ElTag>;
|
||||
},
|
||||
},
|
||||
// 描述
|
||||
{ label: $t('description'), prop: 'description' },
|
||||
// 交易日期
|
||||
{
|
||||
label: $t('transactionDate'),
|
||||
prop: 'transactionDate',
|
||||
width: 190,
|
||||
sortable: true,
|
||||
formatter({ transactionDate }) {
|
||||
return (
|
||||
<ElText type={'success'} style={{ fontWeight: 800 }}>
|
||||
{transactionDate}
|
||||
</ElText>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const form = reactive({
|
||||
// 类型:1 - 收入,-1 - 支出
|
||||
type: props.financialType,
|
||||
// 开始交易日期
|
||||
startDate: props.startDate,
|
||||
// 结束交易日期
|
||||
endDate: props.endDate,
|
||||
pagination: {
|
||||
pageSize: 10,
|
||||
currentPage: 1,
|
||||
layout: 'prev, pager, next',
|
||||
total: 1,
|
||||
align: 'center',
|
||||
hideOnSinglePage: false,
|
||||
},
|
||||
});
|
||||
|
||||
const dataList = ref([]);
|
||||
const loading = ref(false);
|
||||
|
||||
/* 初始化数据 */
|
||||
async function onSearch() {
|
||||
loading.value = true;
|
||||
|
||||
const result = await fetchGetUserBillList({ ...form, ...form.pagination });
|
||||
dataList.value = result.data.list;
|
||||
form.pagination.currentPage = result.data.pageNo;
|
||||
form.pagination.pageSize = result.data.pageSize;
|
||||
form.pagination.total = result.data.total;
|
||||
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
/* 修改分页 */
|
||||
async function onCurrentChange(page: number) {
|
||||
form.pagination.currentPage = page;
|
||||
await onSearch();
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
watch(
|
||||
() => props,
|
||||
async () => {
|
||||
form.startDate = props.startDate;
|
||||
form.endDate = props.endDate;
|
||||
await onSearch();
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<pure-table
|
||||
:columns="columns"
|
||||
:data="dataList"
|
||||
:loading="loading"
|
||||
:loading-config="{ background: 'transparent' }"
|
||||
:pagination="form.pagination"
|
||||
alignWhole="center"
|
||||
row-key="id"
|
||||
showOverflowTooltip
|
||||
@page-current-change="onCurrentChange"
|
||||
>
|
||||
<template #empty>
|
||||
<el-empty :image-size="60" description="暂无数据" style="height: 430px">
|
||||
<template #image>
|
||||
<Empty />
|
||||
</template>
|
||||
</el-empty>
|
||||
</template>
|
||||
<template #operation="{ row }">
|
||||
<el-button :icon="useRenderIcon('ri:search-line')" :title="`查看序号为${row.id}的详情`" circle plain size="small" />
|
||||
</template>
|
||||
</pure-table>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.pure-table-filter {
|
||||
.el-table-filter__list {
|
||||
min-width: 80px;
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
line-height: 28px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-table) {
|
||||
--el-table-border: none;
|
||||
--el-table-border-color: transparent;
|
||||
|
||||
.el-empty__description {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.el-scrollbar__bar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -19,13 +19,9 @@ const props = defineProps({
|
|||
});
|
||||
|
||||
const { isDark } = useDark();
|
||||
|
||||
const theme = computed(() => (isDark.value ? 'dark' : 'light'));
|
||||
|
||||
const chartRef = ref();
|
||||
const { setOptions } = useECharts(chartRef, {
|
||||
theme,
|
||||
});
|
||||
const { setOptions } = useECharts(chartRef, { theme });
|
||||
|
||||
watch(
|
||||
() => props,
|
||||
|
|
|
@ -22,40 +22,23 @@ watch(
|
|||
async () => {
|
||||
await nextTick(); // 确保DOM更新完成后再执行
|
||||
setOptions({
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
},
|
||||
legend: {
|
||||
textStyle: {
|
||||
color: '#606266',
|
||||
fontSize: '0.875rem',
|
||||
},
|
||||
bottom: 0,
|
||||
},
|
||||
tooltip: { trigger: 'item' },
|
||||
legend: { show: true, textStyle: { color: '#606266', fontSize: '0.875rem' }, bottom: 0 },
|
||||
series: [
|
||||
{
|
||||
type: 'pie',
|
||||
radius: [16, 130],
|
||||
radius: [10, 110],
|
||||
roseType: 'area',
|
||||
center: ['50%', '43%'],
|
||||
center: ['50%', '30%'],
|
||||
labelLine: { length: 3, length2: 6, smooth: true },
|
||||
itemStyle: {
|
||||
borderRadius: [5, 5, 5, 5],
|
||||
},
|
||||
label: {
|
||||
position: 'outer',
|
||||
alignTo: 'edge',
|
||||
edgeDistance: 10,
|
||||
},
|
||||
itemStyle: { borderRadius: [5, 5, 5, 5] },
|
||||
label: { position: 'outer', alignTo: 'edge', edgeDistance: 10 },
|
||||
data: props.categoryData,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true,
|
||||
},
|
||||
{ deep: true, immediate: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
|
|
|
@ -7,37 +7,60 @@ import CharLine from '@/components/Analyse/char-line.vue';
|
|||
import CharPie from '@/components/Analyse/char-pie.vue';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import { currentMouth, currentWeek, currentYear } from '@/enums/dateEnums';
|
||||
import AnalyseTable from '@/components/Analyse/analyse-table.vue';
|
||||
import AnalyseTable from '@/components/Analyse/table/analyse-table.vue';
|
||||
|
||||
interface Title {
|
||||
// 分析标题
|
||||
analyse: string;
|
||||
// 分类标题
|
||||
category: string;
|
||||
// 表格标题
|
||||
table: string;
|
||||
// 排行榜标题
|
||||
top: string;
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
// 标题
|
||||
title: { type: Object as PropType<Title> },
|
||||
// 收入还是支出类型
|
||||
financialType: { type: Number as PropType<any> },
|
||||
// 总和
|
||||
count: { type: Number as PropType<any>, default: 0 },
|
||||
// 分析概览图表颜色
|
||||
color: {
|
||||
type: Array as PropType<Array<string>>,
|
||||
},
|
||||
// 表格数据
|
||||
dataList: { type: Array as PropType<any>, default: () => [] },
|
||||
// 查询的表单
|
||||
form: { type: Object as PropType<any>, default: () => ({}) },
|
||||
// 修改当前页
|
||||
onCurrentChange: {
|
||||
type: Function as PropType<any>,
|
||||
default: () => {},
|
||||
},
|
||||
// 查询的日期
|
||||
date: {
|
||||
type: Array as PropType<Array<number>>,
|
||||
default: () => [],
|
||||
},
|
||||
// 概览分析x轴数据
|
||||
analyseXAxis: {
|
||||
type: Array as PropType<Array<number>>,
|
||||
default: () => [],
|
||||
},
|
||||
// 分析数据
|
||||
analyseData: {
|
||||
type: Array as PropType<Array<number>>,
|
||||
default: () => [],
|
||||
},
|
||||
// 分类数据
|
||||
categoryData: {
|
||||
type: Array as PropType<Array<number>>,
|
||||
default: () => [],
|
||||
},
|
||||
// 排行榜数据
|
||||
topData: {
|
||||
type: Array as PropType<Array<number>>,
|
||||
default: () => [],
|
||||
|
@ -46,10 +69,8 @@ const props = defineProps({
|
|||
const emits = defineEmits(['emitDateRange']);
|
||||
|
||||
const { isDark } = useDark();
|
||||
|
||||
// 选择查询日期范围
|
||||
const dateRange = ref(props.date);
|
||||
|
||||
// 日期范围选择
|
||||
const shortcuts = [
|
||||
{ text: $t('thisWeek'), value: currentWeek },
|
||||
|
@ -67,11 +88,13 @@ const onChangeDateRange = () => {
|
|||
<template>
|
||||
<div>
|
||||
<el-row :gutter="24" justify="space-around">
|
||||
<!-- 分析概览 -->
|
||||
<re-col v-motion :enter="{ opacity: 1, y: 0, transition: { delay: 400 } }" :initial="{ opacity: 0, y: 100 }" :value="18" :xs="24" class="mb-[18px]">
|
||||
<el-card class="bar-card" shadow="never">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-md font-medium">{{ title.analyse }}</span>
|
||||
<span>
|
||||
<slot name="formBefore" />
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
:end-placeholder="$t('endDate')"
|
||||
|
@ -83,6 +106,8 @@ const onChangeDateRange = () => {
|
|||
value-format="YYYY-MM-DD"
|
||||
@change="onChangeDateRange"
|
||||
/>
|
||||
<slot name="formAfter" />
|
||||
<el-text class="ml-2" size="large" type="danger">{{ $t('sumUp') }}:{{ count.toFixed(2) }}</el-text>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-between items-start mt-3">
|
||||
|
@ -91,6 +116,7 @@ const onChangeDateRange = () => {
|
|||
</el-card>
|
||||
</re-col>
|
||||
|
||||
<!-- 分类图表-->
|
||||
<re-col v-motion :enter="{ opacity: 1, y: 0, transition: { delay: 400 } }" :initial="{ opacity: 0, y: 100 }" :value="6" :xs="24" class="mb-[18px]">
|
||||
<el-card class="bar-card" shadow="never">
|
||||
<div class="flex justify-between">
|
||||
|
@ -102,15 +128,17 @@ const onChangeDateRange = () => {
|
|||
</el-card>
|
||||
</re-col>
|
||||
|
||||
<!-- 数据统计表格 -->
|
||||
<re-col v-motion :enter="{ opacity: 1, y: 0, transition: { delay: 560 } }" :initial="{ opacity: 0, y: 100 }" :value="18" :xs="24" class="mb-[18px]">
|
||||
<el-card class="h-[580px]" shadow="never">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-md font-medium">{{ title.table }}</span>
|
||||
</div>
|
||||
<analyse-table :endDate="dateRange[1]" :financialType="financialType" :startDate="dateRange[0]" class="mt-3" />
|
||||
<analyse-table :data-list="dataList" :form="form" :on-current-change="onCurrentChange" class="mt-3" />
|
||||
</el-card>
|
||||
</re-col>
|
||||
|
||||
<!-- 排行榜 -->
|
||||
<re-col v-motion :enter="{ opacity: 1, y: 0, transition: { delay: 560 } }" :initial="{ opacity: 0, y: 100 }" :value="6" :xs="24" class="mb-[18px]">
|
||||
<el-card shadow="never">
|
||||
<div class="flex justify-between">
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
<script lang="ts" setup>
|
||||
import PureTable from '@pureadmin/table';
|
||||
import Empty from './empty.svg?component';
|
||||
import { columns } from '@/components/Analyse/table/columns';
|
||||
|
||||
const props = defineProps({
|
||||
dataList: { type: Array as PropType<any>, default: () => [] },
|
||||
form: { type: Object as PropType<any>, default: () => ({}) },
|
||||
onCurrentChange: {
|
||||
type: Function as PropType<any>,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<pure-table
|
||||
:columns="columns"
|
||||
:data="dataList"
|
||||
:height="430"
|
||||
:loading="form.loading"
|
||||
:loading-config="{ background: 'transparent' }"
|
||||
:pagination="form.pagination"
|
||||
alignWhole="center"
|
||||
row-key="id"
|
||||
showOverflowTooltip
|
||||
@page-current-change="onCurrentChange"
|
||||
>
|
||||
<template #empty>
|
||||
<el-empty :image-size="60" description="暂无数据" style="height: 430px">
|
||||
<template #image>
|
||||
<Empty />
|
||||
</template>
|
||||
</el-empty>
|
||||
</template>
|
||||
</pure-table>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.pure-table-filter {
|
||||
.el-table-filter__list {
|
||||
min-width: 80px;
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
line-height: 28px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-table) {
|
||||
--el-table-border: none;
|
||||
--el-table-border-color: transparent;
|
||||
|
||||
.el-empty__description {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.el-scrollbar__bar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,48 @@
|
|||
import { $t } from '@/plugins/i18n';
|
||||
|
||||
export const columns: TableColumnList = [
|
||||
{ type: 'index', index: (index: number) => index + 1, label: '序号', width: 60 },
|
||||
// 金额
|
||||
{
|
||||
label: $t('amount'),
|
||||
prop: 'amount',
|
||||
sortable: true,
|
||||
formatter({ type, amount }) {
|
||||
return type === -1 ? (
|
||||
<ElText size={'large'} type={'danger'} style={{ fontWeight: 800 }}>
|
||||
- {amount}¥
|
||||
</ElText>
|
||||
) : (
|
||||
<ElText size={'large'} type={'success'} style={{ fontWeight: 800 }}>
|
||||
+ {amount}¥
|
||||
</ElText>
|
||||
);
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
// 类别
|
||||
{
|
||||
label: $t('categoryName'),
|
||||
prop: 'categoryName',
|
||||
width: 150,
|
||||
formatter({ categoryName }) {
|
||||
return <ElTag effect={'plain'}>{categoryName}</ElTag>;
|
||||
},
|
||||
},
|
||||
// 描述
|
||||
{ label: $t('description'), prop: 'description' },
|
||||
// 交易日期
|
||||
{
|
||||
label: $t('transactionDate'),
|
||||
prop: 'transactionDate',
|
||||
width: 190,
|
||||
sortable: true,
|
||||
formatter({ transactionDate }) {
|
||||
return (
|
||||
<ElText type={'success'} style={{ fontWeight: 800 }}>
|
||||
{transactionDate}
|
||||
</ElText>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
@ -1,10 +1,10 @@
|
|||
<script lang="ts" setup>
|
||||
import Analyse from '@/components/Analyse/index.vue';
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import dayjs from 'dayjs';
|
||||
import { currentMouth, days } from '@/enums/dateEnums';
|
||||
import { fetchGetExpendOrIncome } from '@/api/v1/financial/user/billUser';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import { fetchGetExpendOrIncome, fetchGetUserBillList } from '@/api/v1/financial/user/billUser';
|
||||
|
||||
const title = {
|
||||
analyse: $t('expenditureAnalysis'),
|
||||
|
@ -19,11 +19,23 @@ const analyseData = ref([]);
|
|||
const categoryList = ref([]);
|
||||
// 排行榜数据
|
||||
const topList = ref([]);
|
||||
|
||||
// 表格数据
|
||||
const dataList = ref([]);
|
||||
// 总金额
|
||||
const count = ref(0);
|
||||
// 查询表单
|
||||
const form = reactive({
|
||||
type: -1,
|
||||
startDate: dayjs(currentMouth[0]).format('YYYY-MM-DD'),
|
||||
endDate: dayjs(currentMouth[1]).format('YYYY-MM-DD'),
|
||||
pagination: {
|
||||
pageSize: 10,
|
||||
currentPage: 1,
|
||||
layout: 'prev, pager, next',
|
||||
total: 1,
|
||||
align: 'center',
|
||||
hideOnSinglePage: false,
|
||||
},
|
||||
});
|
||||
|
||||
/** 查询账单支出 */
|
||||
|
@ -33,6 +45,7 @@ const onSearch = async () => {
|
|||
form.endDate = dayjs(form.endDate).format('YYYY-MM-DD');
|
||||
|
||||
// 获取数据
|
||||
await onTableSearch();
|
||||
const result = await fetchGetExpendOrIncome(form);
|
||||
if (result.code !== 200) return;
|
||||
|
||||
|
@ -42,6 +55,10 @@ const onSearch = async () => {
|
|||
result.data.chartList.forEach(item => {
|
||||
const transactionDate = item.transactionDate;
|
||||
const date = `${dayjs(transactionDate).format('MM-DD')} ${days[dayjs(transactionDate).day()]}`;
|
||||
// 计算总和
|
||||
count.value += Number(item.amount);
|
||||
|
||||
// 设置坐标数据
|
||||
analyseData.value.push(item.amount);
|
||||
analyseXAxis.value.push(date);
|
||||
});
|
||||
|
@ -60,6 +77,26 @@ const onSearch = async () => {
|
|||
});
|
||||
};
|
||||
|
||||
/* 初始化数据 */
|
||||
async function onTableSearch() {
|
||||
form.loading = true;
|
||||
|
||||
// 查询账单数据
|
||||
const result = await fetchGetUserBillList({ ...form, ...form.pagination });
|
||||
dataList.value = result.data.list;
|
||||
form.pagination.currentPage = result.data.pageNo;
|
||||
form.pagination.pageSize = result.data.pageSize;
|
||||
form.pagination.total = result.data.total;
|
||||
|
||||
form.loading = false;
|
||||
}
|
||||
|
||||
/* 修改分页 */
|
||||
async function onCurrentChange(page: number) {
|
||||
form.pagination.currentPage = page;
|
||||
await onSearch();
|
||||
}
|
||||
|
||||
/** 选择查询日期 */
|
||||
const onChangeDateRange = async dateRange => {
|
||||
form.startDate = dateRange[0];
|
||||
|
@ -78,8 +115,12 @@ onMounted(() => {
|
|||
:analyseXAxis="analyseXAxis"
|
||||
:category-data="categoryList"
|
||||
:color="['#41b6ff', '#F56C6C']"
|
||||
:count="count"
|
||||
:data-list="dataList"
|
||||
:date="[form.startDate, form.endDate]"
|
||||
:financialType="form.type"
|
||||
:form="form"
|
||||
:on-current-change="onCurrentChange"
|
||||
:title="title"
|
||||
:top-data="topList"
|
||||
@emit-date-range="onChangeDateRange"
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<script lang="ts" setup>
|
||||
import Analyse from '@/components/Analyse/index.vue';
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { currentMouth, days } from '@/enums/dateEnums';
|
||||
import { fetchGetExpendOrIncome } from '@/api/v1/financial/user/billUser';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import dayjs from 'dayjs';
|
||||
import { currentMouth, days } from '@/enums/dateEnums';
|
||||
import { fetchGetExpendOrIncome, fetchGetUserBillList } from '@/api/v1/financial/user/billUser';
|
||||
|
||||
const title = {
|
||||
analyse: $t('revenueAnalysis'),
|
||||
|
@ -20,20 +20,33 @@ const analyseData = ref([]);
|
|||
const categoryList = ref([]);
|
||||
// 排行榜数据
|
||||
const topList = ref([]);
|
||||
|
||||
// 表格数据
|
||||
const dataList = ref([]);
|
||||
// 总金额
|
||||
const count = ref(0);
|
||||
// 查询表单
|
||||
const form = reactive({
|
||||
type: 1,
|
||||
startDate: dayjs(currentMouth[0]).format('YYYY-MM-DD'),
|
||||
endDate: dayjs(currentMouth[1]).format('YYYY-MM-DD'),
|
||||
pagination: {
|
||||
pageSize: 10,
|
||||
currentPage: 1,
|
||||
layout: 'prev, pager, next',
|
||||
total: 1,
|
||||
align: 'center',
|
||||
hideOnSinglePage: false,
|
||||
},
|
||||
});
|
||||
|
||||
/** 查询账单收入 */
|
||||
/** 查询账单支出 */
|
||||
const onSearch = async () => {
|
||||
// 格式化请求数据
|
||||
form.startDate = dayjs(form.startDate).format('YYYY-MM-DD');
|
||||
form.endDate = dayjs(form.endDate).format('YYYY-MM-DD');
|
||||
|
||||
// 获取数据
|
||||
await onTableSearch();
|
||||
const result = await fetchGetExpendOrIncome(form);
|
||||
if (result.code !== 200) return;
|
||||
|
||||
|
@ -43,6 +56,10 @@ const onSearch = async () => {
|
|||
result.data.chartList.forEach(item => {
|
||||
const transactionDate = item.transactionDate;
|
||||
const date = `${dayjs(transactionDate).format('MM-DD')} ${days[dayjs(transactionDate).day()]}`;
|
||||
// 计算总和
|
||||
count.value += Number(item.amount);
|
||||
|
||||
// 设置坐标数据
|
||||
analyseData.value.push(item.amount);
|
||||
analyseXAxis.value.push(date);
|
||||
});
|
||||
|
@ -61,6 +78,25 @@ const onSearch = async () => {
|
|||
});
|
||||
};
|
||||
|
||||
/* 初始化数据 */
|
||||
async function onTableSearch() {
|
||||
form.loading = true;
|
||||
|
||||
const result = await fetchGetUserBillList({ ...form, ...form.pagination });
|
||||
dataList.value = result.data.list;
|
||||
form.pagination.currentPage = result.data.pageNo;
|
||||
form.pagination.pageSize = result.data.pageSize;
|
||||
form.pagination.total = result.data.total;
|
||||
|
||||
form.loading = false;
|
||||
}
|
||||
|
||||
/* 修改分页 */
|
||||
async function onCurrentChange(page: number) {
|
||||
form.pagination.currentPage = page;
|
||||
await onSearch();
|
||||
}
|
||||
|
||||
/** 选择查询日期 */
|
||||
const onChangeDateRange = async dateRange => {
|
||||
form.startDate = dateRange[0];
|
||||
|
@ -79,8 +115,12 @@ onMounted(() => {
|
|||
:analyseXAxis="analyseXAxis"
|
||||
:category-data="categoryList"
|
||||
:color="['#41b6ff', '#67C23A']"
|
||||
:count="count"
|
||||
:data-list="dataList"
|
||||
:date="[form.startDate, form.endDate]"
|
||||
:financialType="form.type"
|
||||
:form="form"
|
||||
:on-current-change="onCurrentChange"
|
||||
:title="title"
|
||||
:top-data="topList"
|
||||
@emit-date-range="onChangeDateRange"
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
<script lang="ts" setup>
|
||||
import Analyse from '@/components/Analyse/index.vue';
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import LoadingSvg from '@/assets/svg/loading.svg';
|
||||
import { useAdminUserStore } from '@/store/system/adminUser';
|
||||
import dayjs from 'dayjs';
|
||||
import { currentMouth, days } from '@/enums/dateEnums';
|
||||
import { fetchGetExpendOrIncome } from '@/api/v1/financial/user/billUser';
|
||||
import { fetchGetBillList } from '@/api/v1/financial/admin/bill';
|
||||
|
||||
const title = {
|
||||
analyse: $t('expenditureAnalysis'),
|
||||
category: $t('paymentLedger'),
|
||||
table: $t('dataStatistics'),
|
||||
top: $t('rankingList'),
|
||||
};
|
||||
const adminUserStore = useAdminUserStore();
|
||||
const loading = ref(false);
|
||||
// 用户信息列表
|
||||
const userDataList = ref();
|
||||
|
||||
// 分析概览
|
||||
const analyseXAxis = ref([]);
|
||||
const analyseData = ref([]);
|
||||
// 分类数据
|
||||
const categoryList = ref([]);
|
||||
// 排行榜数据
|
||||
const topList = ref([]);
|
||||
const dataList = ref([]);
|
||||
// 总金额
|
||||
const count = ref(0);
|
||||
|
||||
// 查询表单
|
||||
const form = reactive({
|
||||
userId: undefined,
|
||||
type: -1,
|
||||
startDate: dayjs(currentMouth[0]).format('YYYY-MM-DD'),
|
||||
endDate: dayjs(currentMouth[1]).format('YYYY-MM-DD'),
|
||||
pagination: {
|
||||
pageSize: 10,
|
||||
currentPage: 1,
|
||||
layout: 'prev, pager, next',
|
||||
total: 1,
|
||||
align: 'center',
|
||||
hideOnSinglePage: false,
|
||||
},
|
||||
loading: false,
|
||||
});
|
||||
|
||||
/** 查询账单支出 */
|
||||
const onSearch = async () => {
|
||||
// 格式化请求数据
|
||||
form.startDate = dayjs(form.startDate).format('YYYY-MM-DD');
|
||||
form.endDate = dayjs(form.endDate).format('YYYY-MM-DD');
|
||||
|
||||
// 获取数据
|
||||
await onTableSearch();
|
||||
const result = await fetchGetExpendOrIncome(form);
|
||||
if (result.code !== 200) return;
|
||||
|
||||
// 分析概览
|
||||
analyseData.value = [];
|
||||
analyseXAxis.value = [];
|
||||
result.data.chartList.forEach(item => {
|
||||
const transactionDate = item.transactionDate;
|
||||
const date = `${dayjs(transactionDate).format('MM-DD')} ${days[dayjs(transactionDate).day()]}`;
|
||||
// 计算总和
|
||||
count.value += Number(item.amount);
|
||||
|
||||
// 设置坐标数据
|
||||
analyseData.value.push(item.amount);
|
||||
analyseXAxis.value.push(date);
|
||||
});
|
||||
|
||||
// 分类数据
|
||||
categoryList.value = result.data.categoryAmounts.map(categoryAmount => ({
|
||||
value: categoryAmount.amount,
|
||||
name: categoryAmount.categoryName,
|
||||
}));
|
||||
|
||||
// 排行榜
|
||||
topList.value = result.data.list.map(item => {
|
||||
const transactionDate = item.transactionDate;
|
||||
const date = `${dayjs(transactionDate).format('YYYY-MM-DD')} ${days[dayjs(transactionDate).day()]}`;
|
||||
return { date, amount: item.amount, name: item.categoryName };
|
||||
});
|
||||
};
|
||||
|
||||
/* 初始化数据 */
|
||||
async function onTableSearch() {
|
||||
form.loading = true;
|
||||
|
||||
// 查询账单数据
|
||||
const result = await fetchGetBillList({ ...form, ...form.pagination });
|
||||
dataList.value = result.data.list;
|
||||
form.pagination.currentPage = result.data.pageNo;
|
||||
form.pagination.pageSize = result.data.pageSize;
|
||||
form.pagination.total = result.data.total;
|
||||
|
||||
form.loading = false;
|
||||
}
|
||||
|
||||
/* 修改分页 */
|
||||
async function onCurrentChange(page: number) {
|
||||
form.pagination.currentPage = page;
|
||||
await onSearch();
|
||||
}
|
||||
|
||||
/** 选择查询日期 */
|
||||
const onChangeDateRange = dateRange => {
|
||||
form.startDate = dateRange[0];
|
||||
form.endDate = dateRange[1];
|
||||
onSearch();
|
||||
};
|
||||
|
||||
/** 查询用户信息 */
|
||||
const onSearchUserinfo = async (keyword: string) => {
|
||||
loading.value = true;
|
||||
userDataList.value = await adminUserStore.queryUser({ keyword });
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
onSearch();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Analyse
|
||||
:analyse-data="analyseData"
|
||||
:analyseXAxis="analyseXAxis"
|
||||
:category-data="categoryList"
|
||||
:color="['#41b6ff', '#F56C6C']"
|
||||
:count="count"
|
||||
:data-list="dataList"
|
||||
:date="[form.startDate, form.endDate]"
|
||||
:financialType="form.type"
|
||||
:form="form"
|
||||
:on-current-change="onCurrentChange"
|
||||
:title="title"
|
||||
:top-data="topList"
|
||||
@emit-date-range="onChangeDateRange"
|
||||
>
|
||||
<template #formBefore>
|
||||
<el-select
|
||||
v-model="form.userId"
|
||||
:loading="loading"
|
||||
:placeholder="$t('user')"
|
||||
:remote-method="onSearchUserinfo"
|
||||
class="!w-[180px]"
|
||||
clearable
|
||||
filterable
|
||||
remote
|
||||
remote-show-suffix
|
||||
@change="onSearch"
|
||||
>
|
||||
<el-option v-for="item in userDataList" :key="item.id" :label="item.username" :value="item.id" />
|
||||
<template #loading>
|
||||
<el-icon class="is-loading">
|
||||
<LoadingSvg />
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-select>
|
||||
</template>
|
||||
</Analyse>
|
||||
</template>
|
|
@ -0,0 +1,168 @@
|
|||
<script lang="ts" setup>
|
||||
import Analyse from '@/components/Analyse/index.vue';
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import LoadingSvg from '@/assets/svg/loading.svg';
|
||||
import { useAdminUserStore } from '@/store/system/adminUser';
|
||||
import dayjs from 'dayjs';
|
||||
import { currentMouth, days } from '@/enums/dateEnums';
|
||||
import { fetchGetExpendOrIncome } from '@/api/v1/financial/user/billUser';
|
||||
import { fetchGetBillList } from '@/api/v1/financial/admin/bill';
|
||||
|
||||
const title = {
|
||||
analyse: $t('revenueAnalysis'),
|
||||
category: $t('incomeBrackets'),
|
||||
table: $t('dataStatistics'),
|
||||
top: $t('rankingList'),
|
||||
};
|
||||
|
||||
const adminUserStore = useAdminUserStore();
|
||||
const loading = ref(false);
|
||||
// 用户信息列表
|
||||
const userDataList = ref();
|
||||
|
||||
// 分析概览
|
||||
const analyseXAxis = ref([]);
|
||||
const analyseData = ref([]);
|
||||
// 分类数据
|
||||
const categoryList = ref([]);
|
||||
// 排行榜数据
|
||||
const topList = ref([]);
|
||||
const dataList = ref([]);
|
||||
// 总金额
|
||||
const count = ref(0);
|
||||
|
||||
// 查询表单
|
||||
const form = reactive({
|
||||
userId: undefined,
|
||||
type: 1,
|
||||
startDate: dayjs(currentMouth[0]).format('YYYY-MM-DD'),
|
||||
endDate: dayjs(currentMouth[1]).format('YYYY-MM-DD'),
|
||||
pagination: {
|
||||
pageSize: 10,
|
||||
currentPage: 1,
|
||||
layout: 'prev, pager, next',
|
||||
total: 1,
|
||||
align: 'center',
|
||||
hideOnSinglePage: false,
|
||||
},
|
||||
loading: false,
|
||||
});
|
||||
|
||||
/** 查询账单支出 */
|
||||
const onSearch = async () => {
|
||||
// 格式化请求数据
|
||||
form.startDate = dayjs(form.startDate).format('YYYY-MM-DD');
|
||||
form.endDate = dayjs(form.endDate).format('YYYY-MM-DD');
|
||||
|
||||
// 获取数据
|
||||
await onTableSearch();
|
||||
const result = await fetchGetExpendOrIncome(form);
|
||||
if (result.code !== 200) return;
|
||||
|
||||
// 分析概览
|
||||
analyseData.value = [];
|
||||
analyseXAxis.value = [];
|
||||
result.data.chartList.forEach(item => {
|
||||
const transactionDate = item.transactionDate;
|
||||
const date = `${dayjs(transactionDate).format('MM-DD')} ${days[dayjs(transactionDate).day()]}`;
|
||||
// 计算总和
|
||||
count.value += Number(item.amount);
|
||||
|
||||
// 设置坐标数据
|
||||
analyseData.value.push(item.amount);
|
||||
analyseXAxis.value.push(date);
|
||||
});
|
||||
|
||||
// 分类数据
|
||||
categoryList.value = result.data.categoryAmounts.map(categoryAmount => ({
|
||||
value: categoryAmount.amount,
|
||||
name: categoryAmount.categoryName,
|
||||
}));
|
||||
|
||||
// 排行榜
|
||||
topList.value = result.data.list.map(item => {
|
||||
const transactionDate = item.transactionDate;
|
||||
const date = `${dayjs(transactionDate).format('YYYY-MM-DD')} ${days[dayjs(transactionDate).day()]}`;
|
||||
return { date, amount: item.amount, name: item.categoryName };
|
||||
});
|
||||
};
|
||||
|
||||
/* 查询表格数据 */
|
||||
async function onTableSearch() {
|
||||
form.loading = true;
|
||||
|
||||
// 获取账单数据
|
||||
const result = await fetchGetBillList({ ...form, ...form.pagination });
|
||||
dataList.value = result.data.list;
|
||||
form.pagination.currentPage = result.data.pageNo;
|
||||
form.pagination.pageSize = result.data.pageSize;
|
||||
form.pagination.total = result.data.total;
|
||||
|
||||
form.loading = false;
|
||||
}
|
||||
|
||||
/* 修改分页 */
|
||||
async function onCurrentChange(page: number) {
|
||||
form.pagination.currentPage = page;
|
||||
await onSearch();
|
||||
}
|
||||
|
||||
/** 选择查询日期 */
|
||||
const onChangeDateRange = dateRange => {
|
||||
form.startDate = dateRange[0];
|
||||
form.endDate = dateRange[1];
|
||||
onSearch();
|
||||
};
|
||||
|
||||
/** 查询用户数据 */
|
||||
const onSearchUserinfo = async (keyword: string) => {
|
||||
loading.value = true;
|
||||
userDataList.value = await adminUserStore.queryUser({ keyword });
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
onSearch();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Analyse
|
||||
:analyse-data="analyseData"
|
||||
:analyseXAxis="analyseXAxis"
|
||||
:category-data="categoryList"
|
||||
:color="['#41b6ff', '#67C23A']"
|
||||
:count="count"
|
||||
:data-list="dataList"
|
||||
:date="[form.startDate, form.endDate]"
|
||||
:financialType="form.type"
|
||||
:form="form"
|
||||
:on-current-change="onCurrentChange"
|
||||
:title="title"
|
||||
:top-data="topList"
|
||||
@emit-date-range="onChangeDateRange"
|
||||
>
|
||||
<template #formBefore>
|
||||
<el-select
|
||||
v-model="form.userId"
|
||||
:loading="loading"
|
||||
:placeholder="$t('user')"
|
||||
:remote-method="onSearchUserinfo"
|
||||
class="!w-[180px]"
|
||||
clearable
|
||||
filterable
|
||||
remote
|
||||
remote-show-suffix
|
||||
@change="onSearch"
|
||||
>
|
||||
<el-option v-for="item in userDataList" :key="item.id" :label="item.username" :value="item.id" />
|
||||
<template #loading>
|
||||
<el-icon class="is-loading">
|
||||
<LoadingSvg />
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-select>
|
||||
</template>
|
||||
</Analyse>
|
||||
</template>
|
Loading…
Reference in New Issue