Vue\vue3_admin\src\main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
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)
app.use(ElementPlus, {
locale: zhCn,
})
import 'virtual:svg-icons-register'
import allGloablComponent from '@/components/index'
app.use(allGloablComponent)
import '@/styles/main.scss'
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))
}
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'
import { loadEnv } from 'vite'
import { viteMockServe } from 'vite-plugin-mock'
import VueSetupExtend from 'vite-plugin-vue-setup-extend'
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd())
return {
esbuild:{
drop:["console","debugger"]
},
plugins: [
vue(),
VueSetupExtend(),
vueJsx(),
VueDevTools(),
createSvgIconsPlugin({
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
symbolId: 'icon-[dir]-[name]',
}),
viteMockServe({
mockPath: 'mock',
enable: true,
}),
],
base: '/',
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
css: {
preprocessorOptions: {
scss: {
javascriptEnabled: true,
additionalData: '@import "./src/styles/variables.scss";',
},
},
},
server: {
proxy: {
[env.VITE_APP_BASE_API]: {
target: env.VITE_SERVER,
changeOrigin: 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'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
const allGloablComponent: any = { SvgIcon, ProductCategory }
export default {
install(app: any) {
Object.keys(allGloablComponent).forEach((key) => {
app.component(key, allGloablComponent[key])
})
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
},
}
Vue\vue3_admin\src\styles\variables.scss
$base-menu-width: 220px;
$base-menu-min-width: 80px;
$base-menu-background: #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;
$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-main-background: var(--base-main-background, rgb(181, 181, 181));
$base-el-menu-scrollbar-color: orangered;
$base-global-transition:
all 0.33s,
0s height;
@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;
$line-height: 24px;
$blue: #00f;
$red: #f00;
$white: #fff;
$black: #000;
$gray: #ccc;
$text-color: $black;
$inverted-text-color: $white;
Vue\vue3_admin\src\styles\typography.scss
@use 'variables' as *;
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";
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-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;
}
}
}
.el-message {
margin-top: 50px;
.el-message__content {
font-size: 20px;
font-weight: bold;
}
}
.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;
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;
color: rgb(205, 50, 50);
}
}
}
}
#nprogress {
pointer-events: none;
}
#nprogress .bar {
background-image: linear-gradient(to right, cyan, pink, yellow, orangered, red);
position: fixed;
z-index: 1031;
top: 0;
left: 0;
width: 100%;
height: 2px;
}
#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);
}
#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);
}
}