304 lines
9.5 KiB
Vue
304 lines
9.5 KiB
Vue
<script>
|
||
/**
|
||
* 首页消费趋势:账户汇总来自会话总览,折线图则仅将交易第一页最多 200 条记录按近六个月归集。
|
||
* 两者统计来源不同,图表不能作为完整账务报表使用。
|
||
*/
|
||
import "~/assets/styles/ChartBox.CYP_mhat.css";
|
||
import "~/assets/styles/HomeConsumeTrend.DfrmEdD9.css";
|
||
import { toDisplayString } from "vue";
|
||
import { onMounted } from "vue";
|
||
import { createBlock } from "vue";
|
||
import { ref } from "vue";
|
||
import { withCtx } from "vue";
|
||
import { computed } from "vue";
|
||
import { createElementBlock } from "vue";
|
||
import { createElementVNode } from "vue";
|
||
import { createTextVNode } from "vue";
|
||
import { unref } from "vue";
|
||
import { defineComponent } from "vue";
|
||
import { createVNode } from "vue";
|
||
import { openBlock } from "vue";
|
||
import { NuxtLink } from "#components";
|
||
import { useApi } from "~/lib/auth.js";
|
||
import { useAuth } from "~/lib/auth.js";
|
||
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
|
||
import { t as useTheme_t } from "~/lib/useTheme.js";
|
||
import ChartBox from "~/components/ChartBox.vue";
|
||
import ListEmpty from "~/components/ListEmpty.vue";
|
||
import skeleton from "primevue/skeleton";
|
||
var x = {
|
||
class: `home-card`,
|
||
},
|
||
S = {
|
||
class: `home-card-head`,
|
||
},
|
||
C = {
|
||
class: `home-mini-stats`,
|
||
},
|
||
w = {
|
||
class: `home-mini-stat`,
|
||
},
|
||
T = {
|
||
class: `home-mini-value`,
|
||
},
|
||
E = {
|
||
class: `home-mini-stat`,
|
||
},
|
||
D = {
|
||
class: `home-mini-value`,
|
||
},
|
||
O = {
|
||
class: `home-mini-stat`,
|
||
},
|
||
k = {
|
||
class: `home-mini-value`,
|
||
},
|
||
A = {
|
||
class: `chart-wrap`,
|
||
},
|
||
j = {
|
||
key: 0,
|
||
},
|
||
M = 6,
|
||
N = Object.assign(
|
||
_plugin_vue_export_helper_t(
|
||
defineComponent({
|
||
__name: `HomeConsumeTrend`,
|
||
setup(u) {
|
||
let g = useApi(),
|
||
N = useAuth(),
|
||
P = useTheme_t(),
|
||
F = ref([]),
|
||
I = ref(!0),
|
||
L = ref(``);
|
||
// 月份键包含年份,跨年时不会把不同年份的同名月份合并。
|
||
function R(e) {
|
||
let t = new Date();
|
||
return Array.from(
|
||
{
|
||
length: e,
|
||
},
|
||
(n, r) => {
|
||
let i = new Date(
|
||
t.getFullYear(),
|
||
t.getMonth() - (e - 1 - r),
|
||
1,
|
||
);
|
||
return {
|
||
key: `${i.getFullYear()}-${i.getMonth() + 1}`,
|
||
label: `${i.getMonth() + 1}月`,
|
||
};
|
||
},
|
||
);
|
||
}
|
||
// 按秒级 create_time 归入本地月份;没有记录的月份保持为零,图表只反映此页返回的记录。
|
||
onMounted(async () => {
|
||
try {
|
||
let e = await g.get(`/transaction`, {
|
||
page: 1,
|
||
limit: 200,
|
||
}),
|
||
t = R(M),
|
||
n = new Map(t.map((e) => [e.key, 0]));
|
||
for (let t of e.list ?? []) {
|
||
let e = new Date((t.create_time || 0) * 1e3),
|
||
r = `${e.getFullYear()}-${e.getMonth() + 1}`;
|
||
n.has(r) && n.set(r, (n.get(r) ?? 0) + Number(t.amount || 0));
|
||
}
|
||
F.value = t.map((e) => ({
|
||
label: e.label,
|
||
amount: Math.round((n.get(e.key) ?? 0) * 100) / 100,
|
||
}));
|
||
} catch (e) {
|
||
L.value = e instanceof Error ? e.message : `消费记录加载失败`;
|
||
} finally {
|
||
I.value = !1;
|
||
}
|
||
});
|
||
// 图表选项随月份数据与主题更新,ChartBox 负责图表实例的生命周期。
|
||
let z = computed(() => (P.isDark.value ? `#618dff` : `#0052d9`)),
|
||
B = computed(() => ({
|
||
grid: {
|
||
left: 4,
|
||
right: 8,
|
||
top: 16,
|
||
bottom: 0,
|
||
outerBoundsMode: `same`,
|
||
outerBoundsContain: `axisLabel`,
|
||
},
|
||
tooltip: {
|
||
trigger: `axis`,
|
||
valueFormatter: (e) => `¥${Number(e ?? 0).toFixed(2)}`,
|
||
},
|
||
xAxis: {
|
||
type: `category`,
|
||
boundaryGap: !1,
|
||
data: F.value.map((e) => e.label),
|
||
},
|
||
yAxis: {
|
||
type: `value`,
|
||
axisLabel: {
|
||
formatter: `¥{value}`,
|
||
},
|
||
},
|
||
series: [
|
||
{
|
||
type: `line`,
|
||
smooth: !0,
|
||
symbol: `circle`,
|
||
symbolSize: 6,
|
||
data: F.value.map((e) => e.amount),
|
||
itemStyle: {
|
||
color: z.value,
|
||
},
|
||
lineStyle: {
|
||
color: z.value,
|
||
width: 2,
|
||
},
|
||
areaStyle: {
|
||
color: z.value,
|
||
opacity: 0.1,
|
||
},
|
||
},
|
||
],
|
||
}));
|
||
// 顶部账户汇总与趋势请求分开显示,趋势失败不把账户累计消费改成零。
|
||
return (t, r) => {
|
||
let a = NuxtLink,
|
||
u = skeleton,
|
||
m = ListEmpty,
|
||
h = ChartBox;
|
||
return (
|
||
openBlock(),
|
||
createElementBlock(`div`, x, [
|
||
createElementVNode(`div`, S, [
|
||
(r[1] ||= createElementVNode(
|
||
`div`,
|
||
{
|
||
class: `home-card-title`,
|
||
},
|
||
[
|
||
createElementVNode(`i`, {
|
||
class: `pi pi-chart-line`,
|
||
}),
|
||
createTextVNode(`消费趋势`),
|
||
],
|
||
-1,
|
||
)),
|
||
createVNode(
|
||
a,
|
||
{
|
||
to: `/finance`,
|
||
class: `home-card-more`,
|
||
},
|
||
{
|
||
default: withCtx(() => [
|
||
...(r[0] ||= [createTextVNode(`消费记录 ›`, -1)]),
|
||
]),
|
||
_: 1,
|
||
},
|
||
),
|
||
]),
|
||
createElementVNode(`div`, C, [
|
||
createElementVNode(`div`, w, [
|
||
(r[2] ||= createElementVNode(
|
||
`span`,
|
||
{
|
||
class: `home-mini-label`,
|
||
},
|
||
`本月消费`,
|
||
-1,
|
||
)),
|
||
createElementVNode(
|
||
`span`,
|
||
T,
|
||
`¥` +
|
||
toDisplayString(
|
||
unref(N).overview?.this_month_consume ?? `--`,
|
||
),
|
||
1,
|
||
),
|
||
]),
|
||
createElementVNode(`div`, E, [
|
||
(r[3] ||= createElementVNode(
|
||
`span`,
|
||
{
|
||
class: `home-mini-label`,
|
||
},
|
||
`累计消费`,
|
||
-1,
|
||
)),
|
||
createElementVNode(
|
||
`span`,
|
||
D,
|
||
`¥` + toDisplayString(unref(N).overview?.consume ?? `--`),
|
||
1,
|
||
),
|
||
]),
|
||
createElementVNode(`div`, O, [
|
||
(r[4] ||= createElementVNode(
|
||
`span`,
|
||
{
|
||
class: `home-mini-label`,
|
||
},
|
||
`未付订单`,
|
||
-1,
|
||
)),
|
||
createElementVNode(
|
||
`span`,
|
||
k,
|
||
toDisplayString(unref(N).overview?.unpaid_order ?? `--`),
|
||
1,
|
||
),
|
||
]),
|
||
]),
|
||
createElementVNode(`div`, A, [
|
||
unref(I)
|
||
? (openBlock(),
|
||
createElementBlock(`div`, j, [
|
||
createVNode(u, {
|
||
height: `150px`,
|
||
}),
|
||
]))
|
||
: unref(L)
|
||
? (openBlock(),
|
||
createBlock(
|
||
m,
|
||
{
|
||
key: 1,
|
||
icon: `pi pi-exclamation-circle`,
|
||
title: `消费趋势加载失败`,
|
||
description: unref(L),
|
||
},
|
||
null,
|
||
8,
|
||
[`description`],
|
||
))
|
||
: (openBlock(),
|
||
createBlock(
|
||
h,
|
||
{
|
||
key: 2,
|
||
option: unref(B),
|
||
height: 150,
|
||
},
|
||
null,
|
||
8,
|
||
[`option`],
|
||
)),
|
||
]),
|
||
])
|
||
);
|
||
};
|
||
},
|
||
}),
|
||
[[`__scopeId`, `data-v-90c11ad2`]],
|
||
),
|
||
{
|
||
__name: `HomeConsumeTrend`,
|
||
},
|
||
);
|
||
export {};
|
||
export default N;
|
||
</script>
|