初始化本地仓库
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
<!-- 工作台页面 -->
|
||||
<template>
|
||||
<div>
|
||||
<CardList></CardList>
|
||||
|
||||
<ElRow :gutter="20">
|
||||
<ElCol :sm="24" :md="12" :lg="10">
|
||||
<ActiveUser />
|
||||
</ElCol>
|
||||
<ElCol :sm="24" :md="12" :lg="14">
|
||||
<SalesOverview />
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
|
||||
<ElRow :gutter="20">
|
||||
<ElCol :sm="24" :md="24" :lg="12">
|
||||
<NewUser />
|
||||
</ElCol>
|
||||
<ElCol :sm="24" :md="12" :lg="6">
|
||||
<Dynamic />
|
||||
</ElCol>
|
||||
<ElCol :sm="24" :md="12" :lg="6">
|
||||
<TodoList />
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
|
||||
<AboutProject />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import CardList from './modules/card-list.vue'
|
||||
import ActiveUser from './modules/active-user.vue'
|
||||
import SalesOverview from './modules/sales-overview.vue'
|
||||
import NewUser from './modules/new-user.vue'
|
||||
import Dynamic from './modules/dynamic-stats.vue'
|
||||
import TodoList from './modules/todo-list.vue'
|
||||
import AboutProject from './modules/about-project.vue'
|
||||
|
||||
defineOptions({ name: 'Console' })
|
||||
</script>
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<div class="art-card p-5 flex-b mb-5 max-sm:mb-4">
|
||||
<div>
|
||||
<h2 class="text-2xl font-medium">关于项目</h2>
|
||||
<p class="text-g-700 mt-1">{{ systemName }} 是一款兼具设计美学与高效开发的后台系统</p>
|
||||
<p class="text-g-700 mt-1">使用了 Vue3、TypeScript、Vite、Element Plus 等前沿技术</p>
|
||||
|
||||
<div class="flex flex-wrap gap-3.5 max-w-150 mt-9">
|
||||
<div
|
||||
class="w-60 flex-cb h-12.5 px-3.5 border border-g-300 c-p rounded-lg text-sm bg-g-100 duration-300 hover:-translate-y-1 max-sm:w-full"
|
||||
v-for="link in linkList"
|
||||
:key="link.label"
|
||||
@click="goPage(link.url)"
|
||||
>
|
||||
<span class="text-g-700">{{ link.label }}</span>
|
||||
<ArtSvgIcon icon="ri:arrow-right-s-line" class="text-lg text-g-600" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<img class="w-75 max-md:!hidden" src="@imgs/draw/draw1.png" alt="draw1" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import AppConfig from '@/config'
|
||||
import { WEB_LINKS } from '@/utils/constants'
|
||||
|
||||
const systemName = AppConfig.systemInfo.name
|
||||
|
||||
const linkList = [
|
||||
{ label: '项目官网', url: WEB_LINKS.DOCS },
|
||||
{ label: '文档', url: WEB_LINKS.INTRODUCE },
|
||||
{ label: 'Github', url: WEB_LINKS.GITHUB_HOME },
|
||||
{ label: '哔哩哔哩', url: WEB_LINKS.BILIBILI }
|
||||
]
|
||||
|
||||
/**
|
||||
* 在新标签页中打开指定 URL
|
||||
* @param url 要打开的网页地址
|
||||
*/
|
||||
const goPage = (url: string): void => {
|
||||
window.open(url, '_blank', 'noopener,noreferrer')
|
||||
}
|
||||
</script>
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<div class="art-card h-105 p-4 box-border mb-5 max-sm:mb-4">
|
||||
<ArtBarChart
|
||||
class="box-border p-2"
|
||||
barWidth="50%"
|
||||
height="13.7rem"
|
||||
:showAxisLine="false"
|
||||
:data="chartData"
|
||||
:xAxisData="xAxisLabels"
|
||||
/>
|
||||
<div class="ml-1">
|
||||
<h3 class="mt-5 text-lg font-medium">用户概述</h3>
|
||||
<p class="mt-1 text-sm">比上周 <span class="text-success font-medium">+23%</span></p>
|
||||
<p class="mt-1 text-sm">我们为您创建了多个选项,可将它们组合在一起并定制为像素完美的页面</p>
|
||||
</div>
|
||||
<div class="flex-b mt-2">
|
||||
<div class="flex-1" v-for="(item, index) in list" :key="index">
|
||||
<p class="text-2xl text-g-900">{{ item.num }}</p>
|
||||
<p class="text-xs text-g-500">{{ item.name }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
interface UserStatItem {
|
||||
name: string
|
||||
num: string
|
||||
}
|
||||
|
||||
// 最近9个月
|
||||
const xAxisLabels = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月']
|
||||
|
||||
// 每月活跃用户数
|
||||
const chartData = [160, 100, 150, 80, 190, 100, 175, 120, 160]
|
||||
|
||||
/**
|
||||
* 用户统计数据列表
|
||||
* 包含总用户量、总访问量、日访问量和周同比等关键指标
|
||||
*/
|
||||
const list: UserStatItem[] = [
|
||||
{ name: '总用户量', num: '32k' },
|
||||
{ name: '总访问量', num: '128k' },
|
||||
{ name: '日访问量', num: '1.2k' },
|
||||
{ name: '周同比', num: '+5%' }
|
||||
]
|
||||
</script>
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<ElRow :gutter="20" class="flex">
|
||||
<ElCol v-for="(item, index) in dataList" :key="index" :sm="12" :md="6" :lg="6">
|
||||
<div class="art-card relative flex flex-col justify-center h-35 px-5 mb-5 max-sm:mb-4">
|
||||
<span class="text-g-700 text-sm">{{ item.des }}</span>
|
||||
<ArtCountTo class="text-[26px] font-medium mt-2" :target="item.num" :duration="1300" />
|
||||
<div class="flex-c mt-1">
|
||||
<span class="text-xs text-g-600">较上周</span>
|
||||
<span
|
||||
class="ml-1 text-xs font-semibold"
|
||||
:class="[item.change.indexOf('+') === -1 ? 'text-danger' : 'text-success']"
|
||||
>
|
||||
{{ item.change }}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="absolute top-0 bottom-0 right-5 m-auto size-12.5 rounded-xl flex-cc bg-theme/10"
|
||||
>
|
||||
<ArtSvgIcon :icon="item.icon" class="text-xl text-theme" />
|
||||
</div>
|
||||
</div>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
interface CardDataItem {
|
||||
des: string
|
||||
icon: string
|
||||
startVal: number
|
||||
duration: number
|
||||
num: number
|
||||
change: string
|
||||
}
|
||||
|
||||
/**
|
||||
* 卡片统计数据列表
|
||||
* 展示总访问次数、在线访客数、点击量和新用户等核心数据指标
|
||||
*/
|
||||
const dataList = reactive<CardDataItem[]>([
|
||||
{
|
||||
des: '总访问次数',
|
||||
icon: 'ri:pie-chart-line',
|
||||
startVal: 0,
|
||||
duration: 1000,
|
||||
num: 9120,
|
||||
change: '+20%'
|
||||
},
|
||||
{
|
||||
des: '在线访客数',
|
||||
icon: 'ri:group-line',
|
||||
startVal: 0,
|
||||
duration: 1000,
|
||||
num: 182,
|
||||
change: '+10%'
|
||||
},
|
||||
{
|
||||
des: '点击量',
|
||||
icon: 'ri:fire-line',
|
||||
startVal: 0,
|
||||
duration: 1000,
|
||||
num: 9520,
|
||||
change: '-12%'
|
||||
},
|
||||
{
|
||||
des: '新用户',
|
||||
icon: 'ri:progress-2-line',
|
||||
startVal: 0,
|
||||
duration: 1000,
|
||||
num: 156,
|
||||
change: '+30%'
|
||||
}
|
||||
])
|
||||
</script>
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<div class="art-card h-128 p-5 mb-5 max-sm:mb-4">
|
||||
<div class="art-card-header">
|
||||
<div class="title">
|
||||
<h4>动态</h4>
|
||||
<p>新增<span class="text-success">+6</span></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="h-9/10 mt-2 overflow-hidden">
|
||||
<ElScrollbar>
|
||||
<div
|
||||
class="h-17.5 leading-17.5 border-b border-g-300 text-sm overflow-hidden last:border-b-0"
|
||||
v-for="(item, index) in list"
|
||||
:key="index"
|
||||
>
|
||||
<span class="text-g-800 font-medium">{{ item.username }}</span>
|
||||
<span class="mx-2 text-g-600">{{ item.type }}</span>
|
||||
<span class="text-theme">{{ item.target }}</span>
|
||||
</div>
|
||||
</ElScrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
interface DynamicItem {
|
||||
username: string
|
||||
type: string
|
||||
target: string
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户动态列表
|
||||
* 记录用户的关注、发文、提问、兑换等各类活动
|
||||
*/
|
||||
const list = reactive<DynamicItem[]>([
|
||||
{
|
||||
username: '中小鱼',
|
||||
type: '关注了',
|
||||
target: '誶誶淰'
|
||||
},
|
||||
{
|
||||
username: '何小荷',
|
||||
type: '发表文章',
|
||||
target: 'Vue3 + Typescript + Vite 项目实战笔记'
|
||||
},
|
||||
{
|
||||
username: '中小鱼',
|
||||
type: '关注了',
|
||||
target: '誶誶淰'
|
||||
},
|
||||
{
|
||||
username: '何小荷',
|
||||
type: '发表文章',
|
||||
target: 'Vue3 + Typescript + Vite 项目实战笔记'
|
||||
},
|
||||
{
|
||||
username: '誶誶淰',
|
||||
type: '提出问题',
|
||||
target: '主题可以配置吗'
|
||||
},
|
||||
{
|
||||
username: '发呆草',
|
||||
type: '兑换了物品',
|
||||
target: '《奇特的一生》'
|
||||
},
|
||||
{
|
||||
username: '甜筒',
|
||||
type: '关闭了问题',
|
||||
target: '发呆草'
|
||||
},
|
||||
{
|
||||
username: '冷月呆呆',
|
||||
type: '兑换了物品',
|
||||
target: '《高效人士的七个习惯》'
|
||||
}
|
||||
])
|
||||
</script>
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
<template>
|
||||
<div class="art-card p-5 h-128 overflow-hidden mb-5 max-sm:mb-4">
|
||||
<div class="art-card-header">
|
||||
<div class="title">
|
||||
<h4>新用户</h4>
|
||||
<p>这个月增长<span class="text-success">+20%</span></p>
|
||||
</div>
|
||||
<ElRadioGroup v-model="radio2">
|
||||
<ElRadioButton value="本月" label="本月"></ElRadioButton>
|
||||
<ElRadioButton value="上月" label="上月"></ElRadioButton>
|
||||
<ElRadioButton value="今年" label="今年"></ElRadioButton>
|
||||
</ElRadioGroup>
|
||||
</div>
|
||||
<ArtTable
|
||||
class="w-full"
|
||||
:data="tableData"
|
||||
style="width: 100%"
|
||||
size="large"
|
||||
:border="false"
|
||||
:stripe="false"
|
||||
:header-cell-style="{ background: 'transparent' }"
|
||||
>
|
||||
<template #default>
|
||||
<ElTableColumn label="头像" prop="avatar" width="150px">
|
||||
<template #default="scope">
|
||||
<div style="display: flex; align-items: center">
|
||||
<img class="size-9 rounded-lg" :src="scope.row.avatar" alt="avatar" />
|
||||
<span class="ml-2">{{ scope.row.username }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="地区" prop="province" />
|
||||
<ElTableColumn label="性别" prop="avatar">
|
||||
<template #default="scope">
|
||||
<div style="display: flex; align-items: center">
|
||||
<span style="margin-left: 10px">{{ scope.row.sex === 1 ? '男' : '女' }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<ElTableColumn label="进度" width="240">
|
||||
<template #default="scope">
|
||||
<ElProgress
|
||||
:percentage="scope.row.pro"
|
||||
:color="scope.row.color"
|
||||
:stroke-width="4"
|
||||
:aria-label="`${scope.row.username}的完成进度: ${scope.row.pro}%`"
|
||||
/>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
</template>
|
||||
</ArtTable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import avatar1 from '@/assets/images/avatar/avatar1.webp'
|
||||
import avatar2 from '@/assets/images/avatar/avatar2.webp'
|
||||
import avatar3 from '@/assets/images/avatar/avatar3.webp'
|
||||
import avatar4 from '@/assets/images/avatar/avatar4.webp'
|
||||
import avatar5 from '@/assets/images/avatar/avatar5.webp'
|
||||
import avatar6 from '@/assets/images/avatar/avatar6.webp'
|
||||
|
||||
interface UserTableItem {
|
||||
username: string
|
||||
province: string
|
||||
sex: 0 | 1
|
||||
age: number
|
||||
percentage: number
|
||||
pro: number
|
||||
color: string
|
||||
avatar: string
|
||||
}
|
||||
|
||||
const ANIMATION_DELAY = 100
|
||||
|
||||
const radio2 = ref('本月')
|
||||
|
||||
/**
|
||||
* 新用户表格数据
|
||||
* 包含用户基本信息和完成进度
|
||||
*/
|
||||
const tableData = reactive<UserTableItem[]>([
|
||||
{
|
||||
username: '中小鱼',
|
||||
province: '北京',
|
||||
sex: 0,
|
||||
age: 22,
|
||||
percentage: 60,
|
||||
pro: 0,
|
||||
color: 'var(--art-primary)',
|
||||
avatar: avatar1
|
||||
},
|
||||
{
|
||||
username: '何小荷',
|
||||
province: '深圳',
|
||||
sex: 1,
|
||||
age: 21,
|
||||
percentage: 20,
|
||||
pro: 0,
|
||||
color: 'var(--art-secondary)',
|
||||
avatar: avatar2
|
||||
},
|
||||
{
|
||||
username: '誶誶淰',
|
||||
province: '上海',
|
||||
sex: 1,
|
||||
age: 23,
|
||||
percentage: 60,
|
||||
pro: 0,
|
||||
color: 'var(--art-warning)',
|
||||
avatar: avatar3
|
||||
},
|
||||
{
|
||||
username: '发呆草',
|
||||
province: '长沙',
|
||||
sex: 0,
|
||||
age: 28,
|
||||
percentage: 50,
|
||||
pro: 0,
|
||||
color: 'var(--art-info)',
|
||||
avatar: avatar4
|
||||
},
|
||||
{
|
||||
username: '甜筒',
|
||||
province: '浙江',
|
||||
sex: 1,
|
||||
age: 26,
|
||||
percentage: 70,
|
||||
pro: 0,
|
||||
color: 'var(--art-error)',
|
||||
avatar: avatar5
|
||||
},
|
||||
{
|
||||
username: '冷月呆呆',
|
||||
province: '湖北',
|
||||
sex: 1,
|
||||
age: 25,
|
||||
percentage: 90,
|
||||
pro: 0,
|
||||
color: 'var(--art-success)',
|
||||
avatar: avatar6
|
||||
}
|
||||
])
|
||||
|
||||
/**
|
||||
* 添加进度条动画效果
|
||||
* 延迟后将进度值从 0 更新到目标百分比,触发动画
|
||||
*/
|
||||
const addAnimation = (): void => {
|
||||
setTimeout(() => {
|
||||
tableData.forEach((item) => {
|
||||
item.pro = item.percentage
|
||||
})
|
||||
}, ANIMATION_DELAY)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
addAnimation()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.art-card {
|
||||
:deep(.el-radio-button__original-radio:checked + .el-radio-button__inner) {
|
||||
color: var(--el-color-primary) !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div class="art-card h-105 p-5 mb-5 max-sm:mb-4">
|
||||
<div class="art-card-header">
|
||||
<div class="title">
|
||||
<h4>访问量</h4>
|
||||
<p>今年增长<span class="text-success">+15%</span></p>
|
||||
</div>
|
||||
</div>
|
||||
<ArtLineChart
|
||||
height="calc(100% - 56px)"
|
||||
:data="data"
|
||||
:xAxisData="xAxisData"
|
||||
:showAreaColor="true"
|
||||
:showAxisLine="false"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* 全年访问量数据
|
||||
* 记录每月的访问量统计
|
||||
*/
|
||||
const data = [50, 25, 40, 20, 70, 35, 65, 30, 35, 20, 40, 44]
|
||||
|
||||
/**
|
||||
* X 轴月份标签
|
||||
*/
|
||||
const xAxisData = [
|
||||
'1月',
|
||||
'2月',
|
||||
'3月',
|
||||
'4月',
|
||||
'5月',
|
||||
'6月',
|
||||
'7月',
|
||||
'8月',
|
||||
'9月',
|
||||
'10月',
|
||||
'11月',
|
||||
'12月'
|
||||
]
|
||||
</script>
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
<template>
|
||||
<div class="art-card h-128 p-5 mb-5 max-sm:mb-4">
|
||||
<div class="art-card-header">
|
||||
<div class="title">
|
||||
<h4>代办事项</h4>
|
||||
<p>待处理<span class="text-danger">3</span></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="h-[calc(100%-40px)] overflow-auto">
|
||||
<ElScrollbar>
|
||||
<div
|
||||
class="flex-cb h-17.5 border-b border-g-300 text-sm last:border-b-0"
|
||||
v-for="(item, index) in list"
|
||||
:key="index"
|
||||
>
|
||||
<div>
|
||||
<p class="text-sm">{{ item.username }}</p>
|
||||
<p class="text-g-500 mt-1">{{ item.date }}</p>
|
||||
</div>
|
||||
<ElCheckbox v-model="item.complate" />
|
||||
</div>
|
||||
</ElScrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
interface TodoItem {
|
||||
username: string
|
||||
date: string
|
||||
complate: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* 待办事项列表
|
||||
* 记录每日工作任务及完成状态
|
||||
*/
|
||||
const list = reactive<TodoItem[]>([
|
||||
{
|
||||
username: '查看今天工作内容',
|
||||
date: '上午 09:30',
|
||||
complate: true
|
||||
},
|
||||
{
|
||||
username: '回复邮件',
|
||||
date: '上午 10:30',
|
||||
complate: true
|
||||
},
|
||||
{
|
||||
username: '工作汇报整理',
|
||||
date: '上午 11:00',
|
||||
complate: true
|
||||
},
|
||||
{
|
||||
username: '产品需求会议',
|
||||
date: '下午 02:00',
|
||||
complate: false
|
||||
},
|
||||
{
|
||||
username: '整理会议内容',
|
||||
date: '下午 03:30',
|
||||
complate: false
|
||||
},
|
||||
{
|
||||
username: '明天工作计划',
|
||||
date: '下午 06:30',
|
||||
complate: false
|
||||
}
|
||||
])
|
||||
</script>
|
||||
Reference in New Issue
Block a user