mirror of
https://github.com/QingdaoU/OnlineJudge.git
synced 2025-01-16 01:13:47 +00:00
增加了组内可见的公告,编辑了对应的 models 和 js
This commit is contained in:
parent
016a49a53b
commit
97ffd604cf
26
announcement/migrations/0002_auto_20150818_1445.py
Normal file
26
announcement/migrations/0002_auto_20150818_1445.py
Normal file
@ -0,0 +1,26 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('group', '0004_merge'),
|
||||
('announcement', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='announcement',
|
||||
name='groups',
|
||||
field=models.ManyToManyField(to='group.Group'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='announcement',
|
||||
name='is_global',
|
||||
field=models.BooleanField(default=True),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
@ -2,6 +2,7 @@
|
||||
from django.db import models
|
||||
|
||||
from account.models import User
|
||||
from group.models import Group
|
||||
|
||||
|
||||
class Announcement(models.Model):
|
||||
@ -17,6 +18,9 @@ class Announcement(models.Model):
|
||||
last_update_time = models.DateTimeField(auto_now=True)
|
||||
# 是否可见 false的话相当于删除
|
||||
visible = models.BooleanField(default=True)
|
||||
# 公告可见范围 0是全局可见 1是部分小组可见,需要在下面的字段中存储可见的小组
|
||||
is_global = models.BooleanField()
|
||||
groups = models.ManyToManyField(Group)
|
||||
|
||||
class Meta:
|
||||
db_table = "announcement"
|
||||
|
@ -8,6 +8,8 @@ from .models import Announcement
|
||||
class CreateAnnouncementSerializer(serializers.Serializer):
|
||||
title = serializers.CharField(max_length=50)
|
||||
content = serializers.CharField(max_length=10000)
|
||||
is_global = serializers.BooleanField()
|
||||
groups = serializers.ListField(child=serializers.IntegerField(), allow_empty=True)
|
||||
|
||||
|
||||
class AnnouncementSerializer(serializers.ModelSerializer):
|
||||
@ -28,3 +30,5 @@ class EditAnnouncementSerializer(serializers.Serializer):
|
||||
title = serializers.CharField(max_length=50)
|
||||
content = serializers.CharField(max_length=10000)
|
||||
visible = serializers.BooleanField()
|
||||
is_global = serializers.BooleanField()
|
||||
groups = serializers.ListField(child=serializers.IntegerField())
|
||||
|
@ -5,6 +5,8 @@ from django.shortcuts import render
|
||||
from utils.shortcuts import serializer_invalid_response, error_response, success_response
|
||||
|
||||
from utils.shortcuts import paginate, error_page
|
||||
from account.models import SUPER_ADMIN, ADMIN
|
||||
from group.models import Group
|
||||
from .models import Announcement
|
||||
from .serializers import (CreateAnnouncementSerializer, AnnouncementSerializer,
|
||||
EditAnnouncementSerializer)
|
||||
@ -28,9 +30,26 @@ class AnnouncementAdminAPIView(APIView):
|
||||
serializer = CreateAnnouncementSerializer(data=request.data)
|
||||
if serializer.is_valid():
|
||||
data = serializer.data
|
||||
Announcement.objects.create(title=data["title"],
|
||||
content=data["content"],
|
||||
created_by=request.user)
|
||||
groups = []
|
||||
# 如果不是全局公告,就去查询一下小组的id 列表中的内容,注意用户身份
|
||||
if not data["is_global"]:
|
||||
if request.user.admin_type == SUPER_ADMIN:
|
||||
groups = Group.objects.filter(id__in=data["groups"])
|
||||
else:
|
||||
groups = Group.objects.filter(id__in=data["groups"], admin=request.user)
|
||||
if not groups.count():
|
||||
return error_response(u"至少选择一个小组")
|
||||
else:
|
||||
if request.user.admin_type != SUPER_ADMIN:
|
||||
return error_response(u"只有超级管理员可以创建全局公告")
|
||||
|
||||
announcement = Announcement.objects.create(title=data["title"],
|
||||
content=data["content"],
|
||||
created_by=request.user,
|
||||
is_global=data["is_global"])
|
||||
|
||||
announcement.groups.add(*groups)
|
||||
|
||||
return success_response(u"公告发布成功!")
|
||||
else:
|
||||
return serializer_invalid_response(serializer)
|
||||
@ -46,26 +65,43 @@ class AnnouncementAdminAPIView(APIView):
|
||||
if serializer.is_valid():
|
||||
data = serializer.data
|
||||
try:
|
||||
announcement = Announcement.objects.get(id=data["id"])
|
||||
if request.user.admin_type == SUPER_ADMIN:
|
||||
announcement = Announcement.objects.get(id=data["id"])
|
||||
else:
|
||||
announcement = Announcement.objects.get(id=data["id"], admin=request.user)
|
||||
except Announcement.DoesNotExist:
|
||||
return error_response(u"该公告不存在!")
|
||||
return error_response(u"公告不存在")
|
||||
groups = []
|
||||
if not data["is_global"]:
|
||||
if request.user.admin_type == SUPER_ADMIN:
|
||||
groups = Group.objects.filter(id__in=data["groups"])
|
||||
else:
|
||||
groups = Group.objects.filter(id__in=data["groups"], admin=request.user)
|
||||
if not groups.count():
|
||||
return error_response(u"至少选择一个小组")
|
||||
announcement.title = data["title"]
|
||||
announcement.content = data["content"]
|
||||
announcement.visible = data["visible"]
|
||||
announcement.is_global = data["is_global"]
|
||||
announcement.save()
|
||||
|
||||
# 重建小组和公告的对应关系
|
||||
announcement.groups.clear()
|
||||
announcement.groups.add(*groups)
|
||||
return success_response(AnnouncementSerializer(announcement).data)
|
||||
else:
|
||||
return serializer_invalid_response(serializer)
|
||||
|
||||
|
||||
class AnnouncementAPIView(APIView):
|
||||
def get(self, request):
|
||||
"""
|
||||
公告分页json api接口
|
||||
---
|
||||
response_serializer: AnnouncementSerializer
|
||||
"""
|
||||
announcement = Announcement.objects.all().order_by("-last_update_time")
|
||||
if request.user.admin_type == SUPER_ADMIN:
|
||||
announcement = Announcement.objects.all().order_by("-last_update_time")
|
||||
else:
|
||||
announcement = Announcement.objects.filter(admin=request.user)
|
||||
visible = request.GET.get("visible", None)
|
||||
if visible:
|
||||
announcement = announcement.filter(visible=(visible == "true"))
|
||||
|
@ -6,7 +6,7 @@ from django.views.generic import TemplateView
|
||||
from account.views import (UserLoginAPIView, UsernameCheckAPIView, UserRegisterAPIView,
|
||||
UserChangePasswordAPIView, EmailCheckAPIView,
|
||||
UserAdminAPIView, UserInfoAPIView)
|
||||
from announcement.views import AnnouncementAPIView, AnnouncementAdminAPIView
|
||||
from announcement.views import AnnouncementAdminAPIView
|
||||
|
||||
from group.views import (GroupAdminAPIView, GroupMemberAdminAPIView,
|
||||
JoinGroupAPIView, JoinGroupRequestAdminAPIView)
|
||||
@ -38,7 +38,6 @@ urlpatterns = [
|
||||
url(r'^problem/(?P<problem_id>\d+)/$', "problem.views.problem_page", name="problem_page"),
|
||||
url(r'^announcement/(?P<announcement_id>\d+)/$', "announcement.views.announcement_page",
|
||||
name="announcement_page"),
|
||||
url(r'^api/announcements/$', AnnouncementAPIView.as_view(), name="announcement_list_api"),
|
||||
url(r'^admin/contest/$', TemplateView.as_view(template_name="admin/contest/add_contest.html"),
|
||||
name="add_contest_page"),
|
||||
url(r'^problems/$', "problem.views.problem_list_page", name="problem_list_page"),
|
||||
|
@ -1,8 +1,5 @@
|
||||
require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "validator"],
|
||||
function ($, avalon, csrfTokenHeader, bsAlert, editor) {
|
||||
|
||||
|
||||
|
||||
avalon.ready(function () {
|
||||
avalon.vmodels.announcement = null;
|
||||
|
||||
@ -20,7 +17,11 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "validator"],
|
||||
totalPage: 1, // 总页数
|
||||
showVisibleOnly: false, //仅显示可见公告
|
||||
// 编辑
|
||||
newTitle: "",
|
||||
announcementVisible: 0,
|
||||
showGlobalViewRadio: true,
|
||||
isGlobal: true,
|
||||
allGroups: [],
|
||||
getState: function (el) { //获取公告当前状态,显示
|
||||
if (el.visible)
|
||||
return "可见";
|
||||
@ -47,49 +48,75 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "validator"],
|
||||
|
||||
},
|
||||
editAnnouncement: function (announcement) {
|
||||
$("#newTitle").val(announcement.title);
|
||||
vm.newTitle = announcement.title;
|
||||
editAnnouncementEditor.setValue(announcement.content);
|
||||
vm.announcementVisible = announcement.visible;
|
||||
if (vm.editingAnnouncementId == announcement.id)
|
||||
vm.editingAnnouncementId = 0;
|
||||
else
|
||||
vm.editingAnnouncementId = announcement.id;
|
||||
vm.isGlobal = announcement.is_global;
|
||||
for (var i = 0; i < announcement.groups.length; i++) {
|
||||
for (var j = 0; j < vm.allGroups.length; j++) {
|
||||
if (announcement.groups[i] == vm.allGroups[j].id) {
|
||||
vm.allGroups[j].isSelected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
editAnnouncementEditor.focus();
|
||||
},
|
||||
cancelEdit: function () {
|
||||
vm.editingAnnouncementId = 0;
|
||||
},
|
||||
submitChange: function () {
|
||||
var title = $("#newTitle").val();
|
||||
var title = vm.newTitle;
|
||||
var content = editAnnouncementEditor.getValue();
|
||||
|
||||
if (content && title) {
|
||||
$.ajax({
|
||||
beforeSend: csrfTokenHeader,
|
||||
url: "/api/admin/announcement/",
|
||||
dataType: "json",
|
||||
method: "put",
|
||||
data: {
|
||||
id: vm.editingAnnouncementId,
|
||||
title: title,
|
||||
content: content,
|
||||
visible: vm.announcementVisible
|
||||
},
|
||||
success: function (data) {
|
||||
if (!data.code) {
|
||||
bsAlert("修改成功");
|
||||
vm.editingAnnouncementId = 0;
|
||||
getPageData(1);
|
||||
}
|
||||
else {
|
||||
bsAlert(data.data);
|
||||
}
|
||||
if (content == "" || title == "") {
|
||||
bsAlert("标题和内容都不能为空");
|
||||
return false;
|
||||
}
|
||||
|
||||
var selectedGroups = [];
|
||||
if (!vm.isGlobal) {
|
||||
for (var i = 0; i < vm.allGroups.length; i++) {
|
||||
if (vm.allGroups[i].isSelected) {
|
||||
selectedGroups.push(vm.allGroups[i].id);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
bsAlert("标题和公告内容不得为空");
|
||||
|
||||
if (!vm.isGlobal && !selectedGroups.length) {
|
||||
bsAlert("请至少选择一个小组");
|
||||
return false;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
beforeSend: csrfTokenHeader,
|
||||
url: "/api/admin/announcement/",
|
||||
contentType: "application/json",
|
||||
dataType: "json",
|
||||
method: "put",
|
||||
data: JSON.stringify({
|
||||
id: vm.editingAnnouncementId,
|
||||
title: title,
|
||||
content: content,
|
||||
visible: vm.announcementVisible,
|
||||
is_global: vm.isGlobal,
|
||||
groups: selectedGroups
|
||||
}),
|
||||
success: function (data) {
|
||||
if (!data.code) {
|
||||
bsAlert("修改成功");
|
||||
vm.editingAnnouncementId = 0;
|
||||
getPageData(1);
|
||||
}
|
||||
else {
|
||||
bsAlert(data.data);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
vm.$watch("showVisibleOnly", function () {
|
||||
@ -98,8 +125,44 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "validator"],
|
||||
|
||||
getPageData(1);
|
||||
|
||||
$.ajax({
|
||||
url: "/api/admin/group/",
|
||||
method: "get",
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (!data.code) {
|
||||
if (!data.data.length) {
|
||||
bsAlert("您的用户权限只能创建组内公告,但是您还没有创建过小组");
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < data.data.length; i++) {
|
||||
var item = data.data[i];
|
||||
item["isSelected"] = false;
|
||||
vm.allGroups.push(item);
|
||||
}
|
||||
}
|
||||
else {
|
||||
bsAlert(data.data);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
url: "/api/user/",
|
||||
method: "get",
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (!data.code) {
|
||||
if (data.data.admin_type == 1) {
|
||||
vm.isGlobal = false;
|
||||
vm.showGlobalViewRadio = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function getPageData(page) {
|
||||
var url = "/api/announcements/?paging=true&page=" + page + "&page_size=10";
|
||||
var url = "/api/admin/announcement/?paging=true&page=" + page + "&page_size=10";
|
||||
if (vm.showVisibleOnly)
|
||||
url += "&visible=true";
|
||||
$.ajax({
|
||||
@ -122,9 +185,7 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "validator"],
|
||||
}
|
||||
|
||||
//新建公告表单验证与数据提交
|
||||
|
||||
|
||||
$('form').validator().on('submit', function (e) {
|
||||
$("#announcement-form").validator().on('submit', function (e) {
|
||||
if (!e.isDefaultPrevented()) {
|
||||
var title = $("#title").val();
|
||||
var content = createAnnouncementEditor.getValue();
|
||||
@ -132,10 +193,29 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "validator"],
|
||||
bsAlert("请填写公告内容");
|
||||
return false;
|
||||
}
|
||||
var selectedGroups = [];
|
||||
if (!vm.isGlobal) {
|
||||
for (var i = 0; i < vm.allGroups.length; i++) {
|
||||
if (vm.allGroups[i].isSelected) {
|
||||
selectedGroups.push(vm.allGroups[i].id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!vm.isGlobal && !selectedGroups.length) {
|
||||
bsAlert("请至少选择一个小组");
|
||||
return false;
|
||||
}
|
||||
$.ajax({
|
||||
beforeSend: csrfTokenHeader,
|
||||
url: "/api/admin/announcement/",
|
||||
data: {title: title, content: content},
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify({
|
||||
title: title,
|
||||
content: content,
|
||||
is_global: vm.isGlobal,
|
||||
groups: selectedGroups
|
||||
}),
|
||||
dataType: "json",
|
||||
method: "post",
|
||||
success: function (data) {
|
||||
@ -148,7 +228,7 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "editor", "validator"],
|
||||
bsAlert(data.data);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
return false;
|
||||
}
|
||||
})
|
||||
|
@ -7,6 +7,7 @@
|
||||
<th>创建时间</th>
|
||||
<th>更新时间</th>
|
||||
<th>创建者</th>
|
||||
<td>可见范围</td>
|
||||
<th>状态</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
@ -16,6 +17,7 @@
|
||||
<td>{{ el.create_time|date("yyyy-MM-dd HH:mm:ss")}}</td>
|
||||
<td>{{ el.last_update_time|date("yyyy-MM-dd HH:mm:ss")}}</td>
|
||||
<td>{{ el.created_by.username }}</td>
|
||||
<td ms-text="el.is_global?'全局可见':'组内可见'"></td>
|
||||
<td>{{ getState(el)}}</td>
|
||||
<td>
|
||||
<button class="btn-sm btn-info" ms-click="editAnnouncement(el)">编辑</button>
|
||||
@ -36,7 +38,7 @@
|
||||
|
||||
<div class="form-group">
|
||||
<label>标题</label>
|
||||
<input name="title" type="text" class="form-control" id="newTitle" placeholder="公告标题" value=""></div>
|
||||
<input name="title" type="text" class="form-control" id="newTitle" placeholder="公告标题" value="" ms-duplex="newTitle"></div>
|
||||
<div class="form-group">
|
||||
<label>内容</label>
|
||||
<textarea id="edit-announcement-editor"></textarea>
|
||||
@ -44,6 +46,25 @@
|
||||
<div class="form-group">
|
||||
<label>可见 <input ms-duplex-checked="announcementVisible" type="checkbox"/></label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>可见范围</label>
|
||||
|
||||
<div>
|
||||
<span ms-if="showGlobalViewRadio">
|
||||
<input type="radio" value="true" name="isGlobal" ms-duplex-boolean="isGlobal">全局可见
|
||||
</span>
|
||||
<span>
|
||||
<input type="radio" value="false" name="isGlobal" ms-duplex-boolean="isGlobal">小组内可见
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="form-group col-md-12" ms-if="!isGlobal">
|
||||
<!-- radio 的value 没有用 但是没有的话,表单验证会出错-->
|
||||
<div ms-repeat="allGroups" class="col-md-4">
|
||||
<input type="checkbox" value="group_id" ms-duplex-checked="el.isSelected"> {{ el.name }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button ms-click="submitChange()" class="btn btn-primary">提交</button>
|
||||
|
||||
@ -65,6 +86,25 @@
|
||||
</textarea>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>可见范围</label>
|
||||
|
||||
<div>
|
||||
<span ms-if="showGlobalViewRadio">
|
||||
<input type="radio" value="true" name="isGlobal" ms-duplex-boolean="isGlobal">全局可见
|
||||
</span>
|
||||
<span>
|
||||
<input type="radio" value="false" name="isGlobal" ms-duplex-boolean="isGlobal">小组内可见
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="form-group col-md-12" ms-if="!isGlobal">
|
||||
<!-- radio 的value 没有用 但是没有的话,表单验证会出错-->
|
||||
<div ms-repeat="allGroups" class="col-md-4">
|
||||
<input type="checkbox" value="group_id" ms-duplex-checked="el.isSelected"> {{ el.name }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary">提交</button>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user