mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-11-03 13:44:47 +08:00
refactor: 带来更美观精致的首页 (#848)
This commit is contained in:
@@ -1,13 +1,8 @@
|
||||
import {
|
||||
clone,
|
||||
useDark,
|
||||
useECharts,
|
||||
type EchartOptions
|
||||
} from "@pureadmin/utils";
|
||||
import { ref, computed } from "vue";
|
||||
import { tableDataDrag } from "../data";
|
||||
import { message } from "@/utils/message";
|
||||
import { templateRef } from "@vueuse/core";
|
||||
import { ref, type Ref, computed } from "vue";
|
||||
import { clone, useDark, useECharts } from "@pureadmin/utils";
|
||||
|
||||
export function useColumns() {
|
||||
const dataList = ref(clone(tableDataDrag, true).splice(0, 4));
|
||||
@@ -33,19 +28,13 @@ export function useColumns() {
|
||||
|
||||
const { isDark } = useDark();
|
||||
|
||||
const theme: EchartOptions["theme"] = computed(() => {
|
||||
return isDark.value ? "dark" : "light";
|
||||
});
|
||||
const theme = computed(() => (isDark.value ? "dark" : "light"));
|
||||
|
||||
dataList.value.forEach((_, i) => {
|
||||
const { setOptions } = useECharts(
|
||||
templateRef(`PieChartRef${i}`) as Ref<HTMLDivElement>,
|
||||
{
|
||||
theme
|
||||
}
|
||||
);
|
||||
const { setOptions } = useECharts(templateRef(`PieChartRef${i}`), {
|
||||
theme
|
||||
});
|
||||
|
||||
// https://pure-admin-utils.netlify.app/hooks/useEcharts/useEcharts.html
|
||||
setOptions(
|
||||
{
|
||||
tooltip: {
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, type Ref } from "vue";
|
||||
import { useAppStoreHook } from "@/store/modules/app";
|
||||
import {
|
||||
delay,
|
||||
useDark,
|
||||
useECharts,
|
||||
type EchartOptions
|
||||
} from "@pureadmin/utils";
|
||||
import * as echarts from "echarts/core";
|
||||
|
||||
const { isDark } = useDark();
|
||||
|
||||
const theme: EchartOptions["theme"] = computed(() => {
|
||||
return isDark.value ? "dark" : "light";
|
||||
});
|
||||
|
||||
const barChartRef = ref<HTMLDivElement | null>(null);
|
||||
const { setOptions, resize } = useECharts(barChartRef as Ref<HTMLDivElement>, {
|
||||
theme
|
||||
});
|
||||
|
||||
setOptions(
|
||||
{
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
axisPointer: {
|
||||
type: "shadow"
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
bottom: "20px",
|
||||
right: "10px"
|
||||
},
|
||||
legend: {
|
||||
//@ts-expect-error
|
||||
right: true,
|
||||
data: ["watchers", "fork", "star"]
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
type: "category",
|
||||
axisTick: {
|
||||
alignWithLabel: true
|
||||
},
|
||||
axisLabel: {
|
||||
interval: 0
|
||||
// width: "70",
|
||||
// overflow: "truncate"
|
||||
},
|
||||
data: ["2021", "2022", "2023"],
|
||||
triggerEvent: true
|
||||
}
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: "value",
|
||||
triggerEvent: true
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: "watchers",
|
||||
type: "bar",
|
||||
barWidth: "15%",
|
||||
itemStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: "#e6a23c"
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "#eebe77"
|
||||
}
|
||||
])
|
||||
},
|
||||
data: [200, 320, 800]
|
||||
},
|
||||
{
|
||||
name: "fork",
|
||||
type: "bar",
|
||||
barWidth: "15%",
|
||||
itemStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: "#f56c6c"
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "#f89898"
|
||||
}
|
||||
])
|
||||
},
|
||||
data: [1600, 2460, 4500]
|
||||
},
|
||||
{
|
||||
name: "star",
|
||||
type: "bar",
|
||||
barWidth: "15%",
|
||||
itemStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: "#409EFF"
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "#53a7ff"
|
||||
}
|
||||
])
|
||||
},
|
||||
data: [1450, 3620, 7500]
|
||||
}
|
||||
],
|
||||
addTooltip: true
|
||||
},
|
||||
{
|
||||
name: "click",
|
||||
callback: params => {
|
||||
console.log("click", params);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => useAppStoreHook().getSidebarStatus,
|
||||
() => {
|
||||
delay(600).then(() => resize());
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="barChartRef" style="width: 100%; height: 35vh" />
|
||||
</template>
|
||||
@@ -1,30 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { useColumns } from "./columns";
|
||||
const { columnsA, columnsB, columnsC } = useColumns();
|
||||
|
||||
const list = [
|
||||
{
|
||||
columns: columnsA,
|
||||
column: 3
|
||||
},
|
||||
{
|
||||
columns: columnsB,
|
||||
column: 2
|
||||
},
|
||||
{
|
||||
columns: columnsC,
|
||||
column: 1
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PureDescriptions
|
||||
v-for="(item, index) in list"
|
||||
:key="index"
|
||||
:columns="item.columns"
|
||||
:column="item.column"
|
||||
direction="vertical"
|
||||
border
|
||||
/>
|
||||
</template>
|
||||
@@ -1,187 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { useIntervalFn } from "@vueuse/core";
|
||||
import { ref, computed, watch, type Ref } from "vue";
|
||||
import { useAppStoreHook } from "@/store/modules/app";
|
||||
import {
|
||||
delay,
|
||||
useDark,
|
||||
useECharts,
|
||||
type EchartOptions
|
||||
} from "@pureadmin/utils";
|
||||
|
||||
const { isDark } = useDark();
|
||||
|
||||
const theme: EchartOptions["theme"] = computed(() => {
|
||||
return isDark.value ? "dark" : "default";
|
||||
});
|
||||
|
||||
const lineChartRef = ref<HTMLDivElement | null>(null);
|
||||
const { setOptions, getInstance, resize } = useECharts(
|
||||
lineChartRef as Ref<HTMLDivElement>,
|
||||
{ theme }
|
||||
);
|
||||
|
||||
const xData = (() => {
|
||||
const data: any[] = [];
|
||||
for (let i = 1; i < 31; i++) {
|
||||
data.push(`${i}日`);
|
||||
}
|
||||
return data;
|
||||
})();
|
||||
|
||||
setOptions(
|
||||
{
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
axisPointer: {
|
||||
type: "shadow"
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
bottom: "20px",
|
||||
right: "10px"
|
||||
},
|
||||
legend: {
|
||||
//@ts-expect-error
|
||||
right: true,
|
||||
data: ["fork", "star"]
|
||||
},
|
||||
calculable: true,
|
||||
xAxis: [
|
||||
{
|
||||
triggerEvent: true,
|
||||
type: "category",
|
||||
splitLine: {
|
||||
show: false
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
data: xData
|
||||
}
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
triggerEvent: true,
|
||||
type: "value",
|
||||
splitLine: {
|
||||
show: false
|
||||
},
|
||||
axisLine: {
|
||||
show: true
|
||||
}
|
||||
}
|
||||
],
|
||||
dataZoom: [
|
||||
{
|
||||
type: "slider",
|
||||
show: false,
|
||||
realtime: true,
|
||||
startValue: 0,
|
||||
endValue: 24
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: "fork",
|
||||
type: "line",
|
||||
symbolSize: 10,
|
||||
symbol: "circle",
|
||||
color: "#f56c6c",
|
||||
markPoint: {
|
||||
label: {
|
||||
color: "#fff"
|
||||
},
|
||||
data: [
|
||||
{
|
||||
type: "max",
|
||||
name: "最大值"
|
||||
},
|
||||
{
|
||||
type: "min",
|
||||
name: "最小值"
|
||||
}
|
||||
]
|
||||
},
|
||||
data: [
|
||||
509, 917, 2455, 2610, 2719, 3033, 3044, 3085, 2708, 2809, 2117, 2000,
|
||||
1455, 1210, 719, 733, 944, 2285, 2208, 3372, 3936, 3693, 2962, 2810,
|
||||
3519, 2455, 2610, 2719, 2484, 2078
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "star",
|
||||
type: "line",
|
||||
symbolSize: 10,
|
||||
symbol: "circle",
|
||||
color: "#53a7ff",
|
||||
markPoint: {
|
||||
label: {
|
||||
color: "#fff"
|
||||
},
|
||||
data: [
|
||||
{
|
||||
type: "max",
|
||||
name: "最大值"
|
||||
},
|
||||
{
|
||||
type: "min",
|
||||
name: "最小值"
|
||||
}
|
||||
]
|
||||
},
|
||||
data: [
|
||||
2136, 3693, 2962, 3810, 3519, 3484, 3915, 3823, 3455, 4310, 4019,
|
||||
3433, 3544, 3885, 4208, 3372, 3484, 3915, 3748, 3675, 4009, 4433,
|
||||
3544, 3285, 4208, 3372, 3484, 3915, 3823, 4265, 4298
|
||||
]
|
||||
}
|
||||
],
|
||||
addTooltip: true
|
||||
},
|
||||
{
|
||||
name: "click",
|
||||
callback: params => {
|
||||
console.log("click", params);
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "contextmenu",
|
||||
callback: params => {
|
||||
console.log("contextmenu", params);
|
||||
}
|
||||
},
|
||||
// 点击空白处
|
||||
{
|
||||
type: "zrender",
|
||||
name: "click",
|
||||
callback: params => {
|
||||
console.log("点击空白处", params);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let a = 1;
|
||||
useIntervalFn(() => {
|
||||
if (a == xData.length - 24) {
|
||||
a = 0;
|
||||
}
|
||||
getInstance()!.dispatchAction({
|
||||
type: "dataZoom",
|
||||
startValue: a,
|
||||
endValue: a + 24
|
||||
});
|
||||
a++;
|
||||
}, 2000);
|
||||
|
||||
watch(
|
||||
() => useAppStoreHook().getSidebarStatus,
|
||||
() => {
|
||||
delay(600).then(() => resize());
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="lineChartRef" style="width: 100%; height: 35vh" />
|
||||
</template>
|
||||
@@ -1,81 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, type Ref } from "vue";
|
||||
import { useAppStoreHook } from "@/store/modules/app";
|
||||
import {
|
||||
delay,
|
||||
useDark,
|
||||
useECharts,
|
||||
type EchartOptions
|
||||
} from "@pureadmin/utils";
|
||||
|
||||
const { isDark } = useDark();
|
||||
|
||||
const theme: EchartOptions["theme"] = computed(() => {
|
||||
return isDark.value ? "dark" : "light";
|
||||
});
|
||||
|
||||
const pieChartRef = ref<HTMLDivElement | null>(null);
|
||||
const { setOptions, resize } = useECharts(pieChartRef as Ref<HTMLDivElement>, {
|
||||
theme
|
||||
});
|
||||
|
||||
setOptions(
|
||||
{
|
||||
tooltip: {
|
||||
trigger: "item"
|
||||
},
|
||||
legend: {
|
||||
icon: "circle",
|
||||
//@ts-expect-error
|
||||
right: true
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "Github信息",
|
||||
type: "pie",
|
||||
top: "20%",
|
||||
radius: "80%",
|
||||
center: ["40%", "50%"],
|
||||
color: ["#e6a23c", "#f56c6c", "#53a7ff"],
|
||||
data: [
|
||||
{ value: 400, name: "watchers" },
|
||||
{ value: 1600, name: "forks" },
|
||||
{ value: 7200, name: "star" }
|
||||
]
|
||||
// emphasis: {
|
||||
// itemStyle: {
|
||||
// shadowBlur: 10,
|
||||
// shadowOffsetX: 0,
|
||||
// shadowColor: "rgba(0, 0, 0, 0.5)"
|
||||
// }
|
||||
// }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "click",
|
||||
callback: params => {
|
||||
console.log("click", params);
|
||||
}
|
||||
},
|
||||
// 点击空白处
|
||||
{
|
||||
type: "zrender",
|
||||
name: "click",
|
||||
callback: params => {
|
||||
console.log("点击空白处", params);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => useAppStoreHook().getSidebarStatus,
|
||||
() => {
|
||||
delay(600).then(() => resize());
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="pieChartRef" style="width: 100%; height: 35vh" />
|
||||
</template>
|
||||
112
src/views/welcome/components/chart/bar.vue
Normal file
112
src/views/welcome/components/chart/bar.vue
Normal file
@@ -0,0 +1,112 @@
|
||||
<script setup lang="ts">
|
||||
import { useDark, useECharts } from "@pureadmin/utils";
|
||||
import { type PropType, ref, computed, watch, nextTick } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
requireData: {
|
||||
type: Array as PropType<Array<number>>,
|
||||
default: () => []
|
||||
},
|
||||
questionData: {
|
||||
type: Array as PropType<Array<number>>,
|
||||
default: () => []
|
||||
}
|
||||
});
|
||||
|
||||
const { isDark } = useDark();
|
||||
|
||||
const theme = computed(() => (isDark.value ? "dark" : "light"));
|
||||
|
||||
const chartRef = ref();
|
||||
const { setOptions, resize } = useECharts(chartRef, {
|
||||
theme
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props,
|
||||
async () => {
|
||||
await nextTick(); // 确保DOM更新完成后再执行
|
||||
setOptions({
|
||||
resize: false,
|
||||
color: ["#41b6ff", "#e85f33"],
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
axisPointer: {
|
||||
type: "none"
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
top: "20px",
|
||||
left: "50px",
|
||||
right: 0
|
||||
},
|
||||
legend: {
|
||||
data: ["需求人数", "提问数量"],
|
||||
textStyle: {
|
||||
color: "#606266",
|
||||
fontSize: "0.875rem"
|
||||
},
|
||||
bottom: 0
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
type: "category",
|
||||
data: ["周一", "周二", "周三", "周四", "周五", "周六", "周日"],
|
||||
axisLabel: {
|
||||
fontSize: "0.875rem"
|
||||
},
|
||||
axisPointer: {
|
||||
type: "shadow"
|
||||
}
|
||||
}
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: "value",
|
||||
axisLabel: {
|
||||
fontSize: "0.875rem"
|
||||
},
|
||||
splitLine: {
|
||||
show: false // 去网格线
|
||||
}
|
||||
// name: "单位: 个"
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: "需求人数",
|
||||
type: "bar",
|
||||
barWidth: 10,
|
||||
itemStyle: {
|
||||
color: "#41b6ff",
|
||||
borderRadius: [10, 10, 0, 0]
|
||||
},
|
||||
data: props.requireData
|
||||
},
|
||||
{
|
||||
name: "提问数量",
|
||||
type: "bar",
|
||||
barWidth: 10,
|
||||
itemStyle: {
|
||||
color: "#e86033ce",
|
||||
borderRadius: [10, 10, 0, 0]
|
||||
},
|
||||
data: props.questionData
|
||||
}
|
||||
]
|
||||
});
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
);
|
||||
|
||||
defineExpose({
|
||||
resize
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="chartRef" style="width: 100%; height: 365px" />
|
||||
</template>
|
||||
3
src/views/welcome/components/chart/index.ts
Normal file
3
src/views/welcome/components/chart/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export { default as barChart } from "./bar.vue";
|
||||
export { default as lineChart } from "./line.vue";
|
||||
export { default as roundChart } from "./round.vue";
|
||||
61
src/views/welcome/components/chart/line.vue
Normal file
61
src/views/welcome/components/chart/line.vue
Normal file
@@ -0,0 +1,61 @@
|
||||
<script setup lang="ts">
|
||||
import { type PropType, ref, computed } from "vue";
|
||||
import { useDark, useECharts } from "@pureadmin/utils";
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Array as PropType<Array<number>>,
|
||||
default: () => []
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: "#41b6ff"
|
||||
}
|
||||
});
|
||||
|
||||
const { isDark } = useDark();
|
||||
|
||||
const theme = computed(() => (isDark.value ? "dark" : "light"));
|
||||
|
||||
const chartRef = ref();
|
||||
const { setOptions } = useECharts(chartRef, {
|
||||
theme,
|
||||
renderer: "svg"
|
||||
});
|
||||
|
||||
setOptions({
|
||||
xAxis: {
|
||||
type: "category",
|
||||
show: false,
|
||||
data: props.data
|
||||
},
|
||||
grid: {
|
||||
top: "15px",
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0
|
||||
},
|
||||
yAxis: {
|
||||
show: false,
|
||||
type: "value"
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: props.data,
|
||||
type: "line",
|
||||
symbol: "none",
|
||||
smooth: true,
|
||||
color: props.color,
|
||||
lineStyle: {
|
||||
shadowOffsetY: 3,
|
||||
shadowBlur: 7,
|
||||
shadowColor: props.color
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="chartRef" style="width: 100%; height: 60px" />
|
||||
</template>
|
||||
72
src/views/welcome/components/chart/round.vue
Normal file
72
src/views/welcome/components/chart/round.vue
Normal file
@@ -0,0 +1,72 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from "vue";
|
||||
import { useDark, useECharts } from "@pureadmin/utils";
|
||||
|
||||
const { isDark } = useDark();
|
||||
|
||||
const theme = computed(() => (isDark.value ? "dark" : "light"));
|
||||
|
||||
const chartRef = ref();
|
||||
const { setOptions } = useECharts(chartRef, {
|
||||
theme,
|
||||
renderer: "svg"
|
||||
});
|
||||
|
||||
setOptions({
|
||||
title: {
|
||||
text: "100%",
|
||||
left: "47%",
|
||||
top: "30%",
|
||||
textAlign: "center",
|
||||
textStyle: {
|
||||
fontSize: "16",
|
||||
fontWeight: 600
|
||||
}
|
||||
},
|
||||
polar: {
|
||||
radius: ["100%", "90%"],
|
||||
center: ["50%", "50%"]
|
||||
},
|
||||
angleAxis: {
|
||||
max: 100,
|
||||
show: false
|
||||
},
|
||||
radiusAxis: {
|
||||
type: "category",
|
||||
show: true,
|
||||
axisLabel: {
|
||||
show: false
|
||||
},
|
||||
axisLine: {
|
||||
show: false
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: "bar",
|
||||
roundCap: true,
|
||||
barWidth: 2,
|
||||
showBackground: true,
|
||||
backgroundStyle: {
|
||||
color: "#dfe7ef"
|
||||
},
|
||||
data: [100],
|
||||
coordinateSystem: "polar",
|
||||
color: "#7846e5",
|
||||
itemStyle: {
|
||||
shadowBlur: 2,
|
||||
shadowColor: "#7846e5",
|
||||
shadowOffsetX: 0,
|
||||
shadowOffsetY: 0
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="chartRef" style="width: 100%; height: 60px" />
|
||||
</template>
|
||||
@@ -1,113 +0,0 @@
|
||||
import TypeIt from "@/components/ReTypeit";
|
||||
import OfficeBuilding from "@iconify-icons/ep/office-building";
|
||||
import Tickets from "@iconify-icons/ep/tickets";
|
||||
import Location from "@iconify-icons/ep/location";
|
||||
import Iphone from "@iconify-icons/ep/iphone";
|
||||
import Notebook from "@iconify-icons/ep/notebook";
|
||||
import User from "@iconify-icons/ri/user-3-fill";
|
||||
|
||||
export function useColumns() {
|
||||
const lists = [
|
||||
{ type: "", label: "善良" },
|
||||
{ type: "success", label: "好学" },
|
||||
{ type: "info", label: "幽默" },
|
||||
{ type: "danger", label: "旅游" },
|
||||
{ type: "warning", label: "追剧" }
|
||||
];
|
||||
|
||||
const columnsA = [
|
||||
{
|
||||
labelRenderer: () => (
|
||||
<div class="flex items-center">
|
||||
<el-icon>
|
||||
<iconify-icon-offline icon={User} />
|
||||
</el-icon>
|
||||
用户名
|
||||
</div>
|
||||
),
|
||||
value: "乐于分享的程序员小铭"
|
||||
},
|
||||
{
|
||||
labelRenderer: () => (
|
||||
<div class="flex items-center">
|
||||
<el-icon>
|
||||
<iconify-icon-offline icon={Iphone} />
|
||||
</el-icon>
|
||||
手机号
|
||||
</div>
|
||||
),
|
||||
value: "123456789"
|
||||
},
|
||||
{
|
||||
labelRenderer: () => (
|
||||
<div class="flex items-center">
|
||||
<el-icon>
|
||||
<iconify-icon-offline icon={Location} />
|
||||
</el-icon>
|
||||
居住地
|
||||
</div>
|
||||
),
|
||||
value: "中国"
|
||||
}
|
||||
];
|
||||
|
||||
const columnsB = [
|
||||
{
|
||||
labelRenderer: () => (
|
||||
<div class="flex items-center">
|
||||
<el-icon>
|
||||
<iconify-icon-offline icon={Tickets} />
|
||||
</el-icon>
|
||||
标签
|
||||
</div>
|
||||
),
|
||||
cellRenderer: () => {
|
||||
return lists.map(v => {
|
||||
return (
|
||||
<el-tag class="mr-[10px]" type={v.type} size="small" effect="dark">
|
||||
{v.label}
|
||||
</el-tag>
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
labelRenderer: () => (
|
||||
<div class="flex items-center">
|
||||
<el-icon>
|
||||
<iconify-icon-offline icon={OfficeBuilding} />
|
||||
</el-icon>
|
||||
联系地址
|
||||
</div>
|
||||
),
|
||||
value: "中华人民共和国"
|
||||
}
|
||||
];
|
||||
|
||||
const columnsC = [
|
||||
{
|
||||
labelRenderer: () => (
|
||||
<div class="flex items-center">
|
||||
<el-icon>
|
||||
<iconify-icon-offline icon={Notebook} />
|
||||
</el-icon>
|
||||
个性签名
|
||||
</div>
|
||||
),
|
||||
cellRenderer: () => (
|
||||
<TypeIt
|
||||
className={"github"}
|
||||
values={["办法总比困难多"]}
|
||||
cursor={false}
|
||||
speed={100}
|
||||
/>
|
||||
)
|
||||
}
|
||||
];
|
||||
|
||||
return {
|
||||
columnsA,
|
||||
columnsB,
|
||||
columnsC
|
||||
};
|
||||
}
|
||||
104
src/views/welcome/components/table/columns.tsx
Normal file
104
src/views/welcome/components/table/columns.tsx
Normal file
@@ -0,0 +1,104 @@
|
||||
import { tableData } from "../../data";
|
||||
import { delay } from "@pureadmin/utils";
|
||||
import { ref, onMounted, reactive } from "vue";
|
||||
import type { PaginationProps } from "@pureadmin/table";
|
||||
import ThumbUp from "@iconify-icons/ri/thumb-up-line";
|
||||
import Hearts from "@iconify-icons/ri/hearts-line";
|
||||
import Empty from "./empty.svg?component";
|
||||
|
||||
export function useColumns() {
|
||||
const dataList = ref([]);
|
||||
const loading = ref(true);
|
||||
const columns: TableColumnList = [
|
||||
{
|
||||
sortable: true,
|
||||
label: "序号",
|
||||
prop: "id"
|
||||
},
|
||||
{
|
||||
sortable: true,
|
||||
label: "需求人数",
|
||||
prop: "requiredNumber",
|
||||
filterMultiple: false,
|
||||
// filterClassName: "pure-table-filter", // TODO:https://github.com/element-plus/element-plus/pull/15389
|
||||
filters: [
|
||||
{ text: "≥16000", value: "more" },
|
||||
{ text: "<16000", value: "less" }
|
||||
],
|
||||
filterMethod: (value, { requiredNumber }) => {
|
||||
return value === "more"
|
||||
? requiredNumber >= 16000
|
||||
: requiredNumber < 16000;
|
||||
}
|
||||
},
|
||||
{
|
||||
sortable: true,
|
||||
label: "提问数量",
|
||||
prop: "questionNumber"
|
||||
},
|
||||
{
|
||||
sortable: true,
|
||||
label: "解决数量",
|
||||
prop: "resolveNumber"
|
||||
},
|
||||
{
|
||||
sortable: true,
|
||||
label: "用户满意度",
|
||||
minWidth: 100,
|
||||
prop: "satisfaction",
|
||||
cellRenderer: ({ row }) => (
|
||||
<div class="flex justify-center w-full">
|
||||
<span class="flex items-center w-[60px]">
|
||||
<span class="ml-auto mr-2">{row.satisfaction}%</span>
|
||||
<iconifyIconOffline
|
||||
icon={row.satisfaction > 98 ? Hearts : ThumbUp}
|
||||
color="#e85f33"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
sortable: true,
|
||||
label: "统计日期",
|
||||
prop: "date"
|
||||
},
|
||||
{
|
||||
label: "操作",
|
||||
fixed: "right",
|
||||
slot: "operation"
|
||||
}
|
||||
];
|
||||
|
||||
/** 分页配置 */
|
||||
const pagination = reactive<PaginationProps>({
|
||||
pageSize: 10,
|
||||
currentPage: 1,
|
||||
layout: "prev, pager, next",
|
||||
total: 0,
|
||||
align: "center"
|
||||
});
|
||||
|
||||
function onCurrentChange(page: number) {
|
||||
console.log("onCurrentChange", page);
|
||||
loading.value = true;
|
||||
delay(300).then(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
dataList.value = tableData;
|
||||
pagination.total = dataList.value.length;
|
||||
loading.value = false;
|
||||
});
|
||||
|
||||
return {
|
||||
Empty,
|
||||
loading,
|
||||
columns,
|
||||
dataList,
|
||||
pagination,
|
||||
onCurrentChange
|
||||
};
|
||||
}
|
||||
1
src/views/welcome/components/table/empty.svg
Normal file
1
src/views/welcome/components/table/empty.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" class="empty-icon" viewBox="0 0 1024 1024"><path d="M855.6 427.2H168.5c-12.7 0-24.4 6.9-30.6 18L4.4 684.7C1.5 689.9 0 695.8 0 701.8v287.1c0 19.4 15.7 35.1 35.1 35.1H989c19.4 0 35.1-15.7 35.1-35.1V701.8c0-6-1.5-11.8-4.4-17.1L886.2 445.2c-6.2-11.1-17.9-18-30.6-18M673.4 695.6c-16.5 0-30.8 11.5-34.3 27.7-12.7 58.5-64.8 102.3-127.2 102.3s-114.5-43.8-127.2-102.3c-3.5-16.1-17.8-27.7-34.3-27.7H119c-26.4 0-43.3-28-31.1-51.4l81.7-155.8c6.1-11.6 18-18.8 31.1-18.8h622.4c13 0 25 7.2 31.1 18.8l81.7 155.8c12.2 23.4-4.7 51.4-31.1 51.4zm146.5-486.1c-1-1.8-2.1-3.7-3.2-5.5-9.8-16.6-31.1-22.2-47.8-12.6L648.5 261c-17 9.8-22.7 31.6-12.6 48.4.9 1.4 1.7 2.9 2.5 4.4 9.5 17 31.2 22.8 48 13L807 257.3c16.7-9.7 22.4-31 12.9-47.8m-444.5 51.6L255 191.6c-16.7-9.6-38-4-47.8 12.6-1.1 1.8-2.1 3.6-3.2 5.5-9.5 16.8-3.8 38.1 12.9 47.8L337.3 327c16.9 9.7 38.6 4 48-13.1.8-1.5 1.7-2.9 2.5-4.4 10.2-16.8 4.5-38.6-12.4-48.4M512 239.3h2.5c19.5.3 35.5-15.5 35.5-35.1v-139c0-19.3-15.6-34.9-34.8-35.1h-6.4C489.6 30.3 474 46 474 65.2v139c0 19.5 15.9 35.4 35.5 35.1z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
71
src/views/welcome/components/table/index.vue
Normal file
71
src/views/welcome/components/table/index.vue
Normal file
@@ -0,0 +1,71 @@
|
||||
<script setup lang="ts">
|
||||
import { useColumns } from "./columns";
|
||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||
|
||||
const { loading, columns, dataList, pagination, Empty, onCurrentChange } =
|
||||
useColumns();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<pure-table
|
||||
row-key="id"
|
||||
alignWhole="center"
|
||||
showOverflowTooltip
|
||||
:loading="loading"
|
||||
:loading-config="{ background: 'transparent' }"
|
||||
:data="
|
||||
dataList.slice(
|
||||
(pagination.currentPage - 1) * pagination.pageSize,
|
||||
pagination.currentPage * pagination.pageSize
|
||||
)
|
||||
"
|
||||
:columns="columns"
|
||||
:pagination="pagination"
|
||||
@page-current-change="onCurrentChange"
|
||||
>
|
||||
<template #empty>
|
||||
<el-empty description="暂无数据" :image-size="60">
|
||||
<template #image>
|
||||
<Empty />
|
||||
</template>
|
||||
</el-empty>
|
||||
</template>
|
||||
<template #operation="{ row }">
|
||||
<el-button
|
||||
plain
|
||||
circle
|
||||
size="small"
|
||||
:title="`查看序号为${row.id}的详情`"
|
||||
:icon="useRenderIcon('search')"
|
||||
/>
|
||||
</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>
|
||||
134
src/views/welcome/data.ts
Normal file
134
src/views/welcome/data.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
import { dayjs, cloneDeep, getRandomIntBetween } from "./utils";
|
||||
import GroupLine from "@iconify-icons/ri/group-line";
|
||||
import Question from "@iconify-icons/ri/question-answer-line";
|
||||
import CheckLine from "@iconify-icons/ri/chat-check-line";
|
||||
import Smile from "@iconify-icons/ri/star-smile-line";
|
||||
|
||||
const days = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"];
|
||||
|
||||
/** 需求人数、提问数量、解决数量、用户满意度 */
|
||||
const chartData = [
|
||||
{
|
||||
icon: GroupLine,
|
||||
bgColor: "#effaff",
|
||||
color: "#41b6ff",
|
||||
duration: 2200,
|
||||
name: "需求人数",
|
||||
value: 36000,
|
||||
percent: "+88%",
|
||||
data: [2101, 5288, 4239, 4962, 6752, 5208, 7450] // 平滑折线图数据
|
||||
},
|
||||
{
|
||||
icon: Question,
|
||||
bgColor: "#fff5f4",
|
||||
color: "#e85f33",
|
||||
duration: 1600,
|
||||
name: "提问数量",
|
||||
value: 16580,
|
||||
percent: "+70%",
|
||||
data: [2216, 1148, 1255, 788, 4821, 1973, 4379]
|
||||
},
|
||||
{
|
||||
icon: CheckLine,
|
||||
bgColor: "#eff8f4",
|
||||
color: "#26ce83",
|
||||
duration: 1500,
|
||||
name: "解决数量",
|
||||
value: 16499,
|
||||
percent: "+99%",
|
||||
data: [861, 1002, 3195, 1715, 3666, 2415, 3645]
|
||||
},
|
||||
{
|
||||
icon: Smile,
|
||||
bgColor: "#f6f4fe",
|
||||
color: "#7846e5",
|
||||
duration: 100,
|
||||
name: "用户满意度",
|
||||
value: 100,
|
||||
percent: "+100%",
|
||||
data: [100]
|
||||
}
|
||||
];
|
||||
|
||||
/** 分析概览 */
|
||||
const barChartData = [
|
||||
{
|
||||
requireData: [2101, 5288, 4239, 4962, 6752, 5208, 7450],
|
||||
questionData: [2216, 1148, 1255, 1788, 4821, 1973, 4379]
|
||||
},
|
||||
{
|
||||
requireData: [2101, 3280, 4400, 4962, 5752, 6889, 7600],
|
||||
questionData: [2116, 3148, 3255, 3788, 4821, 4970, 5390]
|
||||
}
|
||||
];
|
||||
|
||||
/** 解决概率 */
|
||||
const progressData = [
|
||||
{
|
||||
week: "周一",
|
||||
percentage: 85,
|
||||
duration: 110,
|
||||
color: "#41b6ff"
|
||||
},
|
||||
{
|
||||
week: "周二",
|
||||
percentage: 86,
|
||||
duration: 105,
|
||||
color: "#41b6ff"
|
||||
},
|
||||
{
|
||||
week: "周三",
|
||||
percentage: 88,
|
||||
duration: 100,
|
||||
color: "#41b6ff"
|
||||
},
|
||||
{
|
||||
week: "周四",
|
||||
percentage: 89,
|
||||
duration: 95,
|
||||
color: "#41b6ff"
|
||||
},
|
||||
{
|
||||
week: "周五",
|
||||
percentage: 94,
|
||||
duration: 90,
|
||||
color: "#26ce83"
|
||||
},
|
||||
{
|
||||
week: "周六",
|
||||
percentage: 96,
|
||||
duration: 85,
|
||||
color: "#26ce83"
|
||||
},
|
||||
{
|
||||
week: "周日",
|
||||
percentage: 100,
|
||||
duration: 80,
|
||||
color: "#26ce83"
|
||||
}
|
||||
].reverse();
|
||||
|
||||
/** 数据统计 */
|
||||
const tableData = Array.from({ length: 30 }).map((_, index) => {
|
||||
return {
|
||||
id: index + 1,
|
||||
requiredNumber: getRandomIntBetween(13500, 19999),
|
||||
questionNumber: getRandomIntBetween(12600, 16999),
|
||||
resolveNumber: getRandomIntBetween(13500, 17999),
|
||||
satisfaction: getRandomIntBetween(95, 100),
|
||||
date: dayjs().subtract(index, "day").format("YYYY-MM-DD")
|
||||
};
|
||||
});
|
||||
|
||||
/** 最新动态 */
|
||||
const latestNewsData = cloneDeep(tableData)
|
||||
.slice(0, 14)
|
||||
.map((item, index) => {
|
||||
return Object.assign(item, {
|
||||
date: `${dayjs().subtract(index, "day").format("YYYY-MM-DD")} ${
|
||||
days[dayjs().subtract(index, "day").day()]
|
||||
}`
|
||||
});
|
||||
});
|
||||
|
||||
export { chartData, barChartData, progressData, tableData, latestNewsData };
|
||||
@@ -1,60 +1,50 @@
|
||||
<script setup lang="ts">
|
||||
import dayjs from "dayjs";
|
||||
import MdEditor from "md-editor-v3";
|
||||
import Bar from "./components/Bar.vue";
|
||||
import Pie from "./components/Pie.vue";
|
||||
import Line from "./components/Line.vue";
|
||||
import { getReleases } from "@/api/list";
|
||||
import TypeIt from "@/components/ReTypeit";
|
||||
import { useWindowSize } from "@vueuse/core";
|
||||
import { ref, computed, markRaw } from "vue";
|
||||
import Github from "./components/Github.vue";
|
||||
import { randomColor } from "@pureadmin/utils";
|
||||
import { ref, markRaw } from "vue";
|
||||
import ReCol from "@/components/ReCol";
|
||||
import PureTable from "./components/table/index.vue";
|
||||
import { ReNormalCountTo } from "@/components/ReCountTo";
|
||||
import { useRenderFlicker } from "@/components/ReFlicker";
|
||||
import { barChart, lineChart, roundChart } from "./components/chart";
|
||||
import Segmented, { type OptionsType } from "@/components/ReSegmented";
|
||||
import { useResizeObserver, useDark, debounce, randomGradient } from "./utils";
|
||||
import { chartData, barChartData, progressData, latestNewsData } from "./data";
|
||||
|
||||
defineOptions({
|
||||
name: "Welcome"
|
||||
});
|
||||
|
||||
const list = ref();
|
||||
const loading = ref<boolean>(true);
|
||||
const { version } = __APP_INFO__.pkg;
|
||||
const titleClass = computed(() => {
|
||||
return ["text-base", "font-medium"];
|
||||
});
|
||||
const barCardRef = ref();
|
||||
const barChartRef = ref();
|
||||
const { isDark } = useDark();
|
||||
|
||||
const { height } = useWindowSize();
|
||||
let curWeek = ref(1); // 0上周、1本周
|
||||
const optionsBasis: Array<OptionsType> = [
|
||||
{
|
||||
label: "上周"
|
||||
},
|
||||
{
|
||||
label: "本周"
|
||||
}
|
||||
];
|
||||
|
||||
setTimeout(() => {
|
||||
loading.value = !loading.value;
|
||||
}, 800);
|
||||
|
||||
getReleases().then(({ data }) => {
|
||||
list.value = data.list.map(v => {
|
||||
return {
|
||||
content: v.body,
|
||||
timestamp: dayjs(v.published_at).format("YYYY/MM/DD hh:mm:ss A"),
|
||||
icon: markRaw(
|
||||
useRenderFlicker({
|
||||
background: randomColor({ type: "hex" }) as string
|
||||
})
|
||||
)
|
||||
};
|
||||
});
|
||||
});
|
||||
useResizeObserver(
|
||||
barCardRef,
|
||||
debounce(() => barChartRef.value.resize(), 60)
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<el-row :gutter="24">
|
||||
<el-col
|
||||
<el-row :gutter="24" justify="space-around">
|
||||
<re-col
|
||||
v-for="(item, index) in chartData"
|
||||
:key="index"
|
||||
v-motion
|
||||
:xs="24"
|
||||
:sm="24"
|
||||
:md="12"
|
||||
:lg="12"
|
||||
:xl="12"
|
||||
class="mb-[18px]"
|
||||
:value="6"
|
||||
:md="12"
|
||||
:sm="12"
|
||||
:xs="24"
|
||||
:initial="{
|
||||
opacity: 0,
|
||||
y: 100
|
||||
@@ -63,104 +53,54 @@ getReleases().then(({ data }) => {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: {
|
||||
delay: 200
|
||||
delay: 80 * (index + 1)
|
||||
}
|
||||
}"
|
||||
>
|
||||
<el-card
|
||||
shadow="never"
|
||||
:style="{ height: `calc(${height}px - 35vh - 250px)` }"
|
||||
>
|
||||
<template #header>
|
||||
<a
|
||||
:class="titleClass"
|
||||
href="https://github.com/pure-admin/vue-pure-admin/releases"
|
||||
target="_black"
|
||||
<el-card shadow="never">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-md font-medium">
|
||||
{{ item.name }}
|
||||
</span>
|
||||
<div
|
||||
class="w-8 h-8 flex justify-center items-center rounded-md"
|
||||
:style="{
|
||||
backgroundColor: isDark ? 'transparent' : item.bgColor
|
||||
}"
|
||||
>
|
||||
<TypeIt
|
||||
:className="'type-it2'"
|
||||
:values="[`PureAdmin 版本日志(当前版本 v${version})`]"
|
||||
:cursor="false"
|
||||
:speed="60"
|
||||
<IconifyIconOffline
|
||||
:icon="item.icon"
|
||||
:color="item.color"
|
||||
width="18"
|
||||
/>
|
||||
</a>
|
||||
</template>
|
||||
<el-skeleton animated :rows="7" :loading="loading">
|
||||
<template #default>
|
||||
<el-scrollbar :height="`calc(${height}px - 35vh - 340px)`">
|
||||
<el-timeline v-show="list?.length > 0">
|
||||
<el-timeline-item
|
||||
v-for="(item, index) in list"
|
||||
:key="index"
|
||||
:icon="item.icon"
|
||||
:timestamp="item.timestamp"
|
||||
>
|
||||
<md-editor v-model="item.content" preview-only />
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
<el-empty v-show="list?.length === 0" />
|
||||
</el-scrollbar>
|
||||
</template>
|
||||
</el-skeleton>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col
|
||||
v-motion
|
||||
:xs="24"
|
||||
:sm="24"
|
||||
:md="12"
|
||||
:lg="12"
|
||||
:xl="12"
|
||||
class="mb-[18px]"
|
||||
:initial="{
|
||||
opacity: 0,
|
||||
y: 100
|
||||
}"
|
||||
:enter="{
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: {
|
||||
delay: 200
|
||||
}
|
||||
}"
|
||||
>
|
||||
<el-card
|
||||
shadow="never"
|
||||
:style="{ height: `calc(${height}px - 35vh - 250px)` }"
|
||||
>
|
||||
<template #header>
|
||||
<a
|
||||
:class="titleClass"
|
||||
href="https://github.com/xiaoxian521"
|
||||
target="_black"
|
||||
>
|
||||
<TypeIt
|
||||
:className="'type-it1'"
|
||||
:values="['GitHub信息']"
|
||||
:cursor="false"
|
||||
:speed="120"
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-between items-start mt-3">
|
||||
<div class="w-1/2">
|
||||
<ReNormalCountTo
|
||||
:duration="item.duration"
|
||||
:fontSize="'1.6em'"
|
||||
:startVal="100"
|
||||
:endVal="item.value"
|
||||
/>
|
||||
</a>
|
||||
</template>
|
||||
<el-skeleton animated :rows="7" :loading="loading">
|
||||
<template #default>
|
||||
<el-scrollbar :height="`calc(${height}px - 35vh - 340px)`">
|
||||
<Github />
|
||||
</el-scrollbar>
|
||||
</template>
|
||||
</el-skeleton>
|
||||
<p class="font-medium text-green-500">{{ item.percent }}</p>
|
||||
</div>
|
||||
<lineChart
|
||||
v-if="item.data.length > 1"
|
||||
class="!w-1/2"
|
||||
:color="item.color"
|
||||
:data="item.data"
|
||||
/>
|
||||
<roundChart v-else class="!w-1/2" />
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</re-col>
|
||||
|
||||
<el-col
|
||||
<re-col
|
||||
v-motion
|
||||
:xs="24"
|
||||
:sm="24"
|
||||
:md="12"
|
||||
:lg="8"
|
||||
:xl="8"
|
||||
class="mb-[18px]"
|
||||
:value="18"
|
||||
:xs="24"
|
||||
:initial="{
|
||||
opacity: 0,
|
||||
y: 100
|
||||
@@ -173,37 +113,26 @@ getReleases().then(({ data }) => {
|
||||
}
|
||||
}"
|
||||
>
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<a
|
||||
:class="titleClass"
|
||||
href="https://github.com/pure-admin/vue-pure-admin"
|
||||
target="_black"
|
||||
>
|
||||
<TypeIt
|
||||
:className="'type-it4'"
|
||||
:values="['GitHub折线图信息']"
|
||||
:cursor="false"
|
||||
:speed="120"
|
||||
/>
|
||||
</a>
|
||||
</template>
|
||||
<el-skeleton animated :rows="7" :loading="loading">
|
||||
<template #default>
|
||||
<Line />
|
||||
</template>
|
||||
</el-skeleton>
|
||||
<el-card ref="barCardRef" shadow="never">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-md font-medium">分析概览</span>
|
||||
<Segmented v-model="curWeek" :options="optionsBasis" />
|
||||
</div>
|
||||
<div class="flex justify-between items-start mt-3">
|
||||
<barChart
|
||||
ref="barChartRef"
|
||||
:requireData="barChartData[curWeek].requireData"
|
||||
:questionData="barChartData[curWeek].questionData"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</re-col>
|
||||
|
||||
<el-col
|
||||
<re-col
|
||||
v-motion
|
||||
:xs="24"
|
||||
:sm="24"
|
||||
:md="12"
|
||||
:lg="8"
|
||||
:xl="8"
|
||||
class="mb-[18px]"
|
||||
:value="6"
|
||||
:xs="24"
|
||||
:initial="{
|
||||
opacity: 0,
|
||||
y: 100
|
||||
@@ -212,41 +141,45 @@ getReleases().then(({ data }) => {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: {
|
||||
delay: 400
|
||||
delay: 480
|
||||
}
|
||||
}"
|
||||
>
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<a
|
||||
:class="titleClass"
|
||||
href="https://github.com/pure-admin/vue-pure-admin"
|
||||
target="_black"
|
||||
>
|
||||
<TypeIt
|
||||
:className="'type-it3'"
|
||||
:values="['GitHub饼图信息']"
|
||||
:cursor="false"
|
||||
:speed="120"
|
||||
/>
|
||||
</a>
|
||||
</template>
|
||||
<el-skeleton animated :rows="7" :loading="loading">
|
||||
<template #default>
|
||||
<Pie />
|
||||
</template>
|
||||
</el-skeleton>
|
||||
<div class="flex justify-between">
|
||||
<span class="text-md font-medium">解决概率</span>
|
||||
</div>
|
||||
<div
|
||||
v-for="(item, index) in progressData"
|
||||
:key="index"
|
||||
:class="[
|
||||
'flex',
|
||||
'justify-between',
|
||||
'items-start',
|
||||
index === 0 ? 'mt-8' : 'mt-[2.15rem]'
|
||||
]"
|
||||
>
|
||||
<el-progress
|
||||
:text-inside="true"
|
||||
:percentage="item.percentage"
|
||||
:stroke-width="21"
|
||||
:color="item.color"
|
||||
striped
|
||||
striped-flow
|
||||
:duration="item.duration"
|
||||
/>
|
||||
<span class="text-nowrap ml-2 text-text_color_regular text-sm">
|
||||
{{ item.week }}
|
||||
</span>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</re-col>
|
||||
|
||||
<el-col
|
||||
<re-col
|
||||
v-motion
|
||||
:xs="24"
|
||||
:sm="24"
|
||||
:md="24"
|
||||
:lg="8"
|
||||
:xl="8"
|
||||
class="mb-[18px]"
|
||||
:value="18"
|
||||
:xs="24"
|
||||
:initial="{
|
||||
opacity: 0,
|
||||
y: 100
|
||||
@@ -255,39 +188,94 @@ getReleases().then(({ data }) => {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: {
|
||||
delay: 400
|
||||
delay: 560
|
||||
}
|
||||
}"
|
||||
>
|
||||
<el-card shadow="never" class="h-[580px]">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-md font-medium">数据统计</span>
|
||||
</div>
|
||||
<PureTable class="mt-3" />
|
||||
</el-card>
|
||||
</re-col>
|
||||
|
||||
<re-col
|
||||
v-motion
|
||||
class="mb-[18px]"
|
||||
:value="6"
|
||||
:xs="24"
|
||||
:initial="{
|
||||
opacity: 0,
|
||||
y: 100
|
||||
}"
|
||||
:enter="{
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: {
|
||||
delay: 640
|
||||
}
|
||||
}"
|
||||
>
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<a
|
||||
:class="titleClass"
|
||||
href="https://github.com/pure-admin/vue-pure-admin"
|
||||
target="_black"
|
||||
>
|
||||
<TypeIt
|
||||
:className="'type-it5'"
|
||||
:values="['GitHub柱状图信息']"
|
||||
:cursor="false"
|
||||
:speed="120"
|
||||
/>
|
||||
</a>
|
||||
</template>
|
||||
<el-skeleton animated :rows="7" :loading="loading">
|
||||
<template #default>
|
||||
<Bar />
|
||||
</template>
|
||||
</el-skeleton>
|
||||
<div class="flex justify-between">
|
||||
<span class="text-md font-medium">最新动态</span>
|
||||
</div>
|
||||
<el-scrollbar max-height="504" class="mt-3">
|
||||
<el-timeline>
|
||||
<el-timeline-item
|
||||
v-for="(item, index) in latestNewsData"
|
||||
:key="index"
|
||||
center
|
||||
placement="top"
|
||||
:icon="
|
||||
markRaw(
|
||||
useRenderFlicker({
|
||||
background: randomGradient({
|
||||
randomizeHue: true
|
||||
})
|
||||
})
|
||||
)
|
||||
"
|
||||
:timestamp="item.date"
|
||||
>
|
||||
<p class="text-text_color_regular text-sm">
|
||||
{{
|
||||
`新增 ${item.requiredNumber} 条问题,${item.resolveNumber} 条已解决`
|
||||
}}
|
||||
</p>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
</el-scrollbar>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</re-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-timeline-item) {
|
||||
margin: 6px 0 0 6px;
|
||||
:deep(.el-card) {
|
||||
--el-card-border-color: none;
|
||||
|
||||
/* 解决概率进度条宽度 */
|
||||
.el-progress--line {
|
||||
width: 85%;
|
||||
}
|
||||
|
||||
/* 解决概率进度条字体大小 */
|
||||
.el-progress-bar__innerText {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
/* 隐藏 el-scrollbar 滚动条 */
|
||||
.el-scrollbar__bar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* el-timeline 每一项上下、左右边距 */
|
||||
.el-timeline-item {
|
||||
margin: 0 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.main-content {
|
||||
|
||||
13
src/views/welcome/utils.ts
Normal file
13
src/views/welcome/utils.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export { default as dayjs } from "dayjs";
|
||||
export { useResizeObserver } from "@vueuse/core";
|
||||
export {
|
||||
useDark,
|
||||
debounce,
|
||||
cloneDeep,
|
||||
randomColor,
|
||||
randomGradient
|
||||
} from "@pureadmin/utils";
|
||||
|
||||
export function getRandomIntBetween(min: number, max: number) {
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
}
|
||||
Reference in New Issue
Block a user