admin webpack template
This commit is contained in:
44
frontend/admin/src/App.vue
Normal file
44
frontend/admin/src/App.vue
Normal file
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<div>
|
||||
<unsupported-browser-warning></unsupported-browser-warning>
|
||||
<top-nav></top-nav>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div>
|
||||
<div class="col-md-2">
|
||||
<left-nav></left-nav>
|
||||
</div>
|
||||
<div class="col-md-10">
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
<alert></alert>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<p class="text-muted text-center">Copyright © 2016</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
@import "../../static/css/bootstrap.css";
|
||||
@import "../../static/css/todc-bootstrap.css";
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import unsupportedBrowserWarning from "./components/utils/unsupportedBrowserWarning.vue"
|
||||
import topNav from "./components/utils/topNav.vue"
|
||||
import leftNav from "./components/utils/leftNav.vue"
|
||||
import alert from "./components/utils/alert.vue"
|
||||
|
||||
|
||||
export default({
|
||||
components: {
|
||||
unsupportedBrowserWarning,
|
||||
topNav,
|
||||
leftNav,
|
||||
alert
|
||||
}
|
||||
})
|
||||
</script>
|
||||
167
frontend/admin/src/components/account/editUser.vue
Normal file
167
frontend/admin/src/components/account/editUser.vue
Normal file
@@ -0,0 +1,167 @@
|
||||
<template>
|
||||
<div>
|
||||
<back url="/user"></back>
|
||||
<h3>修改用户信息</h3>
|
||||
<form v-on:submit="submit">
|
||||
<div class="row">
|
||||
<div class="form-group col-md-4"><label>ID</label>
|
||||
<input type="number" class="form-control" v-model="user.id" readonly>
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label>{{ $t("user.username") }}</label>
|
||||
<input type="text" class="form-control" v-model="user.username" maxlength="30" required>
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label>{{ $t("user.realName") }}</label>
|
||||
<input type="text" class="form-control" maxlength="30" v-model="user.real_name" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="form-group col-md-4">
|
||||
<label>{{ $t("user.newPassword") }}</label>
|
||||
<input type="password" class="form-control"
|
||||
placeholder='{{ $t("user.leaveBlankIfDoNotChangePassword")}}' v-model="newPassword">
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label>{{ $t("user.email") }}</label>
|
||||
<input type="email" class="form-control" v-model="user.email" required>
|
||||
</div>
|
||||
<div class="form-group col-md-4">
|
||||
<label>{{ $t("user.adminType") }}</label>
|
||||
<select class="form-control" v-model="user.admin_type">
|
||||
<option v-for="item in adminType" v-bind:value="item.value">{{ $t(item.name) }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="form-group col-md-3">
|
||||
<label>{{ $t("user.openAPIFunction") }}</label>
|
||||
<input type="checkbox" class="form-control" v-model="user.open_api">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label>{{ $t("user.tfaAuth") }}</label>
|
||||
<input type="checkbox" class="form-control" v-model="user.two_factor_auth">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label>{{ $t("user.isDisabled") }}</label>
|
||||
<input type="checkbox" class="form-control" v-model="user.is_disabled">
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="user.admin_type==adminType[1].value">
|
||||
<h4>{{ $t("user.adminExtraPermission") }}</h4>
|
||||
<div class="row">
|
||||
<div class="form-group col-md-3">
|
||||
<label>{{ $t("adminUtils.createPublicContest") }}</label>
|
||||
<input type="checkbox" class="form-control" v-model="permission.createPublicContest">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label>{{ $t("adminUtils.manageAllContest") }}</label>
|
||||
<input type="checkbox" class="form-control" v-model="permission.manageAllContest">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label>{{ $t("adminUtils.manageOwnProblem") }}</label>
|
||||
<input type="checkbox" class="form-control" v-model="permission.manageOwnProblem">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label>{{ $t("adminUtils.manageAllProblem") }}</label>
|
||||
<input type="checkbox" class="form-control" v-model="permission.manageAllProblem">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" class="btn btn-success"
|
||||
value='{{ $t("adminUtils.saveChanges") }}'>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import back from '../utils/back.vue'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
adminType: [{name: "adminUtils.regularUser", value: 0},
|
||||
{name: "adminUtils.admin", "value": 1},
|
||||
{name: "adminUtils.superAdmin", value: 2}],
|
||||
user: {},
|
||||
permission: {
|
||||
manageAllContest: false, createPublicContest: false,
|
||||
manageAllProblem: false, manageOwnProblem: false
|
||||
},
|
||||
newPassword: "",
|
||||
userPermissionNum2Str: {
|
||||
1: "createPublicContest", 2: "manageAllContest",
|
||||
3: "manageAllProblem", 4: "manageOwnProblem"
|
||||
},
|
||||
userPermissionStr2Num: {
|
||||
createPublicContest: 1, manageAllContest: 2,
|
||||
manageAllProblem: 3, manageOwnProblem: 4
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
submit() {
|
||||
var data = {
|
||||
id: this.user.id,
|
||||
username: this.user.username,
|
||||
real_name: this.user.real_name,
|
||||
email: this.user.email,
|
||||
admin_type: this.user.admin_type,
|
||||
open_api: this.user.open_api,
|
||||
two_factor_auth: this.user.two_factor_auth,
|
||||
is_disabled: this.user.is_disabled
|
||||
};
|
||||
if (this.newPassword) {
|
||||
data["password"] = this.newPassword;
|
||||
}
|
||||
if (this.user.admin_type == this.adminType[1].value) {
|
||||
data["admin_extra_permission"] = [];
|
||||
for (var k in this.permission) {
|
||||
if (this.permission[k]) {
|
||||
data["admin_extra_permission"].push(this.userPermissionStr2Num[k])
|
||||
}
|
||||
}
|
||||
}
|
||||
this.request({
|
||||
url: "/api/admin/user/",
|
||||
method: "PUT",
|
||||
data: data,
|
||||
success: (data)=> {
|
||||
// todo
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
route: {
|
||||
data() {
|
||||
this.request({
|
||||
url: "/api/admin/user/?user_id=" + this.$route.params["userId"],
|
||||
method: "GET",
|
||||
success:(data)=> {
|
||||
this.user = data.data;
|
||||
for (var p of data.data.admin_extra_permission) {
|
||||
if (this.userPermissionNum2Str[p]) {
|
||||
this.permission[this.userPermissionNum2Str[p]] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.$watch('permission.manageAllProblem', function (val) {
|
||||
if (val) {
|
||||
this.permission.manageOwnProblem = false;
|
||||
}
|
||||
});
|
||||
this.$watch('permission.manageOwnProblem', function (val) {
|
||||
if (val) {
|
||||
this.permission.manageAllProblem = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
components: {
|
||||
back
|
||||
}
|
||||
}
|
||||
</script>
|
||||
113
frontend/admin/src/components/account/userList.vue
Normal file
113
frontend/admin/src/components/account/userList.vue
Normal file
@@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="right">
|
||||
<form class="form-inline" onsubmit="return false;">
|
||||
<div class="form-group-sm">
|
||||
<label>{{ $t("adminUtils.search") }}</label>
|
||||
<input name="keyword" class="form-control" placeholder='{{ $t("adminUtils.inputKeyword") }}'
|
||||
v-model="keyword">
|
||||
<button type="button" class="btn btn-primary" v-on:click="search">{{ $t("adminUtils.search") }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<br>
|
||||
</div>
|
||||
<table class="table table-striped">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>{{ $t("user.username") }}</th>
|
||||
<th>{{ $t("user.createTime") }}</th>
|
||||
<th>{{ $t("user.realName") }}</th>
|
||||
<th>{{ $t("user.email") }}</th>
|
||||
<th>{{ $t("user.adminType") }}</th>
|
||||
<th>{{ $t("user.management") }}</th>
|
||||
</tr>
|
||||
<tr v-for="user in userList">
|
||||
<td>{{ user.id }}</td>
|
||||
<td>{{ user.username }}</td>
|
||||
<td>{{ user.create_time }}</td>
|
||||
<td>{{ user.real_name }}</td>
|
||||
<td>{{ user.email }}</td>
|
||||
<td>{{ $t(adminType[user.admin_type]) }}</td>
|
||||
<td>
|
||||
<button class="btn-sm btn-info" v-on:click="edit(user.id)">{{ $t("user.edit") }}</button>
|
||||
<a target="_blank" href="/submissions/?user_id={{ user.id }}">
|
||||
{{ $t("user.submission") }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<input type="checkbox" v-model="showAdminOnly"> {{ $t("user.showAdminOnly") }}
|
||||
|
||||
<pager :pagination="pagination" :callback="loadData"></pager>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
import pager from '../utils/pager.vue'
|
||||
|
||||
//import editUser from './editUser.vue'
|
||||
|
||||
export default {
|
||||
data: function () {
|
||||
return {
|
||||
keyword: "",
|
||||
userList: [],
|
||||
adminType: ["adminUtils.regularUser", "adminUtils.admin", "adminUtils.superAdmin"],
|
||||
showAdminOnly: false,
|
||||
|
||||
pagination: {
|
||||
currentPage: 1,
|
||||
totalPages: 10
|
||||
}
|
||||
}
|
||||
},
|
||||
route: {
|
||||
data(){
|
||||
this.$watch('showAdminOnly', function (val) {
|
||||
sessionStorage.showAdminOnly = JSON.stringify(val);
|
||||
this.$router.go({name: this.$route.name, params: {page: 1}});
|
||||
});
|
||||
this.pagination.currentPage = this.$route.params.page;
|
||||
if (sessionStorage.showAdminOnly) {
|
||||
this.showAdminOnly = JSON.parse(sessionStorage.showAdminOnly);
|
||||
}
|
||||
if (sessionStorage.userListSearchKeyword) {
|
||||
this.keyword = sessionStorage.userListSearchKeyword;
|
||||
}
|
||||
this.loadData();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadData() {
|
||||
var url = "/api/admin/user/?paging=true&page_size=2&page=" + this.pagination.currentPage;
|
||||
if (this.keyword) {
|
||||
url += ("&keyword=" + this.keyword)
|
||||
}
|
||||
else if (this.showAdminOnly) {
|
||||
url += "&admin_type=1";
|
||||
}
|
||||
this.request({
|
||||
url: url,
|
||||
method: "GET",
|
||||
success: (data)=> {
|
||||
this.userList = data.data.results;
|
||||
this.pagination.totalPages = data.data.total_page;
|
||||
}
|
||||
})
|
||||
},
|
||||
search() {
|
||||
sessionStorage.userListSearchKeyword = this.keyword;
|
||||
this.pagination.currentPage = 1;
|
||||
this.loadData();
|
||||
},
|
||||
edit(userId) {
|
||||
this.$router.go("/user/edit/" + userId)
|
||||
}
|
||||
},
|
||||
components: {
|
||||
pager
|
||||
}
|
||||
}
|
||||
</script>
|
||||
113
frontend/admin/src/components/utils/alert.vue
Normal file
113
frontend/admin/src/components/utils/alert.vue
Normal file
@@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="modal-mask" v-show="showModal" transition="modal">
|
||||
<div class="modal-wrapper">
|
||||
<div class="modal-container">
|
||||
|
||||
<div class="modal-header">
|
||||
<slot name="header">
|
||||
提示
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<slot name="body">
|
||||
{{ content }}
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<slot name="footer">
|
||||
<button class="modal-default-button"
|
||||
@click="show = false">
|
||||
OK
|
||||
</button>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default({
|
||||
data() {
|
||||
return {
|
||||
showModal: false,
|
||||
content: ""
|
||||
}
|
||||
},
|
||||
events: {
|
||||
"showModal":(content) => {
|
||||
this.showModal = true;
|
||||
this.content = true;
|
||||
setTimeout(()=>{
|
||||
this.showModal = false;
|
||||
}, 2000);
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.modal-mask {
|
||||
position: fixed;
|
||||
z-index: 9998;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, .5);
|
||||
display: table;
|
||||
transition: opacity .3s ease;
|
||||
}
|
||||
|
||||
.modal-wrapper {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.modal-container {
|
||||
width: 300px;
|
||||
margin: 0 auto;
|
||||
padding: 20px 30px;
|
||||
background-color: #fff;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, .33);
|
||||
transition: all .3s ease;
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.modal-header h3 {
|
||||
margin-top: 0;
|
||||
color: #42b983;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.modal-default-button {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/*
|
||||
* the following styles are auto-applied to elements with
|
||||
* v-transition="modal" when their visiblity is toggled
|
||||
* by Vue.js.
|
||||
*
|
||||
* You can easily play with the modal transition by editing
|
||||
* these styles.
|
||||
*/
|
||||
|
||||
.modal-enter, .modal-leave {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.modal-enter .modal-container,
|
||||
.modal-leave .modal-container {
|
||||
-webkit-transform: scale(1.1);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
</style>
|
||||
17
frontend/admin/src/components/utils/back.vue
Normal file
17
frontend/admin/src/components/utils/back.vue
Normal file
@@ -0,0 +1,17 @@
|
||||
<template id="back">
|
||||
<nav>
|
||||
<ul class="pager">
|
||||
<li class="previous">
|
||||
<a href="#" v-link="url">
|
||||
<span aria-hidden="true">←</span>
|
||||
{{ $t("adminUtils.back") }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</template>
|
||||
<script>
|
||||
export default{
|
||||
props: ["url"]
|
||||
}
|
||||
</script>
|
||||
19
frontend/admin/src/components/utils/leftNav.vue
Normal file
19
frontend/admin/src/components/utils/leftNav.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<div id="left-nav">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-header">name</li>
|
||||
<li class="list-group-item">
|
||||
<a v-link="{path: '/user'}">{{ $t("nav.UserManagement") }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
adminNav: [{}, {}]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
91
frontend/admin/src/components/utils/pager.vue
Normal file
91
frontend/admin/src/components/utils/pager.vue
Normal file
@@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<nav v-show="visible">
|
||||
<ul class="pagination pagination-lg">
|
||||
<li class="{{ pagination.currentPage > 1 ? '' : 'disabled' }}">
|
||||
<a href="#" aria-label="Previous" @click.prevent="changePage(1)">
|
||||
<span aria-hidden="true">上一页</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="{{ pagination.currentPage > 1 ? '' : 'disabled' }}">
|
||||
<a href="#" aria-label="Previous" @click.prevent="changePage(pagination.currentPage - 1)">
|
||||
<span aria-hidden="true">«</span>
|
||||
</a>
|
||||
</li>
|
||||
<li v-if="pagination.currentPage > 1 && pagination.currentPage - 1 > offset">
|
||||
<a href="#" aria-label="Next" @click.prevent="changePage(from)">
|
||||
<span aria-hidden="true">...</span>
|
||||
</a>
|
||||
</li>
|
||||
<li v-for="num in data" :class="{'active': num == pagination.currentPage}">
|
||||
<a href="#" @click.prevent="changePage(num)">{{ num }}</a>
|
||||
</li>
|
||||
<li v-if="pagination.totalPages - pagination.currentPage > offset">
|
||||
<a href="#" aria-label="Next" @click.prevent="changePage(to)">
|
||||
<span aria-hidden="true">...</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="{{ pagination.currentPage < pagination.totalPages ? '' : 'disabled' }}">
|
||||
<a href="#" aria-label="Next" @click.prevent="changePage(pagination.currentPage + 1)">
|
||||
<span aria-hidden="true">»</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="{{ pagination.currentPage < pagination.totalPages ? '' : 'disabled' }}">
|
||||
<a href="#" aria-label="Next" @click.prevent="changePage(pagination.totalPages)">
|
||||
<span aria-hidden="true">最后一页</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</template>
|
||||
<script>
|
||||
export default{
|
||||
props: {
|
||||
pagination: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
callback: {
|
||||
type: Function,
|
||||
required: true
|
||||
},
|
||||
offset: {
|
||||
type: Number,
|
||||
default: 4
|
||||
},
|
||||
visible: {
|
||||
type: Number,
|
||||
default: 1
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
data: function () {
|
||||
this.visible = 1;
|
||||
var from = this.pagination.currentPage - this.offset;
|
||||
if (from < 1) {
|
||||
from = 1;
|
||||
}
|
||||
var to = from + (this.offset * 2);
|
||||
if (to >= this.pagination.totalPages) {
|
||||
to = this.pagination.totalPages;
|
||||
}
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
var arr = [];
|
||||
while (from <= to) {
|
||||
arr.push(from);
|
||||
from++;
|
||||
}
|
||||
if (arr.length == 1)
|
||||
this.visible = 0;
|
||||
return arr;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changePage(page) {
|
||||
this.$set('pagination.currentPage', page);
|
||||
this.$router.go({name: this.$route.name, params: {page: page}});
|
||||
this.callback();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
25
frontend/admin/src/components/utils/topNav.vue
Normal file
25
frontend/admin/src/components/utils/topNav.vue
Normal file
@@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<nav class="navbar navbar-masthead navbar-default navbar-static-top">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar"
|
||||
aria-expanded="false" aria-controls="navbar">
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">oj admin</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a href="/" target="_blank">主页</a></li>
|
||||
<li><a href="/problems/" target="_blank">题目</a></li>
|
||||
<li><a href="/contests/" target="_blank">比赛</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
<script>
|
||||
export default{}
|
||||
</script>
|
||||
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div id="browser-unsupported" style="display: none">{{{ $t("adminUtils.unsupportedBrowserWarningMsg") }}}
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default{
|
||||
attached() {
|
||||
if (navigator.userAgent.indexOf("MSIE") > -1) {
|
||||
document.getElementById("browser-unsupported").removeAttribute("style");
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
51
frontend/admin/src/locales.js
Normal file
51
frontend/admin/src/locales.js
Normal file
@@ -0,0 +1,51 @@
|
||||
export default {
|
||||
"zh-cn": {
|
||||
nav: {
|
||||
UserManagement: "用户管理"
|
||||
},
|
||||
pagination: {
|
||||
first: "首页",
|
||||
last: "末页"
|
||||
},
|
||||
modalAlert: {
|
||||
alert: "提示",
|
||||
close: "关闭"
|
||||
},
|
||||
request: {
|
||||
error: "请求失败",
|
||||
succeeded: "操作成功"
|
||||
},
|
||||
user: {
|
||||
username: "用户名",
|
||||
email: "邮箱",
|
||||
realName: "真实姓名",
|
||||
adminType: "用户类型",
|
||||
createTime: "注册时间",
|
||||
management: "管理",
|
||||
edit: "编辑",
|
||||
submission: "提交",
|
||||
newPassword: "新密码",
|
||||
leaveBlankIfDoNotChangePassword: "不需要修改密码请留空",
|
||||
openAPIFunction: "OpenAPI 功能",
|
||||
tfaAuth: "两步验证",
|
||||
isDisabled: "禁用用户",
|
||||
adminExtraPermission: "普通管理员额外权限",
|
||||
showAdminOnly: "只显示管理员"
|
||||
},
|
||||
adminUtils: {
|
||||
search: "搜索",
|
||||
inputKeyword: "输入关键词",
|
||||
regularUser: "普通用户",
|
||||
admin: "普通管理员",
|
||||
superAdmin: "超级管理员",
|
||||
UserDoesNotExist: "用户不存在",
|
||||
back: "返回",
|
||||
saveChanges: "保存修改",
|
||||
createPublicContest: "创建公开比赛",
|
||||
manageAllContest: "管理所有比赛",
|
||||
manageAllProblem: "管理所有题目",
|
||||
manageOwnProblem: "管理自己创建的题目",
|
||||
unsupportedBrowserWarningMsg: "当前网页 <strong>不支持</strong> 你正在使用的浏览器, 为了正常的访问,请到 <a href=\"http://browsehappy.com/\"> 升级你的浏览器</a>"
|
||||
}
|
||||
}
|
||||
};
|
||||
90
frontend/admin/src/main.js
Normal file
90
frontend/admin/src/main.js
Normal file
@@ -0,0 +1,90 @@
|
||||
import Vue from 'vue'
|
||||
import App from './App'
|
||||
import VueRouter from "vue-router"
|
||||
import VueI18n from "vue-i18n"
|
||||
|
||||
import locale from "./locales"
|
||||
|
||||
import userList from "./components/account/userList.vue"
|
||||
import editUser from "./components/account/editUser.vue"
|
||||
|
||||
|
||||
var request = {
|
||||
install: function (Vue, options) {
|
||||
function getCookie(name) {
|
||||
var value = "; " + document.cookie;
|
||||
var parts = value.split("; " + name + "=");
|
||||
if (parts.length == 2) {
|
||||
return parts.pop().split(";").shift();
|
||||
}
|
||||
}
|
||||
|
||||
Vue.prototype.request = function (option) {
|
||||
var request = new XMLHttpRequest();
|
||||
request.open(option.method, option.url, true);
|
||||
request.onerror = function () {
|
||||
if (option.error) {
|
||||
option.error(request)
|
||||
}
|
||||
else {
|
||||
alert("请求失败");
|
||||
}
|
||||
};
|
||||
request.onload = function () {
|
||||
if (request.status >= 200 && request.status < 400) {
|
||||
try {
|
||||
var data = JSON.parse(request.responseText);
|
||||
if (data.code == 1 && data.data) {
|
||||
alert(data.data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
request.onerror();
|
||||
}
|
||||
option.success(data);
|
||||
}
|
||||
else {
|
||||
request.onerror();
|
||||
}
|
||||
};
|
||||
request.setRequestHeader('x-requested-with', 'XMLHttpRequest');
|
||||
if (option.method.toLowerCase() == 'post' || option.method.toLowerCase() == 'put') {
|
||||
request.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
||||
request.setRequestHeader('x-csrftoken', getCookie('csrftoken'));
|
||||
request.send(JSON.stringify(option.data));
|
||||
}
|
||||
else {
|
||||
request.send();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Vue.use(request);
|
||||
|
||||
Vue.use(VueRouter);
|
||||
Vue.use(VueI18n);
|
||||
|
||||
Vue.config.lang = "zh-cn";
|
||||
|
||||
Object.keys(locale).forEach(function (lang) {
|
||||
Vue.locale(lang, locale[lang])
|
||||
});
|
||||
|
||||
|
||||
var router = new VueRouter();
|
||||
|
||||
router.map({
|
||||
"/user/:page": {
|
||||
name: "userList",
|
||||
component: userList
|
||||
},
|
||||
"/user/edit/:userId": {
|
||||
name: "editUser",
|
||||
component: editUser
|
||||
}
|
||||
});
|
||||
|
||||
router.redirect({"/user": "/user/1"});
|
||||
router.start(App, '#app');
|
||||
Reference in New Issue
Block a user