|
@@ -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 { height } = useWindowSize();
|
|
|
+const barCardRef = ref();
|
|
|
+const barChartRef = ref();
|
|
|
+const { isDark } = useDark();
|
|
|
|
|
|
-setTimeout(() => {
|
|
|
- loading.value = !loading.value;
|
|
|
-}, 800);
|
|
|
+let curWeek = ref(1); // 0上周、1本周
|
|
|
+const optionsBasis: Array<OptionsType> = [
|
|
|
+ {
|
|
|
+ label: "上周"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: "本周"
|
|
|
+ }
|
|
|
+];
|
|
|
|
|
|
-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,56 +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>
|
|
|
+ </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"
|
|
|
+ />
|
|
|
+ <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="12"
|
|
|
- :xl="12"
|
|
|
class="mb-[18px]"
|
|
|
+ :value="18"
|
|
|
+ :xs="24"
|
|
|
:initial="{
|
|
|
opacity: 0,
|
|
|
y: 100
|
|
@@ -121,46 +109,30 @@ getReleases().then(({ data }) => {
|
|
|
opacity: 1,
|
|
|
y: 0,
|
|
|
transition: {
|
|
|
- delay: 200
|
|
|
+ delay: 400
|
|
|
}
|
|
|
}"
|
|
|
>
|
|
|
- <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"
|
|
|
- />
|
|
|
- </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>
|
|
|
+ <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
|
|
@@ -169,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-it4'"
|
|
|
- :values="['GitHub折线图信息']"
|
|
|
- :cursor="false"
|
|
|
- :speed="120"
|
|
|
- />
|
|
|
- </a>
|
|
|
- </template>
|
|
|
- <el-skeleton animated :rows="7" :loading="loading">
|
|
|
- <template #default>
|
|
|
- <Line />
|
|
|
- </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="12"
|
|
|
- :lg="8"
|
|
|
- :xl="8"
|
|
|
class="mb-[18px]"
|
|
|
+ :value="18"
|
|
|
+ :xs="24"
|
|
|
:initial="{
|
|
|
opacity: 0,
|
|
|
y: 100
|
|
@@ -212,41 +188,23 @@ getReleases().then(({ data }) => {
|
|
|
opacity: 1,
|
|
|
y: 0,
|
|
|
transition: {
|
|
|
- delay: 400
|
|
|
+ delay: 560
|
|
|
}
|
|
|
}"
|
|
|
>
|
|
|
- <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>
|
|
|
+ <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>
|
|
|
- </el-col>
|
|
|
+ </re-col>
|
|
|
|
|
|
- <el-col
|
|
|
+ <re-col
|
|
|
v-motion
|
|
|
- :xs="24"
|
|
|
- :sm="24"
|
|
|
- :md="24"
|
|
|
- :lg="8"
|
|
|
- :xl="8"
|
|
|
class="mb-[18px]"
|
|
|
+ :value="6"
|
|
|
+ :xs="24"
|
|
|
:initial="{
|
|
|
opacity: 0,
|
|
|
y: 100
|
|
@@ -255,39 +213,69 @@ getReleases().then(({ data }) => {
|
|
|
opacity: 1,
|
|
|
y: 0,
|
|
|
transition: {
|
|
|
- delay: 400
|
|
|
+ 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 {
|