login page
This commit is contained in:
1
frontend/.env.development
Normal file
1
frontend/.env.development
Normal file
@@ -0,0 +1 @@
|
||||
VITE_BASE_URL = /api
|
1
frontend/.env.production
Normal file
1
frontend/.env.production
Normal file
@@ -0,0 +1 @@
|
||||
VITE_BASE_URL = http://127.0.0.1:8000/api/
|
28
frontend/.gitignore
vendored
Normal file
28
frontend/.gitignore
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
coverage
|
||||
*.local
|
||||
|
||||
/cypress/videos/
|
||||
/cypress/screenshots/
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
3
frontend/.vscode/extensions.json
vendored
Normal file
3
frontend/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
|
||||
}
|
39
frontend/README.md
Normal file
39
frontend/README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# frontend
|
||||
|
||||
This template should help get you started developing with Vue 3 in Vite.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
|
||||
|
||||
## Customize configuration
|
||||
|
||||
See [Vite Configuration Reference](https://vitejs.dev/config/).
|
||||
|
||||
## Project Setup
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compile and Hot-Reload for Development
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Compile and Minify for Production
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
### 极简的权限管理
|
||||
1. 前端项目参考Vue-elment-admin
|
||||
|
||||
#### 系统管理
|
||||
- [] 用户管理
|
||||
- [] 角色管理
|
||||
- [] 菜单管理
|
||||
|
||||
#### 系统设置
|
||||
- [] 系统监控
|
13
frontend/index.html
Normal file
13
frontend/index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite App</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
10
frontend/jsconfig.json
Normal file
10
frontend/jsconfig.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"],
|
||||
},
|
||||
"jsx": "preserve"
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
2883
frontend/package-lock.json
generated
Normal file
2883
frontend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
24
frontend/package.json
Normal file
24
frontend/package.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "frontend",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview --port 4173"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.27.2",
|
||||
"element-plus": "^2.2.16",
|
||||
"normalize.css": "^8.0.1",
|
||||
"pinia": "^2.0.21",
|
||||
"pinia-plugin-persistedstate": "^2.2.0",
|
||||
"vue": "^3.2.38",
|
||||
"vue-router": "^4.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^3.0.3",
|
||||
"unplugin-auto-import": "^0.11.2",
|
||||
"unplugin-vue-components": "^0.22.4",
|
||||
"vite": "^3.0.9"
|
||||
}
|
||||
}
|
BIN
frontend/public/favicon.ico
Normal file
BIN
frontend/public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
12
frontend/src/App.vue
Normal file
12
frontend/src/App.vue
Normal file
@@ -0,0 +1,12 @@
|
||||
<script setup>
|
||||
import { RouterView } from 'vue-router'
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RouterView />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
6
frontend/src/assets/base.css
Normal file
6
frontend/src/assets/base.css
Normal file
@@ -0,0 +1,6 @@
|
||||
body,html, #app{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
1
frontend/src/assets/logo.svg
Normal file
1
frontend/src/assets/logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69" xmlns:v="https://vecta.io/nano"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>
|
After Width: | Height: | Size: 308 B |
15
frontend/src/main.js
Normal file
15
frontend/src/main.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import { createApp } from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
||||
import 'normalize.css'
|
||||
import '@/assets/base.css'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
app.use(createPinia())
|
||||
app.use(router)
|
||||
|
||||
app.mount('#app')
|
17
frontend/src/router/index.js
Normal file
17
frontend/src/router/index.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/login',
|
||||
component: () => import('@/views/login.vue')
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
routes: routes
|
||||
})
|
||||
|
||||
export default router
|
36
frontend/src/service/request.js
Normal file
36
frontend/src/service/request.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import axios from "axios";
|
||||
import {message, ElLoading} from 'element-plus'
|
||||
import userStore from '@/stores/user'
|
||||
|
||||
|
||||
const store = userStore()
|
||||
|
||||
export default (config) => {
|
||||
|
||||
const instance = axios.create({
|
||||
baseURL: import.meta.env.VITE_BASE_URL,
|
||||
timeout: 5000,
|
||||
})
|
||||
|
||||
instance.interceptors.request.use(config => {
|
||||
ElLoading.service({
|
||||
title: '请求中.'
|
||||
})
|
||||
config.headers.Authorization = store.accessToken
|
||||
return config
|
||||
})
|
||||
|
||||
instance.interceptors.response.use(res => {
|
||||
if (res.data.code !== 20000 ){
|
||||
message.error(res.data.msg)
|
||||
}
|
||||
ElLoading.close()
|
||||
return res.data
|
||||
}, err => {
|
||||
message.error(err)
|
||||
ElLoading.close()
|
||||
return Promise.reject(err)
|
||||
})
|
||||
|
||||
return instance(config)
|
||||
}
|
23
frontend/src/stores/user.js
Normal file
23
frontend/src/stores/user.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import { ref, computed } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const userStore = defineStore('user', () => {
|
||||
const info = ref({})
|
||||
const token = ref("")
|
||||
const accessToken = computed(() => 'Bearer ' + token)
|
||||
|
||||
return { info, token, accessToken }
|
||||
}, {
|
||||
persist: true,
|
||||
})
|
||||
|
||||
// export const userStore = defineStore('user',{
|
||||
// state: () => ({
|
||||
// token: ""
|
||||
// }),
|
||||
// getters: {
|
||||
// accessToken() {
|
||||
// return `Bearer ${this.token}`
|
||||
// }
|
||||
// }
|
||||
// })
|
79
frontend/src/views/login.vue
Normal file
79
frontend/src/views/login.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<script setup>
|
||||
import { User, Lock } from '@element-plus/icons-vue'
|
||||
import {ref,reactive} from 'vue'
|
||||
|
||||
// 表单配置
|
||||
const rules = {
|
||||
username: [
|
||||
{required: true, message: '请输入用户名', trigger: 'blur'},
|
||||
{min:5, max:20, message: '5~20', trigger: 'blur'}
|
||||
],
|
||||
password: [
|
||||
{required: true, message: '请输入密码', trigger: 'blur'},
|
||||
{min:6, max:12, message: '6~12', trigger: 'blur'}
|
||||
]
|
||||
}
|
||||
|
||||
// 响应式数据
|
||||
const formRef = ref()
|
||||
const formData = reactive({
|
||||
username: 'admin',
|
||||
password: '123456'
|
||||
})
|
||||
|
||||
// 事件
|
||||
const submitForm = (formEl) => {
|
||||
if (!formEl) return
|
||||
formEl.validate( valid => {
|
||||
if (valid) {
|
||||
// 验证通过
|
||||
console.log('submit!')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="login">
|
||||
<div class="continer">
|
||||
<h1>Mini RBAC</h1>
|
||||
<el-form ref="formRef" :model="formData" :rules="rules" status-icon>
|
||||
<el-form-item prop="username">
|
||||
<el-input placeholder="用户名" clearable :prefix-icon="User"
|
||||
v-model.trim="formData.username"/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input placeholder="密码" show-password :prefix-icon="Lock"
|
||||
v-model.trim="formData.password"/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="submitForm(formRef)" >登录</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.login {
|
||||
display: flex;
|
||||
background-color: #2d3a4b;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.continer {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
}
|
||||
.continer h1{
|
||||
color: #fff;
|
||||
}
|
||||
.continer .el-button {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
34
frontend/vite.config.js
Normal file
34
frontend/vite.config.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import { fileURLToPath, URL } from 'node:url'
|
||||
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import AutoImport from 'unplugin-auto-import/vite'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [vue(), AutoImport({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
}), Components({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
}),],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
}
|
||||
},
|
||||
server: {
|
||||
proxy: { // 代理
|
||||
'/api': {
|
||||
target: 'http://localhost:8000',
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => path.replace(/^\/api/, '')
|
||||
},
|
||||
'/socket.io': {
|
||||
target: 'ws://localhost:5000',
|
||||
ws: true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
Reference in New Issue
Block a user