feat(Workplace): Add wrokplace demo
feat(Component): Add Highlight component feat(hooks): Add useTimeAgo hook
This commit is contained in:
parent
3fc79c0ae7
commit
c53fa562e5
Binary file not shown.
After Width: | Height: | Size: 86 KiB |
|
@ -0,0 +1,3 @@
|
||||||
|
import Highlight from './src/Highlight.vue'
|
||||||
|
|
||||||
|
export { Highlight }
|
|
@ -0,0 +1,65 @@
|
||||||
|
<script lang="tsx">
|
||||||
|
import { defineComponent, PropType, computed, h, unref } from 'vue'
|
||||||
|
import { propTypes } from '@/utils/propTypes'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'Highlight',
|
||||||
|
props: {
|
||||||
|
tag: propTypes.string.def('span'),
|
||||||
|
keys: {
|
||||||
|
type: Array as PropType<string[]>,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
color: propTypes.string.def('var(--el-color-primary)')
|
||||||
|
},
|
||||||
|
emits: ['click'],
|
||||||
|
setup(props, { emit, slots }) {
|
||||||
|
const keyNodes = computed(() => {
|
||||||
|
return props.keys.map((key) => {
|
||||||
|
return h(
|
||||||
|
'span',
|
||||||
|
{
|
||||||
|
onClick: () => {
|
||||||
|
emit('click', key)
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
color: props.color,
|
||||||
|
cursor: 'pointer'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
key
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const parseText = (text: string) => {
|
||||||
|
props.keys.forEach((key, index) => {
|
||||||
|
const regexp = new RegExp(key, 'g')
|
||||||
|
text = text.replace(regexp, `{{${index}}}`)
|
||||||
|
})
|
||||||
|
return text.split(/{{|}}/)
|
||||||
|
}
|
||||||
|
|
||||||
|
const renderText = () => {
|
||||||
|
if (!slots?.default) return null
|
||||||
|
const node = slots?.default()[0].children
|
||||||
|
|
||||||
|
if (!node) {
|
||||||
|
return slots?.default()[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
const textArray = parseText(node as string)
|
||||||
|
const regexp = /^[0-9]*$/
|
||||||
|
const nodes = textArray.map((t) => {
|
||||||
|
if (regexp.test(t)) {
|
||||||
|
return unref(keyNodes)[Math.floor(Number(t))] || t
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
})
|
||||||
|
return h(props.tag, nodes)
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => renderText()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
|
@ -38,7 +38,11 @@ const loginOut = () => {
|
||||||
<template>
|
<template>
|
||||||
<ElDropdown :class="prefixCls" trigger="click">
|
<ElDropdown :class="prefixCls" trigger="click">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<img src="@/assets/imgs/avatar.png" alt="" class="w-[calc(var(--tags-view-height)-10px)]" />
|
<img
|
||||||
|
src="@/assets/imgs/avatar.jpg"
|
||||||
|
alt=""
|
||||||
|
class="w-[calc(var(--tags-view-height)-10px)] rounded-[50%]"
|
||||||
|
/>
|
||||||
<span class="<lg:hidden text-14px pl-[5px] text-[var(--top-header-text-color)]">Archer</span>
|
<span class="<lg:hidden text-14px pl-[5px] text-[var(--top-header-text-color)]">Archer</span>
|
||||||
</div>
|
</div>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { useTimeAgo as useTimeAgoCore, UseTimeAgoMessages } from '@vueuse/core'
|
||||||
|
import { computed, unref } from 'vue'
|
||||||
|
import { useLocaleStoreWithOut } from '@/store/modules/locale'
|
||||||
|
|
||||||
|
const TIME_AGO_MESSAGE_MAP: {
|
||||||
|
'zh-CN': UseTimeAgoMessages
|
||||||
|
en: UseTimeAgoMessages
|
||||||
|
} = {
|
||||||
|
'zh-CN': {
|
||||||
|
justNow: '刚刚',
|
||||||
|
past: (n) => (n.match(/\d/) ? `${n}前` : n),
|
||||||
|
future: (n) => (n.match(/\d/) ? `${n}后` : n),
|
||||||
|
month: (n, past) => (n === 1 ? (past ? '上个月' : '下个月') : `${n} 个月`),
|
||||||
|
year: (n, past) => (n === 1 ? (past ? '去年' : '明年') : `${n} 年`),
|
||||||
|
day: (n, past) => (n === 1 ? (past ? '昨天' : '明天') : `${n} 天`),
|
||||||
|
week: (n, past) => (n === 1 ? (past ? '上周' : '下周') : `${n} 周`),
|
||||||
|
hour: (n) => `${n} 小时`,
|
||||||
|
minute: (n) => `${n} 分钟`,
|
||||||
|
second: (n) => `${n} 秒`
|
||||||
|
},
|
||||||
|
en: {
|
||||||
|
justNow: '刚刚',
|
||||||
|
past: (n) => (n.match(/\d/) ? `${n} ago` : n),
|
||||||
|
future: (n) => (n.match(/\d/) ? `in ${n}` : n),
|
||||||
|
month: (n, past) =>
|
||||||
|
n === 1 ? (past ? 'last month' : 'next month') : `${n} month${n > 1 ? 's' : ''}`,
|
||||||
|
year: (n, past) =>
|
||||||
|
n === 1 ? (past ? 'last year' : 'next year') : `${n} year${n > 1 ? 's' : ''}`,
|
||||||
|
day: (n, past) => (n === 1 ? (past ? 'yesterday' : 'tomorrow') : `${n} day${n > 1 ? 's' : ''}`),
|
||||||
|
week: (n, past) =>
|
||||||
|
n === 1 ? (past ? 'last week' : 'next week') : `${n} week${n > 1 ? 's' : ''}`,
|
||||||
|
hour: (n) => `${n} hour${n > 1 ? 's' : ''}`,
|
||||||
|
minute: (n) => `${n} minute${n > 1 ? 's' : ''}`,
|
||||||
|
second: (n) => `${n} second${n > 1 ? 's' : ''}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useTimeAgo = (time: Date | number | string) => {
|
||||||
|
const localeStore = useLocaleStoreWithOut()
|
||||||
|
|
||||||
|
const currentLocale = computed(() => localeStore.getCurrentLocale)
|
||||||
|
|
||||||
|
const timeAgo = useTimeAgoCore(time, {
|
||||||
|
messages: TIME_AGO_MESSAGE_MAP[unref(currentLocale).lang]
|
||||||
|
})
|
||||||
|
|
||||||
|
return timeAgo
|
||||||
|
}
|
|
@ -71,7 +71,8 @@ export default {
|
||||||
menu12: 'Menu1-2',
|
menu12: 'Menu1-2',
|
||||||
menu2: 'Menu2',
|
menu2: 'Menu2',
|
||||||
dashboard: 'Dashboard',
|
dashboard: 'Dashboard',
|
||||||
analysis: 'Analysis'
|
analysis: 'Analysis',
|
||||||
|
workplace: 'Workplace'
|
||||||
},
|
},
|
||||||
analysis: {
|
analysis: {
|
||||||
newUser: 'New user',
|
newUser: 'New user',
|
||||||
|
@ -109,6 +110,28 @@ export default {
|
||||||
saturday: 'Saturday',
|
saturday: 'Saturday',
|
||||||
sunday: 'Sunday'
|
sunday: 'Sunday'
|
||||||
},
|
},
|
||||||
|
workplace: {
|
||||||
|
goodMorning: 'Good morning',
|
||||||
|
happyDay: 'Wish you happy every day!',
|
||||||
|
toady: `It's sunny today`,
|
||||||
|
project: 'Project',
|
||||||
|
access: 'Project access',
|
||||||
|
toDo: 'To do',
|
||||||
|
introduction: 'A serious introduction',
|
||||||
|
more: 'More',
|
||||||
|
shortcutOperation: 'Shortcut operation',
|
||||||
|
operation: 'Operation',
|
||||||
|
index: 'Index',
|
||||||
|
personal: 'Personal',
|
||||||
|
team: 'Team',
|
||||||
|
quote: 'Quote',
|
||||||
|
contribution: 'Contribution',
|
||||||
|
hot: 'Hot',
|
||||||
|
yield: 'Yield',
|
||||||
|
dynamic: 'Dynamic',
|
||||||
|
push: 'push',
|
||||||
|
pushCode: 'Archer push code to GitHub'
|
||||||
|
},
|
||||||
formDemo: {
|
formDemo: {
|
||||||
input: 'Input',
|
input: 'Input',
|
||||||
inputNumber: 'InputNumber',
|
inputNumber: 'InputNumber',
|
||||||
|
|
|
@ -71,7 +71,8 @@ export default {
|
||||||
menu12: '菜单1-2',
|
menu12: '菜单1-2',
|
||||||
menu2: '菜单2',
|
menu2: '菜单2',
|
||||||
dashboard: '首页',
|
dashboard: '首页',
|
||||||
analysis: '分析页'
|
analysis: '分析页',
|
||||||
|
workplace: '工作台'
|
||||||
},
|
},
|
||||||
analysis: {
|
analysis: {
|
||||||
newUser: '新增用户',
|
newUser: '新增用户',
|
||||||
|
@ -109,6 +110,28 @@ export default {
|
||||||
saturday: '周六',
|
saturday: '周六',
|
||||||
sunday: '周日'
|
sunday: '周日'
|
||||||
},
|
},
|
||||||
|
workplace: {
|
||||||
|
goodMorning: '早安',
|
||||||
|
happyDay: '祝你开心每一天!',
|
||||||
|
toady: '今日晴',
|
||||||
|
project: '项目数',
|
||||||
|
access: '项目访问',
|
||||||
|
toDo: '待办',
|
||||||
|
introduction: '一个正经的简介',
|
||||||
|
more: '更多',
|
||||||
|
shortcutOperation: '快捷操作',
|
||||||
|
operation: '操作',
|
||||||
|
index: '指数',
|
||||||
|
personal: '个人',
|
||||||
|
team: '团队',
|
||||||
|
quote: '引用',
|
||||||
|
contribution: '贡献',
|
||||||
|
hot: '热度',
|
||||||
|
yield: '产量',
|
||||||
|
dynamic: '动态',
|
||||||
|
push: '推送',
|
||||||
|
pushCode: 'Archer 推送 代码到 Github'
|
||||||
|
},
|
||||||
formDemo: {
|
formDemo: {
|
||||||
input: '输入框',
|
input: '输入框',
|
||||||
inputNumber: '数字输入框',
|
inputNumber: '数字输入框',
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
import * as echarts from 'echarts/core'
|
import * as echarts from 'echarts/core'
|
||||||
|
|
||||||
import { BarChart, LineChart, PieChart, MapChart, PictorialBarChart } from 'echarts/charts'
|
import {
|
||||||
|
BarChart,
|
||||||
|
LineChart,
|
||||||
|
PieChart,
|
||||||
|
MapChart,
|
||||||
|
PictorialBarChart,
|
||||||
|
RadarChart
|
||||||
|
} from 'echarts/charts'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
TitleComponent,
|
TitleComponent,
|
||||||
|
@ -27,7 +34,8 @@ echarts.use([
|
||||||
PieChart,
|
PieChart,
|
||||||
MapChart,
|
MapChart,
|
||||||
CanvasRenderer,
|
CanvasRenderer,
|
||||||
PictorialBarChart
|
PictorialBarChart,
|
||||||
|
RadarChart
|
||||||
])
|
])
|
||||||
|
|
||||||
export default echarts
|
export default echarts
|
||||||
|
|
|
@ -54,8 +54,16 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
|
||||||
name: 'Analysis',
|
name: 'Analysis',
|
||||||
meta: {
|
meta: {
|
||||||
title: t('router.analysis'),
|
title: t('router.analysis'),
|
||||||
noCache: true,
|
noCache: true
|
||||||
affix: true
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'workplace',
|
||||||
|
component: () => import('@/views/Dashboard/Workplace.vue'),
|
||||||
|
name: 'Workplace',
|
||||||
|
meta: {
|
||||||
|
title: t('router.workplace'),
|
||||||
|
noCache: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -63,3 +63,35 @@ export const findIndex = <T = Recordable>(ary: Array<T>, fn: Fn): number => {
|
||||||
export const trim = (str: string) => {
|
export const trim = (str: string) => {
|
||||||
return str.replace(/(^\s*)|(\s*$)/g, '')
|
return str.replace(/(^\s*)|(\s*$)/g, '')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Date | number | string} time 需要转换的时间
|
||||||
|
* @param {String} fmt 需要转换的格式 如 yyyy-MM-dd、yyyy-MM-dd HH:mm:ss
|
||||||
|
*/
|
||||||
|
export function formatTime(time: Date | number | string, fmt: string) {
|
||||||
|
if (!time) return ''
|
||||||
|
else {
|
||||||
|
const date = new Date(time)
|
||||||
|
const o = {
|
||||||
|
'M+': date.getMonth() + 1,
|
||||||
|
'd+': date.getDate(),
|
||||||
|
'H+': date.getHours(),
|
||||||
|
'm+': date.getMinutes(),
|
||||||
|
's+': date.getSeconds(),
|
||||||
|
'q+': Math.floor((date.getMonth() + 3) / 3),
|
||||||
|
S: date.getMilliseconds()
|
||||||
|
}
|
||||||
|
if (/(y+)/.test(fmt)) {
|
||||||
|
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
|
||||||
|
}
|
||||||
|
for (const k in o) {
|
||||||
|
if (new RegExp('(' + k + ')').test(fmt)) {
|
||||||
|
fmt = fmt.replace(
|
||||||
|
RegExp.$1,
|
||||||
|
RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ setTimeout(() => {
|
||||||
<ElCol :span="24">
|
<ElCol :span="24">
|
||||||
<ElCard shadow="hover" class="mb-20px">
|
<ElCard shadow="hover" class="mb-20px">
|
||||||
<ElSkeleton :loading="loading" animated :rows="4">
|
<ElSkeleton :loading="loading" animated :rows="4">
|
||||||
<Echart :options="lineOptions" :height="400" />
|
<Echart :options="lineOptions" :height="350" />
|
||||||
</ElSkeleton>
|
</ElSkeleton>
|
||||||
</ElCard>
|
</ElCard>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
|
|
|
@ -0,0 +1,299 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useTimeAgo } from '@/hooks/web/useTimeAgo'
|
||||||
|
import { ElRow, ElCol, ElSkeleton, ElCard, ElDivider, ElLink } from 'element-plus'
|
||||||
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { CountTo } from '@/components/CountTo'
|
||||||
|
import { formatTime } from '@/utils'
|
||||||
|
import { Echart } from '@/components/Echart'
|
||||||
|
import { radarOption } from './echarts-data'
|
||||||
|
import { Highlight } from '@/components/Highlight'
|
||||||
|
|
||||||
|
interface Project {
|
||||||
|
name: string
|
||||||
|
icon: string
|
||||||
|
message: string
|
||||||
|
personal: string
|
||||||
|
time: Date | number | string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Dynamic {
|
||||||
|
keys: string[]
|
||||||
|
time: Date | number | string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Team {
|
||||||
|
name: string
|
||||||
|
icon: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const projects: Project[] = [
|
||||||
|
{
|
||||||
|
name: 'Github',
|
||||||
|
icon: 'akar-icons:github-fill',
|
||||||
|
message: t('workplace.introduction'),
|
||||||
|
personal: 'Archer',
|
||||||
|
time: new Date()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Vue',
|
||||||
|
icon: 'logos:vue',
|
||||||
|
message: t('workplace.introduction'),
|
||||||
|
personal: 'Archer',
|
||||||
|
time: new Date()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Angular',
|
||||||
|
icon: 'logos:angular-icon',
|
||||||
|
message: t('workplace.introduction'),
|
||||||
|
personal: 'Archer',
|
||||||
|
time: new Date()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'React',
|
||||||
|
icon: 'logos:react',
|
||||||
|
message: t('workplace.introduction'),
|
||||||
|
personal: 'Archer',
|
||||||
|
time: new Date()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Webpack',
|
||||||
|
icon: 'logos:webpack',
|
||||||
|
message: t('workplace.introduction'),
|
||||||
|
personal: 'Archer',
|
||||||
|
time: new Date()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Vite',
|
||||||
|
icon: 'vscode-icons:file-type-vite',
|
||||||
|
message: t('workplace.introduction'),
|
||||||
|
personal: 'Archer',
|
||||||
|
time: new Date()
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const dynamics: Dynamic[] = [
|
||||||
|
{
|
||||||
|
keys: [t('workplace.push'), 'Github'],
|
||||||
|
time: new Date()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: [t('workplace.push'), 'Github'],
|
||||||
|
time: new Date()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: [t('workplace.push'), 'Github'],
|
||||||
|
time: new Date()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: [t('workplace.push'), 'Github'],
|
||||||
|
time: new Date()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: [t('workplace.push'), 'Github'],
|
||||||
|
time: new Date()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: [t('workplace.push'), 'Github'],
|
||||||
|
time: new Date()
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const team: Team[] = [
|
||||||
|
{
|
||||||
|
name: 'Github',
|
||||||
|
icon: 'akar-icons:github-fill'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Vue',
|
||||||
|
icon: 'logos:vue'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Angular',
|
||||||
|
icon: 'logos:angular-icon'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'React',
|
||||||
|
icon: 'logos:react'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Webpack',
|
||||||
|
icon: 'logos:webpack'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Vite',
|
||||||
|
icon: 'vscode-icons:file-type-vite'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const loading = ref(true)
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
loading.value = false
|
||||||
|
}, 1000)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<ElCard shadow="never">
|
||||||
|
<ElSkeleton :loading="loading" animated>
|
||||||
|
<ElRow :gutter="20" justify="space-between">
|
||||||
|
<ElCol :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<img
|
||||||
|
src="@/assets/imgs/avatar.jpg"
|
||||||
|
alt=""
|
||||||
|
class="w-70px h-70px rounded-[50%] mr-20px"
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<div class="text-20px text-700">
|
||||||
|
{{ t('workplace.goodMorning') }},Archer,{{ t('workplace.happyDay') }}
|
||||||
|
</div>
|
||||||
|
<div class="mt-10px text-14px text-gray-500">
|
||||||
|
{{ t('workplace.toady') }},20℃ - 32℃!
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ElCol>
|
||||||
|
<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="px-8px text-right">
|
||||||
|
<div class="text-14px text-gray-400 mb-20px">{{ t('workplace.project') }}</div>
|
||||||
|
<CountTo class="text-20px" :start-val="0" :end-val="40" :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="10" :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="2340" :duration="2600" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ElCol>
|
||||||
|
</ElRow>
|
||||||
|
</ElSkeleton>
|
||||||
|
</ElCard>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ElRow class="mt-20px" :gutter="20" justify="space-between">
|
||||||
|
<ElCol :xl="16" :lg="16" :md="24" :sm="24" :xs="24" class="mb-20px">
|
||||||
|
<ElSkeleton :loading="loading" animated>
|
||||||
|
<ElCard shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<div class="flex justify-between">
|
||||||
|
<span>{{ t('workplace.project') }}</span>
|
||||||
|
<ElLink type="primary" :underline="false">{{ t('workplace.more') }}</ElLink>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<ElRow>
|
||||||
|
<ElCol
|
||||||
|
v-for="(item, index) in projects"
|
||||||
|
:key="`card-${index}`"
|
||||||
|
:xl="8"
|
||||||
|
:lg="8"
|
||||||
|
:md="12"
|
||||||
|
:sm="24"
|
||||||
|
:xs="24"
|
||||||
|
>
|
||||||
|
<ElCard shadow="hover">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<Icon :icon="item.icon" :size="25" class="mr-10px" />
|
||||||
|
<span class="text-16px">{{ item.name }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="mt-15px text-14px text-gray-400">{{ item.message }}</div>
|
||||||
|
<div class="mt-20px text-12px text-gray-400 flex justify-between">
|
||||||
|
<span>{{ item.personal }}</span>
|
||||||
|
<span>{{ formatTime(item.time, 'yyyy-MM-dd') }}</span>
|
||||||
|
</div>
|
||||||
|
</ElCard>
|
||||||
|
</ElCol>
|
||||||
|
</ElRow>
|
||||||
|
</ElCard>
|
||||||
|
</ElSkeleton>
|
||||||
|
|
||||||
|
<ElSkeleton :loading="loading" animated>
|
||||||
|
<ElCard shadow="never" class="mt-20px">
|
||||||
|
<template #header>
|
||||||
|
<div class="flex justify-between">
|
||||||
|
<span>{{ t('workplace.dynamic') }}</span>
|
||||||
|
<ElLink type="primary" :underline="false">{{ t('workplace.more') }}</ElLink>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div v-for="(item, index) in dynamics" :key="`dynamics-${index}`">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<img
|
||||||
|
src="@/assets/imgs/avatar.jpg"
|
||||||
|
alt=""
|
||||||
|
class="w-35px h-35px rounded-[50%] mr-20px"
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<div class="text-14px">
|
||||||
|
<Highlight :keys="item.keys"> {{ t('workplace.pushCode') }} </Highlight>
|
||||||
|
</div>
|
||||||
|
<div class="mt-15px text-12px text-gray-400">
|
||||||
|
{{ useTimeAgo(item.time) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ElDivider />
|
||||||
|
</div>
|
||||||
|
</ElCard>
|
||||||
|
</ElSkeleton>
|
||||||
|
</ElCol>
|
||||||
|
<ElCol :xl="8" :lg="8" :md="24" :sm="24" :xs="24" class="mb-20px">
|
||||||
|
<ElSkeleton :loading="loading" animated>
|
||||||
|
<ElCard shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('workplace.shortcutOperation') }}</span>
|
||||||
|
</template>
|
||||||
|
<ElCol
|
||||||
|
v-for="item in 9"
|
||||||
|
:key="`card-${item}`"
|
||||||
|
:xl="12"
|
||||||
|
:lg="12"
|
||||||
|
:md="12"
|
||||||
|
:sm="24"
|
||||||
|
:xs="24"
|
||||||
|
class="mb-10px"
|
||||||
|
>
|
||||||
|
<ElLink type="default" :underline="false">
|
||||||
|
{{ t('workplace.operation') }}{{ item }}
|
||||||
|
</ElLink>
|
||||||
|
</ElCol>
|
||||||
|
</ElCard>
|
||||||
|
</ElSkeleton>
|
||||||
|
|
||||||
|
<ElSkeleton :loading="loading" animated>
|
||||||
|
<ElCard shadow="never" class="mt-20px">
|
||||||
|
<template #header>
|
||||||
|
<span>xx{{ t('workplace.index') }}</span>
|
||||||
|
</template>
|
||||||
|
<Echart :options="radarOption" :height="400" />
|
||||||
|
</ElCard>
|
||||||
|
</ElSkeleton>
|
||||||
|
|
||||||
|
<ElSkeleton :loading="loading" animated>
|
||||||
|
<ElCard shadow="never" class="mt-20px">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('workplace.team') }}</span>
|
||||||
|
</template>
|
||||||
|
<ElRow>
|
||||||
|
<ElCol v-for="item in team" :key="`team-${item.name}`" :span="12" class="mb-20px">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<Icon :icon="item.icon" class="mr-10px" />
|
||||||
|
<ElLink type="default" :underline="false">
|
||||||
|
{{ item.name }}
|
||||||
|
</ElLink>
|
||||||
|
</div>
|
||||||
|
</ElCol>
|
||||||
|
</ElRow>
|
||||||
|
</ElCard>
|
||||||
|
</ElSkeleton>
|
||||||
|
</ElCol>
|
||||||
|
</ElRow>
|
||||||
|
</template>
|
|
@ -151,3 +151,34 @@ export const barOptions: EChartsOption = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const radarOption: EChartsOption = {
|
||||||
|
legend: {
|
||||||
|
data: [t('workplace.personal'), t('workplace.team')]
|
||||||
|
},
|
||||||
|
radar: {
|
||||||
|
// shape: 'circle',
|
||||||
|
indicator: [
|
||||||
|
{ name: t('workplace.quote'), max: 65 },
|
||||||
|
{ name: t('workplace.contribution'), max: 160 },
|
||||||
|
{ name: t('workplace.hot'), max: 300 },
|
||||||
|
{ name: t('workplace.yield'), max: 130 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: `xxx${t('workplace.index')}`,
|
||||||
|
type: 'radar',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
value: [42, 30, 20, 35],
|
||||||
|
name: t('workplace.personal')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: [50, 140, 28, 35],
|
||||||
|
name: t('workplace.team')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue