|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 190 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 54 KiB |
@ -1,90 +0,0 @@ |
|||||
<template> |
|
||||
<div ref="chartRef" :style="{ height, width }"></div> |
|
||||
</template> |
|
||||
<script lang="ts"> |
|
||||
import { defineComponent, onMounted, ref, Ref } from 'vue'; |
|
||||
|
|
||||
import { useECharts } from '/@/hooks/web/useECharts'; |
|
||||
|
|
||||
import { basicProps } from './props'; |
|
||||
export default defineComponent({ |
|
||||
name: 'AnalysisLine', |
|
||||
props: basicProps, |
|
||||
setup() { |
|
||||
const chartRef = ref<HTMLDivElement | null>(null); |
|
||||
const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); |
|
||||
|
|
||||
onMounted(() => { |
|
||||
setOptions({ |
|
||||
tooltip: { |
|
||||
trigger: 'axis', |
|
||||
axisPointer: { |
|
||||
// 坐标轴指示器,坐标轴触发有效 |
|
||||
type: 'shadow', // 默认为直线,可选为:'line' | 'shadow' |
|
||||
}, |
|
||||
}, |
|
||||
legend: { |
|
||||
itemWidth: 15, |
|
||||
right: 10, |
|
||||
data: ['产品一', '产品二', '产品三'], |
|
||||
}, |
|
||||
grid: { |
|
||||
left: '3%', |
|
||||
right: '4%', |
|
||||
bottom: '3%', |
|
||||
containLabel: true, |
|
||||
}, |
|
||||
xAxis: [ |
|
||||
{ |
|
||||
type: 'category', |
|
||||
axisTick: { |
|
||||
inside: true, // 刻度朝内 |
|
||||
}, |
|
||||
data: ['付费用户', '免费用户', '自主'], |
|
||||
}, |
|
||||
], |
|
||||
yAxis: [ |
|
||||
{ |
|
||||
type: 'value', |
|
||||
axisTick: { |
|
||||
inside: true, // 刻度朝内 |
|
||||
}, |
|
||||
}, |
|
||||
], |
|
||||
series: [ |
|
||||
{ |
|
||||
name: '产品一', |
|
||||
type: 'bar', |
|
||||
itemStyle: { |
|
||||
color: '#3ca0f6', |
|
||||
}, |
|
||||
data: [3200, 3320, 3010], |
|
||||
animationDuration: 4000, |
|
||||
}, |
|
||||
{ |
|
||||
name: '产品二', |
|
||||
type: 'bar', |
|
||||
itemStyle: { |
|
||||
color: '#7dd9b9', |
|
||||
}, |
|
||||
data: [1200, 2600, 1010], |
|
||||
animationDuration: 4000, |
|
||||
}, |
|
||||
|
|
||||
{ |
|
||||
name: '产品三', |
|
||||
type: 'bar', |
|
||||
itemStyle: { |
|
||||
color: '#e6a23c', |
|
||||
}, |
|
||||
data: [862, 2500, 964], |
|
||||
animationDuration: 4000, |
|
||||
}, |
|
||||
], |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
return { chartRef }; |
|
||||
}, |
|
||||
}); |
|
||||
</script> |
|
||||
@ -1,94 +0,0 @@ |
|||||
<template> |
|
||||
<div ref="chartRef" :style="{ height, width }"></div> |
|
||||
</template> |
|
||||
<script lang="ts"> |
|
||||
import { defineComponent, onMounted, ref, Ref } from 'vue'; |
|
||||
|
|
||||
import { useECharts } from '/@/hooks/web/useECharts'; |
|
||||
|
|
||||
import { basicProps } from './props'; |
|
||||
export default defineComponent({ |
|
||||
name: 'AnalysisLine', |
|
||||
props: basicProps, |
|
||||
setup() { |
|
||||
const chartRef = ref<HTMLDivElement | null>(null); |
|
||||
const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); |
|
||||
|
|
||||
onMounted(() => { |
|
||||
setOptions({ |
|
||||
// title: { |
|
||||
// text: '产品成交额', |
|
||||
// }, |
|
||||
tooltip: { |
|
||||
trigger: 'axis', |
|
||||
padding: 3, |
|
||||
borderColor: '#777', |
|
||||
borderWidth: 1, |
|
||||
}, |
|
||||
legend: { |
|
||||
itemWidth: 15, |
|
||||
itemHeight: 4, |
|
||||
left: 80, |
|
||||
top: 0, |
|
||||
orient: 'horizontal', |
|
||||
data: ['产品一', '产品二'], |
|
||||
}, |
|
||||
grid: { |
|
||||
left: '3%', |
|
||||
right: '4%', |
|
||||
bottom: '3%', |
|
||||
containLabel: true, |
|
||||
}, |
|
||||
xAxis: { |
|
||||
type: 'category', |
|
||||
boundaryGap: false, |
|
||||
axisTick: { |
|
||||
inside: true, // 刻度朝内 |
|
||||
}, |
|
||||
data: [ |
|
||||
'一月', |
|
||||
'二月', |
|
||||
'三月', |
|
||||
'四月', |
|
||||
'五月', |
|
||||
'六月', |
|
||||
'七月', |
|
||||
'八月', |
|
||||
'九月', |
|
||||
'十月', |
|
||||
'十一月', |
|
||||
'十二月', |
|
||||
], |
|
||||
}, |
|
||||
yAxis: { |
|
||||
type: 'value', |
|
||||
axisTick: { |
|
||||
inside: true, // 刻度朝内 |
|
||||
}, |
|
||||
}, |
|
||||
series: [ |
|
||||
{ |
|
||||
name: '产品一', |
|
||||
type: 'line', |
|
||||
itemStyle: { |
|
||||
color: '#5B8FF9', |
|
||||
}, |
|
||||
data: [330, 132, 101, 134, 90, 230, 210, 150, 232, 234, 230, 400], |
|
||||
animationDuration: 4000, |
|
||||
}, |
|
||||
{ |
|
||||
name: '产品二', |
|
||||
type: 'line', |
|
||||
itemStyle: { |
|
||||
color: '#55D187', |
|
||||
}, |
|
||||
data: [220, 182, 191, 234, 290, 330, 310, 330, 232, 201, 330, 190], |
|
||||
animationDuration: 4000, |
|
||||
}, |
|
||||
], |
|
||||
}); |
|
||||
}); |
|
||||
return { chartRef }; |
|
||||
}, |
|
||||
}); |
|
||||
</script> |
|
||||
@ -1,75 +0,0 @@ |
|||||
<template> |
|
||||
<div ref="chartRef" :style="{ height, width }"></div> |
|
||||
</template> |
|
||||
<script lang="ts"> |
|
||||
import { defineComponent, onMounted, ref, Ref } from 'vue'; |
|
||||
|
|
||||
import { useECharts } from '/@/hooks/web/useECharts'; |
|
||||
|
|
||||
import { basicProps } from './props'; |
|
||||
|
|
||||
const m2R2Data = [ |
|
||||
{ value: 335, name: '移动设备', itemStyle: { color: '#1b65b9' } }, |
|
||||
{ value: 310, name: '网页端', itemStyle: { color: '#3ca0f6' } }, |
|
||||
{ value: 234, name: '手表', itemStyle: { color: '#2dc0c0' } }, |
|
||||
{ value: 234, name: '其他', itemStyle: { color: '#7dd9b9' } }, |
|
||||
]; |
|
||||
export default defineComponent({ |
|
||||
props: basicProps, |
|
||||
setup() { |
|
||||
const chartRef = ref<HTMLDivElement | null>(null); |
|
||||
const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); |
|
||||
|
|
||||
onMounted(() => { |
|
||||
setOptions({ |
|
||||
title: [ |
|
||||
{ |
|
||||
text: '总设备', |
|
||||
subtext: '1,430', |
|
||||
textStyle: { |
|
||||
fontSize: 12, |
|
||||
color: '#4B535E85', |
|
||||
}, |
|
||||
subtextStyle: { |
|
||||
fontSize: 24, |
|
||||
color: 'black', |
|
||||
}, |
|
||||
textAlign: 'center', |
|
||||
left: '34.5%', |
|
||||
top: '40%', |
|
||||
}, |
|
||||
], |
|
||||
tooltip: { |
|
||||
trigger: 'item', |
|
||||
}, |
|
||||
legend: { |
|
||||
itemHeight: 10, |
|
||||
type: 'scroll', |
|
||||
orient: 'vertical', |
|
||||
left: '70%', |
|
||||
align: 'left', |
|
||||
top: 'middle', |
|
||||
textStyle: { |
|
||||
color: '#8C8C8C', |
|
||||
}, |
|
||||
height: 250, |
|
||||
}, |
|
||||
series: [ |
|
||||
{ |
|
||||
name: '成交额', |
|
||||
type: 'pie', |
|
||||
center: ['35%', '50%'], |
|
||||
radius: ['45%', '65%'], |
|
||||
label: { |
|
||||
show: false, |
|
||||
}, |
|
||||
data: m2R2Data, |
|
||||
animationDuration: 3000, |
|
||||
}, |
|
||||
], |
|
||||
}); |
|
||||
}); |
|
||||
return { chartRef }; |
|
||||
}, |
|
||||
}); |
|
||||
</script> |
|
||||
@ -1,80 +0,0 @@ |
|||||
import { defineComponent } from 'vue'; |
|
||||
import { Tabs, Row, Col, Progress, Divider } from 'ant-design-vue'; |
|
||||
import { CollapseContainer } from '/@/components/Container/index'; |
|
||||
import TrendLine from './TrendLine.vue'; |
|
||||
import './flow-ana.less'; |
|
||||
const prefixCls = 'flow-analysis'; |
|
||||
export default defineComponent({ |
|
||||
name: 'AnalysisFLow', |
|
||||
setup() { |
|
||||
const renderContent = () => { |
|
||||
return ( |
|
||||
<Row> |
|
||||
{() => ( |
|
||||
<> |
|
||||
<Col md={24} lg={8}> |
|
||||
{() => ( |
|
||||
<CollapseContainer |
|
||||
title="整体流量评分" |
|
||||
canExpan={false} |
|
||||
class={`${prefixCls}__left`} |
|
||||
> |
|
||||
{() => ( |
|
||||
<div> |
|
||||
<div class={`${prefixCls}__score`}> |
|
||||
86.2<span>分</span> |
|
||||
</div> |
|
||||
<div class={`${prefixCls}__rank`}> |
|
||||
排名<span>前20%</span> |
|
||||
</div> |
|
||||
<Progress percent={70} showInfo={false} status="active" /> |
|
||||
<Divider /> |
|
||||
|
|
||||
<ul class={`${prefixCls}__rs`}> |
|
||||
<li> |
|
||||
<span>平均分</span> |
|
||||
<span>77.5</span> |
|
||||
</li> |
|
||||
<li> |
|
||||
<span>最高分</span> |
|
||||
<span>99.5</span> |
|
||||
</li> |
|
||||
<li> |
|
||||
<span>最低分</span> |
|
||||
<span>56.5</span> |
|
||||
</li> |
|
||||
</ul> |
|
||||
</div> |
|
||||
)} |
|
||||
</CollapseContainer> |
|
||||
)} |
|
||||
</Col> |
|
||||
<Col md={24} lg={16}> |
|
||||
{() => ( |
|
||||
<CollapseContainer title="整体流量趋势" canExpan={false}> |
|
||||
{() => <TrendLine />} |
|
||||
</CollapseContainer> |
|
||||
)} |
|
||||
</Col> |
|
||||
</> |
|
||||
)} |
|
||||
</Row> |
|
||||
); |
|
||||
}; |
|
||||
return () => ( |
|
||||
<Tabs class={prefixCls} default-active-key="1"> |
|
||||
{() => [ |
|
||||
<Tabs.TabPane key="1" tab="产品一"> |
|
||||
{() => renderContent()} |
|
||||
</Tabs.TabPane>, |
|
||||
<Tabs.TabPane key="2" tab="产品二"> |
|
||||
{() => renderContent()} |
|
||||
</Tabs.TabPane>, |
|
||||
<Tabs.TabPane key="3" tab="产品三"> |
|
||||
{() => renderContent()} |
|
||||
</Tabs.TabPane>, |
|
||||
]} |
|
||||
</Tabs> |
|
||||
); |
|
||||
}, |
|
||||
}); |
|
||||
@ -0,0 +1,69 @@ |
|||||
|
<template> |
||||
|
<Card title="成交占比" :loading="loading"> |
||||
|
<div ref="chartRef" :style="{ width, height }"></div> |
||||
|
</Card> |
||||
|
</template> |
||||
|
<script lang="ts"> |
||||
|
import { defineComponent, Ref, ref, watch } from 'vue'; |
||||
|
|
||||
|
import { Card } from 'ant-design-vue'; |
||||
|
import { useECharts } from '/@/hooks/web/useECharts'; |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
components: { Card }, |
||||
|
props: { |
||||
|
loading: Boolean, |
||||
|
width: { |
||||
|
type: String as PropType<string>, |
||||
|
default: '100%', |
||||
|
}, |
||||
|
height: { |
||||
|
type: String as PropType<string>, |
||||
|
default: '300px', |
||||
|
}, |
||||
|
}, |
||||
|
setup(props) { |
||||
|
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(function (a, b) { |
||||
|
return a.value - b.value; |
||||
|
}), |
||||
|
roseType: 'radius', |
||||
|
animationType: 'scale', |
||||
|
animationEasing: 'exponentialInOut', |
||||
|
animationDelay: function () { |
||||
|
return Math.random() * 400; |
||||
|
}, |
||||
|
}, |
||||
|
], |
||||
|
}); |
||||
|
}, |
||||
|
{ immediate: true } |
||||
|
); |
||||
|
return { chartRef }; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
@ -0,0 +1,46 @@ |
|||||
|
<template> |
||||
|
<Card |
||||
|
:tab-list="tabListTitle" |
||||
|
v-bind="$attrs" |
||||
|
:active-tab-key="activeKey" |
||||
|
@tabChange="onTabChange" |
||||
|
> |
||||
|
<p v-if="activeKey === 'tab1'"> |
||||
|
<VisitAnalysis /> |
||||
|
</p> |
||||
|
<p v-if="activeKey === 'tab2'"> |
||||
|
<VisitAnalysisBar /> |
||||
|
</p> |
||||
|
</Card> |
||||
|
</template> |
||||
|
<script lang="ts"> |
||||
|
import { defineComponent, ref } from 'vue'; |
||||
|
|
||||
|
import { Card } from 'ant-design-vue'; |
||||
|
|
||||
|
import VisitAnalysis from './VisitAnalysis.vue'; |
||||
|
import VisitAnalysisBar from './VisitAnalysisBar.vue'; |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
components: { Card, VisitAnalysis, VisitAnalysisBar }, |
||||
|
setup() { |
||||
|
const activeKey = ref('tab1'); |
||||
|
|
||||
|
const tabListTitle = [ |
||||
|
{ |
||||
|
key: 'tab1', |
||||
|
tab: '流量趋势', |
||||
|
}, |
||||
|
{ |
||||
|
key: 'tab2', |
||||
|
tab: '访问量', |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
function onTabChange(key) { |
||||
|
activeKey.value = key; |
||||
|
} |
||||
|
return { tabListTitle, activeKey, onTabChange }; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
@ -1,154 +0,0 @@ |
|||||
<template> |
|
||||
<div :class="prefixCls"> |
|
||||
<div :class="`${prefixCls}-header`"> |
|
||||
<div :class="`${prefixCls}__info`"> |
|
||||
<span :class="`${prefixCls}__title`">{{ info.title }}</span> |
|
||||
<span :class="`${prefixCls}__desc`">{{ info.desc }}</span> |
|
||||
</div> |
|
||||
<span :class="`${prefixCls}__tag ${info.status}`">{{ info.text }}</span> |
|
||||
</div> |
|
||||
|
|
||||
<div :class="`${prefixCls}-body mt-5`"> |
|
||||
<div :class="`${prefixCls}__process-nfo`"> |
|
||||
<span>进度</span> |
|
||||
<span>{{ info.percent }}%</span> |
|
||||
</div> |
|
||||
<Progress :percent="info.percent" :showInfo="false" :status="info.status" /> |
|
||||
</div> |
|
||||
<div :class="`${prefixCls}-footer`"> |
|
||||
<span :class="`${prefixCls}__date`"> |
|
||||
更新日期: <span>{{ info.updateTime }}</span> |
|
||||
</span> |
|
||||
<div :class="`${prefixCls}__avatar`"> |
|
||||
<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" /> |
|
||||
<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" /> |
|
||||
<Avatar>+3</Avatar> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
<script lang="ts"> |
|
||||
import { computed, defineComponent, PropType } from 'vue'; |
|
||||
import { Progress, Avatar } from 'ant-design-vue'; |
|
||||
|
|
||||
import { TaskItem } from '../types'; |
|
||||
|
|
||||
export default defineComponent({ |
|
||||
name: 'GrowCard', |
|
||||
components: { Progress, Avatar }, |
|
||||
props: { |
|
||||
info: { |
|
||||
type: Object as PropType<TaskItem>, |
|
||||
default: null, |
|
||||
}, |
|
||||
}, |
|
||||
setup(props) { |
|
||||
return { |
|
||||
prefixCls: 'task-card', |
|
||||
text: computed(() => { |
|
||||
const { status } = props.info || {}; |
|
||||
return status === 'active' |
|
||||
? '进度正常' |
|
||||
: status === 'exception' |
|
||||
? '进度滞后' |
|
||||
: '项目完成'; |
|
||||
}), |
|
||||
}; |
|
||||
}, |
|
||||
}); |
|
||||
</script> |
|
||||
<style lang="less" scoped> |
|
||||
.task-card { |
|
||||
display: flex; |
|
||||
width: calc(100% - 24px); |
|
||||
height: 199px; |
|
||||
padding: 24px 20px 12px 16px; |
|
||||
margin: 0 12px 12px 12px; |
|
||||
background: #fff; |
|
||||
border: 1px solid #ececf2; |
|
||||
border-radius: 12px; |
|
||||
flex-direction: column; |
|
||||
|
|
||||
&-header { |
|
||||
display: flex; |
|
||||
width: 100%; |
|
||||
justify-content: space-between; |
|
||||
align-items: center; |
|
||||
} |
|
||||
|
|
||||
&__tag { |
|
||||
display: inline-block; |
|
||||
padding: 4px 6px; |
|
||||
font-family: PingFangSC-Regular; |
|
||||
font-size: 12px; |
|
||||
border-radius: 6px; |
|
||||
|
|
||||
&.success { |
|
||||
color: #55d187; |
|
||||
background: rgba(85, 209, 135, 0.16); |
|
||||
} |
|
||||
|
|
||||
&.warn { |
|
||||
color: #ffa07d; |
|
||||
background: #ffd16416; |
|
||||
} |
|
||||
|
|
||||
&.done { |
|
||||
color: #0593ff; |
|
||||
background: #0593ff16; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
&__info { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
} |
|
||||
|
|
||||
&__title { |
|
||||
font-family: PingFangSC-Medium; |
|
||||
font-size: 16px; |
|
||||
line-height: 24px; |
|
||||
color: rgba(0, 0, 0, 0.85); |
|
||||
} |
|
||||
|
|
||||
&__desc { |
|
||||
font-family: PingFangSC-Regular; |
|
||||
font-size: 12px; |
|
||||
line-height: 21px; |
|
||||
color: #8181a5; |
|
||||
} |
|
||||
|
|
||||
&__process-nfo { |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
|
|
||||
span { |
|
||||
font-size: 14px; |
|
||||
line-height: 21px; |
|
||||
color: #8181a5; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
&-footer { |
|
||||
display: flex; |
|
||||
width: 100%; |
|
||||
margin-top: 16px; |
|
||||
align-items: center; |
|
||||
justify-content: space-between; |
|
||||
} |
|
||||
|
|
||||
&__date { |
|
||||
font-size: 12px; |
|
||||
line-height: 21px; |
|
||||
color: #2c3a61; |
|
||||
|
|
||||
span { |
|
||||
color: #7c8087; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
&__avatar { |
|
||||
display: flex; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,97 +0,0 @@ |
|||||
<template> |
|
||||
<div ref="chartRef" :style="{ height, width }"></div> |
|
||||
</template> |
|
||||
<script lang="ts"> |
|
||||
import { defineComponent, onMounted, ref, Ref } from 'vue'; |
|
||||
|
|
||||
import { useECharts } from '/@/hooks/web/useECharts'; |
|
||||
|
|
||||
import { basicProps } from './props'; |
|
||||
export default defineComponent({ |
|
||||
props: basicProps, |
|
||||
setup() { |
|
||||
const chartRef = ref<HTMLDivElement | null>(null); |
|
||||
const { setOptions, echarts } = useECharts(chartRef as Ref<HTMLDivElement>); |
|
||||
|
|
||||
onMounted(() => { |
|
||||
setOptions({ |
|
||||
tooltip: { |
|
||||
trigger: 'axis', |
|
||||
padding: 3, |
|
||||
borderColor: '#777', |
|
||||
borderWidth: 1, |
|
||||
}, |
|
||||
legend: { |
|
||||
show: false, |
|
||||
}, |
|
||||
grid: { |
|
||||
left: '3%', |
|
||||
right: '4%', |
|
||||
bottom: '3%', |
|
||||
containLabel: true, |
|
||||
}, |
|
||||
xAxis: { |
|
||||
type: 'category', |
|
||||
boundaryGap: false, |
|
||||
axisTick: { |
|
||||
inside: true, |
|
||||
}, |
|
||||
data: [ |
|
||||
'一月', |
|
||||
'二月', |
|
||||
'三月', |
|
||||
'四月', |
|
||||
'五月', |
|
||||
'六月', |
|
||||
'七月', |
|
||||
'八月', |
|
||||
'九月', |
|
||||
'十月', |
|
||||
'十一月', |
|
||||
'十二月', |
|
||||
], |
|
||||
}, |
|
||||
yAxis: { |
|
||||
type: 'value', |
|
||||
axisTick: { |
|
||||
inside: true, |
|
||||
}, |
|
||||
}, |
|
||||
series: [ |
|
||||
{ |
|
||||
name: '产品一', |
|
||||
type: 'line', |
|
||||
itemStyle: { |
|
||||
color: '#5B8FF9', |
|
||||
}, |
|
||||
areaStyle: { |
|
||||
color: new echarts.graphic.LinearGradient( |
|
||||
0, |
|
||||
0, |
|
||||
0, |
|
||||
1, |
|
||||
[ |
|
||||
{ |
|
||||
offset: 0, |
|
||||
color: '#5B8FF9', |
|
||||
}, |
|
||||
{ |
|
||||
offset: 1, |
|
||||
color: 'rgba(118,168,248, 0)', |
|
||||
}, |
|
||||
], |
|
||||
false |
|
||||
), |
|
||||
shadowColor: 'rgba(118,168,248, 0.9)', |
|
||||
shadowBlur: 20, |
|
||||
}, |
|
||||
data: [134, 330, 132, 101, 90, 230, 210, 150, 230, 400, 232, 234], |
|
||||
animationDuration: 3000, |
|
||||
}, |
|
||||
], |
|
||||
}); |
|
||||
}); |
|
||||
return { chartRef }; |
|
||||
}, |
|
||||
}); |
|
||||
</script> |
|
||||
@ -0,0 +1,146 @@ |
|||||
|
<template> |
||||
|
<div ref="chartRef" :style="{ height, width }"></div> |
||||
|
</template> |
||||
|
<script lang="ts"> |
||||
|
import { defineComponent, onMounted, ref, Ref } from 'vue'; |
||||
|
|
||||
|
import { useECharts } from '/@/hooks/web/useECharts'; |
||||
|
|
||||
|
import { basicProps } from './props'; |
||||
|
export default defineComponent({ |
||||
|
props: basicProps, |
||||
|
setup() { |
||||
|
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: [ |
||||
|
'6:00', |
||||
|
'7:00', |
||||
|
'8:00', |
||||
|
'9:00', |
||||
|
'10:00', |
||||
|
'11:00', |
||||
|
'12:00', |
||||
|
'13:00', |
||||
|
'14:00', |
||||
|
'15:00', |
||||
|
'16:00', |
||||
|
'17:00', |
||||
|
'18:00', |
||||
|
'19:00', |
||||
|
'20:00', |
||||
|
'21:00', |
||||
|
'22:00', |
||||
|
'23: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', |
||||
|
}, |
||||
|
}, |
||||
|
], |
||||
|
}); |
||||
|
}); |
||||
|
return { chartRef }; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
@ -0,0 +1,62 @@ |
|||||
|
<template> |
||||
|
<div ref="chartRef" :style="{ height, width }"></div> |
||||
|
</template> |
||||
|
<script lang="ts"> |
||||
|
import { defineComponent, onMounted, ref, Ref } from 'vue'; |
||||
|
|
||||
|
import { useECharts } from '/@/hooks/web/useECharts'; |
||||
|
|
||||
|
import { basicProps } from './props'; |
||||
|
export default defineComponent({ |
||||
|
props: basicProps, |
||||
|
setup() { |
||||
|
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: [ |
||||
|
'1月', |
||||
|
'2月', |
||||
|
'3月', |
||||
|
'4月', |
||||
|
'5月', |
||||
|
'6月', |
||||
|
'7月', |
||||
|
'8月', |
||||
|
'9月', |
||||
|
'10月', |
||||
|
'11月', |
||||
|
'12月', |
||||
|
], |
||||
|
}, |
||||
|
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, |
||||
|
}, |
||||
|
], |
||||
|
}); |
||||
|
}); |
||||
|
return { chartRef }; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
@ -0,0 +1,107 @@ |
|||||
|
<template> |
||||
|
<Card title="转化率" :loading="loading"> |
||||
|
<div ref="chartRef" :style="{ width, height }"></div> |
||||
|
</Card> |
||||
|
</template> |
||||
|
<script lang="ts"> |
||||
|
import { defineComponent, Ref, ref, watch } from 'vue'; |
||||
|
|
||||
|
import { Card } from 'ant-design-vue'; |
||||
|
import { useECharts } from '/@/hooks/web/useECharts'; |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
components: { Card }, |
||||
|
props: { |
||||
|
loading: Boolean, |
||||
|
width: { |
||||
|
type: String as PropType<string>, |
||||
|
default: '100%', |
||||
|
}, |
||||
|
height: { |
||||
|
type: String as PropType<string>, |
||||
|
default: '300px', |
||||
|
}, |
||||
|
}, |
||||
|
setup(props) { |
||||
|
const chartRef = ref<HTMLDivElement | null>(null); |
||||
|
const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); |
||||
|
watch( |
||||
|
() => props.loading, |
||||
|
() => { |
||||
|
if (props.loading) { |
||||
|
return; |
||||
|
} |
||||
|
setOptions({ |
||||
|
backgroundColor: '#fff', |
||||
|
legend: { |
||||
|
bottom: 0, |
||||
|
data: ['访问', '购买'], |
||||
|
}, |
||||
|
tooltip: {}, |
||||
|
radar: { |
||||
|
radius: '60%', |
||||
|
splitNumber: 8, |
||||
|
indicator: [ |
||||
|
{ |
||||
|
text: '电脑', |
||||
|
max: 100, |
||||
|
}, |
||||
|
{ |
||||
|
text: '充电器', |
||||
|
max: 100, |
||||
|
}, |
||||
|
{ |
||||
|
text: '耳机', |
||||
|
max: 100, |
||||
|
}, |
||||
|
{ |
||||
|
text: '手机', |
||||
|
max: 100, |
||||
|
}, |
||||
|
{ |
||||
|
text: 'Ipad', |
||||
|
max: 100, |
||||
|
}, |
||||
|
{ |
||||
|
text: '耳机', |
||||
|
max: 100, |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
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 } |
||||
|
); |
||||
|
return { chartRef }; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
@ -0,0 +1,88 @@ |
|||||
|
<template> |
||||
|
<Card title="访问来源" :loading="loading"> |
||||
|
<div ref="chartRef" :style="{ width, height }"></div> |
||||
|
</Card> |
||||
|
</template> |
||||
|
<script lang="ts"> |
||||
|
import { defineComponent, Ref, ref, watch } from 'vue'; |
||||
|
|
||||
|
import { Card } from 'ant-design-vue'; |
||||
|
import { useECharts } from '/@/hooks/web/useECharts'; |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
components: { Card }, |
||||
|
props: { |
||||
|
loading: Boolean, |
||||
|
width: { |
||||
|
type: String as PropType<string>, |
||||
|
default: '100%', |
||||
|
}, |
||||
|
height: { |
||||
|
type: String as PropType<string>, |
||||
|
default: '300px', |
||||
|
}, |
||||
|
}, |
||||
|
setup(props) { |
||||
|
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: function () { |
||||
|
return Math.random() * 100; |
||||
|
}, |
||||
|
}, |
||||
|
], |
||||
|
}); |
||||
|
}, |
||||
|
{ immediate: true } |
||||
|
); |
||||
|
return { chartRef }; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
@ -1,56 +0,0 @@ |
|||||
.flow-analysis { |
|
||||
width: 100%; |
|
||||
background: #fff; |
|
||||
|
|
||||
&__left { |
|
||||
padding: 10px 20px !important; |
|
||||
border-right: 1px solid rgba(0, 0, 0, 0.06); |
|
||||
border-radius: 0; |
|
||||
} |
|
||||
|
|
||||
&__score { |
|
||||
margin-top: 20px; |
|
||||
font-size: 30px; |
|
||||
line-height: 38px; |
|
||||
color: rgba(0, 0, 0, 0.85); |
|
||||
|
|
||||
span { |
|
||||
font-size: 20px; |
|
||||
line-height: 28px; |
|
||||
color: rgba(0, 0, 0, 0.85); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
&__rank { |
|
||||
margin: 16px 0; |
|
||||
font-size: 12px; |
|
||||
line-height: 20px; |
|
||||
color: #7c8087; |
|
||||
|
|
||||
span { |
|
||||
display: inline-block; |
|
||||
margin-left: 10px; |
|
||||
color: #1c1d21; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
&__rs { |
|
||||
li { |
|
||||
display: flex; |
|
||||
line-height: 28px; |
|
||||
justify-content: space-between; |
|
||||
|
|
||||
span { |
|
||||
&:nth-child(1) { |
|
||||
font-size: 14px; |
|
||||
color: #1c1d21; |
|
||||
} |
|
||||
|
|
||||
&:nth-child(2) { |
|
||||
font-size: 16px; |
|
||||
color: #1c1d21; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,43 @@ |
|||||
|
export interface GrowCardItem { |
||||
|
icon: string; |
||||
|
title: string; |
||||
|
value: number; |
||||
|
total: number; |
||||
|
color: string; |
||||
|
action: string; |
||||
|
} |
||||
|
|
||||
|
export const growCardList: GrowCardItem[] = [ |
||||
|
{ |
||||
|
title: '访问数', |
||||
|
icon: 'visit-count|svg', |
||||
|
value: 2000, |
||||
|
total: 120000, |
||||
|
color: 'green', |
||||
|
action: '月', |
||||
|
}, |
||||
|
{ |
||||
|
title: '成交额', |
||||
|
icon: 'total-sales|svg', |
||||
|
value: 20000, |
||||
|
total: 500000, |
||||
|
color: 'blue', |
||||
|
action: '月', |
||||
|
}, |
||||
|
{ |
||||
|
title: '下载数', |
||||
|
icon: 'download-count|svg', |
||||
|
value: 8000, |
||||
|
total: 120000, |
||||
|
color: 'orange', |
||||
|
action: '周', |
||||
|
}, |
||||
|
{ |
||||
|
title: '成交数', |
||||
|
icon: 'transaction|svg', |
||||
|
value: 5000, |
||||
|
total: 50000, |
||||
|
color: 'purple', |
||||
|
action: '年', |
||||
|
}, |
||||
|
]; |
||||
@ -1,107 +0,0 @@ |
|||||
import { GrowCardItem, TaskItem } from './types'; |
|
||||
import iconSvg1 from '/@/assets/svg/dashboard/analysis-icon1.svg'; |
|
||||
import iconSvg2 from '/@/assets/svg/dashboard/analysis-icon2.svg'; |
|
||||
import iconSvg3 from '/@/assets/svg/dashboard/analysis-icon3.svg'; |
|
||||
import iconSvg4 from '/@/assets/svg/dashboard/analysis-icon4.svg'; |
|
||||
export const taskList: TaskItem[] = [ |
|
||||
{ |
|
||||
percent: 50, |
|
||||
title: '开发任务一', |
|
||||
updateTime: '2020.7.12', |
|
||||
desc: '开发任务一简介', |
|
||||
status: 'active', |
|
||||
}, |
|
||||
{ |
|
||||
percent: 67, |
|
||||
title: '开发任务二', |
|
||||
updateTime: '2020.3.12', |
|
||||
desc: '开发任务二简介', |
|
||||
status: 'exception', |
|
||||
}, |
|
||||
{ |
|
||||
percent: 100, |
|
||||
title: '开发任务三', |
|
||||
updateTime: '2020.4.12', |
|
||||
desc: '开发任务三简介', |
|
||||
|
|
||||
status: 'success', |
|
||||
}, |
|
||||
]; |
|
||||
export const growCardList: GrowCardItem[] = [ |
|
||||
{ |
|
||||
title: '总用户数', |
|
||||
icon: iconSvg1, |
|
||||
price: 80000, |
|
||||
up: true, |
|
||||
mom: '环比增长', |
|
||||
percent: 2.5, |
|
||||
}, |
|
||||
{ |
|
||||
title: '产品数量', |
|
||||
icon: iconSvg2, |
|
||||
price: 4000, |
|
||||
up: true, |
|
||||
mom: '同比增长', |
|
||||
percent: 3, |
|
||||
}, |
|
||||
{ |
|
||||
title: '总营业额', |
|
||||
icon: iconSvg3, |
|
||||
price: 3000000, |
|
||||
up: false, |
|
||||
mom: '环比降低', |
|
||||
percent: 2, |
|
||||
}, |
|
||||
{ |
|
||||
title: '总任务数', |
|
||||
icon: iconSvg4, |
|
||||
price: 10000, |
|
||||
up: false, |
|
||||
mom: '同比降低', |
|
||||
percent: 1, |
|
||||
}, |
|
||||
]; |
|
||||
export const randomizeArray = function (arg: any) { |
|
||||
const array = arg.slice(); |
|
||||
let currentIndex = array.length, |
|
||||
temporaryValue, |
|
||||
randomIndex; |
|
||||
|
|
||||
while (0 !== currentIndex) { |
|
||||
randomIndex = Math.floor(Math.random() * currentIndex); |
|
||||
currentIndex -= 1; |
|
||||
|
|
||||
temporaryValue = array[currentIndex]; |
|
||||
array[currentIndex] = array[randomIndex]; |
|
||||
array[randomIndex] = temporaryValue; |
|
||||
} |
|
||||
|
|
||||
return array; |
|
||||
}; |
|
||||
|
|
||||
export const sparklineData = [ |
|
||||
47, |
|
||||
45, |
|
||||
54, |
|
||||
38, |
|
||||
56, |
|
||||
24, |
|
||||
65, |
|
||||
31, |
|
||||
37, |
|
||||
39, |
|
||||
62, |
|
||||
51, |
|
||||
35, |
|
||||
41, |
|
||||
35, |
|
||||
27, |
|
||||
93, |
|
||||
53, |
|
||||
61, |
|
||||
27, |
|
||||
54, |
|
||||
43, |
|
||||
19, |
|
||||
46, |
|
||||
]; |
|
||||
@ -1,16 +0,0 @@ |
|||||
export interface GrowCardItem { |
|
||||
icon: string; |
|
||||
title: string; |
|
||||
price: number; |
|
||||
up: boolean; |
|
||||
mom: string; |
|
||||
percent: number; |
|
||||
} |
|
||||
|
|
||||
export interface TaskItem { |
|
||||
percent: number; |
|
||||
status: 'success' | 'exception' | 'active'; |
|
||||
updateTime: string; |
|
||||
title: string; |
|
||||
desc: string; |
|
||||
} |
|
||||
@ -1,494 +0,0 @@ |
|||||
.house-wrap { |
|
||||
position: relative; |
|
||||
width: 600px; |
|
||||
height: 600px; |
|
||||
transform: scale(0.5); |
|
||||
|
|
||||
.house { |
|
||||
position: absolute; |
|
||||
position: relative; |
|
||||
top: 50%; |
|
||||
left: 50%; |
|
||||
display: flex; |
|
||||
width: 400px; |
|
||||
height: 300px; |
|
||||
transform: translateX(-50%) translateY(-13%); |
|
||||
justify-content: center; |
|
||||
perspective: 200px; |
|
||||
} |
|
||||
|
|
||||
.floor { |
|
||||
position: absolute; |
|
||||
bottom: 0; |
|
||||
display: flex; |
|
||||
width: 95%; |
|
||||
height: 30px; |
|
||||
background-color: #e1f6fd; |
|
||||
border: 4px solid #314b70; |
|
||||
border-top-right-radius: 4px; |
|
||||
border-top-left-radius: 4px; |
|
||||
box-shadow: inset 4px 4px 0 #fffdff; |
|
||||
justify-content: center; |
|
||||
} |
|
||||
|
|
||||
.floor::before, |
|
||||
.floor::after { |
|
||||
position: absolute; |
|
||||
bottom: 0; |
|
||||
width: 32%; |
|
||||
height: 60%; |
|
||||
background-image: linear-gradient(to bottom, #e0f5fc 50%, #aac4d0 50%); |
|
||||
border-top: 4px solid #314b70; |
|
||||
border-right: 4px solid #314b70; |
|
||||
border-left: 4px solid #314b70; |
|
||||
border-top-right-radius: 4px; |
|
||||
border-top-left-radius: 4px; |
|
||||
content: ''; |
|
||||
box-shadow: 4px 0 0 #aac4d0; |
|
||||
} |
|
||||
|
|
||||
.floor::after { |
|
||||
top: 0; |
|
||||
width: 25%; |
|
||||
height: 40%; |
|
||||
border-top: none; |
|
||||
border-top-right-radius: 0; |
|
||||
border-top-left-radius: 0; |
|
||||
} |
|
||||
|
|
||||
.wall { |
|
||||
position: absolute; |
|
||||
bottom: 30px; |
|
||||
display: flex; |
|
||||
width: 91%; |
|
||||
height: 175px; |
|
||||
overflow: hidden; |
|
||||
background: #c3e0e7; |
|
||||
border-right: 4px solid #314b70; |
|
||||
border-left: 4px solid #314b70; |
|
||||
justify-content: space-between; |
|
||||
align-items: flex-end; |
|
||||
} |
|
||||
|
|
||||
.window { |
|
||||
position: relative; |
|
||||
width: 34%; |
|
||||
height: 125px; |
|
||||
background: #aac4d0; |
|
||||
border-top: 4px solid #314b70; |
|
||||
border-right: 4px solid #314b70; |
|
||||
border-bottom: none; |
|
||||
border-left: none; |
|
||||
border-top-right-radius: 8px; |
|
||||
box-shadow: inset 0 4px 2px #e0f5fc; |
|
||||
} |
|
||||
|
|
||||
.window::before { |
|
||||
position: absolute; |
|
||||
top: 6%; |
|
||||
left: 0; |
|
||||
width: 94%; |
|
||||
height: 88%; |
|
||||
background-image: linear-gradient(to top, #f3f6fa 47%, #9ab2d3 47%, #9ab2d3 50%, #f3f6fa 50%); |
|
||||
border-top: 4px solid #314b70; |
|
||||
border-right: 4px solid #314b70; |
|
||||
border-bottom: 4px solid #314b70; |
|
||||
border-left: none; |
|
||||
border-top-right-radius: 4px; |
|
||||
border-bottom-right-radius: 4px; |
|
||||
content: ''; |
|
||||
} |
|
||||
|
|
||||
.window::after { |
|
||||
position: absolute; |
|
||||
top: 19%; |
|
||||
left: 20%; |
|
||||
width: 30px; |
|
||||
height: 40px; |
|
||||
background-color: #f9aabe; |
|
||||
border: 4px solid #9ab2d3; |
|
||||
content: ''; |
|
||||
} |
|
||||
|
|
||||
.window:nth-of-type(3) { |
|
||||
border-top: none; |
|
||||
border-right: 4px solid #314b70; |
|
||||
border-bottom: 4px solid #314b70; |
|
||||
border-left: none; |
|
||||
border-top-right-radius: 0; |
|
||||
border-bottom-right-radius: 8px; |
|
||||
transform: rotateZ(180deg); |
|
||||
box-shadow: inset 0 -4px 2px #e0f5fc; |
|
||||
} |
|
||||
|
|
||||
.window:nth-of-type(3)::after { |
|
||||
content: none; |
|
||||
} |
|
||||
|
|
||||
.door { |
|
||||
display: flex; |
|
||||
width: 20%; |
|
||||
height: 130px; |
|
||||
padding-left: 8px; |
|
||||
background-color: #ffc26b; |
|
||||
border: 4px solid #314b70; |
|
||||
border-bottom: none; |
|
||||
border-top-right-radius: 10px; |
|
||||
border-top-left-radius: 10px; |
|
||||
box-shadow: inset 3px 3px #ffe0ad, inset -10px -8px #ffad61, 4px 0 #aac4d0; |
|
||||
flex-direction: column; |
|
||||
justify-content: space-evenly; |
|
||||
align-items: flex-start; |
|
||||
} |
|
||||
|
|
||||
.door__square { |
|
||||
width: 85%; |
|
||||
height: 47px; |
|
||||
border: 4px solid #314b70; |
|
||||
border-radius: 4px; |
|
||||
box-shadow: inset 3px 3px #ffe0ad; |
|
||||
} |
|
||||
|
|
||||
.door__line { |
|
||||
width: 25%; |
|
||||
height: 4px; |
|
||||
background: #314b70; |
|
||||
border-radius: 4px; |
|
||||
} |
|
||||
|
|
||||
.top { |
|
||||
position: absolute; |
|
||||
width: 82%; |
|
||||
height: 30px; |
|
||||
background-color: #aac4d0; |
|
||||
border: 4px solid #314b70; |
|
||||
border-top-right-radius: 4px; |
|
||||
border-top-left-radius: 4px; |
|
||||
box-shadow: inset 4px 4px 0 #e1f6fd; |
|
||||
} |
|
||||
|
|
||||
.circle { |
|
||||
position: absolute; |
|
||||
top: -10%; |
|
||||
display: flex; |
|
||||
width: 115px; |
|
||||
height: 115px; |
|
||||
background-color: #e0f5fc; |
|
||||
border: 4px solid #314b70; |
|
||||
border-radius: 50%; |
|
||||
content: ''; |
|
||||
box-shadow: inset 4px 4px 0 #fffdff, inset 4px -4px 0 #fffdff, inset -4px 4px 0 #fffdff, |
|
||||
inset -4px -4px 0 #fffdff; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
} |
|
||||
|
|
||||
.circle::before, |
|
||||
.circle::after { |
|
||||
position: absolute; |
|
||||
top: 35%; |
|
||||
width: 70%; |
|
||||
height: 4px; |
|
||||
background-color: #314b70; |
|
||||
content: ''; |
|
||||
} |
|
||||
|
|
||||
.circle::after { |
|
||||
top: 20%; |
|
||||
width: 35%; |
|
||||
} |
|
||||
|
|
||||
.plastic { |
|
||||
position: absolute; |
|
||||
top: 30%; |
|
||||
z-index: 100; |
|
||||
width: 100%; |
|
||||
height: 30px; |
|
||||
overflow: hidden; |
|
||||
} |
|
||||
|
|
||||
.plastic__g { |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
width: 100%; |
|
||||
overflow: hidden; |
|
||||
transform: translateY(-22px); |
|
||||
} |
|
||||
|
|
||||
.plastic__item { |
|
||||
width: 43px; |
|
||||
height: 43px; |
|
||||
margin-bottom: 4px; |
|
||||
border: 3px solid #314b70; |
|
||||
border-radius: 50%; |
|
||||
box-shadow: 0 4px 0 #aac4d0; |
|
||||
} |
|
||||
|
|
||||
.plastic__item:nth-child(odd) { |
|
||||
background: #0792d9; |
|
||||
box-shadow: 0 4px 0 #aac4d0, inset 4px 4px 0 #66c8fa; |
|
||||
} |
|
||||
|
|
||||
.plastic__item:nth-child(even) { |
|
||||
background: #fffdff; |
|
||||
} |
|
||||
|
|
||||
.plastic__item:nth-of-type(1), |
|
||||
.plastic__item:nth-last-of-type(1) { |
|
||||
width: 45px; |
|
||||
height: 45px; |
|
||||
box-shadow: none; |
|
||||
box-shadow: inset 4px 4px 0 #66c8fa; |
|
||||
} |
|
||||
|
|
||||
.plastic__item:nth-of-type(5) { |
|
||||
width: 45px; |
|
||||
height: 45px; |
|
||||
} |
|
||||
|
|
||||
.line { |
|
||||
position: absolute; |
|
||||
top: 15px; |
|
||||
display: flex; |
|
||||
width: 90%; |
|
||||
height: 85px; |
|
||||
background-color: #e1f6fd; |
|
||||
border-right: 4px solid #314b70; |
|
||||
border-bottom: 4px solid #314b70; |
|
||||
border-left: 4px solid #314b70; |
|
||||
border-radius: 4px; |
|
||||
transform: rotateX(25deg); |
|
||||
transform-style: preserve-3d; |
|
||||
} |
|
||||
|
|
||||
.line__item { |
|
||||
height: 100%; |
|
||||
flex-grow: 1; |
|
||||
border-right: 4px solid #314b70; |
|
||||
} |
|
||||
|
|
||||
.line__item:nth-child(odd) { |
|
||||
background: #00affa; |
|
||||
box-shadow: inset 4px 4px 0 #66c8fa; |
|
||||
} |
|
||||
|
|
||||
.line__item:nth-child(even) { |
|
||||
background: #fffdff; |
|
||||
} |
|
||||
|
|
||||
.line__item:nth-last-of-type(1) { |
|
||||
border-right: none; |
|
||||
} |
|
||||
|
|
||||
.line__item:nth-child(4), |
|
||||
.line__item:nth-child(5), |
|
||||
.line__item:nth-child(6) { |
|
||||
border-top: 6px solid #314b70; |
|
||||
} |
|
||||
|
|
||||
.tree { |
|
||||
position: absolute; |
|
||||
bottom: 19%; |
|
||||
left: 10%; |
|
||||
display: flex; |
|
||||
width: 100px; |
|
||||
height: 165px; |
|
||||
background-color: #00d398; |
|
||||
border: 4px solid #314b70; |
|
||||
border-radius: 50px; |
|
||||
box-shadow: inset 4px 0 0 #77e4c6, inset -4px 0 0 #00a073; |
|
||||
animation: tree 1s linear alternate infinite; |
|
||||
justify-content: center; |
|
||||
transform-origin: 0% 100%; |
|
||||
} |
|
||||
|
|
||||
.tree__item { |
|
||||
position: absolute; |
|
||||
bottom: -80px; |
|
||||
width: 4px; |
|
||||
height: 140px; |
|
||||
background: #314b70; |
|
||||
} |
|
||||
|
|
||||
.tree__item:nth-of-type(2) { |
|
||||
bottom: 80px; |
|
||||
height: 40px; |
|
||||
border-radius: 20px; |
|
||||
box-shadow: 0 0 0 8px #77e4c6; |
|
||||
} |
|
||||
|
|
||||
.tree__item:nth-of-type(2)::before { |
|
||||
position: absolute; |
|
||||
bottom: -45px; |
|
||||
left: -30px; |
|
||||
width: 20px; |
|
||||
height: 35px; |
|
||||
background-color: #77e4c6; |
|
||||
border-radius: 15px; |
|
||||
content: ''; |
|
||||
} |
|
||||
|
|
||||
.tree__item:nth-of-type(3) { |
|
||||
bottom: 20px; |
|
||||
left: 36%; |
|
||||
width: 4px; |
|
||||
height: 30px; |
|
||||
background-color: #314b70; |
|
||||
transform: rotateZ(-45deg); |
|
||||
} |
|
||||
|
|
||||
.dot { |
|
||||
position: absolute; |
|
||||
bottom: 38px; |
|
||||
width: 100%; |
|
||||
height: 4px; |
|
||||
background-image: linear-gradient( |
|
||||
to right, |
|
||||
#314b70 10%, |
|
||||
transparent 10%, |
|
||||
transparent 11%, |
|
||||
#314b70 11%, |
|
||||
#314b70 85%, |
|
||||
transparent 85%, |
|
||||
transparent 86%, |
|
||||
#314b70 86% |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
.bush__item { |
|
||||
position: absolute; |
|
||||
bottom: 40px; |
|
||||
left: 18%; |
|
||||
width: 80px; |
|
||||
height: 60px; |
|
||||
background-color: #00d398; |
|
||||
border: 1px solid red; |
|
||||
border: 4px solid #314b70; |
|
||||
border-bottom: none; |
|
||||
border-top-right-radius: 100px; |
|
||||
border-top-left-radius: 50px; |
|
||||
box-shadow: inset 4px 0 0 #77e4c6, inset -4px 0 0 #00a073; |
|
||||
animation: bush 2s alternate infinite; |
|
||||
transform-origin: bottom center; |
|
||||
} |
|
||||
|
|
||||
.bush__item:nth-of-type(2) { |
|
||||
left: 13%; |
|
||||
width: 50px; |
|
||||
height: 40px; |
|
||||
border-top-right-radius: 10px; |
|
||||
border-top-left-radius: 50px; |
|
||||
animation: tree 2s alternate reverse infinite 0.5s; |
|
||||
} |
|
||||
|
|
||||
.bush__item::before { |
|
||||
position: absolute; |
|
||||
top: 10px; |
|
||||
left: 10px; |
|
||||
width: 20px; |
|
||||
height: 20px; |
|
||||
background: #77e4c6; |
|
||||
border-radius: 50%; |
|
||||
content: ''; |
|
||||
} |
|
||||
|
|
||||
.cloud { |
|
||||
position: absolute; |
|
||||
top: 200px; |
|
||||
left: 60px; |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
width: 85px; |
|
||||
height: 20px; |
|
||||
border-bottom: 4px solid #e1e8f2; |
|
||||
animation: cloud 4s infinite alternate; |
|
||||
} |
|
||||
|
|
||||
.cloud:nth-of-type(2) { |
|
||||
top: 150px; |
|
||||
left: 50%; |
|
||||
animation: cloud 4s infinite reverse alternate 0.5s; |
|
||||
} |
|
||||
|
|
||||
.cloud:nth-of-type(3) { |
|
||||
top: 250px; |
|
||||
left: 80%; |
|
||||
animation: cloud 4s ease infinite alternate 0.75s; |
|
||||
} |
|
||||
|
|
||||
.cloud__item { |
|
||||
position: relative; |
|
||||
border-top: 20px solid #e1e8f2; |
|
||||
border-right: 20px solid transparent; |
|
||||
border-bottom: 20px solid transparent; |
|
||||
border-left: 20px solid #e1e8f2; |
|
||||
border-radius: 50%; |
|
||||
transform: rotateZ(45deg); |
|
||||
} |
|
||||
|
|
||||
.cloud__item:nth-of-type(2) { |
|
||||
margin-top: 5px; |
|
||||
margin-left: -7px; |
|
||||
border-top: 15px solid #e1e8f2; |
|
||||
border-right: 15px solid transparent; |
|
||||
border-bottom: 15px solid transparent; |
|
||||
border-left: 15px solid #e1e8f2; |
|
||||
} |
|
||||
|
|
||||
.bird { |
|
||||
position: absolute; |
|
||||
right: 10%; |
|
||||
bottom: 40%; |
|
||||
z-index: -1; |
|
||||
width: 20px; |
|
||||
height: 20px; |
|
||||
border-top: 4px solid #becde2; |
|
||||
border-left: 4px solid #becde2; |
|
||||
transform: rotateZ(-135deg); |
|
||||
animation: bird 1s ease alternate infinite; |
|
||||
} |
|
||||
|
|
||||
.bird:nth-of-type(2) { |
|
||||
right: 20%; |
|
||||
bottom: 30%; |
|
||||
width: 15px; |
|
||||
height: 15px; |
|
||||
} |
|
||||
|
|
||||
@keyframes bird { |
|
||||
0% { |
|
||||
transform: scaleY(0.7) rotateZ(-135deg) translateX(0) translateY(0) skew(-10deg, -10deg); |
|
||||
} |
|
||||
|
|
||||
100% { |
|
||||
transform: scaleY(1) rotateZ(-135deg) translateX(50%) translateY(50%) skew(-10deg, -10deg); |
|
||||
} |
|
||||
} |
|
||||
@keyframes tree { |
|
||||
0% { |
|
||||
transform: scaleY(1); |
|
||||
} |
|
||||
|
|
||||
100% { |
|
||||
transform: scaleY(0.975); |
|
||||
} |
|
||||
} |
|
||||
@keyframes bush { |
|
||||
0% { |
|
||||
transform: skewX(-2deg); |
|
||||
} |
|
||||
|
|
||||
100% { |
|
||||
transform: skewX(5deg); |
|
||||
} |
|
||||
} |
|
||||
@keyframes cloud { |
|
||||
0% { |
|
||||
transform: translateX(-10%); |
|
||||
} |
|
||||
|
|
||||
100% { |
|
||||
transform: translateX(20%); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,89 +0,0 @@ |
|||||
<template> |
|
||||
<div class="house-wrap"> |
|
||||
<div class="house"> |
|
||||
<div class="floor"></div> |
|
||||
<div class="wall"> |
|
||||
<div class="window"></div> |
|
||||
<div class="door"> |
|
||||
<div class="door__square"></div> |
|
||||
<div class="door__line"></div> |
|
||||
<div class="door__square"></div> |
|
||||
</div> |
|
||||
<div class="window"></div> |
|
||||
</div> |
|
||||
<div class="top"></div> |
|
||||
<div class="circle"></div> |
|
||||
<div class="plastic"> |
|
||||
<div class="plastic__g"> |
|
||||
<div class="plastic__item"></div> |
|
||||
<div class="plastic__item"></div> |
|
||||
<div class="plastic__item"></div> |
|
||||
<div class="plastic__item"></div> |
|
||||
<div class="plastic__item"></div> |
|
||||
<div class="plastic__item"></div> |
|
||||
<div class="plastic__item"></div> |
|
||||
<div class="plastic__item"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="line"> |
|
||||
<div class="line__item"></div> |
|
||||
<div class="line__item"></div> |
|
||||
<div class="line__item"></div> |
|
||||
<div class="line__item"></div> |
|
||||
<div class="line__item"></div> |
|
||||
<div class="line__item"></div> |
|
||||
<div class="line__item"></div> |
|
||||
<div class="line__item"></div> |
|
||||
<div class="line__item"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="clouds"> |
|
||||
<div class="cloud"> |
|
||||
<div class="cloud__item"></div> |
|
||||
<div class="cloud__item"></div> |
|
||||
</div> |
|
||||
<div class="cloud"> |
|
||||
<div class="cloud__item"></div> |
|
||||
<div class="cloud__item"></div> |
|
||||
</div> |
|
||||
<div class="cloud"> |
|
||||
<div class="cloud__item"></div> |
|
||||
<div class="cloud__item"></div> |
|
||||
</div> |
|
||||
<div class="bird"></div> |
|
||||
</div> |
|
||||
<div class="birds"> |
|
||||
<div class="bird"></div> |
|
||||
<div class="bird"></div> |
|
||||
</div> |
|
||||
<div class="tree"> |
|
||||
<div class="tree__item"></div> |
|
||||
<div class="tree__item"></div> |
|
||||
<div class="tree__item"></div> |
|
||||
</div> |
|
||||
<div class="bush"> |
|
||||
<div class="bush__item"></div> |
|
||||
<div class="bush__item"></div> |
|
||||
</div> |
|
||||
<div class="dot"></div> |
|
||||
</div> |
|
||||
</template> |
|
||||
<script lang="ts"> |
|
||||
import type { PropType } from 'vue'; |
|
||||
import { defineComponent } from 'vue'; |
|
||||
export default defineComponent({ |
|
||||
name: 'House', |
|
||||
props: { |
|
||||
size: { |
|
||||
type: Number as PropType<number>, |
|
||||
default: 600, |
|
||||
}, |
|
||||
}, |
|
||||
setup() { |
|
||||
return {}; |
|
||||
}, |
|
||||
}); |
|
||||
</script> |
|
||||
<style lang="less" scoped> |
|
||||
@import './index.less'; |
|
||||
</style> |
|
||||
@ -1,22 +0,0 @@ |
|||||
<template> |
|
||||
<div class="welcome"> |
|
||||
<House /> |
|
||||
</div> |
|
||||
</template> |
|
||||
<script lang="ts"> |
|
||||
import { defineComponent } from 'vue'; |
|
||||
import House from '../house/index.vue'; |
|
||||
export default defineComponent({ |
|
||||
name: 'Welcome', |
|
||||
components: { House }, |
|
||||
}); |
|
||||
</script> |
|
||||
<style lang="less" scoped> |
|
||||
.welcome { |
|
||||
display: flex; |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
} |
|
||||
</style> |
|
||||
@ -0,0 +1,37 @@ |
|||||
|
<template> |
||||
|
<Card title="最新动态" v-bind="$attrs"> |
||||
|
<template #extra> |
||||
|
<a-button type="link" size="small">更多</a-button> |
||||
|
</template> |
||||
|
<List item-layout="horizontal" :data-source="items"> |
||||
|
<template #renderItem="{ item }"> |
||||
|
<ListItem> |
||||
|
<ListItemMeta> |
||||
|
<template #description> |
||||
|
{{ item.date }} |
||||
|
</template> |
||||
|
<template #title> {{ item.name }} <span v-html="item.desc"> </span> </template> |
||||
|
<template #avatar> |
||||
|
<Icon :icon="item.avatar" :size="30" /> |
||||
|
</template> |
||||
|
</ListItemMeta> |
||||
|
</ListItem> |
||||
|
</template> |
||||
|
</List> |
||||
|
</Card> |
||||
|
</template> |
||||
|
<script lang="ts"> |
||||
|
import { defineComponent } from 'vue'; |
||||
|
|
||||
|
import { Card, List } from 'ant-design-vue'; |
||||
|
import { dynamicInfoItems } from './data'; |
||||
|
import headerImg from '/@/assets/images/header.jpg'; |
||||
|
import { Icon } from '/@/components/Icon'; |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
components: { Card, List, ListItem: List.Item, ListItemMeta: List.Item.Meta, Icon }, |
||||
|
setup() { |
||||
|
return { items: dynamicInfoItems, headerImg }; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
@ -1,100 +0,0 @@ |
|||||
<template> |
|
||||
<CollapseContainer class="news-list" title="动态" :canExpan="false"> |
|
||||
<ScrollContainer> |
|
||||
<List> |
|
||||
<template v-for="item in newList" :key="item.id"> |
|
||||
<ListItem class="news-list__item"> |
|
||||
<ListItemMeta> |
|
||||
<template #avatar> |
|
||||
<img :src="headerImg" class="news-list__item-avatar" /> |
|
||||
</template> |
|
||||
<template #description> |
|
||||
<div class="news-list__item-desc"> |
|
||||
<div class="news-list__item-time mb-1"> |
|
||||
{{ item.sendTime }} |
|
||||
</div> |
|
||||
<div class="news-list__item-title mb-1"> |
|
||||
<span class="news-list__item-light">{{ item.sender }} </span>申请迭代 |
|
||||
<span class="news-list__item-light"> {{ item.title }} </span>发布 |
|
||||
</div> |
|
||||
<div class="news-list__item-cnte p-2"> |
|
||||
<span class="news-list__item-cnte__title"> {{ item.cnteId }}</span> |
|
||||
<br /> |
|
||||
Status: {{ item.cnteStas }} |
|
||||
<br /> |
|
||||
Repository: {{ item.cnteRepo }} |
|
||||
<br /> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
</ListItemMeta> |
|
||||
</ListItem> |
|
||||
</template> |
|
||||
</List> |
|
||||
</ScrollContainer> |
|
||||
</CollapseContainer> |
|
||||
</template> |
|
||||
<script lang="ts"> |
|
||||
import { defineComponent } from 'vue'; |
|
||||
import { List } from 'ant-design-vue'; |
|
||||
import { CollapseContainer, ScrollContainer } from '/@/components/Container/index'; |
|
||||
import headerImg from '/@/assets/images/header.jpg'; |
|
||||
|
|
||||
import { newList } from '../data'; |
|
||||
export default defineComponent({ |
|
||||
components: { |
|
||||
List, |
|
||||
ListItem: List.Item, |
|
||||
ListItemMeta: List.Item.Meta, |
|
||||
CollapseContainer, |
|
||||
ScrollContainer, |
|
||||
}, |
|
||||
setup() { |
|
||||
return { newList, headerImg }; |
|
||||
}, |
|
||||
}); |
|
||||
</script> |
|
||||
<style lang="less" scoped> |
|
||||
.news-list { |
|
||||
&__item { |
|
||||
&-avatar { |
|
||||
width: 35px; |
|
||||
height: 35px; |
|
||||
border-radius: 50%; |
|
||||
} |
|
||||
|
|
||||
&-title { |
|
||||
font-size: 14px; |
|
||||
line-height: 22px; |
|
||||
color: #000; |
|
||||
opacity: 0.65; |
|
||||
} |
|
||||
|
|
||||
&-time { |
|
||||
font-size: 14px; |
|
||||
line-height: 22px; |
|
||||
color: #000; |
|
||||
opacity: 0.45; |
|
||||
} |
|
||||
|
|
||||
&-light { |
|
||||
font-size: 14px; |
|
||||
line-height: 22px; |
|
||||
color: #000; |
|
||||
opacity: 0.85; |
|
||||
} |
|
||||
|
|
||||
&-cnte { |
|
||||
background: #eef3fb; |
|
||||
border-radius: 2px; |
|
||||
opacity: 0.6; |
|
||||
|
|
||||
&__title { |
|
||||
font-size: 14px; |
|
||||
line-height: 22px; |
|
||||
color: rgba(0, 0, 0, 0.85); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,101 +0,0 @@ |
|||||
<template> |
|
||||
<a-row class="prod-total"> |
|
||||
<template v-for="(item, index) in wokbProd" :key="item.type"> |
|
||||
<a-col :xs="12" :sm="6" class="prod-total__item" :class="`prod-total__item-${index}`"> |
|
||||
<div class="img" :class="`prod-total__item-${index}-img`"></div> |
|
||||
<div>{{ item.amount }}</div> |
|
||||
<span>{{ item.type }}</span> |
|
||||
</a-col> |
|
||||
</template> |
|
||||
</a-row> |
|
||||
</template> |
|
||||
<script lang="ts"> |
|
||||
import { defineComponent } from 'vue'; |
|
||||
import { Row, Col } from 'ant-design-vue'; |
|
||||
|
|
||||
import { wokbProd } from '../data'; |
|
||||
// import {ProdTypeEnum} from '@/api/dashboard/model/wokbModel' |
|
||||
export default defineComponent({ |
|
||||
components: { [Row.name]: Row, [Col.name]: Col }, |
|
||||
setup() { |
|
||||
return { wokbProd }; |
|
||||
}, |
|
||||
}); |
|
||||
</script> |
|
||||
<style lang="less" scoped> |
|
||||
.prod-total { |
|
||||
padding: 12px 4px 12px 12px; |
|
||||
background: #fff; |
|
||||
|
|
||||
&__item { |
|
||||
display: inline-block; |
|
||||
flex: 0 0 calc(25% - 8px); |
|
||||
padding: 20px 10px; |
|
||||
margin-right: 8px; |
|
||||
border-radius: 4px; |
|
||||
|
|
||||
span { |
|
||||
font-size: 14px; |
|
||||
line-height: 28px; |
|
||||
} |
|
||||
|
|
||||
div { |
|
||||
font-size: 26px; |
|
||||
} |
|
||||
|
|
||||
.img { |
|
||||
float: left; |
|
||||
width: 62px; |
|
||||
height: 62px; |
|
||||
} |
|
||||
|
|
||||
&-0 { |
|
||||
background: rgba(254, 97, 178, 0.1); |
|
||||
|
|
||||
&-img { |
|
||||
background: url(../../../../assets/images/dashboard/wokb/datashow1.png) no-repeat; |
|
||||
} |
|
||||
|
|
||||
div { |
|
||||
color: #fe61b2; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
&-1 { |
|
||||
background: rgba(254, 163, 64, 0.1); |
|
||||
|
|
||||
&-img { |
|
||||
background: url(../../../..//assets/images/dashboard/wokb/datashow2.png) no-repeat; |
|
||||
} |
|
||||
|
|
||||
div { |
|
||||
color: #fea340; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
&-2 { |
|
||||
background: rgba(172, 70, 255, 0.1); |
|
||||
|
|
||||
&-img { |
|
||||
background: url(../../../..//assets/images/dashboard/wokb/datashow3.png) no-repeat; |
|
||||
} |
|
||||
|
|
||||
div { |
|
||||
color: #9e55ff; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
&-3 { |
|
||||
background: rgba(0, 196, 186, 0.1); |
|
||||
|
|
||||
&-img { |
|
||||
background: url(../../../..//assets/images/dashboard/wokb/datashow4.png) no-repeat; |
|
||||
} |
|
||||
|
|
||||
div { |
|
||||
color: #00c4ba; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -0,0 +1,35 @@ |
|||||
|
<template> |
||||
|
<Card title="项目" v-bind="$attrs"> |
||||
|
<template #extra> |
||||
|
<a-button type="link" size="small">更多</a-button> |
||||
|
</template> |
||||
|
|
||||
|
<template v-for="item in items" :key="item"> |
||||
|
<CardGrid class="!md:w-1/3 !w-full"> |
||||
|
<span class="flex"> |
||||
|
<Icon :icon="item.icon" :color="item.color" size="30" /> |
||||
|
<span class="text-lg ml-4">{{ item.title }}</span> |
||||
|
</span> |
||||
|
<div class="flex mt-2 h-10 text-secondary"> {{ item.desc }} </div> |
||||
|
<div class="flex justify-between text-secondary"> |
||||
|
<span>{{ item.group }}</span> |
||||
|
<span>{{ item.date }}</span> |
||||
|
</div> |
||||
|
</CardGrid> |
||||
|
</template> |
||||
|
</Card> |
||||
|
</template> |
||||
|
<script lang="ts"> |
||||
|
import { defineComponent } from 'vue'; |
||||
|
|
||||
|
import { Card } from 'ant-design-vue'; |
||||
|
import { Icon } from '/@/components/Icon'; |
||||
|
import { groupItems } from './data'; |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
components: { Card, CardGrid: Card.Grid, Icon }, |
||||
|
setup() { |
||||
|
return { items: groupItems }; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
@ -0,0 +1,26 @@ |
|||||
|
<template> |
||||
|
<Card title="快捷导航" v-bind="$attrs"> |
||||
|
<template v-for="item in items" :key="item"> |
||||
|
<CardGrid> |
||||
|
<span class="flex flex-col items-center"> |
||||
|
<Icon :icon="item.icon" :color="item.color" size="20" /> |
||||
|
<span class="text-md mt-2">{{ item.title }}</span> |
||||
|
</span> |
||||
|
</CardGrid> |
||||
|
</template> |
||||
|
</Card> |
||||
|
</template> |
||||
|
<script lang="ts"> |
||||
|
import { defineComponent } from 'vue'; |
||||
|
|
||||
|
import { Card } from 'ant-design-vue'; |
||||
|
import { Icon } from '/@/components/Icon'; |
||||
|
import { navItems } from './data'; |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
components: { Card, CardGrid: Card.Grid, Icon }, |
||||
|
setup() { |
||||
|
return { items: navItems }; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
@ -0,0 +1,107 @@ |
|||||
|
<template> |
||||
|
<Card title="销售统计" :loading="loading"> |
||||
|
<div ref="chartRef" :style="{ width, height }"></div> |
||||
|
</Card> |
||||
|
</template> |
||||
|
<script lang="ts"> |
||||
|
import { defineComponent, Ref, ref, watch } from 'vue'; |
||||
|
|
||||
|
import { Card } from 'ant-design-vue'; |
||||
|
import { useECharts } from '/@/hooks/web/useECharts'; |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
components: { Card }, |
||||
|
props: { |
||||
|
loading: Boolean, |
||||
|
width: { |
||||
|
type: String as PropType<string>, |
||||
|
default: '100%', |
||||
|
}, |
||||
|
height: { |
||||
|
type: String as PropType<string>, |
||||
|
default: '400px', |
||||
|
}, |
||||
|
}, |
||||
|
setup(props) { |
||||
|
const chartRef = ref<HTMLDivElement | null>(null); |
||||
|
const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); |
||||
|
watch( |
||||
|
() => props.loading, |
||||
|
() => { |
||||
|
if (props.loading) { |
||||
|
return; |
||||
|
} |
||||
|
setOptions({ |
||||
|
backgroundColor: '#fff', |
||||
|
legend: { |
||||
|
bottom: 0, |
||||
|
data: ['Visits', 'Sales'], |
||||
|
}, |
||||
|
tooltip: {}, |
||||
|
radar: { |
||||
|
radius: '60%', |
||||
|
splitNumber: 8, |
||||
|
indicator: [ |
||||
|
{ |
||||
|
text: '2017', |
||||
|
max: 100, |
||||
|
}, |
||||
|
{ |
||||
|
text: '2017', |
||||
|
max: 100, |
||||
|
}, |
||||
|
{ |
||||
|
text: '2018', |
||||
|
max: 100, |
||||
|
}, |
||||
|
{ |
||||
|
text: '2019', |
||||
|
max: 100, |
||||
|
}, |
||||
|
{ |
||||
|
text: '2020', |
||||
|
max: 100, |
||||
|
}, |
||||
|
{ |
||||
|
text: '2021', |
||||
|
max: 100, |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
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 } |
||||
|
); |
||||
|
return { chartRef }; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
@ -1,102 +0,0 @@ |
|||||
<template> |
|
||||
<CollapseContainer class="shortcuts" title="快捷入口" :canExpan="false"> |
|
||||
<template #action> |
|
||||
<a-button size="small" type="link"> 新建 </a-button> |
|
||||
</template> |
|
||||
<a-row> |
|
||||
<template v-for="item in shortCuts" :key="item.img"> |
|
||||
<a-col :span="8" class="p-3 shortcuts__item"> |
|
||||
<img :src="item.img" class="mb-2 shortcuts__item-img" /> |
|
||||
<span>{{ item.name }}</span> |
|
||||
</a-col> |
|
||||
</template> |
|
||||
|
|
||||
<a-col :span="8" class="p-3 shortcuts__item"> |
|
||||
<span class="mb-2 shortcuts__item-all"> |
|
||||
<RightOutlined /> |
|
||||
</span> |
|
||||
<br /> |
|
||||
<span>查看全部</span> |
|
||||
</a-col> |
|
||||
</a-row> |
|
||||
</CollapseContainer> |
|
||||
</template> |
|
||||
<script lang="ts"> |
|
||||
import { defineComponent } from 'vue'; |
|
||||
import { Row, Col } from 'ant-design-vue'; |
|
||||
import { CollapseContainer } from '/@/components/Container/index'; |
|
||||
|
|
||||
import { RightOutlined } from '@ant-design/icons-vue'; |
|
||||
import wokbImg1 from '/@/assets/images/dashboard/wokb/attendance.png'; |
|
||||
import wokbImg2 from '/@/assets/images/dashboard/wokb/overtime.png'; |
|
||||
import wokbImg3 from '/@/assets/images/dashboard/wokb/meal.png'; |
|
||||
import wokbImg4 from '/@/assets/images/dashboard/wokb/leave.png'; |
|
||||
import wokbImg5 from '/@/assets/images/dashboard/wokb/stamp.png'; |
|
||||
import wokbImg6 from '/@/assets/images/dashboard/wokb/travel.png'; |
|
||||
import wokbImg7 from '/@/assets/images/dashboard/wokb/performance.png'; |
|
||||
import wokbImg8 from '/@/assets/images/dashboard/wokb/approve.png'; |
|
||||
const shortCuts = [ |
|
||||
{ |
|
||||
img: wokbImg1, |
|
||||
name: '考勤记录', |
|
||||
}, |
|
||||
{ |
|
||||
img: wokbImg2, |
|
||||
name: '加班申请', |
|
||||
}, |
|
||||
{ |
|
||||
img: wokbImg3, |
|
||||
name: '餐补申请', |
|
||||
}, |
|
||||
{ |
|
||||
img: wokbImg4, |
|
||||
name: '请假', |
|
||||
}, |
|
||||
{ |
|
||||
img: wokbImg5, |
|
||||
name: '用章申请', |
|
||||
}, |
|
||||
{ |
|
||||
img: wokbImg6, |
|
||||
name: '差旅报销', |
|
||||
}, |
|
||||
{ |
|
||||
img: wokbImg7, |
|
||||
name: '绩效申请', |
|
||||
}, |
|
||||
{ |
|
||||
img: wokbImg8, |
|
||||
name: '审批', |
|
||||
}, |
|
||||
]; |
|
||||
export default defineComponent({ |
|
||||
components: { [Row.name]: Row, [Col.name]: Col, CollapseContainer, RightOutlined }, |
|
||||
setup() { |
|
||||
return { shortCuts }; |
|
||||
}, |
|
||||
}); |
|
||||
</script> |
|
||||
<style lang="less" scoped> |
|
||||
.shortcuts { |
|
||||
&__item { |
|
||||
text-align: center; |
|
||||
|
|
||||
&-img { |
|
||||
width: 36px; |
|
||||
margin-left: auto; |
|
||||
margin-right: auto; |
|
||||
} |
|
||||
|
|
||||
&-all { |
|
||||
display: inline-block; |
|
||||
width: 36px; |
|
||||
height: 36px; |
|
||||
line-height: 36px; |
|
||||
color: #000; |
|
||||
cursor: pointer; |
|
||||
background: lightgrey; |
|
||||
border-radius: 50%; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,114 +0,0 @@ |
|||||
<template> |
|
||||
<CollapseContainer class="todo-list" title="待办事项" :canExpan="false"> |
|
||||
<template #title> |
|
||||
<span> 待办事项 <span class="todo-list__total">30</span> </span> |
|
||||
</template> |
|
||||
|
|
||||
<List> |
|
||||
<template v-for="item in todoList" :key="item.id"> |
|
||||
<ListItem class="todo-list__item"> |
|
||||
<ListItemMeta> |
|
||||
<template #title> |
|
||||
<div> |
|
||||
<span class="todo-list__item-title">{{ item.title }}</span> |
|
||||
<span class="todo-list__item-memo">{{ item.memo }}</span> |
|
||||
</div> |
|
||||
</template> |
|
||||
<template #description> |
|
||||
<div class="todo-list__item-desc"> |
|
||||
提交人:{{ item.sbmter }} |
|
||||
<br /> |
|
||||
提交时间:{{ item.sbmtTime }} |
|
||||
</div> |
|
||||
</template> |
|
||||
</ListItemMeta> |
|
||||
<a-button type="link"> |
|
||||
<Tag color="blue"> 待审批 </Tag> |
|
||||
</a-button> |
|
||||
</ListItem> |
|
||||
</template> |
|
||||
</List> |
|
||||
<div class="todo-list__all"> |
|
||||
<Tooltip placement="topRight"> |
|
||||
<template #title> 查看更多 </template> |
|
||||
<EllipsisOutlined /> |
|
||||
</Tooltip> |
|
||||
</div> |
|
||||
</CollapseContainer> |
|
||||
</template> |
|
||||
<script lang="ts"> |
|
||||
import { defineComponent } from 'vue'; |
|
||||
import { List, Tag, Tooltip } from 'ant-design-vue'; |
|
||||
import { CollapseContainer } from '/@/components/Container/index'; |
|
||||
|
|
||||
import { EllipsisOutlined } from '@ant-design/icons-vue'; |
|
||||
import { todoList } from '../data'; |
|
||||
|
|
||||
export default defineComponent({ |
|
||||
name: 'TodoList', |
|
||||
components: { |
|
||||
CollapseContainer, |
|
||||
List, |
|
||||
ListItem: List.Item, |
|
||||
ListItemMeta: List.Item.Meta, |
|
||||
Tag, |
|
||||
Tooltip, |
|
||||
EllipsisOutlined, |
|
||||
}, |
|
||||
setup() { |
|
||||
return { todoList }; |
|
||||
}, |
|
||||
}); |
|
||||
</script> |
|
||||
<style lang="less" scoped> |
|
||||
.todo-list { |
|
||||
position: relative; |
|
||||
|
|
||||
&__total { |
|
||||
display: inline-block; |
|
||||
width: 20px; |
|
||||
height: 20px; |
|
||||
font-size: 12px; |
|
||||
line-height: 20px; |
|
||||
color: #fff; |
|
||||
text-align: center; |
|
||||
background: rgba(255, 0, 0, 0.7); |
|
||||
border-radius: 50%; |
|
||||
} |
|
||||
|
|
||||
&__all { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
right: 10px; |
|
||||
height: 56px; |
|
||||
font-size: 24px; |
|
||||
line-height: 56px; |
|
||||
text-align: center; |
|
||||
cursor: pointer; |
|
||||
} |
|
||||
|
|
||||
&__item { |
|
||||
padding: 8px; |
|
||||
|
|
||||
&-title { |
|
||||
font-size: 14px; |
|
||||
font-weight: normal; |
|
||||
line-height: 22px; |
|
||||
color: #1c1d21; |
|
||||
} |
|
||||
|
|
||||
&-memo { |
|
||||
font-size: 12px; |
|
||||
font-weight: normal; |
|
||||
line-height: 22px; |
|
||||
color: #7c8087; |
|
||||
} |
|
||||
|
|
||||
&-desc { |
|
||||
font-size: 12px; |
|
||||
line-height: 22px; |
|
||||
color: #7c8087; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -0,0 +1,37 @@ |
|||||
|
<template> |
||||
|
<div class="lg:flex"> |
||||
|
<Avatar :src="headerImg" :size="72" class="!mx-auto !block" /> |
||||
|
<div class="md:ml-6 flex flex-col justify-center md:mt-0 mt-2"> |
||||
|
<h1 class="md:text-lg text-md">早安, Vben, 开始您一天的工作吧!</h1> |
||||
|
<span class="text-secondary"> 今日晴,20℃ - 32℃! </span> |
||||
|
</div> |
||||
|
<div class="flex flex-1 justify-end md:mt-0 mt-4"> |
||||
|
<div class="flex flex-col justify-center text-right"> |
||||
|
<span class="text-secondary"> 待办 </span> |
||||
|
<span class="text-2xl">2/10</span> |
||||
|
</div> |
||||
|
|
||||
|
<div class="flex flex-col justify-center text-right md:mx-16 mx-12"> |
||||
|
<span class="text-secondary"> 项目 </span> |
||||
|
<span class="text-2xl">8</span> |
||||
|
</div> |
||||
|
<div class="flex flex-col justify-center text-right md:mr-10 mr-4"> |
||||
|
<span class="text-secondary"> 团队 </span> |
||||
|
<span class="text-2xl">300</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
<script lang="ts"> |
||||
|
import { defineComponent } from 'vue'; |
||||
|
|
||||
|
import { Avatar } from 'ant-design-vue'; |
||||
|
|
||||
|
import headerImg from '/@/assets/images/header.jpg'; |
||||
|
export default defineComponent({ |
||||
|
components: { Avatar }, |
||||
|
setup() { |
||||
|
return { headerImg }; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
@ -0,0 +1,156 @@ |
|||||
|
interface GroupItem { |
||||
|
title: string; |
||||
|
icon: string; |
||||
|
color: string; |
||||
|
desc: string; |
||||
|
date: string; |
||||
|
group: string; |
||||
|
} |
||||
|
|
||||
|
interface NavItem { |
||||
|
title: string; |
||||
|
icon: string; |
||||
|
color: string; |
||||
|
} |
||||
|
|
||||
|
interface DynamicInfoItem { |
||||
|
avatar: string; |
||||
|
name: string; |
||||
|
date: string; |
||||
|
desc: string; |
||||
|
} |
||||
|
|
||||
|
export const navItems: NavItem[] = [ |
||||
|
{ |
||||
|
title: '首页', |
||||
|
icon: 'ion:home-outline', |
||||
|
color: '#1fdaca', |
||||
|
}, |
||||
|
{ |
||||
|
title: '仪表盘', |
||||
|
icon: 'ion:grid-outline', |
||||
|
color: '#bf0c2c', |
||||
|
}, |
||||
|
{ |
||||
|
title: '组件', |
||||
|
icon: 'ion:layers-outline', |
||||
|
color: '#e18525', |
||||
|
}, |
||||
|
{ |
||||
|
title: '系统管理', |
||||
|
icon: 'ion:settings-outline', |
||||
|
color: '#3fb27f', |
||||
|
}, |
||||
|
{ |
||||
|
title: '权限管理', |
||||
|
icon: 'ion:key-outline', |
||||
|
color: '#4daf1bc9', |
||||
|
}, |
||||
|
{ |
||||
|
title: '图表', |
||||
|
icon: 'ion:bar-chart-outline', |
||||
|
color: '#00d8ff', |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
export const dynamicInfoItems: DynamicInfoItem[] = [ |
||||
|
{ |
||||
|
avatar: 'dynamic-avatar-1|svg', |
||||
|
name: '威廉', |
||||
|
date: '刚刚', |
||||
|
desc: `在 <a>开源组</a> 创建了项目 <a>Vue</a>`, |
||||
|
}, |
||||
|
{ |
||||
|
avatar: 'dynamic-avatar-2|svg', |
||||
|
name: '艾文', |
||||
|
date: '1个小时前', |
||||
|
desc: `关注了 <a>威廉</a> `, |
||||
|
}, |
||||
|
{ |
||||
|
avatar: 'dynamic-avatar-3|svg', |
||||
|
name: '克里斯', |
||||
|
date: '1天前', |
||||
|
desc: `发布了 <a>个人动态</a> `, |
||||
|
}, |
||||
|
{ |
||||
|
avatar: 'dynamic-avatar-4|svg', |
||||
|
name: 'Vben', |
||||
|
date: '2天前', |
||||
|
desc: `发表文章 <a>如何编写一个Vite插件</a> `, |
||||
|
}, |
||||
|
{ |
||||
|
avatar: 'dynamic-avatar-5|svg', |
||||
|
name: '皮特', |
||||
|
date: '3天前', |
||||
|
desc: `回复了 <a>杰克</a> 的问题 <a>如何进行项目优化?</a>`, |
||||
|
}, |
||||
|
{ |
||||
|
avatar: 'dynamic-avatar-6|svg', |
||||
|
name: '杰克', |
||||
|
date: '1周前', |
||||
|
desc: `关闭了问题 <a>如何运行项目</a> `, |
||||
|
}, |
||||
|
{ |
||||
|
avatar: 'dynamic-avatar-1|svg', |
||||
|
name: '威廉', |
||||
|
date: '1周前', |
||||
|
desc: `发布了 <a>个人动态</a> `, |
||||
|
}, |
||||
|
{ |
||||
|
avatar: 'dynamic-avatar-1|svg', |
||||
|
name: '威廉', |
||||
|
date: '2021-04-01 20:00', |
||||
|
desc: `推送了代码到 <a>Github</a>`, |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
export const groupItems: GroupItem[] = [ |
||||
|
{ |
||||
|
title: 'Github', |
||||
|
icon: 'carbon:logo-github', |
||||
|
color: '', |
||||
|
desc: '不要等待机会,而要创造机会。', |
||||
|
group: '开源组', |
||||
|
date: '2021-04-01', |
||||
|
}, |
||||
|
{ |
||||
|
title: 'Vue', |
||||
|
icon: 'ion:logo-vue', |
||||
|
color: '#3fb27f', |
||||
|
desc: '现在的你决定将来的你。', |
||||
|
group: '算法组', |
||||
|
date: '2021-04-01', |
||||
|
}, |
||||
|
{ |
||||
|
title: 'Html5', |
||||
|
icon: 'ion:logo-html5', |
||||
|
color: '#e18525', |
||||
|
desc: '没有什么才能比努力更重要。', |
||||
|
group: '上班摸鱼', |
||||
|
date: '2021-04-01', |
||||
|
}, |
||||
|
{ |
||||
|
title: 'Angular', |
||||
|
icon: 'ion:logo-angular', |
||||
|
color: '#bf0c2c', |
||||
|
desc: '热情和欲望可以突破一切难关。', |
||||
|
group: 'UI', |
||||
|
date: '2021-04-01', |
||||
|
}, |
||||
|
{ |
||||
|
title: 'React', |
||||
|
icon: 'bx:bxl-react', |
||||
|
color: '#00d8ff', |
||||
|
desc: '健康的身体是实目标的基石。', |
||||
|
group: '技术牛', |
||||
|
date: '2021-04-01', |
||||
|
}, |
||||
|
{ |
||||
|
title: 'Js', |
||||
|
icon: 'ion:logo-javascript', |
||||
|
color: '#4daf1bc9', |
||||
|
desc: '路是走出来的,而不是空想出来的。', |
||||
|
group: '架构组', |
||||
|
date: '2021-04-01', |
||||
|
}, |
||||
|
]; |
||||
@ -1,48 +0,0 @@ |
|||||
export const wokbProd = [ |
|
||||
{ |
|
||||
amount: '20', |
|
||||
type: '成品总数', |
|
||||
}, |
|
||||
{ |
|
||||
amount: '50', |
|
||||
type: '未发布', |
|
||||
}, |
|
||||
{ |
|
||||
amount: '80', |
|
||||
type: '发布中', |
|
||||
}, |
|
||||
{ |
|
||||
amount: '100', |
|
||||
type: '异常', |
|
||||
}, |
|
||||
]; |
|
||||
|
|
||||
export const todoList = (() => { |
|
||||
const ret: any[] = []; |
|
||||
for (let index = 0; index < 3; index++) { |
|
||||
ret.push({ |
|
||||
id: index, |
|
||||
sbmter: '张三', |
|
||||
sbmtTime: new Date().toLocaleString(), |
|
||||
title: '主要', |
|
||||
memo: '工作任务', |
|
||||
}); |
|
||||
} |
|
||||
return ret; |
|
||||
})(); |
|
||||
export const newList = (() => { |
|
||||
const ret: any[] = []; |
|
||||
for (let index = 0; index < 3; index++) { |
|
||||
ret.push({ |
|
||||
id: index, |
|
||||
sender: '李四', |
|
||||
sendTime: new Date().toLocaleString(), |
|
||||
title: '代码', |
|
||||
memo: '工作任务', |
|
||||
cnteId: `c${index}`, |
|
||||
cnteStas: 'opened', |
|
||||
cnteRepo: index, |
|
||||
}); |
|
||||
} |
|
||||
return ret; |
|
||||
})(); |
|
||||
@ -0,0 +1,107 @@ |
|||||
|
<template> |
||||
|
<Card title="销售统计" :loading="loading"> |
||||
|
<div ref="chartRef" :style="{ width, height }"></div> |
||||
|
</Card> |
||||
|
</template> |
||||
|
<script lang="ts"> |
||||
|
import { defineComponent, Ref, ref, watch } from 'vue'; |
||||
|
|
||||
|
import { Card } from 'ant-design-vue'; |
||||
|
import { useECharts } from '/@/hooks/web/useECharts'; |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
components: { Card }, |
||||
|
props: { |
||||
|
loading: Boolean, |
||||
|
width: { |
||||
|
type: String as PropType<string>, |
||||
|
default: '100%', |
||||
|
}, |
||||
|
height: { |
||||
|
type: String as PropType<string>, |
||||
|
default: '400px', |
||||
|
}, |
||||
|
}, |
||||
|
setup(props) { |
||||
|
const chartRef = ref<HTMLDivElement | null>(null); |
||||
|
const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); |
||||
|
watch( |
||||
|
() => props.loading, |
||||
|
() => { |
||||
|
if (props.loading) { |
||||
|
return; |
||||
|
} |
||||
|
setOptions({ |
||||
|
backgroundColor: '#fff', |
||||
|
legend: { |
||||
|
bottom: 0, |
||||
|
data: ['Visits', 'Sales'], |
||||
|
}, |
||||
|
tooltip: {}, |
||||
|
radar: { |
||||
|
radius: '60%', |
||||
|
splitNumber: 8, |
||||
|
indicator: [ |
||||
|
{ |
||||
|
text: '2017', |
||||
|
max: 100, |
||||
|
}, |
||||
|
{ |
||||
|
text: '2017', |
||||
|
max: 100, |
||||
|
}, |
||||
|
{ |
||||
|
text: '2018', |
||||
|
max: 100, |
||||
|
}, |
||||
|
{ |
||||
|
text: '2019', |
||||
|
max: 100, |
||||
|
}, |
||||
|
{ |
||||
|
text: '2020', |
||||
|
max: 100, |
||||
|
}, |
||||
|
{ |
||||
|
text: '2021', |
||||
|
max: 100, |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
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: '#9f8ed7', |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
value: [70, 75, 70, 76, 20, 85], |
||||
|
name: 'Sales', |
||||
|
itemStyle: { |
||||
|
color: '#1edec5', |
||||
|
}, |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
], |
||||
|
}); |
||||
|
}, |
||||
|
{ immediate: true } |
||||
|
); |
||||
|
return { chartRef }; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||