后台管理框架搭建

This commit is contained in:
2023-07-09 19:05:48 +08:00
parent 42f2f6d503
commit 02b58972d6
23 changed files with 1001 additions and 99 deletions

View File

@@ -89,4 +89,7 @@ $--font-path: '~element-ui/lib/theme-chalk/fonts';
}
.el-avatar{
background-color: transparent;
}
.el-tag {
border-radius: 15px!important;
}

View File

@@ -123,7 +123,7 @@
multiple>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件且不超过500kb</div>
<div class="el-upload__tip" slot="tip">只能上传zip文件且不超过50mb</div>
</el-upload>
</div>
@@ -204,7 +204,6 @@ export default {
name: null,
tags: [],
tag: [],
fileList: [],
content: null,
},
rules: {
@@ -320,44 +319,54 @@ export default {
closeUploadFile(){
this.openPublishProject=false;
this.openUploadFile=false;
window.location.reload();
},
submitProject(){
if (this.form.tag) {
this.form.tag = this.form.tag.join(",");
if(this.avatar_url===null||this.form.name===null|| this.form.url===null||this.form.title===null||this.form.content===null||this.form.tag.length===0){
Vue.prototype.$notify.error({
title: '错误',
message: "请先填写相关信息!",
offset: 50
});
}else {
if (this.form.tag) {
this.form.tag = this.form.tag.join(",");
}
Object.assign({}, this.form);
var that=this;
axios({
method: 'post',
// 请求的地址
url: 'http://localhost:8082/helloGithub_war_exploded/commitProject',
// URL 中的查询参数
params: {
projectIco:this.avatar_url,
projectName:this.form.name,
projectUrl:this.form.url,
projectTitle:this.form.title,
projectDescription:this.form.content,
categoryIdList:this.form.tag
}
}).then( (res)=> {
if(res.data.code===200){
Vue.prototype.$notify({
title: '成功',
message: ('i', {style: 'color: teal'}, res.data.msg),
type: 'success',
offset: 50
});
this.openPublishProject=false;
that.openUploadFile=true
}else{
Vue.prototype.$notify.error({
title: '错误',
message: res.data.msg,
offset: 50
});
}
});
}
Object.assign({}, this.form);
var that=this;
axios({
method: 'post',
// 请求的地址
url: 'http://localhost:8082/helloGithub_war_exploded/commitProject',
// URL 中的查询参数
params: {
projectIco:this.avatar_url,
projectName:this.form.name,
projectUrl:this.form.url,
projectTitle:this.form.title,
projectDescription:this.form.content,
categoryIdList:this.form.tag
}
}).then( (res)=> {
if(res.data.code===200){
Vue.prototype.$notify({
title: '成功',
message: ('i', {style: 'color: teal'}, res.data.msg),
type: 'success',
offset: 50
});
this.openPublishProject=false;
that.openUploadFile=true
}else{
Vue.prototype.$notify.error({
title: '错误',
message: res.data.msg,
offset: 50
});
}
});
},
isExist(){
axios({

View File

@@ -17,7 +17,7 @@
</div>
<div v-if="historySearch!==null" v-show="this.$cookie.get('username')!=null">
<el-tag
v-show="historySearch.length!==0"
v-if="historySearch.length!==0"
v-for="(tag,index) in historySearch"
:key="index"
size="small"
@@ -149,6 +149,7 @@ export default {
params: {
}
}).then((res)=>{
console.log(res.data.length);
that.historySearch=res.data;
});

View File

@@ -51,7 +51,7 @@
<el-dropdown-menu slot="dropdown">
<el-dropdown-item><el-link :underline="false" @click="goTo(projectUrl)">源码</el-link></el-dropdown-item>
<el-dropdown-item> <el-link :underline="false" @click="goTo('https://github.com/'+projectName+'/releases')">官方下载</el-link></el-dropdown-item>
<el-dropdown-item v-show="fileAddress!=''"> <el-link @click="Download" :underline="false">快速下载</el-link></el-dropdown-item>
<el-dropdown-item v-show="fileAddress!==undefined"> <el-link @click="Download" :underline="false">快速下载</el-link></el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-button v-show="isRouterAlive" v-if="Like===0" @click="addStar" style="height: 60px;width: 150px;margin-left: 10px" icon="el-icon-star-off" type="success"> {{startNum}}</el-button>
@@ -84,8 +84,8 @@
</tr>
<tr>
<td style="font-size: 20px;color: black;font-weight: bold">{{formatNumber(github.starNum)}}</td>
<td style="font-size: 20px;color: black;font-weight: bold;">{{briefName}}</td>
<td style="font-size: 20px;color: black;font-weight: bold">{{brief}}</td>
<td v-if="github.name!==null" style="font-size: 20px;color: black;font-weight: bold;">{{briefName}}</td>
<td v-if="github.language!==null" style="font-size: 20px;color: black;font-weight: bold">{{brief}}</td>
<td v-if="github.allow_forking" style="font-size: 20px;color: black;font-weight: bold"></td>
<td v-if="!github.allow_forking" style="font-size: 20px;color: black;font-weight: bold"></td>
<td style="font-size: 20px;color: black;font-weight: bold">{{formatNumber(github.subscribers_count)}}</td>
@@ -104,6 +104,7 @@
<tr>
<td style="font-size: 20px;color: black;font-weight: bold">{{github.open_issues_count}}</td>
<td v-if="github.organization==='Organization'" style="font-size: 20px;color: black;font-weight: bold"></td>
<td v-else-if="github.organization!=='Organization'" style="font-size: 20px;color: black;font-weight: bold"></td>
<td style="font-size: 20px;color: black;font-weight: bold">{{github.default_branch}}</td>
<td style="font-size: 20px;color: black;font-weight: bold">{{formatNumber(github.forks_count)}}</td>
<td style="font-size: 20px;color: black;font-weight: bold">{{github.license}}</td>
@@ -117,7 +118,7 @@
<div>
<el-tabs v-model="activeName">
<el-tab-pane label="介绍" name="first">
<el-tiptap v-html="projectDescription" :readonly="true" :showMenubar="false" :extensions="extensions" />
<el-tiptap style="text-align: left;border: 1px solid rgba(150,152,150,0.87)" v-model="projectDescription" :readonly="true" :showMenubar="false" :extensions="extensions" />
<div style="display:flex;align-items: center;flex-direction: row;justify-content: space-between">
<div style="display: flex;flex-direction: row;flex-wrap: nowrap;align-items: center">
<span style="font-size: 14px;margin-top: 10px">收录于: </span><el-tag style="margin-left: 10px;margin-top: 10px" size="medium"> {{periodicals}} </el-tag>
@@ -370,7 +371,7 @@ export default {
totalStar:3.7,
Content:'',
imageUrl:'',
fileAddress:null,
fileAddress:'',
}
},
mounted() {
@@ -378,7 +379,7 @@ export default {
this.getLastComment();
this.isStart();
// this.getUserInfo();
this.getGithub();
},
watch: {
$route () {
@@ -445,6 +446,7 @@ export default {
that.fileAddress=res.data.project.fileAddress;
// that.userUri=res.data.project.userUri;
that.getDetailByGitHub();
// that.getGithub();
that.changeAvatarByLocal();
});
},
@@ -698,19 +700,25 @@ export default {
}
}).then((res)=>{
that.github.starNum=res.data.stargazers_count;
that.github.language=res.data.language;
that.github.watchers_count=res.data.watchers_count;
that.github.subscribers_count=res.data.subscribers_count;
that.github.allow_forking=res.data.allow_forking;
that.github.open_issues_count=res.data.open_issues_count;
that.github.forks_count=res.data.forks_count;
that.github.organization=res.data.organization.type;
that.github.license=res.data.license.spdx_id;
that.github.name=res.data.name;
that.github.default_branch=res.data.default_branch;
that.github.avatar_url=res.data.owner.avatar_url;
that.saveGithubInfo();
if(res.data){
that.github.starNum=res.data.stargazers_count;
that.github.language=res.data.language;
that.github.watchers_count=res.data.watchers_count;
that.github.subscribers_count=res.data.subscribers_count;
that.github.allow_forking=res.data.allow_forking;
that.github.open_issues_count=res.data.open_issues_count;
that.github.forks_count=res.data.forks_count;
that.github.organization=res.data.owner.type;
that.github.license=res.data.license.spdx_id;
that.github.name=res.data.name;
that.github.default_branch=res.data.default_branch;
that.github.avatar_url=res.data.owner.avatar_url;
that.saveGithubInfo();
return true;
}else{
return false;
}
});
},
@@ -756,19 +764,24 @@ export default {
},
changeAvatarByLocal(){
var that=this;
axios({
method: 'post',
// 请求的地址
url: '/api/retUserAv',
// URL 中的查询参数
params:{
username:this.username,
},
responseType:'blob'
}).then((res)=>{
that.imageUrl = window.URL.createObjectURL(res.data)//这里也是关键,调用window的这个方法URL方法
})
if(this.username!==null){
var that=this;
axios({
method: 'post',
// 请求的地址
url: '/api/retUserAv',
// URL 中的查询参数
params:{
username:this.username,
},
responseType:'blob'
}).then((res)=>{
that.imageUrl = window.URL.createObjectURL(res.data)//这里也是关键,调用window的这个方法URL方法
})
}else{
return;
}
},
Download(){
@@ -790,7 +803,36 @@ export default {
// type:"success"
// });
// })
}
},
getGithub(){
var that=this;
axios({
method: 'post',
// 请求的地址
url: 'http://localhost:8082/helloGithub_war_exploded/returnGithubInfo',
// URL 中的查询参数
params: {
projectId:this.$route.query.id
}
}).then(function (res) {
if(!res.data){
return false;
}else{
that.github.starNum=res.data.starCount;
that.github.language=res.data.mainLanguage;
that.github.subscribers_count=res.data.subscriber;
that.github.open_issues_count=res.data.issues;
that.github.forks_count=res.data.forks;
that.github.allow_forking=res.data.isActive;
that.github.license=res.data.protocol;
that.github.name=res.data.name;
that.github.default_branch=res.data.defaultBranch;
that.github.avatar_url=res.data.avatar;
}
});
},
},

View File

@@ -0,0 +1,71 @@
<template>
<div>
<div style="height: 60px;width: 200px;display: flex;align-items: center;justify-content: center">
<span style="font-size: 18px;font-weight: bold;color: #42b983;">
{{systemName}}
</span>
</div>
<el-menu
:collapse="isCollapse"
@close="handleClose"
@open="handleOpen"
active-text-color="#ffd04b"
background-color="#545c64"
class="el-menu-vertical-demo"
text-color="#FBFBFB"
width="200px"
:default-active="$route.path"
router
>
<el-menu-item index="/adminHome"><i class="el-icon-s-home"></i>首页</el-menu-item>
<el-menu-item index="/systemManage"><i class="el-icon-s-tools"></i>系统管理</el-menu-item>
<el-menu-item index="/userManage"><i class="el-icon-user-solid"></i>用户管理</el-menu-item>
<el-menu-item index="/projectManage"><i class="el-icon-s-help"></i>项目管理</el-menu-item>
<el-menu-item index="/articleManage"><i class="el-icon-s-management"></i>文章管理</el-menu-item>
<el-menu-item index="/categoryManage"><i class="el-icon-s-flag"></i>标签管理</el-menu-item>
<el-menu-item index="/commentManage"><i class="el-icon-s-comment"></i>评论管理</el-menu-item>
</el-menu>
</div>
</template>
<script>
export default {
name: "AdminAside",
data() {
return {
systemName:'HelloGithub后台管理'
}
},
methods: {
handleOpen(key, keyPath) {
console.log(key, keyPath);
},
handleClose(key, keyPath) {
console.log(key, keyPath);
},
},
computed:{
isCollapse() {
return this.$store.state.isCollapse;
},
},
}
</script>
<style scoped>
/deep/ .el-submenu__title {
width: 200px;
}
/deep/ .el-menu-item-group__title {
width: 200px;
}
</style>

View File

@@ -0,0 +1,71 @@
<template>
<div style="display:flex;flex-direction: row;justify-content: space-between;background:rgb(84, 92, 100);align-items:center">
<div>
<el-button @click="handleMenu" icon="el-icon-menu" size="mini"></el-button>
<BreadCrumb></BreadCrumb>
</div>
<div>
<el-menu default-active=""
background-color="#545c64"
class="el-menu-demo"
mode="horizontal"
text-color="#ffffff">
<el-menu-item>
<i class="el-icon-s-platform"></i>大屏展示
</el-menu-item>
<el-menu-item>
<el-dropdown trigger="click">
<div style="height:100%;">
<i class="el-icon-user"></i>
<span style="color:#fff">超级管理员</span>
<i class="el-icon-caret-bottom" />
</div>
<el-dropdown-menu>
<!-- <el-dropdown-item>-->
<!-- <span style="display:block;">修改密码</span>-->
<!-- </el-dropdown-item>-->
<el-dropdown-item @click.native="logout">
<span style="display:block;">退出系统</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-menu-item>
</el-menu>
</div>
</div>
</template>
<script>
import BreadCrumb from "@/components/System/BreadCrumb.vue";
export default {
name: "AdminHeader",
components: {BreadCrumb},
data(){
return{
}
},
methods:{
logout(){
if(this.$cookie.get('adminName')){
this.$cookie.delete('adminName');
this.$router.push({
path:'/adminLogin'
})
}
},
handleMenu() {
// 相当于调用这个方法
this.$store.commit('CollapseMenu')
},
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,31 @@
<template>
<div style="display: flex;flex-direction: ">
</div>
</template>
<script>
import * as echarts from 'echarts'
import Vue from "vue";
Vue.prototype.$echarts = echarts;
export default {
data() {
return {
}
},
methods: {
},
mounted() {
}
}
</script>
<style scoped>
</style>

View File

@@ -1,24 +1,143 @@
<template>
<div class="adminLogin">
666
</div>
<el-form ref="ruleForm" class="login_container" :model="login" status-icon :rules="rules" label-width="70px">
<!-- h3要放在里面:只能有一个根,且title也是表单的一部分 -->
<h3 class="login_title">管理员登录</h3>
<!-- prop对应rules里的键 -->
<el-form-item label="账 户" prop="username">
<el-input v-model="login.username" auto-complete="off" placeholder='请输入用户名' clearable></el-input>
</el-form-item>
<el-form-item label="密 码" prop="password">
<el-input type="password" v-model="login.password" auto-complete="new-password"
placeholder='请输入密码'
clearable></el-input>
</el-form-item>
<el-form-item label="验 证" prop="code">
<el-input
prefix-icon="el-icon-mobile-phone"
type="text"
clearable
placeholder="点击图片更换验证码"
v-model="login.code"
class="vertify_code"
auto-complete="false"
style="width: 175px"
></el-input>
<!-- <span class="code">验证码</span> -->
<img :src="imageUrl" @click="resetImg" class="vertify_img"/>
</el-form-item>
<el-form-item>
<div style="display: flex;flex-direction: row;align-items: center;flex-wrap: nowrap;justify-content: space-between">
<el-button @click="resetForm('ruleForm')">重置</el-button>
<el-button @click="submit('ruleForm')" type="primary" style=";margin-top:10px">提交</el-button>
</div>
</el-form-item>
</el-form>
</template>
<script>
import axios from "axios";
import Vue from "vue";
export default {
name: "AdminLogin",
data: function () {
data() {
return {
imageUrl: "http://localhost:8082/helloGithub_war_exploded/VerifycodeServlet?" + new Date().getDate(),
// 登陆数据
login: {
username: '',
password: '',
code:'',
},
// 校验规则
rules: {
username: [{ required: 'true', message: '请输入用户名', trigger: 'blur' }],
password: [{ required: 'true', message: '请输入用户名', trigger: 'blur' }],
code: [{ required: 'true', message: '请输入验证码', trigger: 'blur' }],
}
}
},
methods: {
resetImg() {
this.imageUrl = "http://localhost:8082/helloGithub_war_exploded/VerifycodeServlet?" + new Date().getTime();
},
submit(formName){
var _this=this;
this.$refs[formName].validate((valid) => {
if (valid) {
//调用方法提交
axios({
method: 'post',
// 请求的地址
url: 'http://localhost:8082/helloGithub_war_exploded/adminLogin',
// URL 中的查询参数
params: {
adminname: this.login.username,
password: this.login.password,
code: this.login.code,
}
}).then(function (res) {
if (res.data.code === 200) {
Vue.prototype.$notify({
title: '成功',
message: ('i', {style: 'color: teal'}, res.data.msg),
type: 'success',
offset: 50
});
_this.$cookie.set('adminName',_this.login.username);
_this.$router.push({
path:'/systemIndex',
})
} else {
Vue.prototype.$notify.error({
title: '错误',
message: res.data.msg,
offset: 50
});
}
});
} else {
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
},
}
};
}
</script>
<style scoped>
.login_container {
width: 400px;
border: 1px solid #eaeaea;
margin: 100px auto;
padding: 35px 35px 15px 35px;
box-sizing: border-box;
border-radius: 15px;
background-color: #fff;
box-shadow: 0 0 25px #cac6c6;
.login_title {
color: #505458;
text-align: center;
margin-bottom: 40px;
}
.el-input {
width: 198px;
}
}
</style>

View File

@@ -0,0 +1,22 @@
<template>
<div class="tabs">
</div>
</template>
<script>
export default {
name: "AdminTags",
methods: {
},
computed: {
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,32 @@
<!--面包屑-->
<template>
<el-breadcrumb separator="/" >
<el-breadcrumb-item v-for="(item,index) in lists" :key="item.path">
<router-link style="color: #eeeeee" :to="item.path">{{item.meta.title}}</router-link>
</el-breadcrumb-item>
</el-breadcrumb>
</template>
<script>
export default {
name: "BreadCrumb",
data(){
return{
lists:[] //定义一个数组 用于接收路由信息
}
},
created() {
console.log(this.$route.matched)
this.lists = this.$route.matched //获取路由内的全部信息
},
//这里必须使用监听,否则无法实时获取路由变动信息。
// 监听后路由会实时变动,不然需要手动刷新路径才会改变
watch:{
$route(to,from) {
console.log(to)
this.lists = to.matched
}
},
}
</script>

View File

@@ -0,0 +1,13 @@
<template>
<div>文章管理</div>
</template>
<script>
export default {
name: "articleManage"
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,13 @@
<template>
<div>标签管理</div>
</template>
<script>
export default {
name: "categoryManage"
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,15 @@
<template>
<div>
评论管理
</div>
</template>
<script>
export default {
name: "commentManage"
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,15 @@
<template>
<div>
项目管理
</div>
</template>
<script>
export default {
name: "projectManage"
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,15 @@
<template>
<div>
系统管理
</div>
</template>
<script>
export default {
name: "systemManage"
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,15 @@
<template>
<div>
用户管理
</div>
</template>
<script>
export default {
name: "userManage"
}
</script>
<style scoped>
</style>

View File

@@ -6,6 +6,7 @@ import './assets/styles/element-variables.scss'
import axios from "axios";
import './assets/icon/iconfont.css'
import store from './store'
import * as echarts from 'echarts';//引入echarts
Vue.prototype.$echarts = echarts //引入组件

View File

@@ -11,6 +11,15 @@ import UserInfoPage from "@/components/User/UserInfoPage.vue";
import ProjectDetail from "@/components/Project/ProjectDetail.vue";
import ArticleDetail from "@/components/Paper/ArticleDetail.vue";
import adminLogin from "@/components/System/AdminLogin.vue";
import systemIndex from "@/views/systemIndex.vue";
import AdminHome from "@/components/System/AdminHome.vue";
import systemManage from "@/components/System/Manage/systemManage.vue";
import userManage from "@/components/System/Manage/userManage.vue";
import projectManage from "@/components/System/Manage/projectManage.vue";
import commentManage from "@/components/System/Manage/commentManage.vue";
import categoryManage from "@/components/System/Manage/categoryManage.vue";
import articleManage from "@/components/System/Manage/articleManage.vue";
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
@@ -79,14 +88,65 @@ const routes = [
path: '/adminLogin',
name: 'adminLogin',
component: adminLogin
}
}, {
path: '/systemIndex',
name: 'systemIndex',
component: systemIndex,
redirect: '/adminHome',
children: [
{
path: '/adminHome',
name: 'adminHome',
meta: {title: '首页'},
component: AdminHome
},
{
path: '/systemManage',
meta: {title: '系统管理'},
name: 'systemManage',
component: systemManage
},
{
path: '/userManage',
name: 'userManage',
meta: {title: '用户管理'},
component: userManage
},
{
path: '/projectManage',
meta: {title: '项目管理'},
name: 'projectManage',
component: projectManage
},
{
path: '/commentManage',
name: 'commentManage',
meta: {title: '评论管理'},
component: commentManage
},
{
path: '/categoryManage',
name: 'categoryManage',
meta: {title: '标签管理'},
component: categoryManage
},
{
path: '/articleManage',
meta: {title: '文章管理'},
name: 'articleManage',
component: articleManage
},
]
}
]
const router = new VueRouter({
mode:'history',
mode: 'history',
routes
})

View File

@@ -1,21 +1,18 @@
import Vue from 'vue'
import Vuex from 'vuex'
import Vue from "vue";
import Vuex from 'vuex';
Vue.use(Vuex)
// 创建Vuex实例并导出
export default new Vuex.Store({
state: {
// CookieUserName:""
},
getters: {
},
mutations: {
// saveCookieUserName(state,userName){
// state.pathName = userName;
// },
},
actions: {
},
modules: {
}
})
state: {
isCollapse: false,//导航栏是否折叠
},
mutations: {
// 修改导航栏展开和收起的方法
CollapseMenu(state) {
state.isCollapse = !state.isCollapse
},
}
})

37
src/views/systemIndex.vue Normal file
View File

@@ -0,0 +1,37 @@
<template>
<el-container style="width: 100%;height: 100%;position:fixed;top:0;left: 0;">
<el-aside width="200px" style="background: rgb(84, 92, 100);top:0;left: 0;">
<AdminAside></AdminAside>
</el-aside>
<el-container style="height:calc(100% - 60px)">
<el-header style="padding:0;">
<AdminHeader></AdminHeader>
</el-header>
<AdminTags></AdminTags>
<el-main>
<div style="border:1px solid red;">
<router-view></router-view>
</div>
</el-main>
</el-container>
</el-container>
</template>
<script>
import AdminHeader from "@/components/System/AdminHeader.vue";
import AdminAside from "@/components/System/AdminAside.vue";
import AdminTags from "@/components/System/AdminTags.vue";
export default {
name: "systemIndex",
components:{
AdminTags,
AdminAside,
AdminHeader
}
}
</script>
<style scoped>
</style>