21 changed files with 4 additions and 1113 deletions
@ -1,191 +0,0 @@
|
||||
export enum StationStatus { |
||||
Closed = '0', |
||||
Using = '1', |
||||
} |
||||
|
||||
/** |
||||
* 站点状态 |
||||
*/ |
||||
export const StationStatusOptions = [ |
||||
{ |
||||
value: StationStatus.Closed, |
||||
label: '关闭中', |
||||
}, |
||||
{ |
||||
value: StationStatus.Using, |
||||
label: '使用中', |
||||
}, |
||||
] |
||||
|
||||
export enum StationEnvironments { |
||||
OpenAir = '0', |
||||
Underground = '1', |
||||
Carport = '2', |
||||
} |
||||
|
||||
/** |
||||
* 站点环境 |
||||
*/ |
||||
export const StationEnvironmentOptions = [ |
||||
{ |
||||
value: StationEnvironments.OpenAir, |
||||
label: '露天', |
||||
}, |
||||
{ |
||||
value: StationEnvironments.Underground, |
||||
label: '地下', |
||||
}, |
||||
{ |
||||
value: StationEnvironments.Carport, |
||||
label: '车棚', |
||||
}, |
||||
] |
||||
|
||||
/** |
||||
* 建筑场所 |
||||
*/ |
||||
export const BuildingLotOptions = [ |
||||
{ |
||||
value: '1', |
||||
label: '居民区', |
||||
}, |
||||
{ |
||||
value: '2', |
||||
label: '公共机构', |
||||
}, |
||||
{ |
||||
value: '3', |
||||
label: '企事业单位', |
||||
}, |
||||
{ |
||||
value: '4', |
||||
label: '写字楼', |
||||
}, |
||||
{ |
||||
value: '5', |
||||
label: '工业园区', |
||||
}, |
||||
{ |
||||
value: '6', |
||||
label: '交通枢纽', |
||||
}, |
||||
{ |
||||
value: '7', |
||||
label: '大型文体设施', |
||||
}, |
||||
{ |
||||
value: '8', |
||||
label: '城市绿地', |
||||
}, |
||||
{ |
||||
value: '9', |
||||
label: '大型建筑配建停车场', |
||||
}, |
||||
{ |
||||
value: '10', |
||||
label: '路边停车位', |
||||
}, |
||||
{ |
||||
value: '11', |
||||
label: '城际高速服务区', |
||||
}, |
||||
{ |
||||
value: '255', |
||||
label: '其他', |
||||
}, |
||||
] |
||||
|
||||
/** |
||||
* 运营方式 |
||||
*/ |
||||
export const OperateWayOptions = [ |
||||
{ |
||||
value: 'self', |
||||
label: '自营', |
||||
}, |
||||
{ |
||||
value: 'other', |
||||
label: '代运营', |
||||
}, |
||||
] |
||||
|
||||
export enum ParkingChargeWay { |
||||
Free = '0', |
||||
LimitedFree = '1', |
||||
Changing = '2', |
||||
} |
||||
|
||||
export const ParkingChargeWayOptions = [ |
||||
{ |
||||
value: ParkingChargeWay.Free, |
||||
label: '免费停车', |
||||
}, |
||||
{ |
||||
value: ParkingChargeWay.LimitedFree, |
||||
label: '限时免费', |
||||
}, |
||||
{ |
||||
value: ParkingChargeWay.Changing, |
||||
label: '收费停车', |
||||
}, |
||||
] |
||||
|
||||
/** |
||||
* 支付状态 |
||||
*/ |
||||
export const PayStatusOptions = [ |
||||
{ |
||||
label: '未支付', |
||||
value: 'notPay', |
||||
}, |
||||
{ |
||||
label: '支付中', |
||||
value: 'paying', |
||||
}, |
||||
{ |
||||
label: '支付成功', |
||||
value: 'suc', |
||||
}, |
||||
{ |
||||
label: '支付失败', |
||||
value: 'fail', |
||||
}, |
||||
{ |
||||
label: '待退款', |
||||
value: 'waitRefund', |
||||
}, |
||||
{ |
||||
label: '退款中', |
||||
value: 'refunding', |
||||
}, |
||||
{ |
||||
label: '退款成功', |
||||
value: 'refundSuc', |
||||
}, |
||||
{ |
||||
label: '退款失败', |
||||
value: 'refundFailed', |
||||
}, |
||||
] |
||||
|
||||
/** |
||||
* 支付渠道 |
||||
*/ |
||||
export const PayModesEnum = [ |
||||
{ |
||||
label: '微信分支付', |
||||
value: 'wechatFen', |
||||
}, |
||||
{ |
||||
label: '微信扫码', |
||||
value: '1', |
||||
}, |
||||
{ |
||||
label: '支付宝扫码', |
||||
value: '2', |
||||
}, |
||||
{ |
||||
label: '银座钱包', |
||||
value: '3', |
||||
}, |
||||
] |
@ -1,41 +0,0 @@
|
||||
<script lang="ts" setup> |
||||
import { Card, Tag } from 'ant-design-vue' |
||||
import { growCardList } from '../data' |
||||
import { CountTo } from '@/components/CountTo' |
||||
import { SvgIcon } from '@/components/Icon' |
||||
|
||||
defineProps({ |
||||
loading: { |
||||
type: Boolean, |
||||
}, |
||||
}) |
||||
</script> |
||||
|
||||
<template> |
||||
<div class="md:flex"> |
||||
<template v-for="(item, index) in growCardList" :key="item.title"> |
||||
<Card |
||||
:loading="loading" |
||||
:title="item.title" |
||||
class="w-full md:w-1/4 !md:mt-0" |
||||
:class="{ '!md:mr-4': index + 1 < 4, '!mt-4': index > 0 }" |
||||
> |
||||
<template #extra> |
||||
<Tag :color="item.color"> |
||||
{{ item.action }} |
||||
</Tag> |
||||
</template> |
||||
|
||||
<div class="flex items-center justify-between px-4 py-4"> |
||||
<CountTo prefix="$" :start-val="1" :end-val="item.value" class="text-2xl" /> |
||||
<SvgIcon :name="item.icon" :size="40" /> |
||||
</div> |
||||
|
||||
<div class="flex justify-between p-2 px-4"> |
||||
<span>总{{ item.title }}</span> |
||||
<CountTo prefix="$" :start-val="1" :end-val="item.total" /> |
||||
</div> |
||||
</Card> |
||||
</template> |
||||
</div> |
||||
</template> |
@ -1,61 +0,0 @@
|
||||
<script lang="ts" setup> |
||||
import type { Ref } from 'vue' |
||||
import { ref, watch } from 'vue' |
||||
import { Card } from 'ant-design-vue' |
||||
import { useECharts } from '@/hooks/web/useECharts' |
||||
import { propTypes } from '@/utils/propTypes' |
||||
|
||||
const props = defineProps({ |
||||
loading: Boolean, |
||||
width: propTypes.string.def('100%'), |
||||
height: propTypes.string.def('300px'), |
||||
}) |
||||
|
||||
const chartRef = ref<HTMLDivElement | null>(null) |
||||
const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>) |
||||
|
||||
watch( |
||||
() => props.loading, |
||||
() => { |
||||
if (props.loading) |
||||
return |
||||
|
||||
setOptions({ |
||||
tooltip: { |
||||
trigger: 'item', |
||||
}, |
||||
|
||||
series: [ |
||||
{ |
||||
name: '访问来源', |
||||
type: 'pie', |
||||
radius: '80%', |
||||
center: ['50%', '50%'], |
||||
color: ['#5ab1ef', '#b6a2de', '#67e0e3', '#2ec7c9'], |
||||
data: [ |
||||
{ value: 500, name: '电子产品' }, |
||||
{ value: 310, name: '服装' }, |
||||
{ value: 274, name: '化妆品' }, |
||||
{ value: 400, name: '家居' }, |
||||
].sort((a, b) => { |
||||
return a.value - b.value |
||||
}), |
||||
roseType: 'radius', |
||||
animationType: 'scale', |
||||
animationEasing: 'exponentialInOut', |
||||
animationDelay() { |
||||
return Math.random() * 400 |
||||
}, |
||||
}, |
||||
], |
||||
}) |
||||
}, |
||||
{ immediate: true }, |
||||
) |
||||
</script> |
||||
|
||||
<template> |
||||
<Card title="成交占比" :loading="loading"> |
||||
<div ref="chartRef" :style="{ width, height }" /> |
||||
</Card> |
||||
</template> |
@ -1,34 +0,0 @@
|
||||
<script lang="ts" setup> |
||||
import { ref } from 'vue' |
||||
import { Card } from 'ant-design-vue' |
||||
import VisitAnalysis from './VisitAnalysis.vue' |
||||
import VisitAnalysisBar from './VisitAnalysisBar.vue' |
||||
|
||||
const activeKey = ref('tab1') |
||||
|
||||
const tabListTitle = [ |
||||
{ |
||||
key: 'tab1', |
||||
tab: '流量趋势', |
||||
}, |
||||
{ |
||||
key: 'tab2', |
||||
tab: '访问量', |
||||
}, |
||||
] |
||||
|
||||
function onTabChange(key: string) { |
||||
activeKey.value = key |
||||
} |
||||
</script> |
||||
|
||||
<template> |
||||
<Card :tab-list="tabListTitle" v-bind="$attrs" :active-tab-key="activeKey" @tab-change="onTabChange"> |
||||
<p v-if="activeKey === 'tab1'"> |
||||
<VisitAnalysis /> |
||||
</p> |
||||
<p v-if="activeKey === 'tab2'"> |
||||
<VisitAnalysisBar /> |
||||
</p> |
||||
</Card> |
||||
</template> |
@ -1,83 +0,0 @@
|
||||
<script lang="ts" setup> |
||||
import type { Ref } from 'vue' |
||||
import { onMounted, ref } from 'vue' |
||||
import { basicProps } from './props' |
||||
import { useECharts } from '@/hooks/web/useECharts' |
||||
|
||||
defineProps({ |
||||
...basicProps, |
||||
}) |
||||
const chartRef = ref<HTMLDivElement | null>(null) |
||||
const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>) |
||||
|
||||
onMounted(() => { |
||||
setOptions({ |
||||
tooltip: { |
||||
trigger: 'axis', |
||||
axisPointer: { |
||||
lineStyle: { |
||||
width: 1, |
||||
color: '#019680', |
||||
}, |
||||
}, |
||||
}, |
||||
xAxis: { |
||||
type: 'category', |
||||
boundaryGap: false, |
||||
data: [...Array.from({ length: 18 })].map((_item, index) => `${index + 6}:00`), |
||||
splitLine: { |
||||
show: true, |
||||
lineStyle: { |
||||
width: 1, |
||||
type: 'solid', |
||||
color: 'rgba(226,226,226,0.5)', |
||||
}, |
||||
}, |
||||
axisTick: { |
||||
show: false, |
||||
}, |
||||
}, |
||||
yAxis: [ |
||||
{ |
||||
type: 'value', |
||||
max: 80000, |
||||
splitNumber: 4, |
||||
axisTick: { |
||||
show: false, |
||||
}, |
||||
splitArea: { |
||||
show: true, |
||||
areaStyle: { |
||||
color: ['rgba(255,255,255,0.2)', 'rgba(226,226,226,0.2)'], |
||||
}, |
||||
}, |
||||
}, |
||||
], |
||||
grid: { left: '1%', right: '1%', top: '2 %', bottom: 0, containLabel: true }, |
||||
series: [ |
||||
{ |
||||
smooth: true, |
||||
data: [111, 222, 4000, 18000, 33333, 55555, 66666, 33333, 14000, 36000, 66666, 44444, 22222, 11111, 4000, 2000, 500, 333, 222, 111], |
||||
type: 'line', |
||||
areaStyle: {}, |
||||
itemStyle: { |
||||
color: '#5ab1ef', |
||||
}, |
||||
}, |
||||
{ |
||||
smooth: true, |
||||
data: [33, 66, 88, 333, 3333, 5000, 18000, 3000, 1200, 13000, 22000, 11000, 2221, 1201, 390, 198, 60, 30, 22, 11], |
||||
type: 'line', |
||||
areaStyle: {}, |
||||
itemStyle: { |
||||
color: '#019680', |
||||
}, |
||||
}, |
||||
], |
||||
}) |
||||
}) |
||||
</script> |
||||
|
||||
<template> |
||||
<div ref="chartRef" :style="{ height, width }" /> |
||||
</template> |
@ -1,47 +0,0 @@
|
||||
<script lang="ts" setup> |
||||
import type { Ref } from 'vue' |
||||
import { onMounted, ref } from 'vue' |
||||
import { basicProps } from './props' |
||||
import { useECharts } from '@/hooks/web/useECharts' |
||||
|
||||
defineProps({ |
||||
...basicProps, |
||||
}) |
||||
|
||||
const chartRef = ref<HTMLDivElement | null>(null) |
||||
const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>) |
||||
onMounted(() => { |
||||
setOptions({ |
||||
tooltip: { |
||||
trigger: 'axis', |
||||
axisPointer: { |
||||
lineStyle: { |
||||
width: 1, |
||||
color: '#019680', |
||||
}, |
||||
}, |
||||
}, |
||||
grid: { left: '1%', right: '1%', top: '2 %', bottom: 0, containLabel: true }, |
||||
xAxis: { |
||||
type: 'category', |
||||
data: [...Array.from({ length: 12 })].map((_item, index) => `${index + 1}月`), |
||||
}, |
||||
yAxis: { |
||||
type: 'value', |
||||
max: 8000, |
||||
splitNumber: 4, |
||||
}, |
||||
series: [ |
||||
{ |
||||
data: [3000, 2000, 3333, 5000, 3200, 4200, 3200, 2100, 3000, 5100, 6000, 3200, 4800], |
||||
type: 'bar', |
||||
barMaxWidth: 80, |
||||
}, |
||||
], |
||||
}) |
||||
}) |
||||
</script> |
||||
|
||||
<template> |
||||
<div ref="chartRef" :style="{ height, width }" /> |
||||
</template> |
@ -1,91 +0,0 @@
|
||||
<script lang="ts" setup> |
||||
import type { Ref } from 'vue' |
||||
import { ref, watch } from 'vue' |
||||
import { Card } from 'ant-design-vue' |
||||
import { useECharts } from '@/hooks/web/useECharts' |
||||
import { propTypes } from '@/utils/propTypes' |
||||
|
||||
const props = defineProps({ |
||||
loading: Boolean, |
||||
width: propTypes.string.def('100%'), |
||||
height: propTypes.string.def('300px'), |
||||
}) |
||||
const chartRef = ref<HTMLDivElement | null>(null) |
||||
const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>) |
||||
|
||||
watch( |
||||
() => props.loading, |
||||
() => { |
||||
if (props.loading) |
||||
return |
||||
|
||||
setOptions({ |
||||
legend: { |
||||
bottom: 0, |
||||
data: ['访问', '购买'], |
||||
}, |
||||
tooltip: {}, |
||||
radar: { |
||||
radius: '60%', |
||||
splitNumber: 8, |
||||
indicator: [ |
||||
{ |
||||
name: '电脑', |
||||
}, |
||||
{ |
||||
name: '充电器', |
||||
}, |
||||
{ |
||||
name: '耳机', |
||||
}, |
||||
{ |
||||
name: '手机', |
||||
}, |
||||
{ |
||||
name: 'Ipad', |
||||
}, |
||||
{ |
||||
name: '耳机', |
||||
}, |
||||
], |
||||
}, |
||||
series: [ |
||||
{ |
||||
type: 'radar', |
||||
symbolSize: 0, |
||||
areaStyle: { |
||||
shadowBlur: 0, |
||||
shadowColor: 'rgba(0,0,0,.2)', |
||||
shadowOffsetX: 0, |
||||
shadowOffsetY: 10, |
||||
opacity: 1, |
||||
}, |
||||
data: [ |
||||
{ |
||||
value: [90, 50, 86, 40, 50, 20], |
||||
name: '访问', |
||||
itemStyle: { |
||||
color: '#b6a2de', |
||||
}, |
||||
}, |
||||
{ |
||||
value: [70, 75, 70, 76, 20, 85], |
||||
name: '购买', |
||||
itemStyle: { |
||||
color: '#5ab1ef', |
||||
}, |
||||
}, |
||||
], |
||||
}, |
||||
], |
||||
}) |
||||
}, |
||||
{ immediate: true }, |
||||
) |
||||
</script> |
||||
|
||||
<template> |
||||
<Card title="转化率" :loading="loading"> |
||||
<div ref="chartRef" :style="{ width, height }" /> |
||||
</Card> |
||||
</template> |
@ -1,79 +0,0 @@
|
||||
<script lang="ts" setup> |
||||
import type { Ref } from 'vue' |
||||
import { ref, watch } from 'vue' |
||||
import { Card } from 'ant-design-vue' |
||||
import { useECharts } from '@/hooks/web/useECharts' |
||||
import { propTypes } from '@/utils/propTypes' |
||||
|
||||
const props = defineProps({ |
||||
loading: Boolean, |
||||
width: propTypes.string.def('100%'), |
||||
height: propTypes.string.def('300px'), |
||||
}) |
||||
const chartRef = ref<HTMLDivElement | null>(null) |
||||
const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>) |
||||
|
||||
watch( |
||||
() => props.loading, |
||||
() => { |
||||
if (props.loading) |
||||
return |
||||
|
||||
setOptions({ |
||||
tooltip: { |
||||
trigger: 'item', |
||||
}, |
||||
legend: { |
||||
bottom: '1%', |
||||
left: 'center', |
||||
}, |
||||
series: [ |
||||
{ |
||||
color: ['#5ab1ef', '#b6a2de', '#67e0e3', '#2ec7c9'], |
||||
name: '访问来源', |
||||
type: 'pie', |
||||
radius: ['40%', '70%'], |
||||
avoidLabelOverlap: false, |
||||
itemStyle: { |
||||
borderRadius: 10, |
||||
borderColor: '#fff', |
||||
borderWidth: 2, |
||||
}, |
||||
label: { |
||||
show: false, |
||||
position: 'center', |
||||
}, |
||||
emphasis: { |
||||
label: { |
||||
show: true, |
||||
fontSize: '12', |
||||
fontWeight: 'bold', |
||||
}, |
||||
}, |
||||
labelLine: { |
||||
show: false, |
||||
}, |
||||
data: [ |
||||
{ value: 1048, name: '搜索引擎' }, |
||||
{ value: 735, name: '直接访问' }, |
||||
{ value: 580, name: '邮件营销' }, |
||||
{ value: 484, name: '联盟广告' }, |
||||
], |
||||
animationType: 'scale', |
||||
animationEasing: 'exponentialInOut', |
||||
animationDelay() { |
||||
return Math.random() * 100 |
||||
}, |
||||
}, |
||||
], |
||||
}) |
||||
}, |
||||
{ immediate: true }, |
||||
) |
||||
</script> |
||||
|
||||
<template> |
||||
<Card title="访问来源" :loading="loading"> |
||||
<div ref="chartRef" :style="{ width, height }" /> |
||||
</Card> |
||||
</template> |
@ -1,16 +0,0 @@
|
||||
import type { PropType } from 'vue' |
||||
|
||||
export interface BasicProps { |
||||
width: string |
||||
height: string |
||||
} |
||||
export const basicProps = { |
||||
width: { |
||||
type: String as PropType<string>, |
||||
default: '100%', |
||||
}, |
||||
height: { |
||||
type: String as PropType<string>, |
||||
default: '280px', |
||||
}, |
||||
} |
@ -1,43 +0,0 @@
|
||||
export interface GrowCardItem { |
||||
icon: string |
||||
title: string |
||||
value: number |
||||
total: number |
||||
color: string |
||||
action: string |
||||
} |
||||
|
||||
export const growCardList: GrowCardItem[] = [ |
||||
{ |
||||
title: '访问数', |
||||
icon: 'visit-count', |
||||
value: 2000, |
||||
total: 120000, |
||||
color: 'green', |
||||
action: '月', |
||||
}, |
||||
{ |
||||
title: '成交额', |
||||
icon: 'total-sales', |
||||
value: 20000, |
||||
total: 500000, |
||||
color: 'blue', |
||||
action: '月', |
||||
}, |
||||
{ |
||||
title: '下载数', |
||||
icon: 'download-count', |
||||
value: 8000, |
||||
total: 120000, |
||||
color: 'orange', |
||||
action: '周', |
||||
}, |
||||
{ |
||||
title: '成交数', |
||||
icon: 'transaction', |
||||
value: 5000, |
||||
total: 50000, |
||||
color: 'purple', |
||||
action: '年', |
||||
}, |
||||
] |
@ -1,26 +0,0 @@
|
||||
<script lang="ts" setup> |
||||
import { ref } from 'vue' |
||||
import GrowCard from './components/GrowCard.vue' |
||||
import SiteAnalysis from './components/SiteAnalysis.vue' |
||||
import VisitSource from './components/VisitSource.vue' |
||||
import VisitRadar from './components/VisitRadar.vue' |
||||
import SalesProductPie from './components/SalesProductPie.vue' |
||||
|
||||
const loading = ref(true) |
||||
|
||||
setTimeout(() => { |
||||
loading.value = false |
||||
}, 500) |
||||
</script> |
||||
|
||||
<template> |
||||
<div class="p-4"> |
||||
<GrowCard :loading="loading" class="enter-y" /> |
||||
<SiteAnalysis class="enter-y !my-4" :loading="loading" /> |
||||
<div class="enter-y md:flex"> |
||||
<VisitRadar class="w-full md:w-1/3" :loading="loading" /> |
||||
<VisitSource class="w-full !my-4 md:w-1/3 !md:mx-4 !md:my-0" :loading="loading" /> |
||||
<SalesProductPie class="w-full md:w-1/3" :loading="loading" /> |
||||
</div> |
||||
</div> |
||||
</template> |
@ -1,34 +0,0 @@
|
||||
<script lang="ts" setup> |
||||
import { Card, List } from 'ant-design-vue' |
||||
import { dynamicInfoItems } from './data' |
||||
import { SvgIcon } from '@/components/Icon' |
||||
|
||||
const ListItem = List.Item |
||||
const ListItemMeta = List.Item.Meta |
||||
</script> |
||||
|
||||
<template> |
||||
<Card title="最新动态" v-bind="$attrs"> |
||||
<template #extra> |
||||
<a-button type="link"> |
||||
更多 |
||||
</a-button> |
||||
</template> |
||||
<List item-layout="horizontal" :data-source="dynamicInfoItems"> |
||||
<template #renderItem="{ item }"> |
||||
<ListItem> |
||||
<ListItemMeta> |
||||
<template #description> |
||||
{{ item.date }} |
||||
</template> |
||||
<!-- eslint-disable-next-line --> |
||||
<template #title> {{ item.name }} <span v-html="item.desc"> </span> </template> |
||||
<template #avatar> |
||||
<SvgIcon :name="item.avatar" :size="30" /> |
||||
</template> |
||||
</ListItemMeta> |
||||
</ListItem> |
||||
</template> |
||||
</List> |
||||
</Card> |
||||
</template> |
@ -1,87 +0,0 @@
|
||||
<script lang="ts" setup> |
||||
import { Card, CardGrid } from 'ant-design-vue' |
||||
|
||||
interface GroupItem { |
||||
title: string |
||||
icon: string |
||||
color: string |
||||
desc: string |
||||
date: string |
||||
group: string |
||||
} |
||||
|
||||
const groupItems: GroupItem[] = [ |
||||
{ |
||||
title: 'Github', |
||||
icon: 'i-carbon:logo-github', |
||||
color: '', |
||||
desc: '不要等待机会,而要创造机会。', |
||||
group: '开源组', |
||||
date: '2021-04-01', |
||||
}, |
||||
{ |
||||
title: 'Vue', |
||||
icon: 'i-ion:logo-vue', |
||||
color: '#3fb27f', |
||||
desc: '现在的你决定将来的你。', |
||||
group: '算法组', |
||||
date: '2021-04-01', |
||||
}, |
||||
{ |
||||
title: 'Html5', |
||||
icon: 'i-ion:logo-html5', |
||||
color: '#e18525', |
||||
desc: '没有什么才能比努力更重要。', |
||||
group: '上班摸鱼', |
||||
date: '2021-04-01', |
||||
}, |
||||
{ |
||||
title: 'Angular', |
||||
icon: 'i-ion:logo-angular', |
||||
color: '#bf0c2c', |
||||
desc: '热情和欲望可以突破一切难关。', |
||||
group: 'UI', |
||||
date: '2021-04-01', |
||||
}, |
||||
{ |
||||
title: 'React', |
||||
icon: 'i-bx:bxl-react', |
||||
color: '#00d8ff', |
||||
desc: '健康的身体是实现目标的基石。', |
||||
group: '技术牛', |
||||
date: '2021-04-01', |
||||
}, |
||||
{ |
||||
title: 'Js', |
||||
icon: 'i-ion:logo-javascript', |
||||
color: '#EBD94E', |
||||
desc: '路是走出来的,而不是空想出来的。', |
||||
group: '架构组', |
||||
date: '2021-04-01', |
||||
}, |
||||
] |
||||
</script> |
||||
|
||||
<template> |
||||
<Card title="项目" v-bind="$attrs"> |
||||
<template #extra> |
||||
<a-button type="link"> |
||||
更多 |
||||
</a-button> |
||||
</template> |
||||
|
||||
<CardGrid v-for="item in groupItems" :key="item.title" class="!w-full !md:w-1/3"> |
||||
<span class="flex"> |
||||
<span :class="item.icon" :style="{ color: item.color }" class="text-[30px]" /> |
||||
<span class="ml-4 text-lg">{{ item.title }}</span> |
||||
</span> |
||||
<div class="text-secondary mt-2 h-10 flex"> |
||||
{{ item.desc }} |
||||
</div> |
||||
<div class="text-secondary flex justify-between"> |
||||
<span>{{ item.group }}</span> |
||||
<span>{{ item.date }}</span> |
||||
</div> |
||||
</CardGrid> |
||||
</Card> |
||||
</template> |
@ -1,53 +0,0 @@
|
||||
<script lang="ts" setup> |
||||
import { Card, CardGrid } from 'ant-design-vue' |
||||
|
||||
interface NavItem { |
||||
title: string |
||||
icon: string |
||||
color: string |
||||
} |
||||
|
||||
const navItems: NavItem[] = [ |
||||
{ |
||||
title: '首页', |
||||
icon: 'i-ion:home-outline', |
||||
color: '#1fdaca', |
||||
}, |
||||
{ |
||||
title: '仪表盘', |
||||
icon: 'i-ion:grid-outline', |
||||
color: '#bf0c2c', |
||||
}, |
||||
{ |
||||
title: '组件', |
||||
icon: 'i-ion:layers-outline', |
||||
color: '#e18525', |
||||
}, |
||||
{ |
||||
title: '系统管理', |
||||
icon: 'i-ion:settings-outline', |
||||
color: '#3fb27f', |
||||
}, |
||||
{ |
||||
title: '权限管理', |
||||
icon: 'i-ion:key-outline', |
||||
color: '#4daf1bc9', |
||||
}, |
||||
{ |
||||
title: '图表', |
||||
icon: 'i-ion:bar-chart-outline', |
||||
color: '#00d8ff', |
||||
}, |
||||
] |
||||
</script> |
||||
|
||||
<template> |
||||
<Card title="快捷导航"> |
||||
<CardGrid v-for="item in navItems" :key="item.title"> |
||||
<span class="flex flex-col items-center"> |
||||
<span :class="item.icon" :style="{ color: item.color }" class="text-[20px]" /> |
||||
<span class="text-md mt-2 truncate">{{ item.title }}</span> |
||||
</span> |
||||
</CardGrid> |
||||
</Card> |
||||
</template> |
@ -1,91 +0,0 @@
|
||||
<script lang="ts" setup> |
||||
import type { Ref } from 'vue' |
||||
import { ref, watch } from 'vue' |
||||
import { Card } from 'ant-design-vue' |
||||
import { useECharts } from '@/hooks/web/useECharts' |
||||
import { propTypes } from '@/utils/propTypes' |
||||
|
||||
const props = defineProps({ |
||||
loading: Boolean, |
||||
width: propTypes.string.def('100%'), |
||||
height: propTypes.string.def('400px'), |
||||
}) |
||||
|
||||
const chartRef = ref<HTMLDivElement | null>(null) |
||||
const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>) |
||||
watch( |
||||
() => props.loading, |
||||
() => { |
||||
if (props.loading) |
||||
return |
||||
|
||||
setOptions({ |
||||
legend: { |
||||
bottom: 0, |
||||
data: ['Visits', 'Sales'], |
||||
}, |
||||
tooltip: {}, |
||||
radar: { |
||||
radius: '60%', |
||||
splitNumber: 8, |
||||
indicator: [ |
||||
{ |
||||
name: '2017', |
||||
}, |
||||
{ |
||||
name: '2017', |
||||
}, |
||||
{ |
||||
name: '2018', |
||||
}, |
||||
{ |
||||
name: '2019', |
||||
}, |
||||
{ |
||||
name: '2020', |
||||
}, |
||||
{ |
||||
name: '2021', |
||||
}, |
||||
], |
||||
}, |
||||
series: [ |
||||
{ |
||||
type: 'radar', |
||||
symbolSize: 0, |
||||
areaStyle: { |
||||
shadowBlur: 0, |
||||
shadowColor: 'rgba(0,0,0,.2)', |
||||
shadowOffsetX: 0, |
||||
shadowOffsetY: 10, |
||||
opacity: 1, |
||||
}, |
||||
data: [ |
||||
{ |
||||
value: [90, 50, 86, 40, 50, 20], |
||||
name: 'Visits', |
||||
itemStyle: { |
||||
color: '#b6a2de', |
||||
}, |
||||
}, |
||||
{ |
||||
value: [70, 75, 70, 76, 20, 85], |
||||
name: 'Sales', |
||||
itemStyle: { |
||||
color: '#67e0e3', |
||||
}, |
||||
}, |
||||
], |
||||
}, |
||||
], |
||||
}) |
||||
}, |
||||
{ immediate: true }, |
||||
) |
||||
</script> |
||||
|
||||
<template> |
||||
<Card title="销售统计" :loading="loading"> |
||||
<div ref="chartRef" :style="{ width, height }" /> |
||||
</Card> |
||||
</template> |
@ -1,36 +0,0 @@
|
||||
<script lang="ts" setup> |
||||
import { computed } from 'vue' |
||||
import { Avatar } from 'ant-design-vue' |
||||
import { useUserStore } from '@/store/modules/user' |
||||
import headerImg from '@/assets/images/header.jpg' |
||||
|
||||
const userStore = useUserStore() |
||||
const userinfo = computed(() => userStore.getUserInfo) |
||||
</script> |
||||
|
||||
<template> |
||||
<div class="lg:flex"> |
||||
<Avatar :src="userinfo.user.avatar || headerImg" :size="72" class="!mx-auto !block" /> |
||||
<div class="mt-2 flex flex-col justify-center md:ml-6 md:mt-0"> |
||||
<h1 class="text-md md:text-lg"> |
||||
早安, {{ userinfo.user.real_name }}, 开始您一天的工作吧! |
||||
</h1> |
||||
<span class="text-secondary"> 今日晴,20℃ - 32℃! </span> |
||||
</div> |
||||
<div class="mt-4 flex flex-1 justify-end md:mt-0"> |
||||
<div class="flex flex-col justify-center text-right"> |
||||
<span class="text-secondary"> 待办 </span> |
||||
<span class="text-2xl">2/10</span> |
||||
</div> |
||||
|
||||
<div class="mx-12 flex flex-col justify-center text-right md:mx-16"> |
||||
<span class="text-secondary"> 项目 </span> |
||||
<span class="text-2xl">8</span> |
||||
</div> |
||||
<div class="mr-4 flex flex-col justify-center text-right md:mr-10"> |
||||
<span class="text-secondary"> 团队 </span> |
||||
<span class="text-2xl">300</span> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
@ -1,57 +0,0 @@
|
||||
interface DynamicInfoItem { |
||||
avatar: string |
||||
name: string |
||||
date: string |
||||
desc: string |
||||
} |
||||
|
||||
export const dynamicInfoItems: DynamicInfoItem[] = [ |
||||
{ |
||||
avatar: 'dynamic-avatar-1', |
||||
name: '威廉', |
||||
date: '刚刚', |
||||
desc: '在 <a>开源组</a> 创建了项目 <a>Vue</a>', |
||||
}, |
||||
{ |
||||
avatar: 'dynamic-avatar-2', |
||||
name: '艾文', |
||||
date: '1个小时前', |
||||
desc: '关注了 <a>威廉</a> ', |
||||
}, |
||||
{ |
||||
avatar: 'dynamic-avatar-3', |
||||
name: '克里斯', |
||||
date: '1天前', |
||||
desc: '发布了 <a>个人动态</a> ', |
||||
}, |
||||
{ |
||||
avatar: 'dynamic-avatar-4', |
||||
name: 'Kay', |
||||
date: '2天前', |
||||
desc: '发表文章 <a>如何编写一个Vite插件</a> ', |
||||
}, |
||||
{ |
||||
avatar: 'dynamic-avatar-5', |
||||
name: '皮特', |
||||
date: '3天前', |
||||
desc: '回复了 <a>杰克</a> 的问题 <a>如何进行项目优化?</a>', |
||||
}, |
||||
{ |
||||
avatar: 'dynamic-avatar-6', |
||||
name: '杰克', |
||||
date: '1周前', |
||||
desc: '关闭了问题 <a>如何运行项目</a> ', |
||||
}, |
||||
{ |
||||
avatar: 'dynamic-avatar-1', |
||||
name: '威廉', |
||||
date: '1周前', |
||||
desc: '发布了 <a>个人动态</a> ', |
||||
}, |
||||
{ |
||||
avatar: 'dynamic-avatar-1', |
||||
name: '威廉', |
||||
date: '2021-04-01 20:00', |
||||
desc: '推送了代码到 <a>Github</a>', |
||||
}, |
||||
] |
@ -1,39 +0,0 @@
|
||||
<script lang="ts" setup> |
||||
import { ref } from 'vue' |
||||
import { Card } from 'ant-design-vue' |
||||
import WorkbenchHeader from './components/WorkbenchHeader.vue' |
||||
import ProjectCard from './components/ProjectCard.vue' |
||||
import QuickNav from './components/QuickNav.vue' |
||||
import DynamicInfo from './components/DynamicInfo.vue' |
||||
import SaleRadar from './components/SaleRadar.vue' |
||||
import { PageWrapper } from '@/components/Page' |
||||
|
||||
const loading = ref(true) |
||||
|
||||
setTimeout(() => { |
||||
loading.value = false |
||||
}, 500) |
||||
</script> |
||||
|
||||
<template> |
||||
<PageWrapper> |
||||
<template #headerContent> |
||||
<WorkbenchHeader /> |
||||
</template> |
||||
<div class="lg:flex"> |
||||
<div class="enter-y w-full !mr-4 lg:w-7/10"> |
||||
<ProjectCard :loading="loading" class="enter-y" /> |
||||
<DynamicInfo :loading="loading" class="enter-y !my-4" /> |
||||
</div> |
||||
<div class="enter-y w-full lg:w-3/10"> |
||||
<QuickNav :loading="loading" class="enter-y" /> |
||||
|
||||
<Card class="enter-y !my-4" :loading="loading"> |
||||
<img class="mx-auto h-30 xl:h-50" src="@/assets/svg/illustration.svg"> |
||||
</Card> |
||||
|
||||
<SaleRadar :loading="loading" class="enter-y" /> |
||||
</div> |
||||
</div> |
||||
</PageWrapper> |
||||
</template> |
Loading…
Reference in new issue