diff --git a/package-lock.json b/package-lock.json index 37e26af..c806a0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,14 +21,17 @@ "markdown-loader": "^8.0.0", "marked": "^4.2.2", "mockjs": "^1.1.0", + "nprogress": "^0.2.0", "popper.js": "^1.16.1", "sass-loader": "^13.2.0", "showdown": "^2.1.0", "showdown-highlight": "^3.1.0", "vue": "^2.6.14", + "vue-avatar": "^2.3.3", "vue-router": "^3.6.5", "vue-simple-uploader": "^0.7.6", - "vuetify": "^2.6.12" + "vuetify": "^2.6.12", + "vuex": "^3.6.2" }, "devDependencies": { "@vue/cli-plugin-babel": "~5.0.0", @@ -8089,6 +8092,11 @@ "node": ">=4" } }, + "node_modules/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==" + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz", @@ -10546,6 +10554,15 @@ "csstype": "^3.1.0" } }, + "node_modules/vue-avatar": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/vue-avatar/-/vue-avatar-2.3.3.tgz", + "integrity": "sha512-Z57ILRTkFIAuCH9JiFBxX74C5zua5ub/jRDM/KZ+QKXNfscvmUOgWBs3kA2+wrpZMowIvfLHIT0gvQu1z+zpLg==", + "engines": { + "node": ">= 4.0.0", + "npm": ">= 3.0.0" + } + }, "node_modules/vue-hot-reload-api": { "version": "2.3.4", "resolved": "https://registry.npmmirror.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", @@ -10727,6 +10744,14 @@ "vue": "^2.6.4" } }, + "node_modules/vuex": { + "version": "3.6.2", + "resolved": "https://registry.npmmirror.com/vuex/-/vuex-3.6.2.tgz", + "integrity": "sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==", + "peerDependencies": { + "vue": "^2.0.0" + } + }, "node_modules/watchpack": { "version": "2.4.0", "resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.4.0.tgz", @@ -17835,6 +17860,11 @@ "path-key": "^2.0.0" } }, + "nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==" + }, "nth-check": { "version": "2.1.1", "resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz", @@ -19722,6 +19752,11 @@ "csstype": "^3.1.0" } }, + "vue-avatar": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/vue-avatar/-/vue-avatar-2.3.3.tgz", + "integrity": "sha512-Z57ILRTkFIAuCH9JiFBxX74C5zua5ub/jRDM/KZ+QKXNfscvmUOgWBs3kA2+wrpZMowIvfLHIT0gvQu1z+zpLg==" + }, "vue-hot-reload-api": { "version": "2.3.4", "resolved": "https://registry.npmmirror.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", @@ -19866,6 +19901,12 @@ "integrity": "sha512-qe3hcMpWmT1O15tp+p65lOS7UKZ/hQYQktCsw9iXx2u3RwVbX6GR82gY2iROrKsiAzYDvMgrYxWQwY/pUfkekw==", "requires": {} }, + "vuex": { + "version": "3.6.2", + "resolved": "https://registry.npmmirror.com/vuex/-/vuex-3.6.2.tgz", + "integrity": "sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==", + "requires": {} + }, "watchpack": { "version": "2.4.0", "resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.4.0.tgz", diff --git a/package.json b/package.json index 5d71940..807311c 100644 --- a/package.json +++ b/package.json @@ -20,14 +20,17 @@ "markdown-loader": "^8.0.0", "marked": "^4.2.2", "mockjs": "^1.1.0", + "nprogress": "^0.2.0", "popper.js": "^1.16.1", "sass-loader": "^13.2.0", "showdown": "^2.1.0", "showdown-highlight": "^3.1.0", "vue": "^2.6.14", + "vue-avatar": "^2.3.3", "vue-router": "^3.6.5", "vue-simple-uploader": "^0.7.6", - "vuetify": "^2.6.12" + "vuetify": "^2.6.12", + "vuex": "^3.6.2" }, "devDependencies": { "@vue/cli-plugin-babel": "~5.0.0", diff --git a/src/App.vue b/src/App.vue index 517befc..6ec8076 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,7 +1,97 @@ @@ -9,6 +99,10 @@ import Demo from './components/Demo.vue' import UserPage from './components/UserPage.vue' import RepoBrowser from './components/RepoBrowser.vue' +import page404 from './components/404.vue' +import Avatar from 'vue-avatar' +import store from '@/store' +import axios from '@/axios' export default { @@ -17,12 +111,131 @@ export default { Demo, UserPage, RepoBrowser, + page404, + Avatar, }, + + data: function(){ + return { + searchText: '', + + searchList:[ + // {agentName: "User_A",repoName: "searchResult",star: 1,fork: 0,authority: 1,ownerRepoId: ''} + ], + + starRepoList:[ + {"agentName":"User_A","authority":1,"fork":0,"ownerRepoId":"2666908d8f3dad76eb0b45899a556e0a071f32d7","repoName":"Repo_001","star":0}, + {"agentName":"User_A","authority":1,"fork":0,"ownerRepoId":"4a0f2acceaa4049a570bc52169fbd4683895af74","repoName":"qq","star":0}, + {"agentName":"User_B","authority":1,"fork":0,"ownerRepoId":"5d9f1778a1471c0f9cd24524dc0366756bc0041e","repoName":"Repo_002","star":0}, + {"agentName":"User_A","authority":1,"fork":0,"ownerRepoId":"2666908d8f3dad76eb0b45899a556e0a071f32d7","repoName":"Repo_001","star":0}, + {"agentName":"User_A","authority":1,"fork":0,"ownerRepoId":"4a0f2acceaa4049a570bc52169fbd4683895af74","repoName":"qq","star":0}, + {"agentName":"User_B","authority":1,"fork":0,"ownerRepoId":"5d9f1778a1471c0f9cd24524dc0366756bc0041e","repoName":"Repo_002","star":0}, + {"agentName":"User_A","authority":1,"fork":0,"ownerRepoId":"2666908d8f3dad76eb0b45899a556e0a071f32d7","repoName":"Repo_001","star":0}, + {"agentName":"User_A","authority":1,"fork":0,"ownerRepoId":"4a0f2acceaa4049a570bc52169fbd4683895af74","repoName":"qq","star":0}, + {"agentName":"User_B","authority":1,"fork":0,"ownerRepoId":"5d9f1778a1471c0f9cd24524dc0366756bc0041e","repoName":"Repo_002","star":0}, + {"agentName":"User_A","authority":1,"fork":0,"ownerRepoId":"2666908d8f3dad76eb0b45899a556e0a071f32d7","repoName":"Repo_001","star":0}, + {"agentName":"User_A","authority":1,"fork":0,"ownerRepoId":"4a0f2acceaa4049a570bc52169fbd4683895af74","repoName":"qq","star":0}, + {"agentName":"User_B","authority":1,"fork":0,"ownerRepoId":"5d9f1778a1471c0f9cd24524dc0366756bc0041e","repoName":"Repo_002","star":0}, + ] + }; + }, + computed: { key() { - return this.$route.fullPath + return this.$route.fullPath + }, + userName(){ + var userInfo = store.state.userName; + return userInfo; } - } + }, + + methods: { + enterSearchRepo: function(user, repoName){ + this.$router.push( + { + name: "RepoBrowser", + params:{ + userName: user, + repoParam: repoName, + branchName: "master", + queryPath: "root" + } + } + ) + + //console.log(this.$route.path) + }, + + async startSearch() { + await axios.get('/fuzzySearch/'+this.searchText).then((response)=>{ + this.searchList = response + }) + + }, + + checkVisibility: function(auth) { + if (auth === 1){ + return "public" + } else { + return "private" + } + }, + + extractColorByName(name) { + var temp = []; + temp.push("#"); + for (let index = 0; index < name.length; index++) { + temp.push(parseInt(name[index].charCodeAt(0), 10).toString(16)); + } + return temp.slice(0, 5).join('').slice(0, 4); + }, + + gotoUser(name) { + console.log('lllll=-------') + this.$router.push( + { + name: "UserPage", + params:{ + userName: name, + }, + query: { + path: +new Date() + } + } + ) + }, + + gotoLogin() { + this.$router.push( + { + name: "login", + } + ) + }, + + // 退出事件 + logout() { + this.$confirm('确定退出系统?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'info' + }).then(() => { + this.$store.dispatch('userLogout') + this.$message({ + type: 'success', + message: '退出成功!' + }) + location.reload() + }).catch(() => { + this.$message({ + type: 'info', + message: '已取消退出' + }) + }) + }, + + } } diff --git a/src/assets/github.png b/src/assets/github.png new file mode 100644 index 0000000..4e88f4e Binary files /dev/null and b/src/assets/github.png differ diff --git a/src/axios/index.js b/src/axios/index.js new file mode 100644 index 0000000..3b65bfb --- /dev/null +++ b/src/axios/index.js @@ -0,0 +1,56 @@ +import axios from 'axios' +// 引入进度条 +import nprogress from 'nprogress' +// 引入进度条的样式 +import 'nprogress/nprogress.css' +// 引入store +import store from '@/store' +// 创建axios实例 + +import router from '../router/index' + +nprogress.configure({ showSpinner: false }); + +const requests = axios.create({ + baseURL:"http://10.27.133.155:8080", + // 请求超时的时间 + timeout:5000, +}); + +// 请求拦截器 -- 在请求发出前做些事情 +requests.interceptors.request.use((config) => { + if(window.sessionStorage.getItem('Token')) { + console.log('has token') + console.log(window.sessionStorage.getItem('Token')) + config.headers.Token = window.sessionStorage.getItem('Token'); + } + nprogress.start(); + return config; +}); +// sdad + +// 响应拦截器 +requests.interceptors.response.use((res) => { + console.log('response') + console.log(res) + nprogress.done(); + return res.data; +},(err) => { + console.log('err response') + console.log(err) + console.log(err.response.status) + if (err.response.status === 401) { + alert('forbidden') + router.push({ + name: "404", + }) + } + if (err.response.status === 500 || err.response.status === 404) { + nprogress.done(); + } + nprogress.done(); + return false + // return Promise.reject(new Error('fail')) +}); + +export default requests; diff --git a/src/components/404.vue b/src/components/404.vue new file mode 100644 index 0000000..b702264 --- /dev/null +++ b/src/components/404.vue @@ -0,0 +1,40 @@ + + + \ No newline at end of file diff --git a/src/components/Demo.vue b/src/components/Demo.vue index fb0b5ec..741446c 100644 --- a/src/components/Demo.vue +++ b/src/components/Demo.vue @@ -1,50 +1,72 @@ \ No newline at end of file diff --git a/src/components/login.vue b/src/components/login.vue new file mode 100644 index 0000000..199825a --- /dev/null +++ b/src/components/login.vue @@ -0,0 +1,157 @@ + + + + > + + \ No newline at end of file diff --git a/src/main.js b/src/main.js index a256d50..420afd2 100644 --- a/src/main.js +++ b/src/main.js @@ -15,6 +15,11 @@ import 'highlight.js/styles/googlecode.css' //样式文件 import {lineNumbersBlock} from '@/highlight/highlight-line-number' import Vuetify from 'vuetify' import vuetify from './plugins/vuetify' +import store from "./store"; + +import nprogress from 'nprogress' +import 'nprogress/nprogress.css' +nprogress.configure({ showSpinner: false }); Vue.directive('highlight', { update(el){ @@ -33,6 +38,85 @@ Vue.directive('highlight', { } }) +// router.beforeEach(async (to, from, next) => { +// if (to.path ==='/login') next(); +// let token = window.sessionStorage.getItem('TOKEN'); +// console.log("the token is ->"); +// console.log(token); +// if(token) { +// // 登录 +// if(to.path === '/login') { +// // 登陆后访问登录页 +// next({path:from.path}); +// } else { +// // 登陆后访问非登录页 +// if(store.state.userName === '') { +// // 当空对象作为判断条件时,相当于true。当空对象与布尔值直接比较时,相当于true,但空数组与布尔值直接比较时是false +// // 登录后访问非登录页,如果此时用户信息由于页面刷新,store为空需要再次请求后端,拿到用户信息 +// try { +// await store.dispatch('getUserInfo'); +// next(); +// } catch (error) { +// // token过期 +// await store.dispatch('userLogout'); +// next({path:'/login'}); +// } +// } else { +// // 登录后访问非登录页,无刷新操作 +// next(); +// } +// } +// } else { +// // 未登录 +// Vue.prototype.$message({ +// type: "error", +// message: "请先登录" +// }); +// next('/login') +// } +// }) + + +const WhiteList = ["login","404"] +router.beforeEach((to, from, next) => { + nprogress.start(); + if (!WhiteList.includes(to.name)) { + let token = window.sessionStorage.getItem("Token") + console.log('now token is:') + console.log(token) + if (token) { + // if (!store.state.userName) { + // if (store.dispatch('getUserInfo')) { + // next() + // } else { + // Vue.prototype.$message({ + // type: "error", + // message: "请先登录" + // }); + // next('/login') + // } + // } + next() + } else { + Vue.prototype.$message({ + type: "error", + message: "请先登录" + }); + next('/login') + } + } else { + next() + } +}) + +router.afterEach(() => { + // 关闭进度条 + nprogress.done() +}) + + + + Vue.prototype.$http = axios Vue.config.productionTip = false @@ -41,10 +125,10 @@ Vue.use(uploader); Vue.use(jQuery); Vue.use(hljs); Vue.use(Vuetify); -// Vue.use(hljs.vuePlugin); new Vue({ vuetify, render: h => h(App), - router: router + router: router, + store }).$mount('#app') diff --git a/src/mock/index.js b/src/mock/index.js index c83af45..e07fc3a 100644 --- a/src/mock/index.js +++ b/src/mock/index.js @@ -45,7 +45,23 @@ let joey_userpage = Mock.mock({ "repoList": [{ "repoName": "OOAD_Project", "permission": "public", - "msg": "updated 1 days ago" + "msg": "updated 1 days ago", + "star": 2, + "fork": 1, + }, + { + "repoName": "Demo", + "permission": "public", + "msg": "updated 1 days ago", + "star": 1, + "fork": 0, + }, + { + "repoName": "Test", + "permission": "public", + "msg": "updated 1 days ago", + "star": 0, + "fork": 1, }, ], @@ -56,6 +72,8 @@ let joey_repo_root = Mock.mock({ "display": /list/, "branchList": [ {"branchName": "master"}, + {"branchName": "public"}, + {"branchName": "dev"}, ], "itemList": [ { @@ -81,6 +99,8 @@ let joey_repo_src = Mock.mock({ "display": /list/, "branchList": [ {"branchName": "master"}, + {"branchName": "public"}, + {"branchName": "dev"}, ], "itemList": [ { @@ -102,6 +122,8 @@ let joey_repo_public = Mock.mock({ "display": /list/, "branchList": [ {"branchName": "master"}, + {"branchName": "public"}, + {"branchName": "dev"}, ], "itemList": [ { @@ -117,6 +139,8 @@ let joey_repo_mock = Mock.mock({ "display": /list/, "branchList": [ {"branchName": "master"}, + {"branchName": "public"}, + {"branchName": "dev"}, ], "itemList": [ { @@ -133,6 +157,8 @@ let joey_repo_components = Mock.mock({ "display": /list/, "branchList": [ {"branchName": "master"}, + {"branchName": "public"}, + {"branchName": "dev"}, ], "itemList": [ { @@ -148,39 +174,74 @@ let joey_repo_components = Mock.mock({ // Mock.mock('http://localhost:8080/UserPage/JoeyZi1', () => { // return joey_userpage // }) - - -// Mock.mock(RegExp('/RepoBrowser/JoeyZi1/OOAD_Project/master/root_src_components'), () => { +// Mock.mock('http://localhost:8080/RepoBrowser/JoeyZi1/OOAD_Project/master/root_src_components', () => { // return joey_repo_components // }) - -// Mock.mock(RegExp('/RepoBrowser/JoeyZi1/OOAD_Project/master/root_src_mock'), () => { +// Mock.mock('http://localhost:8080/RepoBrowser/JoeyZi1/OOAD_Project/master/root_src_mock', () => { // return joey_repo_mock // }) - -// Mock.mock(RegExp('/RepoBrowser/JoeyZi1/OOAD_Project/master/root_src'), () => { +// Mock.mock('http://localhost:8080/RepoBrowser/JoeyZi1/OOAD_Project/master/root_src', () => { // return joey_repo_src // }) - -// Mock.mock(RegExp('/RepoBrowser/JoeyZi1/OOAD_Project/master/root_public'), () => { +// Mock.mock('http://localhost:8080/RepoBrowser/JoeyZi1/OOAD_Project/master/root_public', () => { // return joey_repo_public // }) +// Mock.mock('http://localhost:8080/RepoBrowser/JoeyZi1/OOAD_Project/master/root', () => { +// console.log("mock info") +// return joey_repo_root +// }) - -// Mock.mock(RegExp('/RepoBrowser/JoeyZi1/OOAD_Project/master/root'), () => { +// Mock.mock('http://10.27.133.155:8080/UserPage/JoeyZi1', () => { +// return joey_userpage +// }) +// Mock.mock('http://10.27.133.155:8080/RepoBrowser/JoeyZi1/OOAD_Project/master/root_src_components', () => { +// return joey_repo_components +// }) +// Mock.mock('http://10.27.133.155:8080/RepoBrowser/JoeyZi1/OOAD_Project/master/root_src_mock', () => { +// return joey_repo_mock +// }) +// Mock.mock('http://10.27.133.155:8080/RepoBrowser/JoeyZi1/OOAD_Project/master/root_src', () => { +// return joey_repo_src +// }) +// Mock.mock('http://10.27.133.155:8080/RepoBrowser/JoeyZi1/OOAD_Project/master/root_public', () => { +// return joey_repo_public +// }) +// Mock.mock('http://10.27.133.155:8080/RepoBrowser/JoeyZi1/OOAD_Project/master/root', () => { // console.log("mock info") // return joey_repo_root // }) +let img = Mock.mock({ + "Img": "@Image('900x900','@color', 'Random Image')", +}) + +const Random = Mock.Random + +Mock.mock(RegExp('http://10.27.133.155:8080/mock/'), "get", (options) =>{ + console.log('mock') + console.log(options); + console.log(options.url.split('/')); + var t = options.url.split('/') + var name = t[t.length-1] + console.log(name) + var temp = []; + temp.push("#"); + for (let index = 0; index < name.length; index++) { + temp.push(parseInt(name[index].charCodeAt(0), 10).toString(16)); + } + var s = String(temp.slice(0, 5).join('').slice(0, 4)); + console.log(s) + return Mock.mock({ + "Img": Random.image('500x500', s, '#fff',name), + }); +}); + + +//http://10.27.133.155:8080/mock/ let upload_response = Mock.mock({ "status": 200 -}) - -// Mock.mock(RegExp('http://127.0.0.1:8081/upload'), () => { -// console.log("accept file") -// return upload_response -// }) \ No newline at end of file +}) \ No newline at end of file diff --git a/src/router/index.js b/src/router/index.js index 231c990..b5a1433 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -3,6 +3,8 @@ import Demo from '../components/Demo.vue' import RepoBrowser from '../components/RepoBrowser.vue' import UserPage from '../components/UserPage.vue' import VueRouter from 'vue-router' +import page404 from '../components/404.vue' +import login from '../components/login.vue' Vue.use(VueRouter) @@ -10,7 +12,7 @@ const router = new VueRouter({ routes: [ { path: '/', - redirect: "UserPage/JoeyZi1" + redirect: "login" }, { path: '/UserPage/:userName', @@ -22,6 +24,17 @@ const router = new VueRouter({ name: "RepoBrowser", component: RepoBrowser }, + { + path: '/error', + component: page404, + name: "404", + hidden: true + }, + { + path: '/login', + name: "login", + component: login + }, ] }) diff --git a/src/store/index.js b/src/store/index.js new file mode 100644 index 0000000..1926fe1 --- /dev/null +++ b/src/store/index.js @@ -0,0 +1,90 @@ +import Vue from 'vue' +import Vuex from 'vuex' +import axios from '@/axios' +Vue.use(Vuex) + +// 2. 创建对象 +const store = new Vuex.Store({ + state:{ + userName:'', + token: '', + }, + mutations:{ + edit(state, username){ + state.userName = username + }, + USERLOGIN(state,token){ + state.token = token; + }, + USERNAME(state,userName){ + state.userName = userName; + }, + }, + actions:{ + async userLogin(context,form){ + var judge = false; + var token; + // 发送登录请求 + await axios.get('/login/signin/'+ form.account + '/' + form.passWord).then((response)=>{ + judge = response.Login + token = response.Token + }) + if(judge) { + // 存放token + context.commit('USERLOGIN',token); + // localStorage.setItem('Token',token) + window.sessionStorage.removeItem('Token') + window.sessionStorage.setItem('Token', token) + + + //记录用户信息 + context.commit('USERNAME', form.account); + return judge; + } else { + // 登录失败 + return judge; + } + }, + + userLogout(context) { + return new Promise(resolve => { + context.commit('USERLOGIN', ''); + + // localStorage.removeItem('Token'); + // console.log("--------after remove storage-------"); + // console.log(localStorage.getItem('Token')); + // console.log("--------after remove storage-------"); + + context.commit('USERNAME', ''); + window.sessionStorage.removeItem('Token'); + resolve() + }) + + }, + + // getUserInfo() { + // let result = axios.get('/CheckToken').then((response)=>{ + // context.commit('USERNAME',response.name); + // if (response.name === null || response.name === "" || response.name === undefined){ + // return false + // } else { + // return true + // } + // }).catch(function (error) { + // return false + // }); + // return false; + // } + + }, + getters:{ + + }, + modules:{ + + } + +}) + +// 3. 导出store对象 +export default store \ No newline at end of file