提交 af1be976 编写于 作者: 浩星's avatar 浩星

第一次提交

上级 a5450115
...@@ -6,22 +6,17 @@ yarn-debug.log* ...@@ -6,22 +6,17 @@ yarn-debug.log*
yarn-error.log* yarn-error.log*
pnpm-debug.log* pnpm-debug.log*
lerna-debug.log* lerna-debug.log*
package-lock.json
node_modules node_modules
.DS_Store
dist dist
dist-ssr dist-ssr
coverage
*.local *.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files # Editor directories and files
.vscode/* .vscode/*
!.vscode/extensions.json !.vscode/extensions.json
.idea .idea
.DS_Store
*.suo *.suo
*.ntvs* *.ntvs*
*.njsproj *.njsproj
......
MIT License
Copyright (c) 2023 xyz
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
\ No newline at end of file
# VueJS-with-Vite # 项目介绍
[model-vue3-vant](http://gitee.com/xyzcn/model-vue3-vant)是 Vue3 + Vant + Vite 搭建单页面模板template项目。基于 Vue3.2 + TypeScript + vite Vue-Router4.x + Pinia + Vant4.x + Sass 等当前主流技术栈开发
Vue.js 是基于 JavaScript 构建用户界面的库。该模板使用 Vite 来提供应用程序服务。
# 技术栈
## 推荐的IDE设置 - 编程语言:[TypeScript 4.x](https://www.typescriptlang.org/zh/)
- 构建工具:[Vite 2.x](https://cn.vitejs.dev/)
[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). - 前端框架:[Vue 3.x](https://v3.cn.vuejs.org/)
- 路由工具:[Vue Router 4.x](https://next.router.vuejs.org/zh/index.html)
## 自定义配置 - 状态管理 [Pinia 2.x](https://pinia.web3doc.top/)
- H5 端 UI 框架:[vant 4.x](https://vant-contrib.gitee.io/vant/#/zh-CN)
请参阅 [[Vite配置参考](https://vitejs.dev/config/). - CSS 预编译: [Sass ](https://sass.bootcss.com/documentation)
- HTTP 工具:[Axios](https://axios-http.com/)
## 项目设置
# 项目截图
```sh | ![输入图片说明](src/assets/ui/login.png) | ![输入图片说明](src/assets/ui/home.png) |
npm install |---|---|
| ![输入图片说明](src/assets/ui/cate.png) | ![输入图片说明](src/assets/ui/user.png) |
# 项目启动
```shell
# 克隆代码
git clone https://gitee.com/xyzcn/model-vue3-vant.git
# 安装 yarn
npm install -g yarn
# 安装依赖
yarn install
# 启动运行
yarn run dev
``` ```
### 在开发环境中启动和热更新
```sh
npm run dev
```
### 编译用于生产环境 # 联系作者
我的QQ邮箱: 774346441@qq.com
```sh
npm run build
```
...@@ -2,12 +2,26 @@ ...@@ -2,12 +2,26 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover"/>
<title>Vite + Vue + TS</title>
</head> </head>
<style>
* {
margin: 0;
padding: 0;
list-style:none;
}
html,body,#app{
margin: 0;
padding: 0;
height: 100%;
}
</style>
<body> <body>
<div id="app"></div> <div id="app"></div>
<script type="module" src="/src/main.js"></script> <script type="module" src="/src/main.ts"></script>
</body> </body>
</html> </html>
{ {
"name": "vuejs-with-vite", "name": "-model-app-",
"private": true,
"version": "0.0.0", "version": "0.0.0",
"type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vue-tsc && vite build",
"preview": "vite preview --port 4173" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"guess": "^1.0.2", "@types/node": "^20.1.0",
"vue": "^3.2.37" "@vueuse/core": "^10.1.2",
"axios": "^1.4.0",
"pinia": "^2.0.35",
"sass": "^1.62.1",
"vant": "^4.3.1",
"vue": "^3.2.47",
"vue-router": "4"
}, },
"devDependencies": { "devDependencies": {
"@vitejs/plugin-vue": "^3.0.1", "@vitejs/plugin-vue": "^4.1.0",
"vite": "^3.0.1" "typescript": "^5.0.2",
"unplugin-auto-import": "^0.15.3",
"unplugin-vue-components": "^0.24.1",
"vite": "^4.3.2",
"vue-tsc": "^1.4.2"
} }
} }
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
\ No newline at end of file
<script setup>
import HelloWorld from './components/HelloWorld.vue'
import TheWelcome from './components/TheWelcome.vue'
</script>
<template> <template>
<header> <router-view />
<img alt="Vue logo" class="logo" src="./assets/logo.svg" width="125" height="125" />
<div class="wrapper">
<HelloWorld msg="You did it!" />
</div>
</header>
<main>
<TheWelcome />
</main>
</template> </template>
<style scoped> <script setup lang="ts">
header {
line-height: 1.5;
}
.logo { </script>
display: block;
margin: 0 auto 2rem;
}
@media (min-width: 1024px) {
header {
display: flex;
place-items: center;
padding-right: calc(var(--section-gap) / 2);
}
.logo { <style scoped lang="scss">
margin: 0 2rem 0 0;
}
header .wrapper {
display: flex;
place-items: flex-start;
flex-wrap: wrap;
}
}
</style> </style>
import requset from '@/utils/request';
import { AxiosPromise } from 'axios';
import { LoginData, LoginResult } from './types';
export function getLogin(data:LoginData ): AxiosPromise<LoginResult> {
return requset({
url: '/api/v1/login',
method: 'post',
params:data
})
}
//
export interface LoginData {
username?: string;
password?: string;
}
// 响应
export interface LoginResult {
accessToken?: string;
tokenType?: string;
nickname?: string;
avatar?: string;
}
import requset from '@/utils/request';
import { AxiosPromise } from 'axios';
import { UserInfo } from './types';
export function getUserInfo(): AxiosPromise<UserInfo> {
return requset({
url: '/api/v1/user',
method: 'get'
})
}
\ No newline at end of file
export interface UserInfo {
nickname: string;
avatar: string;
roles: string[];
perms: string[];
}
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
\ No newline at end of file
<template>
<div class="img-verify">
<canvas ref="verify" :width="state.width" :height="state.height" @click="handleDraw"></canvas>
</div>
</template>
<script lang="ts" setup >
import { reactive, onMounted, ref } from 'vue'
const verify = ref(null)
const state = reactive({
pool: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890', // 字符串
width: 120,
height: 40,
imgCode: ''
})
onMounted(() => {
// 初始化绘制图片验证码
state.imgCode = draw()
})
// 点击图片重新绘制
const handleDraw = () => {
state.imgCode = draw()
}
// 随机数
const randomNum = (min, max) => {
return parseInt(Math.random() * (max - min) + min)
}
// 随机颜色
const randomColor = (min, max) => {
const r = randomNum(min, max)
const g = randomNum(min, max)
const b = randomNum(min, max)
return `rgb(${r},${g},${b})`
}
// 绘制图片
const draw = () => {
// 3.填充背景颜色,背景颜色要浅一点
const ctx = verify.value.getContext('2d')
// 填充颜色
ctx.fillStyle = randomColor(180, 230)
// 填充的位置
ctx.fillRect(0, 0, state.width, state.height)
// 定义paramText
let imgCode = ''
// 4.随机产生字符串,并且随机旋转
for (let i = 0; i < 4; i++) {
// 随机的四个字
const text = state.pool[randomNum(0, state.pool.length)]
imgCode += text
// 随机的字体大小
const fontSize = randomNum(18, 40)
// 字体随机的旋转角度
const deg = randomNum(-30, 30)
/*
* 绘制文字并让四个文字在不同的位置显示的思路 :
* 1、定义字体
* 2、定义对齐方式
* 3、填充不同的颜色
* 4、保存当前的状态(以防止以上的状态受影响)
* 5、平移translate()
* 6、旋转 rotate()
* 7、填充文字
* 8、restore出栈
* */
ctx.font = fontSize + 'px Simhei'
ctx.textBaseline = 'top'
ctx.fillStyle = randomColor(80, 150)
/*
* save() 方法把当前状态的一份拷贝压入到一个保存图像状态的栈中。
* 这就允许您临时地改变图像状态,
* 然后,通过调用 restore() 来恢复以前的值。
* save是入栈,restore是出栈。
* 用来保存Canvas的状态。save之后,可以调用Canvas的平移、放缩、旋转、错切、裁剪等操作。 restore:用来恢复Canvas之前保存的状态。防止save后对Canvas执行的操作对后续的绘制有影响。
*
* */
ctx.save()
ctx.translate(30 * i + 15, 15)
ctx.rotate((deg * Math.PI) / 180)
// fillText() 方法在画布上绘制填色的文本。文本的默认颜色是黑色。
// 请使用 font 属性来定义字体和字号,并使用 fillStyle 属性以另一种颜色/渐变来渲染文本。
// context.fillText(text,x,y,maxWidth);
ctx.fillText(text, -15 + 5, -15)
ctx.restore()
}
// 5.随机产生5条干扰线,干扰线的颜色要浅一点
for (let i = 0; i < 3; i++) {
ctx.beginPath()
ctx.moveTo(randomNum(0, state.width), randomNum(0, state.height))
ctx.lineTo(randomNum(0, state.width), randomNum(0, state.height))
ctx.strokeStyle = randomColor(180, 230)
ctx.closePath()
ctx.stroke()
}
// 6.随机产生40个干扰的小点
for (let i = 0; i < 40; i++) {
ctx.beginPath()
ctx.arc(randomNum(0, state.width), randomNum(0, state.height), 1, 0, 2 * Math.PI)
ctx.closePath()
ctx.fillStyle = randomColor(150, 200)
ctx.fill()
}
return imgCode
}
defineExpose({ state,handleDraw })
</script>
<style>
.img-verify canvas {
cursor: pointer;
}
</style>
\ No newline at end of file
<template>
<van-grid :class="cardAttr?.goodsCradclass" :column-num="cardAttr?.columnNum" :gutter="props.cardAttr?.gutter" class="goods-crad">
<van-grid-item v-for="(item, index) in goodsList" :key="index" :class="cardAttr?.itemClass">
<transition appear appear-to-class="card-appear-to-class" appear-active-class="card-appear-active-class">
<div class="card-body">
<van-image :src="item.img" />
<div class="name_text">{{ item.name }}</div>
<div class="auther_text">{{ item.auther }}</div>
</div>
</transition>
</van-grid-item>
</van-grid>
</template>
<script setup lang="ts" >
const props = defineProps({
goodsList: {
type: Array<any>,
default: () => {
return [];
},
},
cardAttr: {
type: Object,
default: () => {
return {
columnNum: 2,
gutter: 6,
itemClass: "recommend_item",
};
},
},
});
</script>
<style lang="scss" >
.goods-crad {
.recommend_item {
border-radius: 10px;
max-width: 50%;
.van-grid-item__content {
border-radius: 10px;
}
.van-grid-item__content--surround::after {
border-width: 0;
}
}
.van-grid-item {
max-width: 50%;
}
}
</style>
<style lang="scss" scoped>
.goods-crad {
padding-top: 10px;
padding-bottom: 10px;
.card-body {
text-align: center;
}
.name_text {
overflow: hidden;
-o-text-overflow: ellipsis;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
width: 100%;
text-align: center;
margin-top: 6px;
font-size: 14px;
}
.auther_text {
margin-top: 6px;
font-size: 12px;
color: #ccc;
text-align: center;
}
/** 卡片过渡动画 */
.card-appear-to-class {
transform: scale(1);
}
.card-appear-active-class {
transition: transform 2s ease;
}
}
.boutique-crad {
flex-wrap: nowrap !important;
overflow-x: scroll;
.boutique_item {
width: 25%;
}
}
</style>
\ No newline at end of file
<template>
<!-- :immediate-check="false" -->
<van-pull-refresh v-model="data.freshData.refreshLoad" @refresh="onRefresh" :class="classMap?.refreshClass" @scroll="scrollHander" ref="refReshList">
<van-list class="van-list-body" v-model:loading="data.freshData.listLoading" :offset="20"
:finished="data?.freshData?.listFinished" :finished-text="finishedText" @load="onLoad" >
<slot></slot>
</van-list>
</van-pull-refresh>
</template>
<script setup lang="ts" name="refreshList">
import { reactive, ref, watchEffect } from "vue";
const emit = defineEmits(["onRefresh", "onLoad"]);
const props = defineProps({
freshMap: {
type: Object,
default: () => {
return {
refreshLoad: false,
listLoading: false,
listFinished: false,
};
},
},
//
classMap: {
type: Object,
default: () => {
return {
refreshClass: "",
};
},
},
// 滚动位置
resetScroll: {
type: Number,
default: 0,
},
// 暂无更多
finishedText: {
type: String,
default: '没有更多了',
},
});
const data = reactive({
freshData: props?.freshMap,
});
let refReshList = ref();
//下拉刷新
const onRefresh = () => {
emit("onRefresh");
};
// 触底加载
const onLoad = () => {
emit("onLoad");
};
//重置滚动距离
const resetScroll = () => {
refReshList.value.$el.scrollTop = 0;
};
//滚动监听
const scrollHander = () => { };
watchEffect(() => {
if (props?.resetScroll) {
resetScroll();
}
});
</script>
<style lang="scss" scoped>
.book_box{
height: calc(100vh - 174px);
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}
.classify_refresh_box {
height: calc(100vh - 130px);
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}
.van-list-body {
height: 100%;
}
</style>
\ No newline at end of file
<template>
<van-tabbar v-model="active" route placeholder>
<van-tabbar-item icon="home-o" to="/home" > 首页</van-tabbar-item>
<van-tabbar-item icon="label-o" to="/book" >书架</van-tabbar-item>
<van-tabbar-item icon="apps-o" to="/cate" >分类</van-tabbar-item>
<van-tabbar-item icon="friends-o" to="/user" >我的</van-tabbar-item>
</van-tabbar>
</template>
<script setup lang="ts">
const active = ref(0)
</script>
<style scoped></style>
\ No newline at end of file
export { default as Navbar } from './Navbar/index.vue';
<template>
<section class="main">
<router-view v-slot="{ Component, route }">
<transition name="router-fade" mode="out-in">
<keep-alive>
<component :is="Component" :key="route.fullPath" />
</keep-alive>
</transition>
</router-view>
</section>
<navbar />
</template>
<script setup lang="ts">
import { Navbar } from "./components/index";
</script>
<style lang="scss" scoped>
.main {
position: relative;
width: 100%;
min-height: calc(100vh - 50px);
overflow: hidden;
}
</style>
\ No newline at end of file
import { newImg } from '@/utils/common'
const bookList = [
{ name: '南方有乔木', auther: '使者颜良', img: newImg('cover', '1.png') },
{ name: '无意降落人间', auther: '惊鸿一页', img: newImg('cover', '2.png') },
{ name: '王子与公主的爱情', auther: '山间隐落', img: newImg('cover', '3.png') },
{ name: '奴家有新人', auther: '一笑倾城', img: newImg('cover', '4.png') },
{ name: '回眸为年轻', auther: '雨中落幕', img: newImg('cover', '5.png') },
{ name: '踩着风车在爱你', auther: '乡村仙人', img: newImg('cover', '6.png') },
]
export const homePage = {
swipe_list: [
{ id: 1, name: '背景', pic: newImg('home', 'bk_1.png') },
{ id: 2, name: '背景', pic: newImg('home', 'bk_2.png') },
],
link_list: [
{ id: 1, name: '分类', pic: newImg('home', 'fl.png') },
{ id: 2, name: '完本', pic: newImg('home', 'wb.png') },
{ id: 3, name: '免费', pic: newImg('home', 'mf.png') },
{ id: 4, name: '排行', pic: newImg('home', 'ph.png') },
{ id: 5, name: '福利', pic: newImg('home', 'fli.png') },
],
bookList: bookList
}
export const catePage = {
side_list: [
{ id: 1, name: '精选', },
{ id: 2, name: '言情', },
{ id: 3, name: '玄幻', },
{ id: 4, name: '都市', },
{ id: 5, name: '仙侠', },
{ id: 6, name: '科幻', },
{ id: 7, name: '穿越', },
],
bookList: bookList
}
export const bookPage = {
bookList: bookList
}
\ No newline at end of file
import type { FieldRule } from 'vant'
import { isPassword } from '@/utils/validate'
const nameRules: FieldRule[] = [{ required: true, message: '请输入账号~' }]
const passwordRules: FieldRule[] = [
{ required: true, message: '请输入密码~' },
{ pattern: isPassword(), message: '密码须字母、数字、符号等组合且长度限制6~18位~' }
]
const verifyRules: FieldRule[] = [{ required: true, message: '请输入验证码~' }]
export default {
nameRules,
passwordRules,
verifyRules,
}
import { createApp } from 'vue'
import '@/styles/index.scss'
import App from './App.vue'
import router from '@/router'
import { setupStore } from '@/store';
import 'vant/es/toast/style';
import './permission'
const app = createApp(App)
//pinia
setupStore(app);
app.use(router).mount('#app')
import router from "@/router";
// import { useUserStoreHook } from "@/store/modules/user";
// 白名单路由
// const whiteList = ["/login"];
router.beforeEach(async (to, from, next) => {
next()
// const hasToken = localStorage.getItem("accessToken");
// if (hasToken) {
// } else {
// // 未登录可以访问白名单页面
// if (whiteList.indexOf(to.path) !== -1) {
// next();
// } else {
// next(`/login`);
// }
// }
});
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";
export const Layout = () => import("@/layout/index.vue")
const routes: RouteRecordRaw[] = [
{
path:'/',
redirect:'/login'
},
{
path: '/login',
name: 'login',
component: () => import('@/view/login/index.vue')
},
{
path: "/home",
component: Layout,
children: [
{
path: '',
name: 'home',
component: () => import('@/view/home/index.vue')
}
]
},
{
path: "/book",
component: Layout,
children: [
{
path: '',
name: 'book',
component: () => import('@/view/book/index.vue')
}
]
},
{
path: "/cate",
component: Layout,
children: [
{
path: '',
name: 'cate',
component: () => import('@/view/cate/index.vue')
}
]
},
{
path: "/user",
component: Layout,
children: [
{
path: '',
name: 'user',
component: () => import('@/view/users/index.vue')
}
]
},
]
const router = createRouter({
history: createWebHashHistory(),
routes: routes as RouteRecordRaw[],
})
export default router
import type { App } from 'vue';
import { createPinia } from 'pinia';
const store = createPinia();
// 全局注册 store
export function setupStore(app: App<Element>) {
app.use(store);
}
export { store };
\ No newline at end of file
import { defineStore } from "pinia";
import { store } from '@/store';
import { getLogin } from '@/api/login'
import { LoginData } from "@/api/login/types";
import { useStorage } from '@vueuse/core';
export const userStore = defineStore('user', () => {
// state
const token = useStorage("accessToken", "");
const nickname = ref('');
const avatar = ref('');
function login(loginData: LoginData) {
return new Promise<void>((resolve, reject) => {
getLogin(loginData)
.then(({ data }) => {
token.value = data.tokenType + " " + data.accessToken;
nickname.value = data.nickname;
avatar.value = data.avatar;
resolve();
})
.catch((error) => {
reject(error);
});
});
}
return {
token,
nickname,
avatar,
login,
};
})
// 非setup
export function useUserStoreHook() {
return userStore(store);
}
\ No newline at end of file
.f {
display: flex;
}
.f1 {
flex: 1 ;
}
.f-d-z {
display: flex;
flex: 0 0 auto;
}
.f-z {
display: flex;
flex: 1 1 auto;
}
.f-w {
display: flex;
flex-wrap: wrap;
}
.f-row {
display: flex;
flex-direction: row;
}
.f-row-s {
display: flex;
flex-direction: row;
justify-content: flex-start;
}
.f-row-s-s {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: flex-start;
}
.f-row-s-c {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
.f-row-s-e {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: flex-end;
}
.f-row-c {
display: flex;
flex-direction: row;
justify-content: center;
}
.f-row-c-s {
display: flex;
flex-direction: row;
justify-content: center;
align-items: flex-start;
}
.f-row-c-c {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.f-row-c-e {
display: flex;
flex-direction: row;
justify-content: center;
align-items: flex-end;
}
.f-row-e {
display: flex;
flex-direction: row;
justify-content: flex-end;
}
.f-row-e-s {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: flex-start;
}
.f-row-e-c {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
}
.f-row-e-e {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: flex-end;
}
.f-row-b {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.f-row-b-s {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: flex-start;
}
.f-row-b-c {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.f-row-b-e {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: flex-end;
}
.f-row-a {
display: flex;
flex-direction: row;
justify-content: space-around;
}
.f-row-a-s {
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: flex-start;
}
.f-row-a-c {
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
}
.f-row-a-e {
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: flex-end;
}
.f-col {
display: flex;
flex-direction: column;
}
.f-col-s {
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.f-col-s-s {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
}
.f-col-s-c {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
}
.f-col-s-e {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-end;
}
.f-col-c {
display: flex;
flex-direction: column;
justify-content: center;
}
.f-col-c-s {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
}
.f-col-c-c {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.f-col-c-e {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-end;
}
.f-col-e {
display: flex;
flex-direction: column;
justify-content: flex-end;
}
.f-col-e-s {
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: flex-start;
}
.f-col-e-c {
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: center;
}
.f-col-e-e {
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: flex-end;
}
.f-col-b {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.f-col-b-s {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-start;
}
.f-col-b-c {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
.f-col-b-e {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-end;
}
.f-col-a {
display: flex;
flex-direction: column;
justify-content: space-around;
}
.f-col-a-s {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: flex-start;
}
.f-col-a-c {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
}
.f-col-a-e {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: flex-end;
}
.f-rr {
display: flex;
flex-direction: row-reverse;
}
.f-rr-s {
display: flex;
flex-direction: row-reverse;
justify-content: flex-start;
}
.f-rr-s-s {
display: flex;
flex-direction: row-reverse;
justify-content: flex-start;
align-items: flex-start;
}
.f-rr-s-c {
display: flex;
flex-direction: row-reverse;
justify-content: flex-start;
align-items: center;
}
.f-rr-s-e {
display: flex;
flex-direction: row-reverse;
justify-content: flex-start;
align-items: flex-end;
}
.f-rr-c {
display: flex;
flex-direction: row-reverse;
justify-content: center;
}
.f-rr-c-s {
display: flex;
flex-direction: row-reverse;
justify-content: center;
align-items: flex-start;
}
.f-rr-c-c {
display: flex;
flex-direction: row-reverse;
justify-content: center;
align-items: center;
}
.f-rr-c-e {
display: flex;
flex-direction: row-reverse;
justify-content: center;
align-items: flex-end;
}
.f-rr-e {
display: flex;
flex-direction: row-reverse;
justify-content: flex-end;
}
.f-rr-e-s {
display: flex;
flex-direction: row-reverse;
justify-content: flex-end;
align-items: flex-start;
}
.f-rr-e-c {
display: flex;
flex-direction: row-reverse;
justify-content: flex-end;
align-items: center;
}
.f-rr-e-e {
display: flex;
flex-direction: row-reverse;
justify-content: flex-end;
align-items: flex-end;
}
.f-rr-b {
display: flex;
flex-direction: row-reverse;
justify-content: space-between;
}
.f-rr-b-s {
display: flex;
flex-direction: row-reverse;
justify-content: space-between;
align-items: flex-start;
}
.f-rr-b-c {
display: flex;
flex-direction: row-reverse;
justify-content: space-between;
align-items: center;
}
.f-rr-b-e {
display: flex;
flex-direction: row-reverse;
justify-content: space-between;
align-items: flex-end;
}
.f-rr-a {
display: flex;
flex-direction: row-reverse;
justify-content: space-around;
}
.f-rr-a-s {
display: flex;
flex-direction: row-reverse;
justify-content: space-around;
align-items: flex-start;
}
.f-rr-a-c {
display: flex;
flex-direction: row-reverse;
justify-content: space-around;
align-items: center;
}
.f-rr-a-e {
display: flex;
flex-direction: row-reverse;
justify-content: space-around;
align-items: flex-end;
}
.f-cr {
display: flex;
flex-direction: column-reverse;
}
.f-cr-s {
display: flex;
flex-direction: column-reverse;
justify-content: flex-start;
}
.f-cr-s-s {
display: flex;
flex-direction: column-reverse;
justify-content: flex-start;
align-items: flex-start;
}
.f-cr-s-c {
display: flex;
flex-direction: column-reverse;
justify-content: flex-start;
align-items: center;
}
.f-cr-s-e {
display: flex;
flex-direction: column-reverse;
justify-content: flex-start;
align-items: flex-end;
}
.f-cr-c {
display: flex;
flex-direction: column-reverse;
justify-content: center;
}
.f-cr-c-s {
display: flex;
flex-direction: column-reverse;
justify-content: center;
align-items: flex-start;
}
.f-cr-c-c {
display: flex;
flex-direction: column-reverse;
justify-content: center;
align-items: center;
}
.f-cr-c-e {
display: flex;
flex-direction: column-reverse;
justify-content: center;
align-items: flex-end;
}
.f-cr-e {
display: flex;
flex-direction: column-reverse;
justify-content: flex-end;
}
.f-cr-e-s {
display: flex;
flex-direction: column-reverse;
justify-content: flex-end;
align-items: flex-start;
}
.f-cr-e-c {
display: flex;
flex-direction: column-reverse;
justify-content: flex-end;
align-items: center;
}
.f-cr-e-e {
display: flex;
flex-direction: column-reverse;
justify-content: flex-end;
align-items: flex-end;
}
.f-cr-b {
display: flex;
flex-direction: column-reverse;
justify-content: space-between;
}
.f-cr-b-s {
display: flex;
flex-direction: column-reverse;
justify-content: space-between;
align-items: flex-start;
}
.f-cr-b-c {
display: flex;
flex-direction: column-reverse;
justify-content: space-between;
align-items: center;
}
.f-cr-b-e {
display: flex;
flex-direction: column-reverse;
justify-content: space-between;
align-items: flex-end;
}
.f-cr-a {
display: flex;
flex-direction: column-reverse;
justify-content: space-around;
}
.f-cr-a-s {
display: flex;
flex-direction: column-reverse;
justify-content: space-around;
align-items: flex-start;
}
.f-cr-a-c {
display: flex;
flex-direction: column-reverse;
justify-content: space-around;
align-items: center;
}
.f-cr-a-e {
display: flex;
flex-direction: column-reverse;
justify-content: space-around;
align-items: flex-end;
}
@import './flex.scss';
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
}
\ No newline at end of file
$main-color:#7a8dff;
:root:root{
// Color Palette
--van-black: #000;
--van-white: #fff;
--van-gray-1: #f7f8fa;
--van-gray-2: #f2f3f5;
--van-gray-3: #ebedf0;
--van-gray-4: #dcdee0;
--van-gray-5: #c8c9cc;
--van-gray-6: #969799;
--van-gray-7: #646566;
--van-gray-8: #323233;
--van-red: #ee0a24;
// --van-blue: #5677fc;
--van-blue: #7a8DFF;
--van-orange: #ff976a;
--van-orange-dark: #ed6a0c;
--van-orange-light: #fffbe8;
--van-green: #07c160;
// Gradient Colors
--van-gradient-red: linear-gradient(to right, #ff6034, #ee0a24);
--van-gradient-orange: linear-gradient(to right, #ffd01e, #ff8917);
// Component Colors
--van-primary-color: var(--van-blue);
--van-success-color: var(--van-green);
--van-danger-color: var(--van-red);
--van-warning-color: var(--van-orange);
--van-text-color: var(--van-gray-8);
--van-text-color-2: var(--van-gray-6);
--van-text-color-3: var(--van-gray-5);
--van-active-color: var(--van-gray-2);
--van-active-opacity: 0.6;
--van-disabled-opacity: 0.5;
--van-background: var(--van-gray-1);
--van-background-2: var(--van-white);
// Padding
--van-padding-base: 4px;
--van-padding-xs: 8px;
--van-padding-sm: 12px;
--van-padding-md: 16px;
--van-padding-lg: 24px;
--van-padding-xl: 32px;
// Font
--van-font-size-xs: 10px;
--van-font-size-sm: 12px;
--van-font-size-md: 14px;
--van-font-size-lg: 16px;
--van-font-bold: 600;
--van-line-height-xs: 14px;
--van-line-height-sm: 18px;
--van-line-height-md: 20px;
--van-line-height-lg: 22px;
--van-base-font: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica,
Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB', 'Microsoft Yahei',
sans-serif;
--van-price-font: Avenir-Heavy, PingFang SC, Helvetica Neue, Arial, sans-serif;
// Animation
--van-duration-base: 0.3s;
--van-duration-fast: 0.2s;
--van-ease-out: ease-out;
--van-ease-in: ease-in;
// Border
--van-border-color: var(--van-gray-3);
--van-border-width: 1px;
--van-radius-sm: 2px;
--van-radius-md: 4px;
--van-radius-lg: 8px;
--van-radius-max: 999px;
}
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-auto-import
export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
const computed: typeof import('vue')['computed']
const computedAsync: typeof import('@vueuse/core')['computedAsync']
const computedEager: typeof import('@vueuse/core')['computedEager']
const computedInject: typeof import('@vueuse/core')['computedInject']
const computedWithControl: typeof import('@vueuse/core')['computedWithControl']
const controlledComputed: typeof import('@vueuse/core')['controlledComputed']
const controlledRef: typeof import('@vueuse/core')['controlledRef']
const createApp: typeof import('vue')['createApp']
const createEventHook: typeof import('@vueuse/core')['createEventHook']
const createGlobalState: typeof import('@vueuse/core')['createGlobalState']
const createInjectionState: typeof import('@vueuse/core')['createInjectionState']
const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn']
const createReusableTemplate: typeof import('@vueuse/core')['createReusableTemplate']
const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable']
const createTemplatePromise: typeof import('@vueuse/core')['createTemplatePromise']
const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn']
const customRef: typeof import('vue')['customRef']
const debouncedRef: typeof import('@vueuse/core')['debouncedRef']
const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch']
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
const defineComponent: typeof import('vue')['defineComponent']
const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
const effectScope: typeof import('vue')['effectScope']
const extendRef: typeof import('@vueuse/core')['extendRef']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
const h: typeof import('vue')['h']
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
const inject: typeof import('vue')['inject']
const isDefined: typeof import('@vueuse/core')['isDefined']
const isProxy: typeof import('vue')['isProxy']
const isReactive: typeof import('vue')['isReactive']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable']
const markRaw: typeof import('vue')['markRaw']
const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated']
const onBeforeMount: typeof import('vue')['onBeforeMount']
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onClickOutside: typeof import('@vueuse/core')['onClickOutside']
const onDeactivated: typeof import('vue')['onDeactivated']
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke']
const onLongPress: typeof import('@vueuse/core')['onLongPress']
const onMounted: typeof import('vue')['onMounted']
const onRenderTracked: typeof import('vue')['onRenderTracked']
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
const onScopeDispose: typeof import('vue')['onScopeDispose']
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
const onStartTyping: typeof import('@vueuse/core')['onStartTyping']
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
const provide: typeof import('vue')['provide']
const reactify: typeof import('@vueuse/core')['reactify']
const reactifyObject: typeof import('@vueuse/core')['reactifyObject']
const reactive: typeof import('vue')['reactive']
const reactiveComputed: typeof import('@vueuse/core')['reactiveComputed']
const reactiveOmit: typeof import('@vueuse/core')['reactiveOmit']
const reactivePick: typeof import('@vueuse/core')['reactivePick']
const readonly: typeof import('vue')['readonly']
const ref: typeof import('vue')['ref']
const refAutoReset: typeof import('@vueuse/core')['refAutoReset']
const refDebounced: typeof import('@vueuse/core')['refDebounced']
const refDefault: typeof import('@vueuse/core')['refDefault']
const refThrottled: typeof import('@vueuse/core')['refThrottled']
const refWithControl: typeof import('@vueuse/core')['refWithControl']
const resolveComponent: typeof import('vue')['resolveComponent']
const resolveRef: typeof import('@vueuse/core')['resolveRef']
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const syncRef: typeof import('@vueuse/core')['syncRef']
const syncRefs: typeof import('@vueuse/core')['syncRefs']
const templateRef: typeof import('@vueuse/core')['templateRef']
const throttledRef: typeof import('@vueuse/core')['throttledRef']
const throttledWatch: typeof import('@vueuse/core')['throttledWatch']
const toRaw: typeof import('vue')['toRaw']
const toReactive: typeof import('@vueuse/core')['toReactive']
const toRef: typeof import('vue')['toRef']
const toRefs: typeof import('vue')['toRefs']
const triggerRef: typeof import('vue')['triggerRef']
const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount']
const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount']
const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted']
const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose']
const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted']
const unref: typeof import('vue')['unref']
const unrefElement: typeof import('@vueuse/core')['unrefElement']
const until: typeof import('@vueuse/core')['until']
const useActiveElement: typeof import('@vueuse/core')['useActiveElement']
const useAnimate: typeof import('@vueuse/core')['useAnimate']
const useArrayDifference: typeof import('@vueuse/core')['useArrayDifference']
const useArrayEvery: typeof import('@vueuse/core')['useArrayEvery']
const useArrayFilter: typeof import('@vueuse/core')['useArrayFilter']
const useArrayFind: typeof import('@vueuse/core')['useArrayFind']
const useArrayFindIndex: typeof import('@vueuse/core')['useArrayFindIndex']
const useArrayFindLast: typeof import('@vueuse/core')['useArrayFindLast']
const useArrayIncludes: typeof import('@vueuse/core')['useArrayIncludes']
const useArrayJoin: typeof import('@vueuse/core')['useArrayJoin']
const useArrayMap: typeof import('@vueuse/core')['useArrayMap']
const useArrayReduce: typeof import('@vueuse/core')['useArrayReduce']
const useArraySome: typeof import('@vueuse/core')['useArraySome']
const useArrayUnique: typeof import('@vueuse/core')['useArrayUnique']
const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue']
const useAsyncState: typeof import('@vueuse/core')['useAsyncState']
const useAttrs: typeof import('vue')['useAttrs']
const useBase64: typeof import('@vueuse/core')['useBase64']
const useBattery: typeof import('@vueuse/core')['useBattery']
const useBluetooth: typeof import('@vueuse/core')['useBluetooth']
const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints']
const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel']
const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation']
const useCached: typeof import('@vueuse/core')['useCached']
const useClipboard: typeof import('@vueuse/core')['useClipboard']
const useCloned: typeof import('@vueuse/core')['useCloned']
const useColorMode: typeof import('@vueuse/core')['useColorMode']
const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog']
const useCounter: typeof import('@vueuse/core')['useCounter']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVar: typeof import('@vueuse/core')['useCssVar']
const useCssVars: typeof import('vue')['useCssVars']
const useCurrentElement: typeof import('@vueuse/core')['useCurrentElement']
const useCycleList: typeof import('@vueuse/core')['useCycleList']
const useDark: typeof import('@vueuse/core')['useDark']
const useDateFormat: typeof import('@vueuse/core')['useDateFormat']
const useDebounce: typeof import('@vueuse/core')['useDebounce']
const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn']
const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory']
const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion']
const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation']
const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio']
const useDevicesList: typeof import('@vueuse/core')['useDevicesList']
const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia']
const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility']
const useDraggable: typeof import('@vueuse/core')['useDraggable']
const useDropZone: typeof import('@vueuse/core')['useDropZone']
const useElementBounding: typeof import('@vueuse/core')['useElementBounding']
const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint']
const useElementHover: typeof import('@vueuse/core')['useElementHover']
const useElementSize: typeof import('@vueuse/core')['useElementSize']
const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility']
const useEventBus: typeof import('@vueuse/core')['useEventBus']
const useEventListener: typeof import('@vueuse/core')['useEventListener']
const useEventSource: typeof import('@vueuse/core')['useEventSource']
const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper']
const useFavicon: typeof import('@vueuse/core')['useFavicon']
const useFetch: typeof import('@vueuse/core')['useFetch']
const useFileDialog: typeof import('@vueuse/core')['useFileDialog']
const useFileSystemAccess: typeof import('@vueuse/core')['useFileSystemAccess']
const useFocus: typeof import('@vueuse/core')['useFocus']
const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin']
const useFps: typeof import('@vueuse/core')['useFps']
const useFullscreen: typeof import('@vueuse/core')['useFullscreen']
const useGamepad: typeof import('@vueuse/core')['useGamepad']
const useGeolocation: typeof import('@vueuse/core')['useGeolocation']
const useIdle: typeof import('@vueuse/core')['useIdle']
const useImage: typeof import('@vueuse/core')['useImage']
const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll']
const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver']
const useInterval: typeof import('@vueuse/core')['useInterval']
const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn']
const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier']
const useLastChanged: typeof import('@vueuse/core')['useLastChanged']
const useLink: typeof import('vue-router')['useLink']
const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage']
const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys']
const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory']
const useMediaControls: typeof import('@vueuse/core')['useMediaControls']
const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery']
const useMemoize: typeof import('@vueuse/core')['useMemoize']
const useMemory: typeof import('@vueuse/core')['useMemory']
const useMounted: typeof import('@vueuse/core')['useMounted']
const useMouse: typeof import('@vueuse/core')['useMouse']
const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement']
const useMousePressed: typeof import('@vueuse/core')['useMousePressed']
const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver']
const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage']
const useNetwork: typeof import('@vueuse/core')['useNetwork']
const useNow: typeof import('@vueuse/core')['useNow']
const useObjectUrl: typeof import('@vueuse/core')['useObjectUrl']
const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination']
const useOnline: typeof import('@vueuse/core')['useOnline']
const usePageLeave: typeof import('@vueuse/core')['usePageLeave']
const useParallax: typeof import('@vueuse/core')['useParallax']
const useParentElement: typeof import('@vueuse/core')['useParentElement']
const usePerformanceObserver: typeof import('@vueuse/core')['usePerformanceObserver']
const usePermission: typeof import('@vueuse/core')['usePermission']
const usePointer: typeof import('@vueuse/core')['usePointer']
const usePointerLock: typeof import('@vueuse/core')['usePointerLock']
const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe']
const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme']
const usePreferredContrast: typeof import('@vueuse/core')['usePreferredContrast']
const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark']
const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages']
const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion']
const usePrevious: typeof import('@vueuse/core')['usePrevious']
const useRafFn: typeof import('@vueuse/core')['useRafFn']
const useRefHistory: typeof import('@vueuse/core')['useRefHistory']
const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
const useRoute: typeof import('vue-router')['useRoute']
const useRouter: typeof import('vue-router')['useRouter']
const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation']
const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea']
const useScriptTag: typeof import('@vueuse/core')['useScriptTag']
const useScroll: typeof import('@vueuse/core')['useScroll']
const useScrollLock: typeof import('@vueuse/core')['useScrollLock']
const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage']
const useShare: typeof import('@vueuse/core')['useShare']
const useSlots: typeof import('vue')['useSlots']
const useSorted: typeof import('@vueuse/core')['useSorted']
const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition']
const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis']
const useStepper: typeof import('@vueuse/core')['useStepper']
const useStorage: typeof import('@vueuse/core')['useStorage']
const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync']
const useStyleTag: typeof import('@vueuse/core')['useStyleTag']
const useSupported: typeof import('@vueuse/core')['useSupported']
const useSwipe: typeof import('@vueuse/core')['useSwipe']
const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList']
const useTextDirection: typeof import('@vueuse/core')['useTextDirection']
const useTextSelection: typeof import('@vueuse/core')['useTextSelection']
const useTextareaAutosize: typeof import('@vueuse/core')['useTextareaAutosize']
const useThrottle: typeof import('@vueuse/core')['useThrottle']
const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn']
const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory']
const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo']
const useTimeout: typeof import('@vueuse/core')['useTimeout']
const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn']
const useTimeoutPoll: typeof import('@vueuse/core')['useTimeoutPoll']
const useTimestamp: typeof import('@vueuse/core')['useTimestamp']
const useTitle: typeof import('@vueuse/core')['useTitle']
const useToNumber: typeof import('@vueuse/core')['useToNumber']
const useToString: typeof import('@vueuse/core')['useToString']
const useToggle: typeof import('@vueuse/core')['useToggle']
const useTransition: typeof import('@vueuse/core')['useTransition']
const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams']
const useUserMedia: typeof import('@vueuse/core')['useUserMedia']
const useVModel: typeof import('@vueuse/core')['useVModel']
const useVModels: typeof import('@vueuse/core')['useVModels']
const useVibrate: typeof import('@vueuse/core')['useVibrate']
const useVirtualList: typeof import('@vueuse/core')['useVirtualList']
const useWakeLock: typeof import('@vueuse/core')['useWakeLock']
const useWebNotification: typeof import('@vueuse/core')['useWebNotification']
const useWebSocket: typeof import('@vueuse/core')['useWebSocket']
const useWebWorker: typeof import('@vueuse/core')['useWebWorker']
const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn']
const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus']
const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll']
const useWindowSize: typeof import('@vueuse/core')['useWindowSize']
const watch: typeof import('vue')['watch']
const watchArray: typeof import('@vueuse/core')['watchArray']
const watchAtMost: typeof import('@vueuse/core')['watchAtMost']
const watchDebounced: typeof import('@vueuse/core')['watchDebounced']
const watchDeep: typeof import('@vueuse/core')['watchDeep']
const watchEffect: typeof import('vue')['watchEffect']
const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable']
const watchImmediate: typeof import('@vueuse/core')['watchImmediate']
const watchOnce: typeof import('@vueuse/core')['watchOnce']
const watchPausable: typeof import('@vueuse/core')['watchPausable']
const watchPostEffect: typeof import('vue')['watchPostEffect']
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
const watchThrottled: typeof import('@vueuse/core')['watchThrottled']
const watchTriggerable: typeof import('@vueuse/core')['watchTriggerable']
const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter']
const whenever: typeof import('@vueuse/core')['whenever']
}
// for type re-export
declare global {
// @ts-ignore
export type { Component, ComponentPublicInstance, ComputedRef, InjectionKey, PropType, Ref, VNode } from 'vue'
}
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
import '@vue/runtime-core'
export {}
declare module '@vue/runtime-core' {
export interface GlobalComponents {
ImageVerify: typeof import('./../components/ImageVerify/ImageVerify.vue')['default']
List: typeof import('./../components/common/list.vue')['default']
Refresh: typeof import('./../components/Refresh/index.vue')['default']
RefreshList: typeof import('./../components/refreshList/index.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
VanButton: typeof import('vant/es')['Button']
VanCell: typeof import('vant/es')['Cell']
VanCellGroup: typeof import('vant/es')['CellGroup']
VanEmpty: typeof import('vant/es')['Empty']
VanField: typeof import('vant/es')['Field']
VanForm: typeof import('vant/es')['Form']
VanGrid: typeof import('vant/es')['Grid']
VanGridItem: typeof import('vant/es')['GridItem']
VanIcon: typeof import('vant/es')['Icon']
VanImage: typeof import('vant/es')['Image']
VanList: typeof import('vant/es')['List']
VanNavBar: typeof import('vant/es')['NavBar']
VanPullRefresh: typeof import('vant/es')['PullRefresh']
VanRadio: typeof import('vant/es')['Radio']
VanRadioGroup: typeof import('vant/es')['RadioGroup']
VanSearch: typeof import('vant/es')['Search']
VanSidebar: typeof import('vant/es')['Sidebar']
VanSidebarItem: typeof import('vant/es')['SidebarItem']
VanSticky: typeof import('vant/es')['Sticky']
VanSwipe: typeof import('vant/es')['Swipe']
VanSwipeItem: typeof import('vant/es')['SwipeItem']
VanTabbar: typeof import('vant/es')['Tabbar']
VanTabbarItem: typeof import('vant/es')['TabbarItem']
VanTag: typeof import('vant/es')['Tag']
}
}
/// <reference types="vite/client" />
/**
* 获取本地图
* @param name // 文件名 如 doc.png
* @returns {*|string}
*/
export function newImg(file: string, name: string) :string {
return new URL(`/src/assets/${file}/${name}`, import.meta.url).href;
}
\ No newline at end of file
import axios, { InternalAxiosRequestConfig, AxiosResponse } from 'axios'
const service = axios.create({
baseURL: '',
timeout: 50000,
headers: { 'Content-Type': 'application/json;charset=utf-8' }
})
service.interceptors.request.use((config: InternalAxiosRequestConfig) => {
// if(token){
// config.headers.Authorization = token
// }
return config
}, (error: any) => {
return Promise.reject(error)
}
)
service.interceptors.response.use((response: AxiosResponse) => {
const { code, msg } = response.data
if (code == '00000') {
return response.data
}
return Promise.reject(new Error(msg || 'Error'))
}, (error: any) => {
if (error.response.data) {
const { code, msg } = error.response.data
if (code == '401') {
}
}
return Promise.reject(error.message)
}
)
export default service
\ No newline at end of file
/**
* 密码须字母、数字、符号等组合且长度限制6~18位~
* @param
* @returns {}
*/
export function isPassword(): RegExp {
const reg = /^(?![0-9]+$)(?![a-z]+$)(?![A-Z]+$)(?!([^(0-9a-zA-Z)])+$).{6,}$/;
return reg
}
\ No newline at end of file
<template>
<div>
<div class="book f-row-b-c">
<div>书架</div>
<van-icon name="wap-nav" size="20" />
</div>
<div class="book_body ">
<van-cell title="正在阅读" value="查看更多" is-link />
<refreshList :freshMap="freshMap" :classMap="classMap" @refresh="onRefresh" @onLoad="onLoad" >
<div>
<List :goodsList="bookList" :cardAttr="cardAttr"></List>
</div>
<van-empty v-if="bookList.length == 0" class="no-data" description="暂无数据" />
</refreshList>
</div>
</div>
</template>
<script setup lang="ts">
import { bookPage } from '@/libs/mock'
var bookList = bookPage.bookList
const freshMap = reactive({
refreshLoad: false,
listLoading: false,
listFinished: false,
});
const cardAttr = reactive({
columnNum: 3,
gutter: 10,
itemClass: "recommend_item",
});
const classMap = reactive({
refreshClass: "book_box",
});
//下拉刷新
const onRefresh = () => {
freshMap.refreshLoad = true;
setTimeout(() => {
bookList= bookPage.bookList
freshMap.refreshLoad = false;
}, 1000)
};
// 触底加载
const onLoad = () => {
console.log(2223);
bookList = bookList.concat(bookPage.bookList)
freshMap.listLoading = false;
freshMap.listFinished = false;
if (bookList.length > 50) {
freshMap.listFinished = true;
}
};
</script>
<style lang="scss" scoped>
.book {
padding: 0 15px;
position: relative;
background: linear-gradient(90deg, rgba(205, 218, 252), rgba(255, 240, 230, ));
height: 80px;
line-height: 50px;
}
.book::after {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 40px;
background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #fff);
}
</style>
\ No newline at end of file
<template>
<div>
<div class="cate f-row-b-c">
<div>全部书籍</div>
<van-icon name="search" size="18" />
</div>
<div class="cate_body f">
<van-sidebar v-model="active" class="sidebarwp">
<van-sidebar-item v-for="(item, index) in side_list" :key="index" :title="item.name" />
</van-sidebar>
<div class="by_rg f1">
<refreshList :freshMap="freshMap" :classMap="classMap" @refresh="onRefresh" @onLoad="onLoad" :resetScroll="resetScroll">
<div>
<List :goodsList="bookList" :cardAttr="cardAttr"></List>
</div>
<van-empty v-if="bookList.length == 0" class="no-data" description="暂无数据" />
</refreshList>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { catePage } from '@/libs/mock'
const side_list = catePage.side_list
var bookList = catePage.bookList
const active = ref(0)
const resetScroll = ref(0);
const freshMap = reactive({
refreshLoad: false,
listLoading: false,
listFinished: false,
});
const cardAttr = reactive({
columnNum: 2,
gutter: 10,
itemClass: "recommend_item",
});
const classMap = reactive({
refreshClass: "classify_refresh_box",
});
//下拉刷新
const onRefresh = () => {
freshMap.refreshLoad = true;
setTimeout(() => {
bookList= catePage.bookList
freshMap.refreshLoad = false;
}, 1000)
};
// 触底加载
const onLoad = () => {
bookList = bookList.concat(catePage.bookList)
freshMap.listLoading = false;
freshMap.listFinished = false;
if (bookList.length > 50) {
freshMap.listFinished = true;
}
};
</script>
<style lang="scss" scoped>
.cate {
padding: 0 15px;
position: relative;
background: linear-gradient(90deg, rgba(205, 218, 252), rgba(255, 240, 230, ));
height: 80px;
line-height: 50px;
}
.cate::after {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 40px;
background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #fff);
}
.sidebarwp {
height: calc(100vh - 130px);
.van-sidebar-item {
background-color: #fff;
text-align: center;
}
.van-sidebar-item--select {
font-size: 18px;
}
}
</style>
\ No newline at end of file
<template >
<div>
<div class="home " >
<van-sticky>
<div :style="style">
<van-search v-model="value" placeholder="请输入搜索关键词" shape="round" />
</div>
</van-sticky>
</div>
<van-swipe class="my-swipe" :autoplay="3000" indicator-color="white">
<van-swipe-item v-for="(item, i) in swipe_list" :key="i">
<van-image :src="item.pic" class="imged" fit="cover" />
</van-swipe-item>
</van-swipe>
<van-grid square :border="false" class="fl_wp" :column-num="5" >
<van-grid-item v-for="(item, i) in link_list" :key="i" @click="tabClick(item)">
<template #icon>
<van-image :src="item.pic" class="imged" />
</template>
<template #text>
<span class="mc">{{ item.name }}</span>
</template>
</van-grid-item>
</van-grid>
<div class="lines"></div>
<div class="warp_body">
<refreshList :freshMap="freshMap" @refresh="onRefresh" @onLoad="onLoad">
<div class="recommend_box">
<van-cell :border="false" title="推荐" />
<div class="recommend_body">
<List :goodsList="bookList"></List>
</div>
</div>
</refreshList>
</div>
</div>
</template>
<script setup lang="ts">
import { homePage } from '@/libs/mock'
import router from '@/router';
const value = ref('')
const style = ref(null)
const freshMap = reactive({
refreshLoad: false,
listLoading: false,
listFinished: false,
});
var bookList = homePage.bookList
const swipe_list = homePage.swipe_list
const link_list = homePage.link_list
const tabClick = (item:any) =>{
console.log(item);
switch (item.id) {
case 1 :
case 4 :
router.push('/cate')
break;
case 2 :
case 3 :
router.push('/book')
break;
default:
break;
}
}
//下拉刷新
const onRefresh = () => {
freshMap.refreshLoad = true;
setTimeout(() => {
bookList = homePage.bookList
freshMap.refreshLoad = false;
}, 1000)
};
// 触底加载
const onLoad = () => {
bookList = bookList.concat(homePage.bookList)
freshMap.listLoading = false;
freshMap.listFinished = false;
if (bookList.length > 50) {
freshMap.listFinished = true;
}
};
onMounted(() => {
window.addEventListener("scroll", windowScroll);
})
const windowScroll = () => {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
const opacity = Math.abs(Math.round(scrollTop)) / 250;
style.value = {background: `linear-gradient(90deg, rgba(205, 218, 252,${opacity}), rgba(255, 240, 230,${opacity} ))`}
}
onBeforeUnmount(()=>{
window.removeEventListener("scroll", windowScroll);
})
</script>
<style lang="scss" scoped>
.home {
position: relative;
background: linear-gradient(90deg, rgba(205, 218, 252), rgba(255, 240, 230, ));
height: 80px;
line-height: 50px;
.van-search {
background-color: transparent;
}
}
.home::after {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 40px;
background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #fff);
}
.lines {
width: 100%;
height: 14px;
background-color: #f7f8fa;
margin: 10px 0;
}
.my-swipe {
height: 150px;
margin: 5px 12px 15px;
border-radius: 12px;
}
.fl_wp {
.imged {
width: 40px;
}
.mc {
font-size: 14px;
}
}
</style>
\ No newline at end of file
<template>
<div class="login">
<div>
<img class="img-a" src="@/assets/login/2.png">
<img class="img-b" src="@/assets/login/3.png">
</div>
<div class="f-col-c-c container">
<van-form @submit="submitForm" ref="faultForm" validate-first show-error>
<h4>欢迎回来!</h4>
<van-cell-group inset>
<van-field v-model="state.username" label="用户名" placeholder="请输入用户名" clearable label-width="70px"
:rules="nameRules" required label-align="top" />
<van-field label-class="phone-input" v-model="state.password"
:right-icon="!passwordStatus ? 'closed-eye' : 'eye'" :type="!passwordStatus ? 'password' : 'text'"
required label="密码" @click-right-icon=" passwordStatus = !passwordStatus" placeholder="请输入密码"
label-width="70px" :rules="passwordRules" label-align="top" />
<van-field v-model="state.verify" center label="验证码" placeholder="请输入验证码" label-width="70px"
:rules="verifyRules" required label-align="top">
<template #button>
<image-verify ref="verifyRef" />
</template>
</van-field>
</van-cell-group>
<div class="subbut">
<van-button block round type="primary" :loading="loading" loading-text="登录中..." native-type="submit">
</van-button>
</div>
</van-form>
</div>
</div>
</template>
<script lang="ts" setup>
import loginRule from '@/libs/rules'
const { nameRules, passwordRules, verifyRules } = loginRule;
import { showToast } from 'vant';
import { useRouter } from 'vue-router';
const router = useRouter()
import { userStore } from '@/store/modules/user'
const useStore = userStore();
const verifyRef = ref(null)
const passwordStatus = ref(false)
const loading = ref(false)
const imgCode = ref('')
const state = reactive({
username: 'admin',
password: 'root123',
verify: '',
})
const submitForm = async () => {
imgCode.value = verifyRef.value.state.imgCode || ''
if (state.verify.toLowerCase() != imgCode.value.toLowerCase()) return verifyRef.value.handleDraw(),showToast('验证码有误~')
subLogin()
}
const subLogin = () => {
// const loginObj = { username: state.username, password: state.password }
// useStore.login(loginObj).then(() => {
router.replace('/home')
// }).catch(()=>{
// verifyRef.value.handleDraw()
// }).finally(() => {
// loading.value = false;
// });
}
</script>
<style lang="scss" scoped>
.login {
width: 100%;
height: 100%;
.img-a {
position: fixed;
top: -150px;
right: 0;
z-index: -1;
}
.img-b {
position: fixed;
bottom: -150px;
left: -50px;
z-index: -1;
}
}
.container {
width: 100%;
height: 100%;
h4 {
padding: 26px;
}
.subbut {
width: 85%;
margin: 16px auto;
}
}
</style>
\ No newline at end of file
<template>
<div class="users">
<div class="userinfo">
<div class="f-row-e-s pd"><van-icon name="envelop-o" color="#7a8dff" /></div>
<div class="tpinfo f-row-s-c">
<van-image round width="60px" height="60px" :src="txpng" class="tximg" />
<div class="f-row-s-c f-z ">
<div class="f-z">
<div>晴空下的她*</div>
</div>
<van-icon name="arrow" color="#7a8dff" />
</div>
</div>
<div class="vipcard f-row-c-c ">
<div class="vipnr f-row-b-c">
<div class="vipwz f-row-b-c">
<div>VIP</div>
<div>定制专属服务</div>
<van-icon name="arrow" />
</div>
</div>
</div>
</div>
<div class="content">
<van-cell-group inset>
<van-cell v-for="(item,index) in list " :key="index" center >
<template #title>
<van-icon :name="item.icon" color="#4c5c86" size="15" />
<span class="custom-title">{{item.name}}</span>
</template>
<template #right-icon>
<van-icon name="arrow" color="#4c5c86"/>
</template>
</van-cell>
</van-cell-group>
</div>
</div>
</template>
<script setup lang="ts">
import { newImg } from '@/utils/common';
const txpng = newImg('user', 'tx.png')
const list =[
{name:'阅读历史',icon:'clock-o',},
{name:'我的下载',icon:'down',},
{name:'意见反馈',icon:'chat-o',},
{name:'用户协议',icon:'orders-o',},
{name:'关于我们',icon:'info-o',},
{name:'个人设置',icon:'setting-o',},
]
</script>
<style scoped lang="scss">
.users{
height: calc(100vh - 50px);
background-color: #f7f8fa;
}
.userinfo {
position: relative;
background: linear-gradient(90deg, rgba(205, 218, 252), rgba(255, 240, 230, ));
height: 200px;
.pd {
padding: 10px;
}
.tpinfo {
padding: 20px;
.tximg {
border: 1px solid #7a8DFF;
margin-right: 10px;
}
}
}
.userinfo::after {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 50px;
background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #f7f8fa);
}
.vipcard {
.vipnr {
width: 90%;
z-index: 999 !important;
height: 70px;
border-radius: 50px;
background: linear-gradient(90deg, rgba(97, 107, 239, .6), rgba(205, 218, 252), );
.vipwz {
width: 100%;
padding: 0 20px;
font-weight: 900;
color: #fff;
font-size: 19px;
font-style:oblique;
}
}
}
.content{
margin-top: 30px;
.custom-title{
padding: 0 10px;
color: #4c5c86;
}
}
.van-cell{
padding:16px;
}
</style>
\ No newline at end of file
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
/* Linting */
"strict": false,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"baseUrl": "./",
"paths":{
"@": ["src"],
"@/*": ["src/*"],
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }],
}
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
server: {
host: true
},
plugins: [vue()]
})
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 自动导入vue中hook reactive ref等
import AutoImport from "unplugin-auto-import/vite"
import Components from 'unplugin-vue-components/vite';
import { VantResolver } from 'unplugin-vue-components/resolvers';
import path from "path";
const pathSrc = path.resolve(__dirname, "./src");
export default defineConfig({
resolve:{
alias: {
'@': pathSrc,
},
},
plugins: [
vue(),
AutoImport({
//安装两行后你会发现在组件中不用再导入ref,reactive等
imports: ['vue', 'vue-router',"@vueuse/core"],
//存放的位置
dts: "src/types/auto-import.d.ts",
}),
Components({
// 按需导入vant组件
resolvers: [VantResolver()],
// 引入组件的,包括自定义组件 存放的位置
dts: "src/types/components.d.ts",
}),
],
css: {
preprocessorOptions: {
//定义全局scss变量
scss: {
additionalData: `@import "@/styles/mixin.scss";@import "@/styles/vant.scss";`
}
}
}
})
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册