diff --git a/article/views.py b/article/views.py index 91387a9..8d11b17 100644 --- a/article/views.py +++ b/article/views.py @@ -35,6 +35,7 @@ class CategoryViewSet(viewsets.ModelViewSet): queryset = Category.objects.all() serializer_class = CategorySerializer permission_classes = [IsAdminUserOrReadOnly] + pagination_class = None # 不进行翻页 def get_serializer_class(self): if self.action == 'list': @@ -48,6 +49,7 @@ class TagViewSet(viewsets.ModelViewSet): queryset = Tag.objects.all() serializer_class = TagSerializer permission_classes = [IsAdminUserOrReadOnly] + pagination_class = None # 不进行翻页 class AvatarViewSet(viewsets.ModelViewSet): diff --git a/db.sqlite3 b/db.sqlite3 index d5e7602..24808d2 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ diff --git a/frontend/src/components/ArticleList.vue b/frontend/src/components/ArticleList.vue index 33e56b5..88f12eb 100644 --- a/frontend/src/components/ArticleList.vue +++ b/frontend/src/components/ArticleList.vue @@ -1,5 +1,10 @@ @@ -42,9 +39,9 @@ import { useRoute } from "vue-router"; export default { name: "ArticleList", setup() { - onMounted(()=>{ - get_article_data(); - }) + onMounted(() => { + get_article_data(); + }); let articles = ref([]); // 保存当前页的所有文章 let previous = ref(null); // 保存上一页的url let next = ref(null); // 保存下一页的url @@ -82,7 +79,7 @@ export default { break; default: // 首页需要特殊处理 - if (!('page' in router.query)) return 1; + if (!("page" in router.query)) return 1; if (router.query.page === null) return 1; return router.query.page; } @@ -96,17 +93,17 @@ export default { const get_article_data = () => { let article_url = "http://127.0.0.1:6789/api/article"; // BaseUrl - let params = new URLSearchParams(); - // 注意 appendIfExists 方法是原生没有的 - // 原生只有 append 方法,但此方法不能判断值是否存在 - // 只有这两种参数存在时才加入url - params.appendIfExists('page', router.query.page); - params.appendIfExists('search', router.query.search); - // 这下可以同时传入多种参数 - const paramsString = params.toString(); - if (paramsString.charAt(0) !== '') { - article_url += '/?' + paramsString; - } + let params = new URLSearchParams(); + // 注意 appendIfExists 方法是原生没有的 + // 原生只有 append 方法,但此方法不能判断值是否存在 + // 只有这两种参数存在时才加入url + params.appendIfExists("page", router.query.page); + params.appendIfExists("search", router.query.search); + // 这下可以同时传入多种参数 + const paramsString = params.toString(); + if (paramsString.charAt(0) !== "") { + article_url += "/?" + paramsString; + } $.ajax({ url: article_url, type: "GET", @@ -117,27 +114,27 @@ export default { }, }); }; - // 在翻页后取得包括page和search的正确路径 - const get_path = (direction) => { - let url = ""; - try { - - switch(direction) { - case 'next': - if (next.value !== undefined) { - url += (new URL(next.value)).search - } - break; - case 'previous': - if (previous.value !== undefined) { - url += (new URL(previous.value)).search - } - break; - } - } - catch { return url} - return url; - } + // 在翻页后取得包括page和search的正确路径 + const get_path = (direction) => { + let url = ""; + try { + switch (direction) { + case "next": + if (next.value !== undefined) { + url += new URL(next.value).search; + } + break; + case "previous": + if (previous.value !== undefined) { + url += new URL(previous.value).search; + } + break; + } + } catch { + return url; + } + return url; + }; return { articles, @@ -145,7 +142,7 @@ export default { is_page_exists, get_page_param, get_article_data, - get_path, + get_path, }; }, watch: { @@ -166,7 +163,7 @@ export default { font-size: 1.2rem; font-weight: bolder; text-decoration: none; - color: blue; + color: blue; padding: 5px 0 5px 0; } @@ -182,7 +179,7 @@ export default { #paginator { text-align: center; - padding-bottom: 4rem; + padding-bottom: 4rem; } #paginator a { @@ -195,4 +192,14 @@ export default { padding-left: 10px; padding-right: 10px; } + +.category { + padding: 5px 10px 5px 10px; + margin: 5px 5px 5px 0; + font-family: Georgia, Arial, sans-serif; + font-size: small; + background-color: darkred; + color: whitesmoke; + border-radius: 15px; +} diff --git a/frontend/src/components/BlogHeader.vue b/frontend/src/components/BlogHeader.vue index acd3cef..4e9b7bc 100644 --- a/frontend/src/components/BlogHeader.vue +++ b/frontend/src/components/BlogHeader.vue @@ -29,8 +29,14 @@ 用户中心 - + 发表文章 + + + 退出 @@ -51,6 +57,9 @@ import { ref } from "vue"; import SearchButton from "@/components/SearchButton.vue"; import authorization from "@/utils/authorization"; +const storage = localStorage; + + export default { name: "BlogHeader", components: { @@ -60,28 +69,33 @@ export default { authorization().then((data) => ([this.haslogin, this.username] = data)); }, setup() { + let username = ref(""); let haslogin = ref(false); - + let isSuperUser = ref(false); const quit = () => { - const storage = localStorage; - window.alert("已退出登录!"); + window.alert("已退出登录!"); console.log("登出成功,过期时间: ", new Date().toLocaleString()); storage.clear(); // 清除所有有效信息 haslogin.value = false; }; + isSuperUser.value = JSON.parse(localStorage.getItem('is_superuser_blog')); + + return { username, haslogin, + isSuperUser, quit, }; - }, - methods: { - refresh() { - this.username = localStorage.getItem('username_blog'); - } - } + }, + + methods: { + refresh() { + this.username = localStorage.getItem("username_blog"); + }, + }, }; @@ -89,7 +103,7 @@ export default { /* 样式来源: https://www.runoob.com/css/css-dropdowns.html* / /* 下拉按钮样式 */ .dropbtn { - width: 10vw; + width: 10vw; background-color: mediumslateblue; color: white; padding: 8px 8px 30px 8px; @@ -98,8 +112,8 @@ export default { cursor: pointer; height: 2vw; border-radius: 5px; - text-overflow: ellipsis; - overflow: hidden; + text-overflow: ellipsis; + overflow: hidden; } /* 容器
- 需要定位下拉内容 */ .dropdown { @@ -149,7 +163,7 @@ export default { .grid-1 { display: grid; - grid-template-columns: 8fr 2fr ; + grid-template-columns: 8fr 2fr; } .login-link { diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js index ec4056f..a18f58b 100644 --- a/frontend/src/router/index.js +++ b/frontend/src/router/index.js @@ -4,6 +4,7 @@ import ArticleDetail from '@/views/ArticleDetailView.vue' import LoginView from '@/views/LoginView.vue' import RegisterView from '@/views/RegisterView.vue' import UserCenter from '@/views/UserCenterView.vue' +import ArticleCreate from '@/views/ArticleCreate.vue' const routes = [ { @@ -31,6 +32,12 @@ const routes = [ name: "UserCenter", component: UserCenter, }, + { + path : "/article/create/", + name: "ArticleCreate", + component: ArticleCreate, + + } ] const router = createRouter({ diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js index f5cdea6..3912ada 100644 --- a/frontend/src/store/index.js +++ b/frontend/src/store/index.js @@ -2,10 +2,14 @@ import { createStore } from 'vuex' export default createStore({ state: { + islogin: false // 用户是否登录,默认没有登录 }, getters: { }, mutations: { + updateIsLogin(state,islogin) { + state.islogin = islogin; + }, }, actions: { }, diff --git a/frontend/src/views/ArticleCreate.vue b/frontend/src/views/ArticleCreate.vue new file mode 100644 index 0000000..469e37e --- /dev/null +++ b/frontend/src/views/ArticleCreate.vue @@ -0,0 +1,208 @@ + + + + + diff --git a/frontend/src/views/LoginView.vue b/frontend/src/views/LoginView.vue index d05896b..55606fc 100644 --- a/frontend/src/views/LoginView.vue +++ b/frontend/src/views/LoginView.vue @@ -66,6 +66,15 @@ export default { storage.setItem('refresh_blog', resp.refresh); storage.setItem('expired_time', expiredTime); storage.setItem('username_blog', username.value); + // 保存该用户是否为管理员 + $.ajax({ + url: 'http://127.0.0.1:6789/api/user/' + username.value + '/', + type: 'GET', + success(resp){ + storage.setItem('is_superuser_blog',resp.is_superuser); + } + }); + console.log("登录时间: ",new Date().toLocaleString()); router.push({ name: "home" }); }, diff --git a/frontend/src/views/RegisterView.vue b/frontend/src/views/RegisterView.vue index 86706e3..0aad480 100644 --- a/frontend/src/views/RegisterView.vue +++ b/frontend/src/views/RegisterView.vue @@ -82,16 +82,12 @@ export default { username: username.value, password: password.value, }, - success(resp) { - console.log(resp); + success() { window.alert("注册成功!即将跳转到登陆页面!"); setTimeout(() => { router.push({ name: "login" }); // 注册成功,跳转登录页面 }, 200); }, - error(resp) { - console.log(resp); - }, }); }; diff --git a/user_info/serializers.py b/user_info/serializers.py index 0147d5d..03151b6 100644 --- a/user_info/serializers.py +++ b/user_info/serializers.py @@ -26,9 +26,11 @@ class UserRegisterSerializer(serializers.ModelSerializer): 'id', 'username', 'password', + 'is_superuser', # 是否是管理员 ] extra_kwargs = { - 'password': {'write_only': True} + 'password': {'write_only': True}, + 'is_superuser': {'read_only': True}, } def create(self, validated_data):