提交 1cd75fcf 编写于 作者: V vben

feat(workbench): add workbench page

上级 21d0ed92
......@@ -30,6 +30,7 @@ export function useApexCharts(elRef: Ref<HTMLDivElement>) {
return;
}
chartInstanceRef.value = null;
chartInstance.destroy();
});
return {
setOptions,
......
......@@ -5,9 +5,13 @@ const menu: MenuModule = {
name: 'Dashboard',
path: '/dashboard',
children: [
{
path: '/workbench',
name: '工作台',
},
{
path: '/welcome',
name: '欢迎',
name: '',
},
],
},
......
......@@ -7,7 +7,7 @@ export default {
path: '/dashboard',
name: 'Dashboard',
component: PAGE_LAYOUT_COMPONENT,
redirect: '/dashboard/welcome',
redirect: '/dashboard/workbench',
meta: {
icon: 'ant-design:home-outlined',
title: 'Dashboard',
......@@ -20,7 +20,15 @@ export default {
name: 'Welcome',
component: () => import('/@/views/dashboard/welcome/index.vue'),
meta: {
title: '欢迎页',
title: '首页',
},
},
{
path: '/workbench',
name: 'Workbench',
component: () => import('/@/views/dashboard/workbench/index.vue'),
meta: {
title: '工作台',
affix: true,
},
},
......
<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="/@/assets/images/header.jpg" 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 }}&nbsp;</span>申请迭代
<span class="news-list__item-light">&nbsp;{{ item.title }}&nbsp;</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 { newList } from '../data';
export default defineComponent({
components: {
List,
ListItem: List.Item,
ListItemMeta: List.Item.Meta,
CollapseContainer,
ScrollContainer,
},
setup() {
return { newList };
},
});
</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: #2c3a61;
}
}
}
}
</style>
<template>
<Row class="prod-total">
<template v-for="(item, index) in wokbProd" :key="item.type">
<Col :xs="12" :sm="6" class="prod-total__item" :class="`prod-total__item-${index}`">
<div class="img" :class="`prod-total__item-${index}-img`" />
<div>{{ item.amount }}</div>
<span>{{ item.type }}</span>
</Col>
</template>
</Row>
</template>
<script lang="tsx">
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, Col },
setup() {
return { wokbProd };
},
});
</script>
<style lang="less" scoped>
.prod-total {
padding: 12px 4px 12px 12px;
background: #fff;
&__item {
display: inline-block;
width: 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>
<template>
<CollapseContainer class="shortcuts" title="快捷入口" :canExpan="false">
<template #action>
<a-button size="small" type="link"> 新建 </a-button>
</template>
<Row>
<template v-for="item in shortCuts" :key="item.img">
<Col :span="8" class="shortcuts__item p-3">
<img :src="item.img" class="shortcuts__item-img mb-2" />
<br />
<span>{{ item.name }}</span>
</Col>
</template>
<Col :span="8" class="shortcuts__item p-3">
<span class="shortcuts__item-all mb-2">
<RightOutlined />
</span>
<br />
<span>查看全部</span>
</Col>
</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, Col, CollapseContainer, RightOutlined },
setup() {
return { shortCuts };
},
});
</script>
<style lang="less" scoped>
.shortcuts {
&__item {
text-align: center;
&-img {
width: 36px;
}
&-all {
display: inline-block;
width: 36px;
height: 36px;
line-height: 36px;
color: #000;
cursor: pointer;
background: lightgrey;
border-radius: 50%;
}
}
}
</style>
<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>
<template>
<CollapseContainer title="任务安排" :canExpan="false">
<div ref="chartRef" :style="{ width: '100%' }" />
</CollapseContainer>
</template>
<script lang="ts">
import { defineComponent, Ref, ref, onMounted } from 'vue';
import { CollapseContainer } from '/@/components/Container/index';
import { useApexCharts } from '/@/hooks/web/useApexCharts';
import moment from 'moment';
export default defineComponent({
components: { CollapseContainer },
setup() {
const chartRef = ref<HTMLDivElement | null>(null);
const { setOptions } = useApexCharts(chartRef as Ref<HTMLDivElement>);
onMounted(() => {
setOptions({
series: [
{
data: [
{
x: 'Analysis',
y: [new Date('2019-02-27').getTime(), new Date('2019-03-04').getTime()],
fillColor: '#008FFB',
},
{
x: 'Design',
y: [new Date('2019-03-04').getTime(), new Date('2019-03-08').getTime()],
fillColor: '#00E396',
},
{
x: 'Coding',
y: [new Date('2019-03-07').getTime(), new Date('2019-03-10').getTime()],
fillColor: '#775DD0',
},
{
x: 'Testing',
y: [new Date('2019-03-08').getTime(), new Date('2019-03-12').getTime()],
fillColor: '#FEB019',
},
{
x: 'Deployment',
y: [new Date('2019-03-12').getTime(), new Date('2019-03-17').getTime()],
fillColor: '#FF4560',
},
],
},
],
chart: {
height: 350,
type: 'rangeBar',
},
plotOptions: {
bar: {
horizontal: true,
distributed: true,
dataLabels: {
hideOverflowingLabels: false,
},
},
},
dataLabels: {
enabled: true,
formatter: function (val: any, opts: any) {
var label = opts.w.globals.labels[opts.dataPointIndex];
var a = moment(val[0]);
var b = moment(val[1]);
var diff = b.diff(a, 'days');
return label + ': ' + diff + (diff > 1 ? ' days' : ' day');
},
style: {
colors: ['#f3f4f5', '#fff'],
},
},
xaxis: {
type: 'datetime',
},
yaxis: {
show: false,
},
grid: {
row: {
colors: ['#f3f4f5', '#fff'],
opacity: 1,
},
},
});
});
return { chartRef };
},
});
</script>
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;
})();
<template>
<Row class="workbench p-4" :gutter="12">
<Col :md="24" :lg="17">
<ProdTotal class="mb-3" />
<TodoList class="mb-3" />
<NewsList class="mb-3" />
</Col>
<Col :md="24" :lg="7">
<img src="/@/assets/images/dashboard/wokb/wokb.png" class="workbench__wokb-img mb-3" />
<ShortCuts class="mb-3" />
<Week class="mb-3" />
</Col>
</Row>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { Row, Col } from 'ant-design-vue';
import ProdTotal from './components/ProdTotal.vue';
import TodoList from './components/TodoList.vue';
import Week from './components/Week.vue';
import NewsList from './components/NewsList.vue';
import ShortCuts from './components/ShortCuts.vue';
export default defineComponent({
components: { Row, Col, ProdTotal, TodoList, Week, ShortCuts, NewsList },
setup() {
return {};
},
});
</script>
<style lang="less" scoped>
.workbench {
&__wokb-img {
width: 100%;
height: 240px;
}
}
</style>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册