mirror of https://github.com/openspug/spug
add module
parent
87baca7f26
commit
3a0aa86797
|
@ -201,6 +201,7 @@ def handle_user_info(user, x_real_ip):
|
||||||
History.objects.create(user=user, ip=x_real_ip)
|
History.objects.create(user=user, ip=x_real_ip)
|
||||||
verify_ip = AppSetting.get_default('verify_ip', True)
|
verify_ip = AppSetting.get_default('verify_ip', True)
|
||||||
return json_response({
|
return json_response({
|
||||||
|
'id': user.id,
|
||||||
'access_token': user.access_token,
|
'access_token': user.access_token,
|
||||||
'nickname': user.nickname,
|
'nickname': user.nickname,
|
||||||
'is_supper': user.is_supper,
|
'is_supper': user.is_supper,
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Copyright: (c) OpenSpug Organization. https://github.com/openspug/spug
|
||||||
|
# Copyright: (c) <spug.dev@gmail.com>
|
||||||
|
# Released under the AGPL-3.0 License.
|
|
@ -0,0 +1,24 @@
|
||||||
|
# Copyright: (c) OpenSpug Organization. https://github.com/openspug/spug
|
||||||
|
# Copyright: (c) <spug.dev@gmail.com>
|
||||||
|
# Released under the AGPL-3.0 License.
|
||||||
|
from django.db import models
|
||||||
|
from libs.mixins import ModelMixin
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class Notice(models.Model, ModelMixin):
|
||||||
|
title = models.CharField(max_length=100)
|
||||||
|
content = models.TextField()
|
||||||
|
is_stress = models.BooleanField(default=False)
|
||||||
|
read_ids = models.TextField(default='[]')
|
||||||
|
sort_id = models.IntegerField(default=0, db_index=True)
|
||||||
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
|
def to_view(self):
|
||||||
|
tmp = self.to_dict()
|
||||||
|
tmp['read_ids'] = json.loads(self.read_ids)
|
||||||
|
return tmp
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
db_table = 'notices'
|
||||||
|
ordering = ('-sort_id',)
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Copyright: (c) OpenSpug Organization. https://github.com/openspug/spug
|
||||||
|
# Copyright: (c) <spug.dev@gmail.com>
|
||||||
|
# Released under the AGPL-3.0 License.
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
from .views import *
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('', NoticeView.as_view()),
|
||||||
|
]
|
|
@ -0,0 +1,64 @@
|
||||||
|
# Copyright: (c) OpenSpug Organization. https://github.com/openspug/spug
|
||||||
|
# Copyright: (c) <spug.dev@gmail.com>
|
||||||
|
# Released under the AGPL-3.0 License.
|
||||||
|
from django.views.generic import View
|
||||||
|
from libs import json_response, JsonParser, Argument
|
||||||
|
from apps.notice.models import Notice
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class NoticeView(View):
|
||||||
|
def get(self, request):
|
||||||
|
notices = Notice.objects.all()
|
||||||
|
return json_response([x.to_view() for x in notices])
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
form, error = JsonParser(
|
||||||
|
Argument('id', type=int, required=False),
|
||||||
|
Argument('title', help='请输入标题'),
|
||||||
|
Argument('content', help='请输入内容'),
|
||||||
|
Argument('is_stress', type=bool, default=False),
|
||||||
|
).parse(request.body)
|
||||||
|
if error is None:
|
||||||
|
if form.is_stress:
|
||||||
|
Notice.objects.update(is_stress=False)
|
||||||
|
if form.id:
|
||||||
|
Notice.objects.filter(pk=form.id).update(**form)
|
||||||
|
else:
|
||||||
|
notice = Notice.objects.create(**form)
|
||||||
|
notice.sort_id = notice.id
|
||||||
|
notice.save()
|
||||||
|
return json_response(error=error)
|
||||||
|
|
||||||
|
def patch(self, request):
|
||||||
|
form, error = JsonParser(
|
||||||
|
Argument('id', type=int, help='参数错误'),
|
||||||
|
Argument('sort', filter=lambda x: x in ('up', 'down'), required=False),
|
||||||
|
Argument('read', required=False)
|
||||||
|
).parse(request.body)
|
||||||
|
if error is None:
|
||||||
|
notice = Notice.objects.filter(pk=form.id).first()
|
||||||
|
if not notice:
|
||||||
|
return json_response(error='未找到指定记录')
|
||||||
|
if form.sort:
|
||||||
|
if form.sort == 'up':
|
||||||
|
tmp = Notice.objects.filter(sort_id__gt=notice.sort_id).last()
|
||||||
|
else:
|
||||||
|
tmp = Notice.objects.filter(sort_id__lt=notice.sort_id).first()
|
||||||
|
if tmp:
|
||||||
|
tmp.sort_id, notice.sort_id = notice.sort_id, tmp.sort_id
|
||||||
|
tmp.save()
|
||||||
|
if form.read:
|
||||||
|
read_ids = json.loads(notice.read_ids)
|
||||||
|
read_ids.append(str(request.user.id))
|
||||||
|
notice.read_ids = json.dumps(read_ids)
|
||||||
|
notice.save()
|
||||||
|
return json_response(error=error)
|
||||||
|
|
||||||
|
def delete(self, request):
|
||||||
|
form, error = JsonParser(
|
||||||
|
Argument('id', type=int, help='参数错误')
|
||||||
|
).parse(request.GET)
|
||||||
|
if error is None:
|
||||||
|
Notice.objects.filter(pk=form.id).delete()
|
||||||
|
return json_response(error=error)
|
|
@ -47,6 +47,7 @@ INSTALLED_APPS = [
|
||||||
'apps.deploy',
|
'apps.deploy',
|
||||||
'apps.notify',
|
'apps.notify',
|
||||||
'apps.repository',
|
'apps.repository',
|
||||||
|
'apps.notice',
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
|
|
@ -33,5 +33,6 @@ urlpatterns = [
|
||||||
path('home/', include('apps.home.urls')),
|
path('home/', include('apps.home.urls')),
|
||||||
path('notify/', include('apps.notify.urls')),
|
path('notify/', include('apps.notify.urls')),
|
||||||
path('file/', include('apps.file.urls')),
|
path('file/', include('apps.file.urls')),
|
||||||
|
path('notice/', include('apps.notice.urls')),
|
||||||
path('apis/', include('apps.apis.urls')),
|
path('apis/', include('apps.apis.urls')),
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) OpenSpug Organization. https://github.com/openspug/spug
|
||||||
|
* Copyright (c) <spug.dev@gmail.com>
|
||||||
|
* Released under the AGPL-3.0 License.
|
||||||
|
*/
|
||||||
|
import React from 'react';
|
||||||
|
import { Row, Col } from 'antd';
|
||||||
|
import { AuthDiv } from 'components';
|
||||||
|
import StatisticsCard from './StatisticCard';
|
||||||
|
import AlarmTrend from './AlarmTrend';
|
||||||
|
import RequestTop from './RequestTop';
|
||||||
|
import LoginActive from './LoginActive';
|
||||||
|
|
||||||
|
class HomeIndex extends React.Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<AuthDiv auth="home.home.view">
|
||||||
|
<StatisticsCard/>
|
||||||
|
<AlarmTrend/>
|
||||||
|
<Row style={{marginTop: 20}}>
|
||||||
|
<Col span={13}>
|
||||||
|
<RequestTop/>
|
||||||
|
</Col>
|
||||||
|
<Col span={10} offset={1}>
|
||||||
|
<LoginActive/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</AuthDiv>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HomeIndex
|
|
@ -0,0 +1,30 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Avatar, Button, Card, Col, Row } from 'antd';
|
||||||
|
import styles from './index.module.less';
|
||||||
|
|
||||||
|
function NavIndex(props) {
|
||||||
|
return (
|
||||||
|
<Card title="便捷导航" className={styles.nav} extra={<Button type="link">编辑</Button>}>
|
||||||
|
<Row gutter={24}>
|
||||||
|
<Col span={6}>
|
||||||
|
<Card>
|
||||||
|
<Card.Meta
|
||||||
|
avatar={<Avatar src="https://gitee.com/openspug/index/raw/master/img/gitlab.png"/>}
|
||||||
|
title="Gitlab"
|
||||||
|
description="Gitlab 内部代码仓库,请使用公司LDAP账户登录"/>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
<Col span={6}>
|
||||||
|
<Card>
|
||||||
|
<Card.Meta
|
||||||
|
avatar={<Avatar src="https://gitee.com/openspug/index/raw/master/img/wiki.png"/>}
|
||||||
|
title="Wiki系统"
|
||||||
|
description="文档系统,技术架构及技术文档"/>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NavIndex
|
|
@ -0,0 +1,121 @@
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { Button, Card, List, Modal, Form, Input, Switch, Divider, Badge } from 'antd';
|
||||||
|
import { DownSquareOutlined, PlusOutlined, UpSquareOutlined } from '@ant-design/icons';
|
||||||
|
import { http } from 'libs';
|
||||||
|
import styles from "./index.module.less";
|
||||||
|
|
||||||
|
function NoticeIndex(props) {
|
||||||
|
const id = localStorage.getItem('id');
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const [fetching, setFetching] = useState(true);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [isEdit, setIsEdit] = useState(false);
|
||||||
|
const [records, setRecords] = useState([]);
|
||||||
|
const [record, setRecord] = useState();
|
||||||
|
const [notice, setNotice] = useState();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetch()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
function fetch() {
|
||||||
|
setFetching(true);
|
||||||
|
http.get('/api/notice/')
|
||||||
|
.then(res => setRecords(res))
|
||||||
|
.finally(() => setFetching(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSubmit() {
|
||||||
|
setLoading(true);
|
||||||
|
const formData = form.getFieldsValue();
|
||||||
|
formData['id'] = record.id;
|
||||||
|
http.post('/api/notice/', formData)
|
||||||
|
.then(() => {
|
||||||
|
fetch()
|
||||||
|
setRecord(null)
|
||||||
|
})
|
||||||
|
.finally(() => setLoading(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
function showForm(info) {
|
||||||
|
setRecord(info);
|
||||||
|
setTimeout(() => form.resetFields())
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSort(e, info, sort) {
|
||||||
|
e.stopPropagation();
|
||||||
|
http.patch('/api/notice/', {id: info.id, sort})
|
||||||
|
.then(() => fetch())
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleRead() {
|
||||||
|
if (!notice.read_ids.includes(id)) {
|
||||||
|
const formData = {id: notice.id, read: 1};
|
||||||
|
http.patch('/api/notice/', formData)
|
||||||
|
.then(() => fetch())
|
||||||
|
}
|
||||||
|
setNotice(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
title="系统公告"
|
||||||
|
loading={fetching}
|
||||||
|
className={styles.notice}
|
||||||
|
extra={<Button type="link" onClick={() => setIsEdit(!isEdit)}>{isEdit ? '完成' : '编辑'}</Button>}>
|
||||||
|
{isEdit ? (
|
||||||
|
<List>
|
||||||
|
<div className={styles.add} onClick={() => showForm({})}><PlusOutlined/>新建公告</div>
|
||||||
|
{records.map(item => (
|
||||||
|
<List.Item key={item.id} onClick={() => showForm(item)}>
|
||||||
|
<div className={styles.item}>
|
||||||
|
<UpSquareOutlined onClick={e => handleSort(e, item, 'up')}/>
|
||||||
|
<Divider type="vertical"/>
|
||||||
|
<DownSquareOutlined onClick={e => handleSort(e, item, 'down')}/>
|
||||||
|
<span className={styles.title} style={{marginLeft: 24}}>{item.title}</span>
|
||||||
|
</div>
|
||||||
|
</List.Item>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
) : (
|
||||||
|
<List>
|
||||||
|
{records.map(item => (
|
||||||
|
<List.Item key={item.id} onClick={() => setNotice(item)}>
|
||||||
|
<Badge dot={!item.read_ids.includes(id)}><span className={styles.title}>{item.title}</span></Badge>
|
||||||
|
<span style={{fontSize: 12, color: '#999'}}>{item.created_at.substr(0, 10)}</span>
|
||||||
|
</List.Item>
|
||||||
|
))}
|
||||||
|
{records.length === 0 && (
|
||||||
|
<div style={{marginTop: 12, color: '#999'}}>暂无公告信息</div>
|
||||||
|
)}
|
||||||
|
</List>
|
||||||
|
)}
|
||||||
|
<Modal
|
||||||
|
title="编辑公告"
|
||||||
|
visible={record}
|
||||||
|
afterClose={() => console.log('after close')}
|
||||||
|
onCancel={() => setRecord(null)}
|
||||||
|
confirmLoading={loading}
|
||||||
|
onOk={handleSubmit}>
|
||||||
|
<Form form={form} initialValues={record} labelCol={{span: 5}} wrapperCol={{span: 18}}>
|
||||||
|
<Form.Item name="is_stress" valuePropName="checked" tooltip="自动弹窗强提醒,仅能设置一条公告。" label="弹窗提醒">
|
||||||
|
<Switch checkedChildren="开启" unCheckedChildren="关闭"/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item required name="title" label="公告标题">
|
||||||
|
<Input placeholder="请输入"/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item required name="content" tooltip="" label="公告内容">
|
||||||
|
<Input.TextArea placeholder="请输入"/>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
{notice ? (
|
||||||
|
<Modal title={notice.title} visible={notice} footer={null} onCancel={handleRead}>
|
||||||
|
{notice.content}
|
||||||
|
</Modal>
|
||||||
|
) : null}
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NoticeIndex
|
|
@ -0,0 +1,15 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Button, Card, List } from 'antd';
|
||||||
|
|
||||||
|
function TodoIndex(props) {
|
||||||
|
return (
|
||||||
|
<Card title="待办事项" bodyStyle={{height: 220, padding: '0 24px'}}>
|
||||||
|
<List>
|
||||||
|
<List.Item extra={<Button type="link">已完成</Button>}>发布申请 测试未附件 需要你审核。</List.Item>
|
||||||
|
<List.Item>工单 资源添加 需要你审核。</List.Item>
|
||||||
|
</List>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TodoIndex
|
|
@ -1,33 +1,28 @@
|
||||||
/**
|
|
||||||
* Copyright (c) OpenSpug Organization. https://github.com/openspug/spug
|
|
||||||
* Copyright (c) <spug.dev@gmail.com>
|
|
||||||
* Released under the AGPL-3.0 License.
|
|
||||||
*/
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Row, Col } from 'antd';
|
import { Row, Col } from 'antd';
|
||||||
import { AuthDiv } from 'components';
|
import { Breadcrumb } from 'components';
|
||||||
import StatisticsCard from './StatisticCard';
|
import NoticeIndex from './Notice';
|
||||||
import AlarmTrend from './AlarmTrend';
|
import TodoIndex from './Todo';
|
||||||
import RequestTop from './RequestTop';
|
import NavIndex from './Nav';
|
||||||
import LoginActive from './LoginActive';
|
|
||||||
|
|
||||||
class HomeIndex extends React.Component {
|
function HomeIndex() {
|
||||||
render() {
|
return (
|
||||||
return (
|
<div>
|
||||||
<AuthDiv auth="home.home.view">
|
<Breadcrumb>
|
||||||
<StatisticsCard/>
|
<Breadcrumb.Item>首页</Breadcrumb.Item>
|
||||||
<AlarmTrend/>
|
<Breadcrumb.Item>工作台</Breadcrumb.Item>
|
||||||
<Row style={{marginTop: 20}}>
|
</Breadcrumb>
|
||||||
<Col span={13}>
|
<Row gutter={12}>
|
||||||
<RequestTop/>
|
<Col span={16}>
|
||||||
</Col>
|
<TodoIndex/>
|
||||||
<Col span={10} offset={1}>
|
</Col>
|
||||||
<LoginActive/>
|
<Col span={8}>
|
||||||
</Col>
|
<NoticeIndex/>
|
||||||
</Row>
|
</Col>
|
||||||
</AuthDiv>
|
</Row>
|
||||||
)
|
<NavIndex/>
|
||||||
}
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default HomeIndex
|
export default HomeIndex
|
|
@ -0,0 +1,69 @@
|
||||||
|
.notice {
|
||||||
|
:global(.ant-card-body) {
|
||||||
|
height: 220px;
|
||||||
|
padding: 0 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
cursor: pointer;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.title:hover {
|
||||||
|
color: #1890ff
|
||||||
|
}
|
||||||
|
|
||||||
|
.add {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 8px;
|
||||||
|
height: 30px;
|
||||||
|
border-radius: 2px;
|
||||||
|
border: 1px dashed #d9d9d9;
|
||||||
|
font-size: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add:hover {
|
||||||
|
border: 1px dashed #1890ff;
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
:global(.anticon) {
|
||||||
|
cursor: pointer;
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav {
|
||||||
|
margin-top: 12px;
|
||||||
|
|
||||||
|
:global(.ant-card) {
|
||||||
|
height: 120px;
|
||||||
|
background-color: #fafafa;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
:global(.ant-card-meta-description) {
|
||||||
|
display: -webkit-box;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -64,6 +64,7 @@ export default function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
function doLogin(data) {
|
function doLogin(data) {
|
||||||
|
localStorage.setItem('id', data['id']);
|
||||||
localStorage.setItem('token', data['access_token']);
|
localStorage.setItem('token', data['access_token']);
|
||||||
localStorage.setItem('nickname', data['nickname']);
|
localStorage.setItem('nickname', data['nickname']);
|
||||||
localStorage.setItem('is_supper', data['is_supper']);
|
localStorage.setItem('is_supper', data['is_supper']);
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {
|
import {
|
||||||
|
DashboardOutlined,
|
||||||
DesktopOutlined,
|
DesktopOutlined,
|
||||||
CloudServerOutlined,
|
CloudServerOutlined,
|
||||||
CodeOutlined,
|
CodeOutlined,
|
||||||
|
@ -15,41 +16,41 @@ import {
|
||||||
AlertOutlined,
|
AlertOutlined,
|
||||||
SettingOutlined
|
SettingOutlined
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
|
|
||||||
import HomeIndex from './pages/home';
|
import HomeIndex from './pages/home';
|
||||||
|
import DashboardIndex from './pages/dashboard';
|
||||||
import HostIndex from './pages/host';
|
import HostIndex from './pages/host';
|
||||||
|
|
||||||
import ExecTask from './pages/exec/task';
|
import ExecTask from './pages/exec/task';
|
||||||
import ExecTemplate from './pages/exec/template';
|
import ExecTemplate from './pages/exec/template';
|
||||||
|
|
||||||
import DeployApp from './pages/deploy/app';
|
import DeployApp from './pages/deploy/app';
|
||||||
import DeployRepository from './pages/deploy/repository';
|
import DeployRepository from './pages/deploy/repository';
|
||||||
import DeployRequest from './pages/deploy/request';
|
import DeployRequest from './pages/deploy/request';
|
||||||
import DoExt1Index from './pages/deploy/do/Ext1Index';
|
import DoExt1Index from './pages/deploy/do/Ext1Index';
|
||||||
import DoExt2Index from './pages/deploy/do/Ext2Index';
|
import DoExt2Index from './pages/deploy/do/Ext2Index';
|
||||||
|
|
||||||
import ScheduleIndex from './pages/schedule';
|
import ScheduleIndex from './pages/schedule';
|
||||||
|
|
||||||
import ConfigEnvironment from './pages/config/environment';
|
import ConfigEnvironment from './pages/config/environment';
|
||||||
import ConfigService from './pages/config/service';
|
import ConfigService from './pages/config/service';
|
||||||
import ConfigApp from './pages/config/app';
|
import ConfigApp from './pages/config/app';
|
||||||
import ConfigSetting from './pages/config/setting';
|
import ConfigSetting from './pages/config/setting';
|
||||||
|
|
||||||
import MonitorIndex from './pages/monitor';
|
import MonitorIndex from './pages/monitor';
|
||||||
|
|
||||||
import AlarmIndex from './pages/alarm/alarm';
|
import AlarmIndex from './pages/alarm/alarm';
|
||||||
import AlarmGroup from './pages/alarm/group';
|
import AlarmGroup from './pages/alarm/group';
|
||||||
import AlarmContact from './pages/alarm/contact';
|
import AlarmContact from './pages/alarm/contact';
|
||||||
|
|
||||||
import SystemAccount from './pages/system/account';
|
import SystemAccount from './pages/system/account';
|
||||||
import SystemRole from './pages/system/role';
|
import SystemRole from './pages/system/role';
|
||||||
import SystemSetting from './pages/system/setting';
|
import SystemSetting from './pages/system/setting';
|
||||||
|
|
||||||
import WelcomeIndex from './pages/welcome/index';
|
import WelcomeIndex from './pages/welcome/index';
|
||||||
import WelcomeInfo from './pages/welcome/info';
|
import WelcomeInfo from './pages/welcome/info';
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
{icon: <DesktopOutlined/>, title: '工作台', auth: 'home.home.view', path: '/home', component: HomeIndex},
|
{icon: <DesktopOutlined/>, title: '工作台', auth: 'home.home.view', path: '/home', component: HomeIndex},
|
||||||
|
{
|
||||||
|
icon: <DashboardOutlined/>,
|
||||||
|
title: 'Dashboard',
|
||||||
|
auth: 'home.home.view',
|
||||||
|
path: '/dashboard',
|
||||||
|
component: DashboardIndex
|
||||||
|
},
|
||||||
{icon: <CloudServerOutlined/>, title: '主机管理', auth: 'host.host.view', path: '/host', component: HostIndex},
|
{icon: <CloudServerOutlined/>, title: '主机管理', auth: 'host.host.view', path: '/host', component: HostIndex},
|
||||||
{
|
{
|
||||||
icon: <CodeOutlined/>, title: '批量执行', auth: 'exec.task.do|exec.template.view', child: [
|
icon: <CodeOutlined/>, title: '批量执行', auth: 'exec.task.do|exec.template.view', child: [
|
||||||
|
|
Loading…
Reference in New Issue