更新依赖和一些基础的功能

This commit is contained in:
2025-05-15 21:24:56 +08:00
parent 6b9faa702b
commit 7efc3dfd67
12 changed files with 1297 additions and 43 deletions

View File

@@ -1,38 +1,10 @@
<script setup>
import HelloWorld from './components/HelloWorld.vue'
</script>
<template>
<div class="bg-gray-100 min-h-screen">
<header class="bg-gradient-to-r from-blue-500 to-indigo-600 text-white py-4 px-6 flex items-center justify-between">
<div class="flex items-center space-x-4">
<!-- Logo -->
<img src="https://via.placeholder.com/40" alt="Logo" class="h-8 w-8 rounded-full">
<span class="font-bold">My App</span>
</div>
<!-- Menu -->
<nav class="hidden md:flex space-x-4">
<a href="#" class="hover:text-gray-300">Home</a>
<a href="#" class="hover:text-gray-300">About</a>
<a href="#" class="hover:text-gray-300">Services</a>
<a href="#" class="hover:text-gray-300">Contact</a>
</nav>
<!-- User Profile -->
<div class="flex items-center space-x-4">
<button class="text-sm bg-gray-800 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded">
Personal Center
</button>
<img src="https://via.placeholder.com/40" alt="User Avatar" class="h-8 w-8 rounded-full cursor-pointer">
</div>
</header>
<main class="p-6">
<slot></slot>
</main>
</div>
<router-view />
</template>
<style scoped>
<style lang='scss' scoped>
</style>

75
src/api/request.js Normal file
View File

@@ -0,0 +1,75 @@
import axios from 'axios';
import {message as msg} from "ant-design-vue";
// 创建 Axios 实例
const service = axios.create({
baseURL: '/api/', // 这里可以设置你的 API 基础地址
timeout: 5000 // 请求超时时间
});
// 请求拦截器
service.interceptors.request.use(
config => {
// 从本地存储中获取 token
const token = localStorage.getItem('token');
if (token) {
// 设置请求头中的 Authorization
config.headers['Authorization'] = `Bearer ${token}`;
}
return config;
},
error => {
console.log(error); // 打印错误信息
return Promise.reject(error);
}
);
// 响应拦截器
service.interceptors.response.use(
response => {
const {code, result, message} = response.data;
if (code === 0) {
return result;
} else {
if (code === 401) {
msg.error(message).then(r => {
localStorage.removeItem('token');
localStorage.removeItem('user');
window.location.href = '/'
msg.destroy()
})
return;
}
msg.error(message).then(r => {
msg.destroy()
})
}
},
error => {
console.log('err' + error); // 打印错误信息
return Promise.reject(error);
}
);
// 封装 get 请求
const get = (url, params = {}) => {
return service.get(url, { params });
};
// 封装 post 请求
const post = (url, data = {}) => {
return service.post(url, data);
};
// 封装上传文件请求
const upload = (url, file) => {
const formData = new FormData();
formData.append('file', file);
return service.post(url, formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
};
export { get, post, upload };

10
src/api/request/upload.js Normal file
View File

@@ -0,0 +1,10 @@
import {upload} from '../request.js'
const prefix = 'upload'
export function uploadImageApi(credentials) {
return upload(`${prefix}/image`, credentials)
}
export function uploadVideoApi(credentials) {
return upload(`${prefix}/video`, credentials)
}

92
src/api/request/user.js Normal file
View File

@@ -0,0 +1,92 @@
import {get, post} from '../request.js'
const prefix = 'user'
/**
* 登录
* @param credentials
* @returns {Promise<axios.AxiosResponse<any>>}
*/
export function loginApi(credentials) {
return post('login', credentials)
}
/**
* 注册
* @param credentials
* @returns {Promise<axios.AxiosResponse<any>>}
*/
export function registerApi(credentials) {
return post('register', credentials)
}
/**
* 获取用户列表
* @param credentials
* @returns {Promise<axios.AxiosResponse<any>>}
*/
export function userListApi(credentials) {
return get(`${prefix}/list`, credentials)
}
/**
* 获取当前登录用户信息
* @param credentials
* @returns {Promise<axios.AxiosResponse<any>>}
*/
export function userMyInfoApi(credentials) {
return get(`${prefix}/my-info`, credentials)
}
/**
* 获取用户统计信息
* @param credentials
* @returns {Promise<axios.AxiosResponse<any>>}
*/
export function userStatsApi(credentials) {
return get(`${prefix}/user-stats`, credentials)
}
/**
* 创建用户
* @param credentials
* @returns {Promise<axios.AxiosResponse<any>>}
*/
export function createUserApi(credentials) {
return post(`${prefix}/create`, credentials)
}
/**
* 更新用户
* @param credentials
* @returns {Promise<axios.AxiosResponse<any>>}
*/
export function updateUserApi(credentials) {
return post(`${prefix}/update`, credentials)
}
/**
* 删除用户
* @param credentials
* @returns {Promise<axios.AxiosResponse<any>>}
*/
export function deleteUserApi(credentials) {
return post(`${prefix}/delete`, credentials)
}
/**
* 重置密码
* @param credentials
* @returns {Promise<axios.AxiosResponse<any>>}
*/
export function resetPasswordApi(credentials) {
return post(`${prefix}/reset-password`, credentials)
}
/**
* 重置密码
* @param credentials
* @returns {Promise<axios.AxiosResponse<any>>}
*/
export function changePasswordApi(credentials) {
return post(`${prefix}/change-password`, credentials)
}

32
src/layouts/Header.vue Normal file
View File

@@ -0,0 +1,32 @@
<script setup lang="ts">
</script>
<template>
<header class="bg-gradient-to-r from-blue-500 to-indigo-600 text-white py-4 px-6 flex items-center justify-between">
<div class="flex items-center space-x-4">
<!-- Logo -->
<img src="https://via.placeholder.com/40" alt="Logo" class="h-8 w-8 rounded-full">
<span class="font-bold">My App</span>
</div>
<!-- Menu -->
<nav class="hidden md:flex space-x-4">
<a href="#" class="hover:text-gray-300">首页</a>
<a href="#" class="hover:text-gray-300">About</a>
<a href="#" class="hover:text-gray-300">Services</a>
<a href="#" class="hover:text-gray-300">Contact</a>
</nav>
<!-- User Profile -->
<div class="flex items-center space-x-4">
<button class="text-sm bg-gray-800 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded">
Personal Center
</button>
<img src="https://via.placeholder.com/40" alt="User Avatar" class="h-8 w-8 rounded-full cursor-pointer">
</div>
</header>
</template>
<style lang="scss" scoped>
</style>

View File

@@ -1,5 +1,16 @@
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import Antd from 'ant-design-vue'
import './style.css'
import App from './App.vue'
// 注册路由
import router from './router'
createApp(App).mount('#app')
const app = createApp(App)
// 注册Ant Design组件
app.use(createPinia())
app.use(router)
app.use(Antd)
app.mount('#app')

38
src/router/index.js Normal file
View File

@@ -0,0 +1,38 @@
import { createRouter, createWebHistory } from 'vue-router'
import { useUserStore } from '@/stores/user'
import MainLayout from '@/layouts/Header.vue'
// 在路由配置中添加个人中心路由
const routes = [
{
path: '/',
component: MainLayout,
children: [
{ path: '', name: 'Home', component: () => import('@/views/index/index.vue') },
]
},
]
const router = createRouter({
history: createWebHistory(),
routes,
scrollBehavior(to, from, savedPosition) {
return savedPosition || { top: 0 }
}
})
router.beforeEach((to, from) => {
const userStore = useUserStore()
if (to.meta.requiresAuth && !userStore.user) {
return { name: 'Login', query: { redirect: to.fullPath } }
}
})
export default router
router.beforeEach((to, from) => {
const userStore = useUserStore()
if (to.meta.requiresAuth && !userStore.user) {
return { name: 'Login', query: { redirect: to.fullPath } }
}
})

87
src/stores/user.js Normal file
View File

@@ -0,0 +1,87 @@
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import {loginApi, registerApi} from "@/api/request/user.js";
import {message, notification} from "ant-design-vue";
export const useUserStore = defineStore('user', () => {
const user = ref(JSON.parse(localStorage.getItem('user') || 'null'))
const modal = ref(localStorage.getItem('authModal') || 'false')
// 添加初始化状态校验
const initUser = () => {
const userData = localStorage.getItem('user')
if (!userData) return null
try {
return JSON.parse(userData)
} catch {
localStorage.removeItem('user')
localStorage.removeItem('token')
return null
}
}
const isAuthenticated = computed(() => !!user.value?.nick_name)
function login(credentials, functionName) {
console.log(functionName, 'sssssssssssss')
loginApi({
account: credentials.username,
password: credentials.password,
remember: credentials.remember,
}).then((res) => {
const userData = {
nick_name: res.nick_name,
role_name: res.role_name,
role_value: res.role_value,
}
user.value = userData;
localStorage.setItem('user', JSON.stringify(userData))
localStorage.setItem('token', res.token)
notification.success({
message: '登录成功',
description: `欢迎回来${res.nick_name}`,
})
functionName()
})
}
function register(credentials, functionName) {
registerApi({
account: credentials.username,
password: credentials.password,
email: credentials.email,
code: credentials.code,
}).then((res) => {
const userData = {
nick_name: res.nick_name,
role_name: res.role_name,
role_value: res.role_value,
}
user.value = userData;
localStorage.setItem('user', JSON.stringify(userData))
localStorage.setItem('token', res.token)
message.success('注册成功')
functionName()
})
}
function logout() {
user.value = null
localStorage.removeItem('user')
localStorage.removeItem('token')
}
function setModal(value) {
modal.value = modal.value === 'false' ? 'true' : 'false';
localStorage.setItem('authModal', value)
}
return {
modal,
user,
isAuthenticated,
setModal,
login,
register,
logout
}
})

11
src/views/index/index.vue Normal file
View File

@@ -0,0 +1,11 @@
<script setup lang="ts">
</script>
<template>
你好
</template>
<style scoped>
</style>