login page

This commit is contained in:
zy7y
2022-09-11 18:34:18 +08:00
commit a1c23c8cf8
52 changed files with 4149 additions and 0 deletions

View File

@@ -0,0 +1 @@
VITE_BASE_URL = /api

1
frontend/.env.production Normal file
View File

@@ -0,0 +1 @@
VITE_BASE_URL = http://127.0.0.1:8000/api/

28
frontend/.gitignore vendored Normal file
View 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
View File

@@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
}

39
frontend/README.md Normal file
View 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
View 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
View File

@@ -0,0 +1,10 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
},
"jsx": "preserve"
},
"exclude": ["node_modules", "dist"]
}

2883
frontend/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

24
frontend/package.json Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

12
frontend/src/App.vue Normal file
View File

@@ -0,0 +1,12 @@
<script setup>
import { RouterView } from 'vue-router'
</script>
<template>
<RouterView />
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,6 @@
body,html, #app{
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}

View 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
View 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')

View 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

View 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)
}

View 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}`
// }
// }
// })

View 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
View 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
}
}
}
})