From 73232d9e661c53775c9dffa242cbce77f44bf906 Mon Sep 17 00:00:00 2001 From: vapao Date: Mon, 29 Mar 2021 10:48:07 +0800 Subject: [PATCH] fix issue --- spug_api/apps/home/models.py | 18 +++++ spug_api/apps/home/navigation.py | 59 ++++++++++++++++ spug_api/apps/home/urls.py | 2 + spug_web/src/pages/home/Nav.js | 85 +++++++++++++++-------- spug_web/src/pages/home/NavForm.js | 49 +++++++++++-- spug_web/src/pages/home/Notice.js | 11 +-- spug_web/src/pages/home/Todo.js | 5 +- spug_web/src/pages/home/index.module.less | 6 +- 8 files changed, 191 insertions(+), 44 deletions(-) create mode 100644 spug_api/apps/home/navigation.py diff --git a/spug_api/apps/home/models.py b/spug_api/apps/home/models.py index 4cd0faa..30aabd8 100644 --- a/spug_api/apps/home/models.py +++ b/spug_api/apps/home/models.py @@ -22,3 +22,21 @@ class Notice(models.Model, ModelMixin): class Meta: db_table = 'notices' ordering = ('-sort_id',) + + +class Navigation(models.Model, ModelMixin): + title = models.CharField(max_length=64) + desc = models.CharField(max_length=128) + logo = models.TextField() + links = models.TextField() + 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['links'] = json.loads(self.links) + return tmp + + class Meta: + db_table = 'navigations' + ordering = ('-sort_id',) diff --git a/spug_api/apps/home/navigation.py b/spug_api/apps/home/navigation.py new file mode 100644 index 0000000..bf28df8 --- /dev/null +++ b/spug_api/apps/home/navigation.py @@ -0,0 +1,59 @@ +# Copyright: (c) OpenSpug Organization. https://github.com/openspug/spug +# Copyright: (c) +# Released under the AGPL-3.0 License. +from django.views.generic import View +from libs import json_response, JsonParser, Argument +from apps.home.models import Navigation +import json + + +class NavView(View): + def get(self, request): + navs = Navigation.objects.all() + return json_response([x.to_view() for x in navs]) + + def post(self, request): + form, error = JsonParser( + Argument('id', type=int, required=False), + Argument('title', help='请输入导航标题'), + Argument('desc', help='请输入导航描述'), + Argument('logo', help='请上传导航logo'), + Argument('links', type=list, filter=lambda x: len(x), help='请设置导航链接'), + ).parse(request.body) + if error is None: + form.links = json.dumps(form.links) + if form.id: + Navigation.objects.filter(pk=form.id).update(**form) + else: + nav = Navigation.objects.create(**form) + nav.sort_id = nav.id + nav.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), + ).parse(request.body) + if error is None: + nav = Navigation.objects.filter(pk=form.id).first() + if not nav: + return json_response(error='未找到指定记录') + if form.sort: + if form.sort == 'up': + tmp = Navigation.objects.filter(sort_id__gt=nav.sort_id).last() + else: + tmp = Navigation.objects.filter(sort_id__lt=nav.sort_id).first() + if tmp: + tmp.sort_id, nav.sort_id = nav.sort_id, tmp.sort_id + tmp.save() + nav.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: + Navigation.objects.filter(pk=form.id).delete() + return json_response(error=error) diff --git a/spug_api/apps/home/urls.py b/spug_api/apps/home/urls.py index bfb22df..138ca0e 100644 --- a/spug_api/apps/home/urls.py +++ b/spug_api/apps/home/urls.py @@ -5,6 +5,7 @@ from django.urls import path from .views import * from apps.home.notice import NoticeView +from apps.home.navigation import NavView urlpatterns = [ path('statistic/', get_statistic), @@ -12,4 +13,5 @@ urlpatterns = [ path('deploy/', get_deploy), path('request/', get_request), path('notice/', NoticeView.as_view()), + path('navigation/', NavView.as_view()), ] diff --git a/spug_web/src/pages/home/Nav.js b/spug_web/src/pages/home/Nav.js index 4ebe92d..b3487ca 100644 --- a/spug_web/src/pages/home/Nav.js +++ b/spug_web/src/pages/home/Nav.js @@ -7,54 +7,79 @@ import React, { useState, useEffect } from 'react'; import { Avatar, Button, Card, Col, Row } from 'antd'; import { LeftSquareOutlined, RightSquareOutlined, EditOutlined, PlusOutlined } from '@ant-design/icons'; import NavForm from './NavForm'; +import { http } from 'libs'; import styles from './index.module.less'; function NavIndex(props) { - const [isEdit, setIsEdit] = useState(true); + const [isEdit, setIsEdit] = useState(false); + const [records, setRecords] = useState([]); const [record, setRecord] = useState(); - function handleSubmit() { + useEffect(() => { + fetchRecords() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + function fetchRecords() { + http.get('/api/home/navigation/') + .then(res => setRecords(res)) + } + + function handleSubmit() { + fetchRecords(); + setRecord(null) + } + + function handleSort(info, sort) { + http.patch('/api/home/navigation/', {id: info.id, sort}) + .then(() => fetchRecords()) } return ( - 编辑}> + setIsEdit(!isEdit)}>{isEdit ? '完成' : '编辑'}}> {isEdit ? ( -
setRecord({links: [{}]})}>
+
setRecord({links: [{}]})}> + + 新建 +
+ {records.map(item => ( + + handleSort(item, 'up')}/>, + handleSort(item, 'down')}/>, + setRecord(item)}/> + ]}> + } + title={item.title} + description={item.desc}/> + + + ))}
) : ( - -
- - - 演示地址 - ]}> - } - title="Gitlab" - description="Gitlab 内部代码仓库,请使用公司LDAP账户登录"/> - - - - , - , - - ]}> - } - title="Wiki系统" - description="文档系统,技术架构及技术文档"/> - - + {records.map(item => ( + + {x.name})}> + } + title={item.title} + description={item.desc}/> + + + ))}
)} - {record ? setRecord(null)}/> : null} + {record ? setRecord(null)} onOk={handleSubmit}/> : null}
) } diff --git a/spug_web/src/pages/home/NavForm.js b/spug_web/src/pages/home/NavForm.js index c3aed6e..6451ac4 100644 --- a/spug_web/src/pages/home/NavForm.js +++ b/spug_web/src/pages/home/NavForm.js @@ -3,9 +3,10 @@ * Copyright (c) * Released under the AGPL-3.0 License. */ -import React, { useState } from 'react'; -import { Form, Input, Modal, Button } from 'antd'; +import React, { useState, useEffect } from 'react'; +import { Form, Input, Modal, Button, Upload, message } from 'antd'; import { PlusOutlined, MinusCircleOutlined } from '@ant-design/icons'; +import { http } from 'libs'; import styles from './index.module.less'; import lds from 'lodash'; @@ -13,10 +14,27 @@ function NavForm(props) { const [form] = Form.useForm(); const [loading, setLoading] = useState(false); const [record, setRecord] = useState(props.record); + const [fileList, setFileList] = useState([]); + + useEffect(() => { + if (props.record.logo) { + setFileList([{uid: 0, thumbUrl: props.record.logo}]) + } + }, [props.record]) function handleSubmit() { const formData = form.getFieldsValue(); - console.log(formData) + const links = record.links.filter(x => x.name && x.url); + if (links.length === 0) return message.error('请设置至少一条导航链接'); + if (fileList.length === 0) return message.error('请上传导航logo'); + formData.id = record.id; + formData.links = links; + formData.logo = fileList[0].thumbUrl; + setLoading(true); + http.post('/api/home/navigation/', formData) + .then(() => { + props.onOk(); + }, () => setLoading(false)) } function add() { @@ -34,15 +52,38 @@ function NavForm(props) { setRecord(lds.cloneDeep(record)) } + function beforeUpload(file) { + if (file.size / 1024 > 100) { + message.error('图片将直接存储至数据库,请上传小于100KB的图片'); + setTimeout(() => setFileList([])) + } + return false + } + return ( console.log('after close')} onCancel={props.onCancel} confirmLoading={loading} onOk={handleSubmit}>
+ + setFileList(fileList)}> + {fileList.length === 0 && ( +
+ +
点击上传
+
+ )} +
+
diff --git a/spug_web/src/pages/home/Notice.js b/spug_web/src/pages/home/Notice.js index 0710421..2caa415 100644 --- a/spug_web/src/pages/home/Notice.js +++ b/spug_web/src/pages/home/Notice.js @@ -20,10 +20,11 @@ function NoticeIndex(props) { const [notice, setNotice] = useState(); useEffect(() => { - fetch() + fetchRecords() + // eslint-disable-next-line react-hooks/exhaustive-deps }, []) - function fetch() { + function fetchRecords() { setFetching(true); http.get('/api/home/notice/') .then(res => { @@ -43,7 +44,7 @@ function NoticeIndex(props) { formData['id'] = record.id; http.post('/api/home/notice/', formData) .then(() => { - fetch() + fetchRecords() setRecord(null) }) .finally(() => setLoading(false)) @@ -57,14 +58,14 @@ function NoticeIndex(props) { function handleSort(e, info, sort) { e.stopPropagation(); http.patch('/api/home/notice/', {id: info.id, sort}) - .then(() => fetch()) + .then(() => fetchRecords()) } function handleRead() { if (!notice.read_ids.includes(id)) { const formData = {id: notice.id, read: 1}; http.patch('/api/home/notice/', formData) - .then(() => fetch()) + .then(() => fetchRecords()) } setNotice(null); } diff --git a/spug_web/src/pages/home/Todo.js b/spug_web/src/pages/home/Todo.js index d718e39..88b4d04 100644 --- a/spug_web/src/pages/home/Todo.js +++ b/spug_web/src/pages/home/Todo.js @@ -4,14 +4,13 @@ * Released under the AGPL-3.0 License. */ import React from 'react'; -import { Button, Card, List } from 'antd'; +import { Card, List } from 'antd'; function TodoIndex(props) { return ( - 已完成}>发布申请 测试未附件 需要你审核。 - 工单 资源添加 需要你审核。 + 工单 ECS购买 需要你审核。 ) diff --git a/spug_web/src/pages/home/index.module.less b/spug_web/src/pages/home/index.module.less index c0cfa7c..cbb8042 100644 --- a/spug_web/src/pages/home/index.module.less +++ b/spug_web/src/pages/home/index.module.less @@ -68,6 +68,7 @@ height: 166px; border: 1px dashed #d9d9d9; display: flex; + flex-direction: column; justify-content: center; align-items: center; } @@ -79,13 +80,14 @@ :global(.ant-card) { height: 166px; - background-color: #fafafa; + background-color: #fdfdfd; :global(.ant-card-actions) { - background-color: #f0f0f0; + background-color: #fafafa; } :global(.ant-card-meta-description) { + height: 44px; display: -webkit-box; text-overflow: ellipsis; overflow: hidden;