perf:工作台页面展示优化
This commit is contained in:
parent
c02c6eab68
commit
8e986bfa5a
@ -1,9 +1,5 @@
|
|||||||
import request from '@/config/axios'
|
import request from '@/config/axios'
|
||||||
import type { WorkplaceTotal, Project, Dynamic, Team, RadarData, Shortcuts } from './types'
|
import type { Project, Dynamic, Team, RadarData, Shortcuts } from './types'
|
||||||
|
|
||||||
export const getCountApi = (): Promise<IResponse<WorkplaceTotal>> => {
|
|
||||||
return request.get({ url: '/vadmin/workplace/total' })
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getProjectApi = (): Promise<IResponse<Project>> => {
|
export const getProjectApi = (): Promise<IResponse<Project>> => {
|
||||||
return request.get({ url: '/vadmin/workplace/project' })
|
return request.get({ url: '/vadmin/workplace/project' })
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
export type WorkplaceTotal = {
|
|
||||||
project: number
|
|
||||||
access: number
|
|
||||||
todo: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Project = {
|
export type Project = {
|
||||||
name: string
|
name: string
|
||||||
icon: string
|
icon: string
|
||||||
|
@ -22,6 +22,9 @@ export interface UserState {
|
|||||||
gender?: string
|
gender?: string
|
||||||
roles?: Recordable[]
|
roles?: Recordable[]
|
||||||
create_datetime?: string
|
create_datetime?: string
|
||||||
|
is_reset_password?: boolean
|
||||||
|
last_login?: string
|
||||||
|
last_ip?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AuthState {
|
export interface AuthState {
|
||||||
|
@ -108,3 +108,128 @@ export function toAnyString() {
|
|||||||
})
|
})
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小数转折扣
|
||||||
|
* 例子:0.85 -> 8.5折
|
||||||
|
* 例子:0.5 -> 5折
|
||||||
|
*/
|
||||||
|
export const convertToDiscount = (decimal: number | undefined): string => {
|
||||||
|
if (decimal === undefined) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
const discount = decimal * 10
|
||||||
|
if (discount === 10) {
|
||||||
|
return '无折扣'
|
||||||
|
}
|
||||||
|
return discount % 1 === 0 ? `${discount}折` : `${discount.toFixed(1)}折`
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前时间
|
||||||
|
* 返回:yyyy-MM-dd HH:mm:ss
|
||||||
|
*/
|
||||||
|
export const getCurrentDateTime = (): string => {
|
||||||
|
const now: Date = new Date()
|
||||||
|
|
||||||
|
const year: number = now.getFullYear()
|
||||||
|
const month: number = now.getMonth() + 1
|
||||||
|
const day: number = now.getDate()
|
||||||
|
const hours: number = now.getHours()
|
||||||
|
const minutes: number = now.getMinutes()
|
||||||
|
const seconds: number = now.getSeconds()
|
||||||
|
|
||||||
|
// 格式化为字符串
|
||||||
|
const formattedDateTime = `${year}-${padZero(month)}-${padZero(day)} ${padZero(hours)}:${padZero(
|
||||||
|
minutes
|
||||||
|
)}:${padZero(seconds)}`
|
||||||
|
|
||||||
|
return formattedDateTime
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前日期
|
||||||
|
* 返回:yyyy-MM-dd HH:mm:ss
|
||||||
|
*/
|
||||||
|
export const getCurrentDate = (): string => {
|
||||||
|
const now: Date = new Date()
|
||||||
|
|
||||||
|
const year: number = now.getFullYear()
|
||||||
|
const month: number = now.getMonth() + 1
|
||||||
|
const day: number = now.getDate()
|
||||||
|
|
||||||
|
// 格式化为字符串
|
||||||
|
const formattedDate = `${year}-${padZero(month)}-${padZero(day)}`
|
||||||
|
|
||||||
|
return formattedDate
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助函数:在数字小于10时,在前面补零
|
||||||
|
export const padZero = (num: number): string => {
|
||||||
|
return num < 10 ? `0${num}` : `${num}`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将base64编码的字符串转换为文件
|
||||||
|
export const base64ToFile = (dataURI, filename): File => {
|
||||||
|
const arr = dataURI.split(',')
|
||||||
|
const mime = arr[0].match(/:(.*?);/)[1]
|
||||||
|
const bstr = atob(arr[1])
|
||||||
|
let n = bstr.length
|
||||||
|
const u8arr = new Uint8Array(n)
|
||||||
|
while (n--) {
|
||||||
|
u8arr[n] = bstr.charCodeAt(n)
|
||||||
|
}
|
||||||
|
return new File([u8arr], filename, { type: mime })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据当前时间获取祝福语
|
||||||
|
export const getGreeting = (): string => {
|
||||||
|
const now = new Date()
|
||||||
|
const hour = now.getHours()
|
||||||
|
|
||||||
|
if (hour >= 6 && hour < 10) {
|
||||||
|
return '早上好'
|
||||||
|
} else if (hour >= 10 && hour < 13) {
|
||||||
|
return '中午好'
|
||||||
|
} else if (hour >= 13 && hour < 18) {
|
||||||
|
return '下午好'
|
||||||
|
} else {
|
||||||
|
return '晚上好'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前星期几
|
||||||
|
export const getDayOfWeek = (): string => {
|
||||||
|
const daysOfWeek: string[] = [
|
||||||
|
'星期日',
|
||||||
|
'星期一',
|
||||||
|
'星期二',
|
||||||
|
'星期三',
|
||||||
|
'星期四',
|
||||||
|
'星期五',
|
||||||
|
'星期六'
|
||||||
|
]
|
||||||
|
const date: Date = new Date()
|
||||||
|
const dayOfWeekIndex: number = date.getDay()
|
||||||
|
return daysOfWeek[dayOfWeekIndex]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数字转金额
|
||||||
|
// 作者:时光足迹
|
||||||
|
// 链接:https://juejin.cn/post/7028086399601475591
|
||||||
|
// 来源:稀土掘金
|
||||||
|
export const formatMoney = (amount, currency = true): string => {
|
||||||
|
const formatter = new Intl.NumberFormat('zh-CN', {
|
||||||
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2,
|
||||||
|
useGrouping: true
|
||||||
|
})
|
||||||
|
|
||||||
|
const formattedAmount = formatter.format(amount)
|
||||||
|
|
||||||
|
if (currency) {
|
||||||
|
return `¥${formattedAmount}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return formattedAmount
|
||||||
|
}
|
||||||
|
@ -3,27 +3,19 @@ import { useTimeAgo } from '@/hooks/web/useTimeAgo'
|
|||||||
import { ElRow, ElCol, ElSkeleton, ElCard, ElDivider, ElLink } from 'element-plus'
|
import { ElRow, ElCol, ElSkeleton, ElCard, ElDivider, ElLink } from 'element-plus'
|
||||||
import { useI18n } from '@/hooks/web/useI18n'
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
import { ref, reactive, computed } from 'vue'
|
import { ref, reactive, computed } from 'vue'
|
||||||
import { CountTo } from '@/components/CountTo'
|
import { formatTime, getGreeting, getCurrentDate, getDayOfWeek } from '@/utils'
|
||||||
import { formatTime } from '@/utils'
|
|
||||||
import { Highlight } from '@/components/Highlight'
|
import { Highlight } from '@/components/Highlight'
|
||||||
import {
|
import {
|
||||||
getCountApi,
|
|
||||||
getProjectApi,
|
getProjectApi,
|
||||||
getDynamicApi,
|
getDynamicApi,
|
||||||
getTeamApi,
|
getTeamApi,
|
||||||
getShortcutsApi
|
getShortcutsApi
|
||||||
} from '@/api/dashboard/workplace'
|
} from '@/api/dashboard/workplace'
|
||||||
import type {
|
import type { Project, Dynamic, Team, Shortcuts } from '@/api/dashboard/workplace/types'
|
||||||
WorkplaceTotal,
|
|
||||||
Project,
|
|
||||||
Dynamic,
|
|
||||||
Team,
|
|
||||||
Shortcuts
|
|
||||||
} from '@/api/dashboard/workplace/types'
|
|
||||||
import avatar from '@/assets/imgs/avatar.jpg'
|
import avatar from '@/assets/imgs/avatar.jpg'
|
||||||
import { useAuthStoreWithOut } from '@/store/modules/auth'
|
import { useAuthStore } from '@/store/modules/auth'
|
||||||
|
|
||||||
const authStore = useAuthStoreWithOut()
|
const authStore = useAuthStore()
|
||||||
|
|
||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
|
|
||||||
@ -31,20 +23,6 @@ const toLink = (link: string) => {
|
|||||||
window.open(link)
|
window.open(link)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取统计数
|
|
||||||
let totalSate = reactive<WorkplaceTotal>({
|
|
||||||
project: 0,
|
|
||||||
access: 0,
|
|
||||||
todo: 0
|
|
||||||
})
|
|
||||||
|
|
||||||
const getCount = async () => {
|
|
||||||
const res = await getCountApi().catch(() => {})
|
|
||||||
if (res) {
|
|
||||||
totalSate = Object.assign(totalSate, res.data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let projects = reactive<Project[]>([])
|
let projects = reactive<Project[]>([])
|
||||||
|
|
||||||
// 获取项目数
|
// 获取项目数
|
||||||
@ -88,7 +66,7 @@ const getTeam = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const getAllApi = async () => {
|
const getAllApi = async () => {
|
||||||
await Promise.all([getCount(), getProject(), getDynamic(), getTeam()])
|
await Promise.all([getProject(), getDynamic(), getTeam()])
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,10 +91,10 @@ const user = computed(() => authStore.getUser)
|
|||||||
/>
|
/>
|
||||||
<div class="truncate">
|
<div class="truncate">
|
||||||
<div class="text-20px text-700 truncate">
|
<div class="text-20px text-700 truncate">
|
||||||
{{ t('workplace.goodMorning') }},{{ user.name }},{{ t('workplace.happyDay') }}
|
{{ getGreeting() }},{{ user.name }},{{ t('workplace.happyDay') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-10px text-14px text-gray-500">
|
<div class="mt-10px text-14px text-gray-500">
|
||||||
{{ t('workplace.toady') }},20℃ - 32℃!
|
{{ getCurrentDate() }},{{ getDayOfWeek() }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -124,33 +102,8 @@ const user = computed(() => authStore.getUser)
|
|||||||
<ElCol :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
|
<ElCol :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
|
||||||
<div class="flex h-70px items-center justify-end <sm:mt-20px">
|
<div class="flex h-70px items-center justify-end <sm:mt-20px">
|
||||||
<div class="px-8px text-right">
|
<div class="px-8px text-right">
|
||||||
<div class="text-14px text-gray-400 mb-20px">{{ t('workplace.project') }}</div>
|
<div class="text-14px text-gray-400 mb-20px">最近登录时间</div>
|
||||||
<CountTo
|
<span class="text-20px">{{ user.last_login?.split(' ')[0] }}</span>
|
||||||
class="text-20px"
|
|
||||||
:start-val="0"
|
|
||||||
:end-val="totalSate.project"
|
|
||||||
:duration="2600"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<ElDivider direction="vertical" />
|
|
||||||
<div class="px-8px text-right">
|
|
||||||
<div class="text-14px text-gray-400 mb-20px">{{ t('workplace.toDo') }}</div>
|
|
||||||
<CountTo
|
|
||||||
class="text-20px"
|
|
||||||
:start-val="0"
|
|
||||||
:end-val="totalSate.todo"
|
|
||||||
:duration="2600"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<ElDivider direction="vertical" border-style="dashed" />
|
|
||||||
<div class="px-8px text-right">
|
|
||||||
<div class="text-14px text-gray-400 mb-20px">{{ t('workplace.access') }}</div>
|
|
||||||
<CountTo
|
|
||||||
class="text-20px"
|
|
||||||
:start-val="0"
|
|
||||||
:end-val="totalSate.access"
|
|
||||||
:duration="2600"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
|
@ -19,23 +19,13 @@ app = APIRouter()
|
|||||||
###########################################################
|
###########################################################
|
||||||
# 工作区管理
|
# 工作区管理
|
||||||
###########################################################
|
###########################################################
|
||||||
@app.get("/total", summary="获取统计")
|
|
||||||
async def get_total(auth: Auth = Depends(AllUserAuth())):
|
|
||||||
data = {
|
|
||||||
"project": 40,
|
|
||||||
"access": await LoginRecordDal(auth.db).get_count(),
|
|
||||||
"todo": 10
|
|
||||||
}
|
|
||||||
return SuccessResponse(data)
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/project", summary="获取项目")
|
@app.get("/project", summary="获取项目")
|
||||||
async def get_project():
|
async def get_project():
|
||||||
data = [
|
data = [
|
||||||
{
|
{
|
||||||
"name": 'Mysql',
|
"name": 'Mysql',
|
||||||
"icon": 'vscode-icons:file-type-mysql',
|
"icon": 'vscode-icons:file-type-mysql',
|
||||||
"message": 'MySQL 是最流行的关系型数据库管理系统',
|
"message": '最流行的关系型数据库管理系统',
|
||||||
"personal": 'kinit',
|
"personal": 'kinit',
|
||||||
"link": "https://www.mysql.com/",
|
"link": "https://www.mysql.com/",
|
||||||
"time": datetime.datetime.now().strftime("%Y-%m-%d")
|
"time": datetime.datetime.now().strftime("%Y-%m-%d")
|
||||||
@ -59,7 +49,7 @@ async def get_project():
|
|||||||
{
|
{
|
||||||
"name": 'Element-plus',
|
"name": 'Element-plus',
|
||||||
"icon": 'logos:element',
|
"icon": 'logos:element',
|
||||||
"message": '基于 Vue3,面向设计师和开发者的组件库',
|
"message": '面向设计师和开发者的组件库',
|
||||||
"personal": 'kinit',
|
"personal": 'kinit',
|
||||||
"link": "https://element-plus.org/zh-CN/",
|
"link": "https://element-plus.org/zh-CN/",
|
||||||
"time": datetime.datetime.now().strftime("%Y-%m-%d")
|
"time": datetime.datetime.now().strftime("%Y-%m-%d")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user