实验面板

V0.1
yujialong 1 year ago
parent e62ecd40b3
commit eea2542e90
  1. 27
      package-lock.json
  2. 1
      package.json
  3. 16
      src/api/login.ts
  4. 8
      src/api/system.ts
  5. 1716
      src/components/Panel/index.vue
  6. 14
      src/permission.ts
  7. 3
      src/router/index.ts
  8. 30
      src/store/useCurrentUser.ts
  9. 2
      src/views/Home.vue
  10. 62
      src/views/Login.vue

27
package-lock.json generated

@ -1156,6 +1156,11 @@
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
"dev": true "dev": true
}, },
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
},
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz",
@ -1247,6 +1252,11 @@
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
"dev": true "dev": true
}, },
"cssfilter": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz",
"integrity": "sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw=="
},
"csstype": { "csstype": {
"version": "2.6.19", "version": "2.6.19",
"resolved": "https://registry.npmmirror.com/csstype/-/csstype-2.6.19.tgz", "resolved": "https://registry.npmmirror.com/csstype/-/csstype-2.6.19.tgz",
@ -3078,6 +3088,14 @@
"integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==",
"dev": true "dev": true
}, },
"mavon-editor": {
"version": "2.10.4",
"resolved": "https://registry.npmjs.org/mavon-editor/-/mavon-editor-2.10.4.tgz",
"integrity": "sha512-CFsBLkgt/KZBDg+SJYe2fyYv4zClY149PiwpH0rDAiiP4ae1XNs0GC8nBsoTeipsHcebDLN1QMkt3bUsnMDjQw==",
"requires": {
"xss": "^1.0.6"
}
},
"memoize-one": { "memoize-one": {
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz", "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz",
@ -5150,6 +5168,15 @@
"mkdirp": "^0.5.1" "mkdirp": "^0.5.1"
} }
}, },
"xss": {
"version": "1.0.14",
"resolved": "https://registry.npmjs.org/xss/-/xss-1.0.14.tgz",
"integrity": "sha512-og7TEJhXvn1a7kzZGQ7ETjdQVS2UfZyTlsEdDOqvQF7GoxNfY+0YLCzBy1kPdsDDx4QuNAonQPddpsn6Xl/7sw==",
"requires": {
"commander": "^2.20.3",
"cssfilter": "0.0.10"
}
},
"xtend": { "xtend": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz", "resolved": "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz",

@ -18,6 +18,7 @@
"element-plus": "^2.0.2", "element-plus": "^2.0.2",
"js-cookie": "^3.0.1", "js-cookie": "^3.0.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"mavon-editor": "^2.10.4",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"path-to-regexp": "^6.2.0", "path-to-regexp": "^6.2.0",
"tinymce": "^5.9.2", "tinymce": "^5.9.2",

@ -1,16 +0,0 @@
import axios from '@/utils/request';
export interface LoginParam {
username: string;
password: string;
browser?: boolean;
}
export interface RefreshTokenParam {
refreshToken: string;
browser?: boolean;
}
export const accountLogin = async (data: LoginParam): Promise<any> => (await axios.post('/auth/jwt/login', data)).data;
export const accountRefreshToken = async (data: RefreshTokenParam): Promise<any> => (await axios.post('/auth/jwt/refresh-token', data)).data;
export const queryCurrentUser = async (): Promise<any> => (await axios.get('/user/current')).data;

@ -0,0 +1,8 @@
import axios from '@/utils/request';
export const pageStuAssessment = async (data: Record<string, any>): Promise<any> => (await axios.post('/occupationlab/occupationlab/assessment/pageStuAssessment', data)).data;
export const getProjectBySystemId = async (data: Record<string, any>): Promise<any> =>
(await axios.get('/occupationlab/occupationlab/projectManage/getProjectBySystemId', data)).data;
export const getProjectDetail = async (data: Record<string, any>): Promise<any> => (await axios.get('/occupationlab/occupationlab/projectManage/getProjectDetail', data)).data;
export const getDetailById = async (id: number | string): Promise<any> => (await axios.get(`/occupationlab/occupationlab/assessment/getDetailById?id=${id}`)).data;
export const getCompetition = async (id: number | string): Promise<any> => (await axios.post(`/competition/competition/management/getCompetition?competitionId=${id}`)).data;

File diff suppressed because it is too large Load Diff

@ -3,7 +3,6 @@ import 'nprogress/nprogress.css'; // progress bar style
import { RouteLocationNormalized } from 'vue-router'; import { RouteLocationNormalized } from 'vue-router';
import getPageTitle from '@/utils/getPageTitle'; import getPageTitle from '@/utils/getPageTitle';
import { getAccessToken } from '@/utils/auth'; // get token from cookie import { getAccessToken } from '@/utils/auth'; // get token from cookie
import { hasCurrentUser, fetchCurrentUser, hasPermission } from '@/store/useCurrentUser';
import router from './router'; import router from './router';
NProgress.configure({ showSpinner: false }); // NProgress Configuration NProgress.configure({ showSpinner: false }); // NProgress Configuration
@ -20,19 +19,6 @@ router.beforeEach(async (to: RouteLocationNormalized) => {
NProgress.start(); NProgress.start();
return true; return true;
} }
// 需要权限
const toLogin = `${LOGIN_PATH}?redirect=${to.path}`;
// 未登录,跳转到登录页面
if (!isLogin) return toLogin;
NProgress.start();
if (!hasCurrentUser()) {
const user = await fetchCurrentUser();
// 没有获取到当前用户数据,代表accessToken已经失效,需要重新登录。
if (!user) {
NProgress.done();
return toLogin;
}
}
// 没有权限 // 没有权限
if (!hasPermission(to.meta?.requiresPermission)) { if (!hasPermission(to.meta?.requiresPermission)) {
NProgress.done(); NProgress.done();

@ -1,6 +1,5 @@
import { Component } from 'vue'; import { Component } from 'vue';
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'; import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
import { Document, Tools, UserFilled, Operation } from '@element-plus/icons-vue';
import Layout from '@/layout/index.vue'; import Layout from '@/layout/index.vue';
declare module 'vue-router' { declare module 'vue-router' {
@ -8,11 +7,9 @@ declare module 'vue-router' {
hidden?: boolean; hidden?: boolean;
title?: string; title?: string;
icon?: Component; icon?: Component;
// requiresPermission?: string;
} }
} }
export const routes: Array<RouteRecordRaw> = [ export const routes: Array<RouteRecordRaw> = [
// { path: '/product', component: () => import('@/views/product/index.vue'), meta: { hidden: true } },
{ path: '/404', component: () => import('@/views/404.vue'), meta: { hidden: true } }, { path: '/404', component: () => import('@/views/404.vue'), meta: { hidden: true } },
{ path: '/403', component: () => import('@/views/403.vue'), meta: { hidden: true } }, { path: '/403', component: () => import('@/views/403.vue'), meta: { hidden: true } },
{ {

@ -1,6 +1,5 @@
import { reactive, readonly } from 'vue'; import { reactive, readonly } from 'vue';
import { RouteRecordRaw } from 'vue-router'; import { RouteRecordRaw } from 'vue-router';
import { accountLogin, accountRefreshToken, LoginParam, queryCurrentUser } from '@/api/login';
import { setAccessToken, removeAccessToken, setAccessAt, setSessionTimeout, removeSessionTimeout } from '@/utils/auth'; import { setAccessToken, removeAccessToken, setAccessAt, setSessionTimeout, removeSessionTimeout } from '@/utils/auth';
export interface CurrentUser { export interface CurrentUser {
@ -13,38 +12,9 @@ export interface CurrentUser {
const state = reactive<CurrentUser>({}); const state = reactive<CurrentUser>({});
const setCurrentUser = (user: CurrentUser): void => {
Object.assign(state, user);
};
export const currentUser = readonly(state);
export const login = async (params: LoginParam): Promise<any> => {
const data = await accountLogin(params);
if (data.status === 0) {
const { result } = data;
const now = new Date().getTime();
setAccessToken(result.accessToken);
setSessionTimeout(result.sessionTimeout);
setAccessAt(now);
}
return data;
};
export const logout = (): void => { export const logout = (): void => {
removeAccessToken(); removeAccessToken();
removeSessionTimeout(); removeSessionTimeout();
setCurrentUser({});
};
export const fetchCurrentUser = async (): Promise<any> => {
const user = await queryCurrentUser();
if (user) {
setCurrentUser({ username: user.username, avatar: user.avatar, permissions: user.permissions, loginDate: user.loginDate, loginIp: user.loginIp });
} else {
removeAccessToken();
}
return user;
}; };
export const hasCurrentUser = (): boolean => state.username !== undefined; export const hasCurrentUser = (): boolean => state.username !== undefined;

@ -58,12 +58,14 @@
alt="" /> alt="" />
<div class="absolute bottom-2 right-1 w-[262px] h-[74px] bg-[url('@/assets/images/level/submit.png')] bg-[length:100%_100%] bg-no-repeat cursor-pointer hover:bg-[url('@/assets/images/level/submit-hover.png')]"></div> <div class="absolute bottom-2 right-1 w-[262px] h-[74px] bg-[url('@/assets/images/level/submit.png')] bg-[length:100%_100%] bg-no-repeat cursor-pointer hover:bg-[url('@/assets/images/level/submit-hover.png')]"></div>
</div> </div>
<!-- <Panel /> -->
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from 'vue'; import { ref, onMounted } from 'vue';
import { checkPointList } from '@/api/judgment'; import { checkPointList } from '@/api/judgment';
import Panel from '@/components/Panel';
const collected = ref<boolean>(false); const collected = ref<boolean>(false);
const levels = ref<Record<string, any>[]>([]); const levels = ref<Record<string, any>[]>([]);

@ -1,62 +0,0 @@
<template>
<div class="h-full p-3 bg-gray-100">
<el-form ref="form" :model="bean" class="mx-auto md:max-w-xs">
<h3 class="py-5 text-center text-3xl font-bold text-primary">UJCMS</h3>
<el-alert v-if="error" :title="error" type="error" class="mb-3" :closable="false" show-icon />
<el-form-item prop="username" :rules="[{ required: true, message: () => $t('v.required') }]">
<el-input ref="username" v-model="bean.username" type="text" name="username" :placeholder="$t('username')" :prefix-icon="User" autocomplete="on" />
</el-form-item>
<el-form-item prop="password" :rules="[{ required: true, message: () => $t('v.required') }]">
<el-input ref="password" v-model="bean.password" type="password" name="password" :placeholder="$t('password')" :prefix-icon="Lock" show-password />
</el-form-item>
<el-button type="primary" native-type="submit" class="w-full" :loading="loading" @click.prevent="handleLogin">{{ $t('login') }}</el-button>
</el-form>
</div>
</template>
<script setup lang="ts">
import { ref, watchEffect } from 'vue';
import { LocationQueryValue, useRoute, useRouter } from 'vue-router';
import { User, Lock } from '@element-plus/icons-vue';
import { login } from '@/store/useCurrentUser';
const form = ref<any>();
const bean = ref<any>({});
const error = ref<string | null>(null);
const loading = ref<boolean>(false);
const redirect = ref<string | null>(null);
const route = useRoute();
const router = useRouter();
if (import.meta.env.MODE === 'development') {
bean.value = { username: 'admin', password: 'password' };
} else if (import.meta.env.MODE === 'staging') {
bean.value = { username: 'demo', password: '123' };
}
watchEffect(() => {
redirect.value = route.query.redirect as LocationQueryValue;
});
const handleLogin = () => {
form.value.validate(async (valid: boolean) => {
if (!valid) return;
loading.value = true;
try {
const data = await login(bean.value);
//
if (data.status !== 0) {
error.value = data.message;
return;
}
if (redirect.value) {
router.push(redirect.value);
} else {
// 403 使 router.push 403
window.location.reload();
}
} finally {
loading.value = false;
}
});
};
</script>
Loading…
Cancel
Save