Vue\vue3_admin\src\main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' //持久化插件
// 引入element-plus插件与样式
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
// 配置element-plus 国际化 报红忽略://@ts-ignore
import zhCn from 'element-plus/es/locale/lang/zh-cn'
// 引入暗黑模式需要的样式
import 'element-plus/theme-chalk/dark/css-vars.css'
import App from './App.vue'
import router from './router'
// 获取应用实例对象
const app = createApp(App)
// 安装element-plus插件 并配置语言为zhCn中文
// app.use(ElementPlus)
app.use(ElementPlus, {
locale: zhCn,
})
// svg插件需要的配置代码
import 'virtual:svg-icons-register'
// 引用svg图标库 // 使用自定义组件全局注册
// import SvgIcon from '@/components/SvgIcon/index.vue'
// app.component('SvgIcon',SvgIcon)
// 引入自定义插件对象:注册整个项目全局组件
import allGloablComponent from '@/components/index'
// 安装自定义插件
app.use(allGloablComponent)
// 引入模板的全局样式
import '@/styles/main.scss'
// // 测试代码,测试假接口能否使用
// import axios from 'axios'
// axios({
// // 请求地址
// url: '/api/user/login',
// // 请求方式
// method: 'post',
// data: {
// username: 'admin',
// password: '111111'
// }
// })
//引入粒子效果开始
// import Particles from 'particles.vue3'
// app.use(Particles)
// 安装pinia插件并启用持久化插件
// app.use(createPinia())
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
app.use(pinia)
// 引入路由鉴权文件
import './permission'
// 初始化路由
import { anyRoutes } from './router/routes'
const userAsyncRoute = JSON.parse(localStorage.getItem('userAsyncRoute') as any) // 获取本地动态权限路由
if (userAsyncRoute && userAsyncRoute.length > 0) {
userAsyncRoute.forEach((route: any) => {
router.addRoute(route)
});
anyRoutes.forEach((route: any) => {
router.addRoute(route)
});
}
// 默认开启暗黑模式
if (!localStorage.getItem("darkMode")) {
localStorage.setItem("darkMode", String(true))
}
// console.log('main', router.getRoutes())
//引入自定义指令文件
import { isHasButton } from '@/directive/has'
isHasButton(app)
// 注册模板路由
app.use(router)
// 将应用挂载到挂载点上
app.mount('#app')
Vue\vue3_admin\vite.config.ts
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import VueDevTools from 'vite-plugin-vue-devtools'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import path from 'path'
// https://vitejs.dev/config/
// export default defineConfig({
// plugins: [
// vue(),
// vueJsx(),
// VueDevTools(),
// createSvgIconsPlugin({
// // Specify the icon folder to be cached
// iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
// // Specify symbolId format
// symbolId: 'icon-[dir]-[name]',
// }),
// ],
// base: './',
// resolve: {
// alias: {
// '@': fileURLToPath(new URL('./src', import.meta.url))
// }
// },
// css: {
// preprocessorOptions: {
// scss: {
// javascriptEnabled: true,
// additionalData: '@import "./src/styles/variables.scss";',
// },
// },
// },
// })
// import { UserConfigExport, ConfigEnv, loadEnv } from 'vite'
import { loadEnv } from 'vite'
import { viteMockServe } from 'vite-plugin-mock'
import VueSetupExtend from 'vite-plugin-vue-setup-extend'
// export default ({ command, mode }: ConfigEnv): UserConfigExport => {
// export default defineConfig(({ command, mode }) => {
export default defineConfig(({ mode }) => {
// 获取各种环境下对应的变量
const env = loadEnv(mode, process.cwd())
return {
esbuild:{//打包时去除console和debugger代码
drop:["console","debugger"]
},
plugins: [
vue(),
VueSetupExtend(),
vueJsx(),
VueDevTools(),
createSvgIconsPlugin({
// Specify the icon folder to be cached
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
// Specify symbolId format
symbolId: 'icon-[dir]-[name]',
}),
viteMockServe({
mockPath: 'mock',
enable: true,
}),
],
base: '/',
// base: './',
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
css: {
preprocessorOptions: {
scss: {
javascriptEnabled: true,
additionalData: '@import "./src/styles/variables.scss";',
},
},
},
server: {
proxy: {
// 字符串简写写法:http://localhost:5173/foo -> http://localhost:4567/foo
// '/foo': 'http://localhost:4567',
// 带选项写法:http://localhost:5173/api/bar -> http://jsonplaceholder.typicode.com/bar
[env.VITE_APP_BASE_API]: {
// 后端代理服务器地址
target: env.VITE_SERVER,
// 是否代理跨域
changeOrigin: true,
// 路径是否重写
// rewrite: (path) => path.replace(/^\/api/, ''),
},
// 正则表达式写法:http://localhost:5173/fallback/ -> http://jsonplaceholder.typicode.com/
// '^/fallback/.*': {
// target: 'http://jsonplaceholder.typicode.com',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/fallback/, ''),
// },
// // 使用 proxy 实例
// '/api': {
// target: 'http://jsonplaceholder.typicode.com',
// changeOrigin: true,
// configure: (proxy, options) => {
// // proxy 是 'http-proxy' 的实例
// }
// },
// // 代理 websockets 或 socket.io 写法:ws://localhost:5173/socket.io -> ws://localhost:5174/socket.io
// '/socket.io': {
// target: 'ws://localhost:5174',
// ws: true,
// },
},
},
}
})
Vue\vue3_admin.env.development
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'development'
VITE_APP_TITLE = '硅谷甄选运营平台'
VITE_APP_BASE_API = '/api'
# VITE_SERVER = 'http://168.12.1.50:5000'
VITE_SERVER = 'http://localhost:5000' # 常用工具包\Python_Pyjwt_Flask.py
Vue\vue3_admin\src\components\index.ts
//引入项目中全部的全局组件
import SvgIcon from './SvgIcon/index.vue'
import ProductCategory from './ProductCategory/index.vue'
//引入element-plus提供全部图标组件
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
//全局对象
const allGloablComponent: any = { SvgIcon, ProductCategory }
// console.log(Object.keys(allGloablComponent))
//对外暴露插件对象
export default {
//务必叫做install方法
install(app: any) {
//注册项目全部的全局组件
Object.keys(allGloablComponent).forEach((key) => {
//注册为全局组件
app.component(key, allGloablComponent[key])
})
//将element-plus提供图标注册为全局组件
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
// console.log(key, component)
app.component(key, component)
}
},
}
Vue\vue3_admin\src\styles\variables.scss
/**
* Variables
*/
// 左侧的菜单样式
$base-menu-width: 220px;
$base-menu-min-width: 80px;
$base-menu-background: #001529;
// $base-font-corlor: #001529;
$base-font-corlor: var(--base-font-corlor, #001529);
$base-menu-border-radius: 1px 2px 2px 1px;
// 左侧菜单按钮效果
$base-el-menu-background-color: transparent; // 默认背景透明
$base-el-menu-background-color-hover: rgb(28, 145, 208); // 悬停背景颜色
$base-el-menu-background-color-active: rgb(5, 121, 183); // 点击背景颜色
$base-el-menu-font-color: var(--base-el-menu-font-color, rgb(226, 149, 7)); // 菜单字体颜色
$base-el-menu-font-color-active: orangered; // 菜单激活字体颜色
$base-el-menu-font-weight: bold; // 字体粗细
$base-el-menu-font-size: 18px; // 默认字体大小
$base-el-menu-font-size-hover: 20px; // 悬停字体大小
$base-el-menu-font-size-active: 19px; // 点击后字体大小
$base-el-menu-filter-drop-shadow-hover: 0px 0px 8px white; // 悬停阴影
$base-el-menu-filter-drop-shadow-active: 0px 0px 10px black; // 点击阴影
// 左侧logo区域样式
$base-menu-logo-height: 50px;
$base-menu-logo-font-size: 20px;
// 顶部导航区域样式
$base-tabbar-height: 50px;
$base-tabbar-background: var(--base-tabbar-background, linear-gradient(to right, #8faecb, #17426a, #8faecb));
// $base-tabbar-background: var(--base-tabbar-background, linear-gradient(to right, #102131, #11283e, #102131));
// MAIN内容展示区域
$base-main-background: var(--base-main-background, rgb(181, 181, 181));
// $base-main-background: var(--base-main-background, rgb(79, 78, 78));
// 滚动条样式
$base-el-menu-scrollbar-color: orangered; // 滚动条颜色
// 全局过渡效果
$base-global-transition:
all 0.33s,
0s height;
// // 暗黑模式
// $is-dark-mode: false; // 默认设置为 false,表示不是暗黑模式
// // 当启用暗黑模式时,替换颜色
// @if $is-dark-mode {
// $base-font-corlor: white;
// }
/*
* Fonts
* ========================================================================== */
@import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@300&display=swap");
$font-family-google: "Open Sans", sans-serif;
/*设置英文字体*/
$font-family-default: Arial, Helvetica, sans-serif;
$font-family-title: Arial, Helvetica, sans-serif;
/*设置中文字体两种*/
/* 第一种设置方式 */
$font-family-zh: "Microsoft JhengHei", "微软雅黑", STXihei;
/* 第二种设置方式 */
$font-family-zh-hw: "华文细黑", "SimSun", "宋体";
$body-font: $font-family-default;
$body-font-weight: 400;
$header-font: $font-family-title;
$basic-font-size: 100%;
$paragraph: 16px;
// Golden ration for 16px font-size
$line-height: 24px;
// For REM / EM
//$basic-font-size: 62.5%;
//$paragraph: 1.6rem;
//$line-height: 2.4rem;
/*
* Palette
* ========================================================================== */
/*
* Basic Colors
* ========================================================================== */
$blue: #00f;
$red: #f00;
$white: #fff;
$black: #000;
$gray: #ccc;
/*
* Mixing Colors
* ========================================================================== */
$text-color: $black;
$inverted-text-color: $white;
Vue\vue3_admin\src\styles\typography.scss
@use 'variables' as *;
/**
* Typography
*/
html,
body {
font-family: $body-font;
font-weight: $body-font-weight;
}
html {
font-size: $basic-font-size;
}
body {
color: $text-color;
font-size: $paragraph;
line-height: $line-height;
}
h1,
h2,
h3 {
font-family: $header-font;
font-weight: 600;
}
html,
button,
input,
select,
textarea {
color: $text-color;
}
a {
color: $text-color;
text-decoration: none;
&:visited {
outline: 0;
}
&:focus,
&:active,
&:hover {
text-decoration: underline;
outline: 0;
}
}
i,
em {
font-style: italic;
}
b,
strong {
font-weight: bold;
}
.br {
display: block;
}
Vue\vue3_admin\src\styles\main.scss
@import "scss-reset/reset";
// @use '../node_modules/scss-reset/src/scss/_reset.scss';
// @import 'scss-reset/reset';
// <link rel="stylesheet" href="https://unpkg.com/scss-reset/reset.css">
// 'node_modules/scss-reset/src/scss/_variables.scss';
// 'node_modules/scss-reset/src/scss/_typography.scss';
// 全局样式
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
font-family: $body-font;
overflow: hidden; // 弹窗影响滚动条以上全局设置
}
// 全局样式
#app {
height: 100%;
overflow: auto; // 弹窗影响滚动条以上全局设置
}
// 气泡删除弹窗样式全局
.el-popconfirm__main {
font-size: 18px;
// 删除气泡图标
.el-popconfirm__icon {
font-size: 22px;
font-weight: bold;
}
}
// 滚动条外观设置
::-webkit-scrollbar {
width: 9px;
}
::-webkit-scrollbar-track {
background-color: $base-menu-background;
}
::-webkit-scrollbar-thumb {
width: 8px;
// background-color: $base-el-menu-scrollbar-color;
background-color: $base-el-menu-font-color;
border-radius: 5px;
}
// 折叠菜单弹出窗样式
.el-popper {
transition: all 0.35s;
.el-menu--popup-container {
border-radius: 5px;
border: 5px solid #001529;
margin: 0;
padding: 0;
.el-menu {
border-radius: 10px;
border: 5px solid #001529;
margin: 0;
padding: 0;
}
}
}
// ElMessage提示信息样式
.el-message {
margin-top: 50px;
.el-message__content {
font-size: 20px;
font-weight: bold;
}
}
// notification提示信息弹出窗样式
.el-form-item__error {
font-size: 18px;
font-weight: bold;
}
.success-message {
margin-top: 60px;
.el-notification__group {
.el-notification__title {
font-size: 20px;
color: green;
text-shadow: 2px 2px 2px $base-font-corlor;
}
.el-notification__content {
p {
font-size: 20px;
// font-weight: 300;
color: rgb(73, 128, 0);
}
}
}
}
.error-message {
margin-top: 60px;
.el-notification__group {
.el-notification__title {
font-size: 20px;
color: red;
text-shadow: 2px 2px 2px $base-font-corlor;
}
.el-notification__content {
p {
font-size: 20px;
// font-weight: 300;
color: rgb(205, 50, 50);
}
}
}
}
/*进度条效果*/
/* Make clicks pass-through */
#nprogress {
pointer-events: none;
}
#nprogress .bar {
// background: #29d;
background-image: linear-gradient(to right, cyan, pink, yellow, orangered, red);
position: fixed;
z-index: 1031;
top: 0;
left: 0;
width: 100%;
height: 2px;
}
/* Fancy blur effect */
#nprogress .peg {
display: block;
position: absolute;
right: 0px;
width: 100px;
height: 100%;
box-shadow:
0 0 10px #29d,
0 0 5px #29d;
opacity: 1;
-webkit-transform: rotate(3deg) translate(0px, -4px);
-ms-transform: rotate(3deg) translate(0px, -4px);
transform: rotate(3deg) translate(0px, -4px);
}
/* Remove these to get rid of the spinner */
#nprogress .spinner {
display: block;
position: fixed;
z-index: 1031;
top: 15px;
right: 15px;
}
#nprogress .spinner-icon {
width: 18px;
height: 18px;
box-sizing: border-box;
border: solid 2px transparent;
border-top-color: #29d;
border-left-color: #29d;
border-radius: 50%;
-webkit-animation: nprogress-spinner 400ms linear infinite;
animation: nprogress-spinner 400ms linear infinite;
}
.nprogress-custom-parent {
overflow: hidden;
position: relative;
}
.nprogress-custom-parent #nprogress .spinner,
.nprogress-custom-parent #nprogress .bar {
position: absolute;
}
@-webkit-keyframes nprogress-spinner {
0% {
-webkit-transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
}
}
@keyframes nprogress-spinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}