This commit is contained in:
Lau-Laptop\Lau 2023-12-18 17:59:40 +08:00
commit e1695ce65b
29 changed files with 6581 additions and 0 deletions

4
.env.development Normal file
View File

@ -0,0 +1,4 @@
NODE_ENV = development
VITE_APP_TITLE = 标题
VITE_BASE_URL = /
VITE_API_BASE_URL = /api

4
.env.production Normal file
View File

@ -0,0 +1,4 @@
NODE_ENV = production
VITE_APP_TITLE = 标题
VITE_BASE_URL = ./
VITE_API_BASE_URL = /api

14
.eslintrc.cjs Normal file
View File

@ -0,0 +1,14 @@
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
root: true,
'extends': [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-prettier/skip-formatting'
],
parserOptions: {
ecmaVersion: 'latest'
}
}

30
.gitignore vendored Normal file
View File

@ -0,0 +1,30 @@
# 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?
*.tsbuildinfo

8
.prettierrc.json Normal file
View File

@ -0,0 +1,8 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"semi": false,
"tabWidth": 2,
"singleQuote": true,
"printWidth": 100,
"trailingComma": "none"
}

8
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,8 @@
{
"recommendations": [
"Vue.volar",
"Vue.vscode-typescript-vue-plugin",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}

44
README.md Normal file
View File

@ -0,0 +1,44 @@
# vue3-template
基于vite的vue3 项目基础模板
vue33.3.11
vue-router4.2.5
pinia2.1.7
element-plus2.4.4
store持久化存储pinia-plugin-persistedstate 3.2.1
https://prazdevs.github.io/pinia-plugin-persistedstate/guide/config.html
mitt3.0.1
## Customize configuration
vite配置 [Vite Configuration Reference](https://vitejs.dev/config/).
## 项目初始化
```sh
npm install
```
### 运行dev服务
```sh
npm run dev
```
### 构建项目
```sh
npm run build
```
### eslint检测 [ESLint](https://eslint.org/)
```sh
npm run lint
```

13
index.html Normal file
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="zh-hans">
<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>

8
jsconfig.json Normal file
View File

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

6059
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

36
package.json Normal file
View File

@ -0,0 +1,36 @@
{
"name": "vue3-template",
"version": "0.1.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite --mode development",
"serve": "vite --mode development",
"build": "vite build --mode production",
"preview": "vite preview --mode development",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore",
"format": "prettier --write src/"
},
"dependencies": {
"axios": "^1.6.2",
"element-plus": "^2.4.4",
"mitt": "^3.0.1",
"pinia": "^2.1.7",
"pinia-plugin-persistedstate": "^3.2.1",
"qs": "^6.11.2",
"vue": "^3.3.11",
"vue-router": "^4.2.5"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.3.3",
"@vitejs/plugin-vue": "^4.5.2",
"@vue/eslint-config-prettier": "^8.0.0",
"eslint": "^8.49.0",
"eslint-plugin-vue": "^9.17.0",
"prettier": "^3.0.3",
"sass": "^1.69.5",
"unplugin-auto-import": "^0.17.2",
"unplugin-vue-components": "^0.26.0",
"vite": "^5.0.10"
}
}

BIN
public/api/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

7
src/App.vue Normal file
View File

@ -0,0 +1,7 @@
<script setup></script>
<template>
<RouterView />
</template>
<style scoped></style>

15
src/api/login.js Normal file
View File

@ -0,0 +1,15 @@
import http from '@/utils/http'
/**
* @function login 登录接口
* @param {Object} data 登录数据
* @param {String} data.account 账号
* @param {String} data.password 密码
* */
export const login = (data) => {
return http({
url: '/login',
method: 'post',
data
})
}

14
src/api/test.js Normal file
View File

@ -0,0 +1,14 @@
import http from '@/utils/http'
/**
* @returns {AxiosPromise}
* */
export const getTest = () => {
return http({
url: '/favicon.ico',
method: 'get',
params: {
t: Date.now()
}
})
}

86
src/assets/base.css Normal file
View File

@ -0,0 +1,86 @@
/* color palette from <https://github.com/vuejs/theme> */
:root {
--vt-c-white: #ffffff;
--vt-c-white-soft: #f8f8f8;
--vt-c-white-mute: #f2f2f2;
--vt-c-black: #181818;
--vt-c-black-soft: #222222;
--vt-c-black-mute: #282828;
--vt-c-indigo: #2c3e50;
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
--vt-c-text-light-1: var(--vt-c-indigo);
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
--vt-c-text-dark-1: var(--vt-c-white);
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
}
/* semantic color variables for this project */
:root {
--color-background: var(--vt-c-white);
--color-background-soft: var(--vt-c-white-soft);
--color-background-mute: var(--vt-c-white-mute);
--color-border: var(--vt-c-divider-light-2);
--color-border-hover: var(--vt-c-divider-light-1);
--color-heading: var(--vt-c-text-light-1);
--color-text: var(--vt-c-text-light-1);
--section-gap: 160px;
}
@media (prefers-color-scheme: dark) {
:root {
--color-background: var(--vt-c-black);
--color-background-soft: var(--vt-c-black-soft);
--color-background-mute: var(--vt-c-black-mute);
--color-border: var(--vt-c-divider-dark-2);
--color-border-hover: var(--vt-c-divider-dark-1);
--color-heading: var(--vt-c-text-dark-1);
--color-text: var(--vt-c-text-dark-2);
}
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
font-weight: normal;
}
body {
min-height: 100vh;
color: var(--color-text);
background: var(--color-background);
transition:
color 0.5s,
background-color 0.5s;
line-height: 1.6;
font-family:
Inter,
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
Oxygen,
Ubuntu,
Cantarell,
'Fira Sans',
'Droid Sans',
'Helvetica Neue',
sans-serif;
font-size: 15px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

1
src/assets/logo.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><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: 276 B

10
src/assets/reset.css Normal file
View File

@ -0,0 +1,10 @@
html,
body,
ul,
ol,
li,
img,
div {
margin: 0;
padding: 0;
}

View File

@ -0,0 +1,23 @@
<script setup>
import { onMounted, onBeforeUnmount } from 'vue'
import mitt from 'mitt'
const mitter = mitt()
onMounted(() => {
mitter.on('test', (data) => {
console.log(data)
})
})
onBeforeUnmount(() => {
mitter.off('test', () => {
console.log('mitter OFF')
})
})
</script>
<template>
<div></div>
</template>
<style lang="scss" scoped></style>

26
src/main.js Normal file
View File

@ -0,0 +1,26 @@
import './assets/reset.css'
import { createApp } from 'vue'
import pinia from './stores/pinia'
import App from './App.vue'
import router from './router'
import 'element-plus/dist/index.css'
const app = createApp(App)
// 全局自定义指令
app.directive('permission', {
mounted(el, binding) {
const { value } = binding
if (value.includes(1)) {
el.hidden = true
}
}
})
app.use(pinia)
app.use(router)
app.mount('#app')

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

@ -0,0 +1,9 @@
import { createRouter, createWebHistory } from 'vue-router'
import routes from './routes'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes
})
export default router

21
src/router/routes.js Normal file
View File

@ -0,0 +1,21 @@
import HomeView from '../views/HomeView.vue'
const routes = [
{
path: '/',
name: 'home',
meta: {
title: '首页'
},
component: HomeView
},
{
path: '/about',
name: 'about',
meta: {
title: '关于'
},
component: () => import('../views/AboutView.vue')
}
]
export default routes

7
src/stores/pinia.js Normal file
View File

@ -0,0 +1,7 @@
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
const store = createPinia()
store.use(piniaPluginPersistedstate)
export default store

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

@ -0,0 +1,29 @@
import { defineStore } from 'pinia'
import { ref, reactive } from 'vue'
const useUser = defineStore(
'user',
() => {
const name = ref('张三')
const age = ref(18)
const loginInfo = reactive({
token: '123',
lastLoginTime: ''
})
const modifyLoginInfo = (data) => {
loginInfo.token = data.token
loginInfo.lastLoginTime = data.lastLoginTime
}
return { name, age, loginInfo, modifyLoginInfo }
},
{
// 持久化存储
persist: {
storage: window.localStorage
}
}
)
export default useUser

54
src/utils/http.js Normal file
View File

@ -0,0 +1,54 @@
import axios from 'axios'
import router from '@/router'
import { ElMessage } from 'element-plus'
const API_URL = import.meta.env.VITE_API_BASE_URL
// console.log(API_URL)
const http = axios.create({
baseURL: API_URL,
timeout: 30 * 1000,
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
// 请求不携带cookie
withCredentials: false
})
// 请求拦截
http.interceptors.request.use(
(config) => {
config.headers.Authorization = `Bearer ${localStorage.getItem('token') || 'NoToken'}`
return config
},
(error) => {
return Promise.reject(error)
}
)
// 响应拦截
http.interceptors.response.use(
(res) => {
if (res.status === 200) {
const code = res.data.code || 0
// 根据返回的自定义code来做不同的处理
if (code === 401) {
ElMessage({
type: 'warning',
message: '登录已过期 或 未登录,请重新登录',
duration: 2000
})
router.push({ path: '/login' })
}
}
return res.data
},
(error) => {
return Promise.reject(error)
}
)
export default http

8
src/views/AboutView.vue Normal file
View File

@ -0,0 +1,8 @@
<script setup>
</script>
<template>
<div></div>
</template>
<style lang="scss" scoped></style>

7
src/views/HomeView.vue Normal file
View File

@ -0,0 +1,7 @@
<script setup>
</script>
<template>
<div></div>
</template>

36
vite.config.js Normal file
View File

@ -0,0 +1,36 @@
import { defineConfig, loadEnv } from 'vite'
import { fileURLToPath, URL } from 'node:url'
import process from 'node:process'
import vue from '@vitejs/plugin-vue'
// 按需导入 Element-plus 模块
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(({ mode }) => {
console.log(mode)
return {
base: loadEnv(mode, process.cwd()).VITE_BASE_URL,
plugins: [
vue(),
// Element-plus 按需导入模块
AutoImport({
resolvers: [ElementPlusResolver()]
}),
Components({
resolvers: [ElementPlusResolver()]
})
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
server: {
port: 3002,
proxy: {}
}
}
})