Files
cneicy 42dfead9cd
前端验证 / verify (push) Failing after 15m3s
feat(ui): 优化控制台响应式布局与视觉体验
- 统一页面标题、圆角、字体和响应式断点,调整暗色主题及图表配色
- 新增表格列标签插件,在窄屏下将表格转换为卡片布局,优化实例、订单、工单等列表展示
- 支持移动端点击订单行进入详情,并完善订单凭据的打印布局
- 在财务中心展示本月及累计消费,补充充值关闭时的提示
- 优化工单详情布局,将附件上传入口整合至富文本编辑器工具栏
- 调整实例操作按钮、SSH 密钥操作及安全菜单图标
- 为多个页面显式导入 definePageMeta,完善页面元数据声明
2026-11-07 00:09:57 +08:00

304 lines
9.5 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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 ? `#60a5fa` : `#2563eb`)),
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>