feat(workbench): add workbench page
| | |
| | | return; |
| | | } |
| | | chartInstanceRef.value = null; |
| | | chartInstance.destroy(); |
| | | }); |
| | | return { |
| | | setOptions, |
| | |
| | | path: '/dashboard', |
| | | children: [ |
| | | { |
| | | path: '/workbench', |
| | | name: '工作台', |
| | | }, |
| | | { |
| | | path: '/welcome', |
| | | name: '欢迎页', |
| | | name: '首页', |
| | | }, |
| | | ], |
| | | }, |
| | |
| | | path: '/dashboard', |
| | | name: 'Dashboard', |
| | | component: PAGE_LAYOUT_COMPONENT, |
| | | redirect: '/dashboard/welcome', |
| | | redirect: '/dashboard/workbench', |
| | | meta: { |
| | | icon: 'ant-design:home-outlined', |
| | | title: 'Dashboard', |
| | |
| | | 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, |
| | | }, |
| | | }, |
New file |
| | |
| | | <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 }} </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 { 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> |
New file |
| | |
| | | <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> |
New file |
| | |
| | | <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> |
New file |
| | |
| | | <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> |
New file |
| | |
| | | <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> |
New file |
| | |
| | | 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; |
| | | })(); |
New file |
| | |
| | | <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> |