wip: 略微大更新一波

main
NoahLan 7 months ago
parent b8572d6304
commit 6edcbbf0ab

@ -1,4 +0,0 @@
> 1%
last 2 versions
not dead
not ie 11

12
.env

@ -1,11 +1,11 @@
# 项目基本地址
VITE_BASE_URL=/
# 项目名称
VITE_APP_NAME=N-Admin后台管理系统
VITE_APP_NAME=NPin 后台管理系统
# 项目标题
VITE_APP_TITLE=N-Admin后台管理系统
VITE_APP_TITLE=NPin 后台管理系统
# 项目描述
VITE_APP_DESC=N-Admin Background Management System
VITE_APP_DESC=NPin Background Management System
# API访问地址
VITE_API_URL=/api
@ -20,12 +20,14 @@ VITE_ICON_LOCAL_PREFIX=nl
VITE_ICON_UNOCSS_PREFIX=i
# 是否开启请求代理
VITE_HTTP_PROXY=false
# 是否开启打包文件大小结果分析
VITE_VISUALIZER=true
# VITE_VISUALIZER=true
# 是否开启打包压缩 gzip | brotliCompress | deflate | deflateRaw
VITE_COMPRESS='none'
# 是否应用pwa
VITE_PWA=false
VITE_PWA=true
# 是否启用Markdown插件
VITE_MARKDOWN=true
# 是否开启Mock

3
.gitignore vendored

@ -32,7 +32,4 @@ pnpm-debug.log*
*.sln
*.sw?
package-lock.json
pnpm-lock.yaml
.history

@ -1,4 +1,4 @@
FROM node:16-alpine as build-stage
FROM node:20-alpine as build-stage
WORKDIR /app
RUN corepack enable

@ -1 +1 @@
# N-Admin-UI-Vitesse
# NPinFront-UI-Vitesse

@ -0,0 +1,187 @@
import type { ComponentResolver, SideEffectsInfo } from 'unplugin-vue-components'
const components = [
// Form
'AutoComplete',
'Calendar',
'CascadeSelect',
'Checkbox',
'Chips',
'ColorPicker',
'Dropdown',
'Editor',
'FloatLabel',
'IconField',
'InputGroup',
'InputMask',
'InputNumber',
'InputOtp',
'InputSwitch',
'InputText',
'Knob',
'Listbox',
'MultiSelect',
'Password',
'RadioButton',
'Rating',
'SelectButton',
'Slider',
'Textarea',
'ToggleButton',
'TreeSelect',
// Button
'Button',
'SpeedDial',
'SplitButton',
// Data
'DataTable',
'DataView',
'OrderList',
'OrgChart',
'Paginator',
'PickList',
'Tree',
'TreeTable',
'Timeline',
'VirtualScroller',
// Panel
'Accordion',
'Card',
'Deferred',
'Divider',
'Fieldset',
'Panel',
'ScrollPanel',
'Splitter',
'Stepper',
'TabView',
'TabPanel',
'Toolbar',
// Overlay
'ConfirmDialog',
'ConfirmPopup',
'DynamicDialog',
'Tooltip', // need to add directive
// must be registered globally in order for the XXX service to work properly
'OverlayPanel',
'Sidebar',
// File
'FileUpload',
// Menu
'Breadcrumb',
'ContextMenu',
'Dock',
'Menu',
'Menubar',
'MegaMenu',
'PanelMenu',
'Steps',
'TabMenu',
'TieredMenu',
// Messages
'Toast',
// Toast must be registered globally in order for the XXX service to work properly
'Message',
'InlineMessage',
// Media
'Carousel',
'Galleria',
'Image',
// Misc
'Avatar',
'Badge',
'BlockUI',
'Chip',
'FocusTrap',
'Inplace',
'MeterGroup',
'ScrollTop',
'Skeleton',
'ProgressBar',
'ProgressSpinner',
'AnimateOnScroll',
'Ripple',
'StyleClass',
'Tag',
'Terminal',
]
export interface PrimeVueResolverOptions {
/**
* import style along with components
*
* @default true
*/
importStyle?: boolean
/**
* import `primeicons' icons
*
* requires package `primeicons`
*
* @default true
*/
importIcons?: boolean
/**
* imports a free theme - set theme name here (e.g. saga-blue)
*
* @default ''
*/
importTheme?: string
/**
* prefix for components (e.g. 'P' to resolve Menu from PMenu)
*
* @default ''
*/
prefix?: string
}
/**
* Resolver for PrimeVue - If you're using a component with the same tag as an native HTML element (e.g. button) the component must be in uppercase
*
* @link https://github.com/primefaces/primevue
*/
export function PrimeVueResolver(options: PrimeVueResolverOptions = {}): ComponentResolver {
return {
type: 'component',
resolve: (name: string) => {
const sideEffects: SideEffectsInfo = []
if (options.importStyle) {
sideEffects.push('primevue/resources/primevue.min.css')
}
if (options.importIcons) {
sideEffects.push('primeicons/primeicons.css')
}
if (options.importTheme) {
sideEffects.push(
`primevue/resources/themes/${options.importTheme}/theme.css`,
)
}
if (options.prefix) {
if (!name.startsWith(options.prefix)) {
return
}
name = name.substring(options.prefix.length)
}
if (components.includes(name)) {
return {
from: `primevue/${name.toLowerCase()}`,
sideEffects,
}
}
},
}
}

@ -1,8 +1,9 @@
import antfu from '@antfu/eslint-config'
import unocss from '@unocss/eslint-plugin'
export default antfu(
{
unocss: true,
formatters: true,
languageOptions: {},
rules: {
'curly': 'off',
@ -12,5 +13,4 @@ export default antfu(
'no-console': 'off',
},
},
unocss.configs.flat,
)

@ -1,32 +1,34 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="renderer" content="webkit" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="apple-touch-icon" href="/pwa-192x192.png" />
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#00aba9" />
<meta name="msapplication-TileColor" content="#00aba9" />
<title>%VITE_APP_NAME%</title>
<script>
;(function () {
const prefersDark =
window.matchMedia &&
window.matchMedia('(prefers-color-scheme: dark)').matches
const setting = localStorage.getItem('vueuse-color-scheme') || 'auto'
if (setting === 'dark' || (prefersDark && setting !== 'light'))
document.documentElement.classList.toggle('dark', true)
})()
</script>
</head>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="renderer" content="webkit" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="apple-touch-icon" href="/pwa-192x192.png">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#00aba9">
<meta name="msapplication-TileColor" content="#00aba9">
<title>%VITE_APP_NAME%</title>
<script>
(function () {
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
const setting = localStorage.getItem('vueuse-color-scheme') || 'auto'
if (setting === 'dark' || (prefersDark && setting !== 'light')) {
document.documentElement.classList.toggle('dark', true)
}
})()
</script>
</head>
<body class="font-sans">
<div id="app">
<div id="appLoading"></div>
</div>
<script type="module" src="/src/main.ts"></script>
<noscript>This website requires JavaScript to function properly. Please enable JavaScript to continue.</noscript>
</body>
</html>
<body class="font-sans">
<div id="app">
<div id="appLoading"></div>
</div>
<script type="module" src="/src/main.ts"></script>
<noscript
>This website requires JavaScript to function properly. Please enable
JavaScript to continue.</noscript
>
</body>
</html>

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2021 johncampionjr
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.

@ -1,245 +0,0 @@
# vite-plugin-vue-layouts
[![npm version](https://img.shields.io/npm/v/vite-plugin-vue-layouts)](https://www.npmjs.com/package/vite-plugin-vue-layouts)
> Router based layout for Vue 3 applications using [Vite](https://github.com/vitejs/vite)
## Overview
This works best along with the [vite-plugin-pages](https://github.com/hannoeru/vite-plugin-pages).
Layouts are stored in the `/src/layouts` folder by default and are standard Vue components with a `<router-view></router-view>` in the template.
Pages without a layout specified use `default.vue` for their layout.
You can use route blocks to allow each page to determine its layout. The block below in a page will look for `/src/layouts/users.vue` for its layout.
See the [Vitesse starter template](https://github.com/antfu/vitesse) for a working example.
```html
<route lang="yaml">
meta:
layout: users
</route>
```
## Getting Started
Install Layouts:
```bash
$ npm install -D vite-plugin-vue-layouts
```
Add to your `vite.config.js`:
```js
import Vue from '@vitejs/plugin-vue'
import Pages from 'vite-plugin-pages'
import Layouts from 'vite-plugin-vue-layouts'
export default {
plugins: [Vue(), Pages(), Layouts()],
}
```
In main.ts, you need to add a few lines to import the generated code and setup the layouts.
```js
import { createRouter } from 'vue-router'
import { setupLayouts } from 'virtual:generated-layouts'
import generatedRoutes from 'virtual:generated-pages'
const routes = setupLayouts(generatedRoutes)
const router = createRouter({
// ...
routes,
})
```
## Client Types
If you want type definition of `virtual:generated-layouts`, add `vite-plugin-vue-layouts/client` to `compilerOptions.types` of your `tsconfig`:
```json
{
"compilerOptions": {
"types": ["vite-plugin-vue-layouts/client"]
}
}
```
## Configuration
```ts
interface UserOptions {
layoutsDirs?: string | string[]
exclude: string[]
defaultLayout?: string
}
```
### Using configuration
To use custom configuration, pass your options to Layouts when instantiating the plugin:
```js
// vite.config.js
import Layouts from 'vite-plugin-vue-layouts'
export default {
plugins: [
Layouts({
layoutsDirs: 'src/mylayouts',
defaultLayout: 'myDefault'
}),
],
}
```
### layoutsDirs
Relative path to the layouts directory. Supports globs.
All .vue files in this folder are imported async into the generated code.
Can also be an array of layout dirs
Any files named `__*__.vue` will be excluded, and you can specify any additional exclusions with the `exclude` option
**Default:** `'src/layouts'`
## How it works
`setupLayouts` transforms the original `router` by
1. Replacing every page with its specified layout
2. Appending the original page in the `children` property.
Simply put, layouts are [nested routes](https://next.router.vuejs.org/guide/essentials/nested-routes.html#nested-routes) with the same path.
Before:
```
router: [ page1, page2, page3 ]
```
After `setupLayouts()`:
```
router: [
layoutA: page1,
layoutB: page2,
layoutA: page3,
]
```
That means you have the full flexibility of the [vue-router API](https://next.router.vuejs.org/api/) at your disposal.
## Common patterns
### Transitions
Layouts and Transitions work as expected and explained in the [vue-router docs](https://next.router.vuejs.org/guide/advanced/transitions.html) only as long as `Component` changes on each route. So if you want a transition between pages with the same layout *and* a different layout, you have to mutate `:key` on `<component>` (for a detailed example, see the vue docs about [transitions between elements](https://v3.vuejs.org/guide/transitions-enterleave.html#transitioning-between-elements)).
`App.vue`
```html
<template>
<router-view v-slot="{ Component, route }">
<transition name="slide">
<component :is="Component" :key="route" />
</transition>
</router-view>
</template>
```
Now Vue will always trigger a transition if you change the route.
### Data from layout to page
If you want to send data *down* from the layout to the page, use props
```
<router-view foo="bar" />
```
### Set static data at the page
If you want to set state in your page and do something with it in your layout, add additional properties to a route's `meta` property. Doing so only works if you know the state at build-time.
You can use the `<route>` block if you work with [vite-plugin-pages](https://github.com/hannoeru/vite-plugin-pages).
In `page.vue`:
```html
<template><div>Content</div></template>
<route lang="yaml">
meta:
layout: default
bgColor: yellow
</route>
```
Now you can read `bgColor` in `layout.vue`:
```html
<script setup>
import { useRouter } from 'vue-router'
</script>
<template>
<div :style="`background: ${useRouter().currentRoute.value.meta.bgColor};`">
<router-view />
</div>
</template>
```
### Data dynamically from page to layout
If you need to set `bgColor` dynamically at run-time, you can use [custom events](https://v3.vuejs.org/guide/component-custom-events.html#custom-events).
Emit the event in `page.vue`:
```html
<script setup>
import { defineEmit } from 'vue'
const emit = defineEmit(['setColor'])
if (2 + 2 === 4)
emit('setColor', 'green')
else
emit('setColor', 'red')
</script>
```
Listen for `setColor` custom-event in `layout.vue`:
```html
<script setup>
import { ref } from 'vue'
const bgColor = ref('yellow')
const setBg = (color) => {
bgColor.value = color
}
</script>
<template>
<main :style="`background: ${bgColor};`">
<router-view @set-color="setBg" />
</main>
</template>
```
## ClientSideLayout
The clientSideLayout uses a simpler [virtual file](https://vitejs.dev/guide/api-plugin.html#importing-a-virtual-file) + [glob import](https://vitejs.dev/guide/features.html#glob-import) scheme, This means that its hmr is faster and more accurate, but also more limited
### Usage
```js
// vite.config.js
import { ClientSideLayout } from 'vite-plugin-vue-layouts'
export default {
plugins: [
ClientSideLayout({
layoutsDir: 'src/mylayouts', // default to 'src/layout'
defaultLayout: 'myDefault', // default to 'default', no need '.vue'
importMode: 'sync' // The default will automatically detect -> ssg is syncother is async
}),
],
}
```

@ -1,14 +0,0 @@
/**
* @deprecated
*/
declare module 'layouts-generated' {
import type { RouteRecordRaw } from 'vue-router'
export function setupLayouts(routes: RouteRecordRaw[]): RouteRecordRaw[]
}
declare module 'virtual:generated-layouts' {
import type { RouteRecordRaw } from 'vue-router'
export function setupLayouts(routes: RouteRecordRaw[]): RouteRecordRaw[]
}

@ -1,68 +0,0 @@
{
"name": "vite-plugin-vue-layouts",
"version": "0.8.0",
"description": "Router based layout plugin for Vite and Vue",
"author": "johncampionjr <npm@relate.dev>",
"license": "MIT",
"homepage": "https://github.com/johncampionjr/vite-plugin-vue-layouts",
"repository": {
"type": "git",
"url": "https://github.com/johncampionjr/vite-plugin-vue-layouts"
},
"bugs": "https://github.com/johncampionjr/vite-plugin-vue-layouts",
"exports": {
".": {
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"require": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"./*": "./*"
},
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"files": [
"client.d.ts",
"dist"
],
"scripts": {
"dev": "npm run build -- --watch",
"build": "tsup src/index.ts --dts --format cjs,esm && cp dist/index.d.ts dist/index.d.mts",
"prepublishOnly": "npm run build",
"release": "npx bumpp --commit --tag --push && npm publish",
"example:dev": "npm -C examples/spa run dev",
"example:build": "npm -C examples/spa run build",
"example:serve": "npm -C examples/spa run serve",
"example:build-ssg": "npm -C examples/ssg run build",
"example:serve-ssg": "npm -C examples/ssg run serve"
},
"peerDependencies": {
"vite": "^2.5.0 || ^3.0.0-0 || ^4.0.0",
"vue": "^2.6.12 || ^3.2.4",
"vue-router": "^3.5.1 || ^4.0.11"
},
"dependencies": {
"debug": "^4.3.3",
"fast-glob": "^3.2.11",
"local-pkg": "^0.4.3"
},
"devDependencies": {
"@antfu/eslint-config": "^0.7.0",
"@types/debug": "^4.1.7",
"@types/node": "^16.11.26",
"@typescript-eslint/eslint-plugin": "^4.33.0",
"cross-env": "^7.0.3",
"eslint": "^7.32.0",
"rollup": "^2.68.0",
"tsup": "^4.14.0",
"typescript": "^4.6.2",
"vite": "^2.8.6",
"vue": "^3.2.31",
"vue-router": "^4.0.13"
}
}

@ -1,16 +1,17 @@
[build.environment]
NODE_VERSION = "16"
[build]
publish = "dist"
command = "pnpm run build"
publish = "dist"
command = "pnpm run build"
[build.environment]
NODE_VERSION = "20"
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
from = "/*"
to = "/index.html"
status = 200
[[headers]]
for = "/manifest.webmanifest"
[headers.values]
Content-Type = "application/manifest+json"
for = "/manifest.webmanifest"
[headers.values]
Content-Type = "application/manifest+json"

@ -1,21 +1,18 @@
{
"name": "n-admin-ui",
"name": "npin-front",
"type": "module",
"version": "1.0.0",
"private": true,
"packageManager": "pnpm@8.5.1",
"description": "description",
"packageManager": "pnpm@8.15.5",
"description": "NPin前端项目",
"author": {
"name": "NorthLan"
},
"engines": {
"node": ">=16.15.1",
"pnpm": ">=8.1.0"
},
"scripts": {
"build": "vite build",
"build-ssg": "vite-ssg build",
"predev": "esno build/generate/index.ts && pnpm run icon:dev",
"dev": "vite --port 8088",
"dev": "vite --port 3333",
"lint": "eslint .",
"preview": "vite preview",
"preview-https": "serve dist",
@ -30,80 +27,82 @@
"icon:prod": "esno build/icon prod"
},
"dependencies": {
"@unhead/vue": "^1.7.4",
"@unocss/reset": "^0.55.7",
"@vueuse/core": "^10.5.0",
"@unhead/vue": "^1.9.4",
"@unocss/reset": "^0.59.0",
"@vueuse/core": "^10.9.0",
"nprogress": "^0.2.0",
"pinia": "^2.1.7",
"vue": "^3.3.6",
"vue-demi": "^0.14.6",
"vue-i18n": "^9.5.0",
"vue-router": "^4.2.5"
"vue": "^3.4.21",
"vue-demi": "^0.14.7",
"vue-i18n": "^9.11.1",
"vue-router": "^4.3.0"
},
"devDependencies": {
"@ant-design/colors": "^7.0.0",
"@antfu/eslint-config": "1.0.0-beta.28",
"@iconify/json": "^2.2.141",
"@iconify/tools": "^3.0.6",
"@ant-design/colors": "^7.0.2",
"@antfu/eslint-config": "^2.14.0",
"@iconify/json": "^2.2.199",
"@iconify/tools": "^3.0.7",
"@iconify/types": "^2.0.0",
"@iconify/utils": "^2.1.11",
"@iconify/utils": "^2.1.22",
"@iconify/vue": "^4.1.1",
"@intlify/unplugin-vue-i18n": "^1.4.0",
"@types/markdown-it-link-attributes": "^3.0.3",
"@types/nprogress": "^0.2.2",
"@types/qs": "^6.9.9",
"@types/sortablejs": "^1.15.4",
"@unocss/eslint-config": "^0.57.0",
"@vitejs/plugin-vue": "^4.4.0",
"@vue-macros/reactivity-transform": "^0.3.23",
"@vue-macros/short-vmodel": "^1.3.0",
"@vue-macros/volar": "^0.14.3",
"@vue/test-utils": "^2.4.1",
"@intlify/unplugin-vue-i18n": "^4.0.0",
"@niku/vite-env-caster": "^1.0.2",
"@shikijs/markdown-it": "^1.3.0",
"@types/markdown-it-link-attributes": "^3.0.5",
"@types/nprogress": "^0.2.3",
"@types/qs": "^6.9.14",
"@types/sortablejs": "^1.15.8",
"@unocss/eslint-plugin": "^0.59.3",
"@vitejs/plugin-vue": "^5.0.4",
"@vue-macros/short-vmodel": "^1.4.3",
"@vue-macros/volar": "^0.18.18",
"@vue/test-utils": "^2.4.5",
"chalk": "^5.3.0",
"critters": "^0.0.20",
"critters": "^0.0.22",
"cross-env": "^7.0.3",
"cypress": "^13.3.2",
"cypress-vite": "^1.4.2",
"easy-fns-ts": "^1.2.3",
"eslint": "^8.52.0",
"cypress": "^13.7.2",
"cypress-vite": "^1.5.0",
"eslint": "^8.57.0",
"eslint-plugin-cypress": "^2.15.1",
"esno": "^4.0.0",
"eslint-plugin-format": "^0.1.0",
"esno": "^4.7.0",
"fast-glob": "^3.3.2",
"https-localhost": "^4.7.1",
"less": "^4.2.0",
"lint-staged": "^14.0.1",
"lint-staged": "^15.2.2",
"markdown-it-link-attributes": "^4.0.1",
"markdown-it-shiki": "^0.9.0",
"naive-ui": "^2.35.0",
"path-to-regexp": "^6.2.1",
"pinia-plugin-persistedstate": "^3.2.0",
"pnpm": "^8.9.2",
"shiki": "^0.14.5",
"simple-git-hooks": "^2.9.0",
"sortablejs": "^1.15.0",
"taze": "^0.11.4",
"typescript": "^5.2.2",
"typescript-json-schema": "^0.62.0",
"unocss": "^0.55.7",
"unplugin-auto-import": "^0.16.6",
"unplugin-vue-components": "^0.25.2",
"unplugin-vue-macros": "^2.6.1",
"unplugin-vue-markdown": "^0.24.3",
"vite": "^4.5.0",
"vite-bundle-visualizer": "^0.10.0",
"naive-ui": "^2.38.1",
"path-to-regexp": "^6.2.2",
"pinia-plugin-persistedstate": "^3.2.1",
"pnpm": "^8.15.6",
"primeicons": "^7.0.0",
"primelocale": "^0.0.1",
"primevue": "^4.0.0-beta.1",
"rollup": "^4.14.1",
"shiki": "^1.2.2",
"simple-git-hooks": "^2.11.1",
"sortablejs": "^1.15.2",
"taze": "^0.13.3",
"typescript": "^5.4.4",
"unocss": "^0.59.3",
"unplugin-auto-import": "^0.17.5",
"unplugin-vue-components": "^0.26.0",
"unplugin-vue-macros": "^2.9.0",
"unplugin-vue-markdown": "^0.26.0",
"unplugin-vue-router": "^0.8.5",
"vite": "^5.2.8",
"vite-bundle-visualizer": "^1.1.0",
"vite-plugin-banner": "^0.7.1",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-inspect": "^0.7.40",
"vite-plugin-pages": "^0.31.0",
"vite-plugin-pwa": "^0.16.5",
"vite-plugin-inspect": "^0.8.3",
"vite-plugin-pwa": "^0.19.8",
"vite-plugin-svg-icons": "^2.0.1",
"vite-plugin-vue-component-preview": "^1.1.6",
"vite-plugin-vue-devtools": "1.0.0-rc.5",
"vite-plugin-vue-layouts": "file:lib/vite-plugin-vue-layouts",
"vite-plugin-webfont-dl": "^3.7.6",
"vite-plugin-vue-devtools": "^7.0.25",
"vite-plugin-vue-layouts": "^0.11.0",
"vite-plugin-webfont-dl": "^3.9.3",
"vitest": "^0.34.6",
"vue-request": "^2.0.4",
"vue-tsc": "^1.8.20",
"vue-tsc": "^1.8.27",
"vuedraggable": "^4.1.0"
},
"simple-git-hooks": {

File diff suppressed because it is too large Load Diff

@ -14,6 +14,7 @@ declare global {
const $toRef: typeof import('vue/macros')['$toRef']
const EffectScope: typeof import('vue')['EffectScope']
const NLBreakpointsEnum2: typeof import('naive-ui')['NLBreakpointsEnum2']
const Router: typeof import('vue-router/auto')['Router']
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
const computed: typeof import('vue')['computed']
@ -34,17 +35,22 @@ declare global {
const createMediaPrefersColorSchemeListen: typeof import('./composables/web/theme')['createMediaPrefersColorSchemeListen']
const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn']
const createReusableTemplate: typeof import('@vueuse/core')['createReusableTemplate']
const createRouter: typeof import('vue-router/auto')['createRouter']
const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable']
const createTemplatePromise: typeof import('@vueuse/core')['createTemplatePromise']
const createThemeColorListen: typeof import('./composables/web/theme')['createThemeColorListen']
const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn']
const createWebHistory: typeof import('vue-router/auto')['createWebHistory']
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 definePage: typeof import('unplugin-vue-router/runtime')['definePage']
const definePreset: typeof import('./composables/primevue/hooks')['definePreset']
const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
const effectScope: typeof import('vue')['effectScope']
const envD: typeof import('./types/env.d')['default']
const extendRef: typeof import('@vueuse/core')['extendRef']
const getActiveHead: typeof import('@unhead/vue')['getActiveHead']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
@ -69,8 +75,8 @@ declare global {
const oauthLoginByPhone: typeof import('./api/auth/auth')['oauthLoginByPhone']
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 onBeforeRouteLeave: typeof import('vue-router/auto')['onBeforeRouteLeave']
const onBeforeRouteUpdate: typeof import('vue-router/auto')['onBeforeRouteUpdate']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onClickOutside: typeof import('@vueuse/core')['onClickOutside']
@ -129,6 +135,9 @@ declare global {
const unref: typeof import('vue')['unref']
const unrefElement: typeof import('@vueuse/core')['unrefElement']
const until: typeof import('@vueuse/core')['until']
const updatePreset: typeof import('./composables/primevue/hooks')['updatePreset']
const updatePrimaryPalette: typeof import('./composables/primevue/hooks')['updatePrimaryPalette']
const updateSurfacePalette: typeof import('./composables/primevue/hooks')['updateSurfacePalette']
const useActiveElement: typeof import('@vueuse/core')['useActiveElement']
const useAnimate: typeof import('@vueuse/core')['useAnimate']
const useAppConfig: typeof import('./composables/config/app-config')['useAppConfig']
@ -160,8 +169,10 @@ declare global {
const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation']
const useCached: typeof import('@vueuse/core')['useCached']
const useClipboard: typeof import('@vueuse/core')['useClipboard']
const useClipboardItems: typeof import('@vueuse/core')['useClipboardItems']
const useCloned: typeof import('@vueuse/core')['useCloned']
const useColorMode: typeof import('@vueuse/core')['useColorMode']
const useConfirm: typeof import('./composables/primevue/hooks')['useConfirm']
const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog']
const useContext: typeof import('./composables/context')['useContext']
const useCounter: typeof import('@vueuse/core')['useCounter']
@ -219,7 +230,7 @@ declare global {
const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier']
const useLastChanged: typeof import('@vueuse/core')['useLastChanged']
const useLayout: typeof import('./composables/layout')['useLayout']
const useLink: typeof import('vue-router')['useLink']
const useLink: typeof import('vue-router/auto')['useLink']
const useLoadMore: typeof import('./composables/request')['useLoadMore']
const useLoadingBar: typeof import('naive-ui')['useLoadingBar']
const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage']
@ -262,7 +273,9 @@ declare global {
const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark']
const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages']
const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion']
const usePreset: typeof import('./composables/primevue/hooks')['usePreset']
const usePrevious: typeof import('@vueuse/core')['usePrevious']
const usePrimeVue: typeof import('./composables/primevue/hooks')['usePrimeVue']
const usePromise: typeof import('./composables/promise')['usePromise']
const useRafFn: typeof import('@vueuse/core')['useRafFn']
const useRedo: typeof import('./composables/page')['useRedo']
@ -271,9 +284,9 @@ declare global {
const useRequestProvider: typeof import('./composables/request')['useRequestProvider']
const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
const useRootSetting: typeof import('./composables/setting/root-setting')['useRootSetting']
const useRoute: typeof import('vue-router')['useRoute']
const useRoute: typeof import('vue-router/auto')['useRoute']
const useRouteStore: typeof import('./stores/routes')['useRouteStore']
const useRouter: typeof import('vue-router')['useRouter']
const useRouter: typeof import('vue-router/auto')['useRouter']
const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation']
const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea']
const useScriptTag: typeof import('@vueuse/core')['useScriptTag']
@ -294,6 +307,7 @@ declare global {
const useStepper: typeof import('@vueuse/core')['useStepper']
const useStorage: typeof import('@vueuse/core')['useStorage']
const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync']
const useStyle: typeof import('./composables/primevue/hooks')['useStyle']
const useStyleTag: typeof import('@vueuse/core')['useStyleTag']
const useSupported: typeof import('@vueuse/core')['useSupported']
const useSwipe: typeof import('@vueuse/core')['useSwipe']
@ -302,6 +316,7 @@ declare global {
const useTextDirection: typeof import('@vueuse/core')['useTextDirection']
const useTextSelection: typeof import('@vueuse/core')['useTextSelection']
const useTextareaAutosize: typeof import('@vueuse/core')['useTextareaAutosize']
const useTheme: typeof import('./composables/primevue/hooks')['useTheme']
const useThemeStore: typeof import('./stores/theme')['useThemeStore']
const useThrottle: typeof import('@vueuse/core')['useThrottle']
const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn']
@ -314,6 +329,7 @@ declare global {
const useTitle: typeof import('@vueuse/core')['useTitle']
const useToNumber: typeof import('@vueuse/core')['useToNumber']
const useToString: typeof import('@vueuse/core')['useToString']
const useToast: typeof import('./composables/primevue/hooks')['useToast']
const useToggle: typeof import('@vueuse/core')['useToggle']
const useTransition: typeof import('@vueuse/core')['useTransition']
const useTransitionSetting: typeof import('./composables/setting/transition-setting')['useTransitionSetting']
@ -354,10 +370,12 @@ declare global {
declare global {
// @ts-ignore
export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
import('vue')
}
// for vue template auto import
import { UnwrapRef } from 'vue'
declare module 'vue' {
interface GlobalComponents {}
interface ComponentCustomProperties {
readonly $$: UnwrapRef<typeof import('vue/macros')['$$']>
readonly $: UnwrapRef<typeof import('vue/macros')['$']>
@ -396,8 +414,10 @@ declare module 'vue' {
readonly debouncedWatch: UnwrapRef<typeof import('@vueuse/core')['debouncedWatch']>
readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']>
readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']>
readonly definePage: UnwrapRef<typeof import('unplugin-vue-router/runtime')['definePage']>
readonly eagerComputed: UnwrapRef<typeof import('@vueuse/core')['eagerComputed']>
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
readonly envD: UnwrapRef<typeof import('./types/env.d')['default']>
readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']>
readonly getActiveHead: UnwrapRef<typeof import('@unhead/vue')['getActiveHead']>
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
@ -422,8 +442,8 @@ declare module 'vue' {
readonly oauthLoginByPhone: UnwrapRef<typeof import('./api/auth/auth')['oauthLoginByPhone']>
readonly onActivated: UnwrapRef<typeof import('vue')['onActivated']>
readonly onBeforeMount: UnwrapRef<typeof import('vue')['onBeforeMount']>
readonly onBeforeRouteLeave: UnwrapRef<typeof import('vue-router')['onBeforeRouteLeave']>
readonly onBeforeRouteUpdate: UnwrapRef<typeof import('vue-router')['onBeforeRouteUpdate']>
readonly onBeforeRouteLeave: UnwrapRef<typeof import('vue-router/auto')['onBeforeRouteLeave']>
readonly onBeforeRouteUpdate: UnwrapRef<typeof import('vue-router/auto')['onBeforeRouteUpdate']>
readonly onBeforeUnmount: UnwrapRef<typeof import('vue')['onBeforeUnmount']>
readonly onBeforeUpdate: UnwrapRef<typeof import('vue')['onBeforeUpdate']>
readonly onClickOutside: UnwrapRef<typeof import('@vueuse/core')['onClickOutside']>
@ -513,6 +533,7 @@ declare module 'vue' {
readonly useBrowserLocation: UnwrapRef<typeof import('@vueuse/core')['useBrowserLocation']>
readonly useCached: UnwrapRef<typeof import('@vueuse/core')['useCached']>
readonly useClipboard: UnwrapRef<typeof import('@vueuse/core')['useClipboard']>
readonly useClipboardItems: UnwrapRef<typeof import('@vueuse/core')['useClipboardItems']>
readonly useCloned: UnwrapRef<typeof import('@vueuse/core')['useCloned']>
readonly useColorMode: UnwrapRef<typeof import('@vueuse/core')['useColorMode']>
readonly useConfirmDialog: UnwrapRef<typeof import('@vueuse/core')['useConfirmDialog']>
@ -572,7 +593,6 @@ declare module 'vue' {
readonly useKeyModifier: UnwrapRef<typeof import('@vueuse/core')['useKeyModifier']>
readonly useLastChanged: UnwrapRef<typeof import('@vueuse/core')['useLastChanged']>
readonly useLayout: UnwrapRef<typeof import('./composables/layout')['useLayout']>
readonly useLink: UnwrapRef<typeof import('vue-router')['useLink']>
readonly useLoadMore: UnwrapRef<typeof import('./composables/request')['useLoadMore']>
readonly useLoadingBar: UnwrapRef<typeof import('naive-ui')['useLoadingBar']>
readonly useLocalStorage: UnwrapRef<typeof import('@vueuse/core')['useLocalStorage']>
@ -624,9 +644,9 @@ declare module 'vue' {
readonly useRequestProvider: UnwrapRef<typeof import('./composables/request')['useRequestProvider']>
readonly useResizeObserver: UnwrapRef<typeof import('@vueuse/core')['useResizeObserver']>
readonly useRootSetting: UnwrapRef<typeof import('./composables/setting/root-setting')['useRootSetting']>
readonly useRoute: UnwrapRef<typeof import('vue-router')['useRoute']>
readonly useRoute: UnwrapRef<typeof import('vue-router/auto')['useRoute']>
readonly useRouteStore: UnwrapRef<typeof import('./stores/routes')['useRouteStore']>
readonly useRouter: UnwrapRef<typeof import('vue-router')['useRouter']>
readonly useRouter: UnwrapRef<typeof import('vue-router/auto')['useRouter']>
readonly useScreenOrientation: UnwrapRef<typeof import('@vueuse/core')['useScreenOrientation']>
readonly useScreenSafeArea: UnwrapRef<typeof import('@vueuse/core')['useScreenSafeArea']>
readonly useScriptTag: UnwrapRef<typeof import('@vueuse/core')['useScriptTag']>
@ -705,6 +725,7 @@ declare module 'vue' {
}
}
declare module '@vue/runtime-core' {
interface GlobalComponents {}
interface ComponentCustomProperties {
readonly $$: UnwrapRef<typeof import('vue/macros')['$$']>
readonly $: UnwrapRef<typeof import('vue/macros')['$']>
@ -743,8 +764,10 @@ declare module '@vue/runtime-core' {
readonly debouncedWatch: UnwrapRef<typeof import('@vueuse/core')['debouncedWatch']>
readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']>
readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']>
readonly definePage: UnwrapRef<typeof import('unplugin-vue-router/runtime')['definePage']>
readonly eagerComputed: UnwrapRef<typeof import('@vueuse/core')['eagerComputed']>
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
readonly envD: UnwrapRef<typeof import('./types/env.d')['default']>
readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']>
readonly getActiveHead: UnwrapRef<typeof import('@unhead/vue')['getActiveHead']>
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
@ -769,8 +792,8 @@ declare module '@vue/runtime-core' {
readonly oauthLoginByPhone: UnwrapRef<typeof import('./api/auth/auth')['oauthLoginByPhone']>
readonly onActivated: UnwrapRef<typeof import('vue')['onActivated']>
readonly onBeforeMount: UnwrapRef<typeof import('vue')['onBeforeMount']>
readonly onBeforeRouteLeave: UnwrapRef<typeof import('vue-router')['onBeforeRouteLeave']>
readonly onBeforeRouteUpdate: UnwrapRef<typeof import('vue-router')['onBeforeRouteUpdate']>
readonly onBeforeRouteLeave: UnwrapRef<typeof import('vue-router/auto')['onBeforeRouteLeave']>
readonly onBeforeRouteUpdate: UnwrapRef<typeof import('vue-router/auto')['onBeforeRouteUpdate']>
readonly onBeforeUnmount: UnwrapRef<typeof import('vue')['onBeforeUnmount']>
readonly onBeforeUpdate: UnwrapRef<typeof import('vue')['onBeforeUpdate']>
readonly onClickOutside: UnwrapRef<typeof import('@vueuse/core')['onClickOutside']>
@ -860,6 +883,7 @@ declare module '@vue/runtime-core' {
readonly useBrowserLocation: UnwrapRef<typeof import('@vueuse/core')['useBrowserLocation']>
readonly useCached: UnwrapRef<typeof import('@vueuse/core')['useCached']>
readonly useClipboard: UnwrapRef<typeof import('@vueuse/core')['useClipboard']>
readonly useClipboardItems: UnwrapRef<typeof import('@vueuse/core')['useClipboardItems']>
readonly useCloned: UnwrapRef<typeof import('@vueuse/core')['useCloned']>
readonly useColorMode: UnwrapRef<typeof import('@vueuse/core')['useColorMode']>
readonly useConfirmDialog: UnwrapRef<typeof import('@vueuse/core')['useConfirmDialog']>
@ -919,7 +943,6 @@ declare module '@vue/runtime-core' {
readonly useKeyModifier: UnwrapRef<typeof import('@vueuse/core')['useKeyModifier']>
readonly useLastChanged: UnwrapRef<typeof import('@vueuse/core')['useLastChanged']>
readonly useLayout: UnwrapRef<typeof import('./composables/layout')['useLayout']>
readonly useLink: UnwrapRef<typeof import('vue-router')['useLink']>
readonly useLoadMore: UnwrapRef<typeof import('./composables/request')['useLoadMore']>
readonly useLoadingBar: UnwrapRef<typeof import('naive-ui')['useLoadingBar']>
readonly useLocalStorage: UnwrapRef<typeof import('@vueuse/core')['useLocalStorage']>
@ -971,9 +994,9 @@ declare module '@vue/runtime-core' {
readonly useRequestProvider: UnwrapRef<typeof import('./composables/request')['useRequestProvider']>
readonly useResizeObserver: UnwrapRef<typeof import('@vueuse/core')['useResizeObserver']>
readonly useRootSetting: UnwrapRef<typeof import('./composables/setting/root-setting')['useRootSetting']>
readonly useRoute: UnwrapRef<typeof import('vue-router')['useRoute']>
readonly useRoute: UnwrapRef<typeof import('vue-router/auto')['useRoute']>
readonly useRouteStore: UnwrapRef<typeof import('./stores/routes')['useRouteStore']>
readonly useRouter: UnwrapRef<typeof import('vue-router')['useRouter']>
readonly useRouter: UnwrapRef<typeof import('vue-router/auto')['useRouter']>
readonly useScreenOrientation: UnwrapRef<typeof import('@vueuse/core')['useScreenOrientation']>
readonly useScreenSafeArea: UnwrapRef<typeof import('@vueuse/core')['useScreenSafeArea']>
readonly useScriptTag: UnwrapRef<typeof import('@vueuse/core')['useScriptTag']>

@ -7,6 +7,7 @@ export {}
declare module 'vue' {
export interface GlobalComponents {
Button: typeof import('primevue/button')['default']
LAppProvider: typeof import('./components/LAppProvider/index.vue')['default']
LAuth: typeof import('./components/LAuth/index.ts')['default']
LAuthBg: typeof import('./components/LAuth/bg.vue')['default']
@ -35,7 +36,9 @@ declare module 'vue' {
NIcon: typeof import('naive-ui')['NIcon']
NInput: typeof import('naive-ui')['NInput']
NInputGroup: typeof import('naive-ui')['NInputGroup']
NInputGroupLabel: typeof import('naive-ui')['NInputGroupLabel']
NInputNumber: typeof import('naive-ui')['NInputNumber']
NLAuthLayout: typeof import('naive-ui')['NLAuthLayout']
NLayout: typeof import('naive-ui')['NLayout']
NLayoutContent: typeof import('naive-ui')['NLayoutContent']
NLayoutFooter: typeof import('naive-ui')['NLayoutFooter']
@ -59,6 +62,12 @@ declare module 'vue' {
NText: typeof import('naive-ui')['NText']
NTooltip: typeof import('naive-ui')['NTooltip']
NWatermark: typeof import('naive-ui')['NWatermark']
PButton: typeof import('primevue/button')['default']
PCalendar: typeof import('primevue/calendar')['default']
PConfirmDialog: typeof import('primevue/confirmdialog')['default']
PDivider: typeof import('primevue/divider')['default']
PTabPanel: typeof import('primevue/tabpanel')['default']
PTabView: typeof import('primevue/tabview')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
}

@ -0,0 +1,13 @@
// export { useConfirm } from 'primevue/useconfirm'
// export { useDialog } from 'primevue/usedialog'
// export { useStyle } from 'primevue/usestyle'
// export { useToast } from 'primevue/usetoast'
// export { usePrimeVue } from 'primevue/unstyled'
// export {
// definePreset,
// updatePreset,
// updatePrimaryPalette,
// updateSurfacePalette,
// usePreset,
// useTheme
// } from 'primevue/themes'

@ -9,8 +9,8 @@ export function useMenu() {
if (!unref(initMenu)) {
await routeStore.buildMenu()
}
const menuList = unref(menuListRef)
return filterTree(menuList, hideFilter)
const menuList = filterTree(unref(menuListRef), hideFilter)
return menuList
}
const getCurrentParentPath = async (currentPath: string) => {

@ -184,16 +184,26 @@ export function useAppTheme() {
const darkRef = useDark({
selector: 'html',
attribute: 'theme-mode',
attribute: 'class',
valueDark: 'dark',
valueLight: '',
valueLight: 'light',
})
const toggleDark = useToggle(darkRef)
const isDark = computed(() => unref(darkRef) && unref(theme) === ThemeEnum.DARK)
const toggleTheme = (dark: boolean) => {
theme.value = dark ? ThemeEnum.DARK : ThemeEnum.LIGHT
toggleDark(dark)
const tt = (dark: boolean) => {
theme.value = dark ? ThemeEnum.DARK : ThemeEnum.LIGHT
toggleDark(dark)
}
// @ts-expect-error newapi
if (!document.startViewTransition) {
tt(dark)
return
}
// @ts-expect-error newapi
document.startViewTransition(() => tt(dark))
}
// sidebar

@ -45,7 +45,7 @@ watch(() => x.value, () => {
return
}
if (props.fn) {
console.log('dragbarfn')
// console.log('dragbarfn')
props.fn(n)
}
pX = x.value
@ -94,21 +94,21 @@ watch(
<style lang="less" scoped>
.drag-bar {
position: absolute;
z-index: 999;
top: 0;
right: -2px;
width: 2px;
height: 100%;
border-top: none;
border-bottom: none;
cursor: col-resize;
&__hide {
display: none;
}
&:hover {
background-color: var(--primary-color);
box-shadow: 0 0 4px 0 rgb(28 36 56 / 15%);
}
position: absolute;
z-index: 999;
top: 0;
right: -2px;
width: 2px;
height: 100%;
border-top: none;
border-bottom: none;
cursor: col-resize;
&__hide {
display: none;
}
&:hover {
background-color: var(--primary-color);
box-shadow: 0 0 4px 0 rgb(28 36 56 / 15%);
}
}
</style>

@ -1,3 +1,4 @@
import env from 'nenv'
import { createHead } from '@unhead/vue'
import App from './App.vue'
@ -6,8 +7,9 @@ import AppLoading from './AppLoading.vue'
import './styles'
import { setupPinia } from './modules/pinia'
import { setupI18n } from './modules/i18n'
import { initRouter, setupRouterGuards } from './modules/router/router'
import { setupPWA } from './modules/pwa'
import { initRouter, setupRouterGuards } from './modules/router/router'
// import { setupPrimeVue } from './modules/primevue'
import 'virtual:svg-icons-register'
{
@ -26,16 +28,15 @@ import 'virtual:svg-icons-register'
(async () => {
// loadingApp
const appLoading = createApp(AppLoading)
// setupPinia(appLoading)
// setup I18n
// await setupI18n(appLoading)
appLoading.mount('#appLoading')
const app = createApp(App)
setupPinia(app)
// initApplication
app.use(createHead())
// primevue
// setupPrimeVue(app)
// pinia
setupPinia(app)
// setup I18n
await setupI18n(app)
@ -48,7 +49,12 @@ import 'virtual:svg-icons-register'
await router.isReady()
// pwa
await setupPWA()
if (env.VITE_PWA) {
await setupPWA()
}
const head = createHead()
app.use(head)
// mount
app.mount('#app')

@ -11,7 +11,7 @@ pinia.use(resetSetupStorePlugin)
// 持久化插件(localStorage)
pinia.use(createPersistedState({
storage: localStorage,
key: id => `${import.meta.env}__${id}`,
key: id => `${import.meta.env.MODE}__${id}`,
}))
export function setupPinia(app: App<Element>) {

@ -0,0 +1,47 @@
import type { App } from 'vue'
import PrimeVue from 'primevue/config'
// @ts-expect-error mjs
import PrimeOne from 'primevue/themes/primeone'
// @ts-expect-error mjs
import Aura from 'primevue/themes/primeone/aura'
import ConfirmationService from 'primevue/confirmationservice'
import DialogService from 'primevue/dialogservice'
import ToastService from 'primevue/toastservice'
// directive
import Tooltip from 'primevue/tooltip'
import Badge from 'primevue/badgedirective'
import Ripple from 'primevue/ripple'
import Styleclass from 'primevue/styleclass'
import Focustrap from 'primevue/focustrap'
import Animateonscroll from 'primevue/animateonscroll'
// locale
import zhCN from 'primelocale/zh-CN.json'
export function setupPrimeVue(app: App<Element>) {
app.use(PrimeVue, {
ripple: true,
theme: {
base: PrimeOne,
preset: Aura,
options: {
prefix: 'p',
darkModeSelector: '.dark',
},
},
locale: Object.assign({ fileSizeType: '文件大小类型' }, zhCN['zh-CN']),
})
app.use(ConfirmationService)
app.use(DialogService)
app.use(ToastService)
// directive
app.directive('tooltip', Tooltip)
app.directive('badge', Badge)
app.directive('ripple', Ripple)
app.directive('styleclass', Styleclass)
app.directive('focustrap', Focustrap)
app.directive('animateonscroll', Animateonscroll)
}

@ -1,5 +1,5 @@
import NProgress from 'nprogress'
import type { Router } from 'vue-router'
import type { Router } from 'vue-router/auto'
const LOADED_PAGE_POOL = new Map<string, boolean>()

@ -1,6 +1,5 @@
import type { Router } from 'vue-router'
import { createRouter, createWebHistory } from 'vue-router'
import type { RouteRecordRaw, Router } from 'vue-router/auto'
import { createRouter, createWebHistory } from 'vue-router/auto'
import { setupLayouts } from 'virtual:generated-layouts'
import { createNProgressGuard } from './nprogress'
import { createTabsGuard } from './tabs'
@ -11,13 +10,16 @@ export let router: Router
export function initRouter(path: string): Router {
const routeStore = useRouteStore()
const routes = routeStore.initRoutes()
router = createRouter({
history: createWebHistory(path),
strict: false,
routes: setupLayouts(routes),
scrollBehavior: () => ({ left: 0, top: 0 }),
extendRoutes: (routes: RouteRecordRaw[]) => {
const initialRoutes = routeStore.initRoutes(routes)
console.log('🚀 ~ initRouter ~ setupLayouts(initialRoutes):', initialRoutes, setupLayouts(initialRoutes))
return setupLayouts(initialRoutes)
},
})
return router

@ -1,4 +1,4 @@
import type { Router } from 'vue-router'
import type { Router } from 'vue-router/auto'
export function createTabsGuard(router: Router, func: AnyFunction<any>) {
router.beforeEach(async (to) => {

@ -0,0 +1,13 @@
<script setup lang="ts">
definePage({
meta: {
title: 'menu.login',
hideInMenu: true,
layout: 'page-layout',
},
})
</script>
<template>
<RouterView />
</template>

@ -1,6 +1,12 @@
<script setup lang="ts">
import type { FormInst, FormRules } from 'naive-ui'
definePage({
meta: {
ignore: true,
},
})
const { t } = useI18n()
const { runAsync: auth, loading: authLoading } = useRequest(login, { manual: true })
@ -26,7 +32,7 @@ function submit() {
return
}
const res = await auth(formModelRef)
console.log('🚀 ~ formElRef?.validate ~ res.token:', res.token)
console.log('🚀 ~ formElRef?.validate ~ res:', res)
}).catch((_) => { })
}
</script>
@ -46,8 +52,8 @@ function submit() {
</NFormItem>
<NFormItem path="credentials">
<NInput
$value="formModelRef.credentials" clearable :placeholder="$t('auth.login.account.credentials.placeholder')"
show-password-on="click" type="password"
$value="formModelRef.credentials" clearable
:placeholder="$t('auth.login.account.credentials.placeholder')" show-password-on="click" type="password"
>
<template #prefix>
<LIcon icon="carbon-locked" />
@ -66,8 +72,3 @@ function submit() {
</NForm>
</div>
</template>
<route lang="yaml">
meta:
ignore: true
</route>

@ -1,6 +1,12 @@
<script setup lang="ts">
import type { FormInst, FormRules } from 'naive-ui'
definePage({
meta: {
ignore: true,
},
})
const { t } = useI18n()
const { runAsync: auth, loading: authLoading } = useRequest(loginByCode, { manual: true })
@ -26,7 +32,7 @@ function submit() {
return
}
const res = await auth(formModelRef)
console.log('🚀 ~ formElRef?.validate ~ res.token:', res.token)
console.log('🚀 ~ formElRef?.validate ~ res:', res)
}).catch((_) => { })
}
</script>
@ -65,8 +71,3 @@ function submit() {
</NForm>
</div>
</template>
<route lang="yaml">
meta:
ignore: true
</route>

@ -1,6 +1,12 @@
<script setup lang="ts">
import AccountLogin from './comp/account.vue'
import SMSLogin from './comp/sms.vue'
import AccountLogin from './components/account.vue'
import SMSLogin from './components/sms.vue'
definePage({
meta: {
title: 'menu.login',
},
})
const { t } = useI18n()
useHead({
@ -28,10 +34,3 @@ useHead({
</div>
</LAuthLayout>
</template>
<route lang="yaml">
meta:
title: menu.login
hideInMenu: true
layout: page-layout
</route>

@ -0,0 +1,13 @@
<script setup lang="ts">
definePage({
meta: {
title: 'menu.register',
hideInMenu: true,
layout: 'page-layout',
},
})
</script>
<template>
<RouterView />
</template>

@ -3,6 +3,12 @@ import type { FormInst, FormItemRule, FormRules } from 'naive-ui'
import CredentialPopover from './credential-popover.vue'
import { CredentialsFlags } from './types'
definePage({
meta: {
ignore: true,
},
})
const { t } = useI18n()
function onlyAllowNumber(val: string) {
@ -150,8 +156,3 @@ function submit() {
</NForm>
</div>
</template>
<route lang="yaml">
meta:
ignore: true
</route>

@ -6,6 +6,12 @@ const props = withDefaults(defineProps<{
}>(), {
flags: CredentialsFlags.none,
})
definePage({
meta: {
ignore: true,
},
})
</script>
<template>
@ -57,8 +63,3 @@ const props = withDefaults(defineProps<{
</NSpace>
</NPopover>
</template>
<route lang="yaml">
meta:
ignore: true
</route>

@ -1,6 +1,12 @@
<script setup lang="ts">
import type { FormInst, FormRules } from 'naive-ui'
definePage({
meta: {
ignore: true,
},
})
function onlyAllowNumber(val: string) {
return !val || /^\d+$/.test(val)
}
@ -73,8 +79,3 @@ function submit() {
</NForm>
</div>
</template>
<route lang="yaml">
meta:
ignore: true
</route>

@ -1,6 +1,12 @@
<script setup lang="ts">
import Account from './comp/account.vue'
import SMS from './comp/sms.vue'
import Account from './components/account.vue'
import SMS from './components/sms.vue'
definePage({
meta: {
title: 'menu.register',
},
})
</script>
<template>
@ -15,10 +21,3 @@ import SMS from './comp/sms.vue'
</NTabs>
</LAuthLayout>
</template>
<route lang="yaml">
meta:
layout: page-layout
hideInMenu: true
title: 注册
</route>

@ -1,6 +1,5 @@
import { acceptHMRUpdate, defineStore } from 'pinia'
import type { RouteRecordRaw } from 'vue-router'
import pageRoutes from '~pages'
import type { RouteRecordRaw } from 'vue-router/auto'
import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '~/modules/router/routes/basic'
import { cloneDeep, filterTree, transformRouteToMenu } from '~/utils'
import { PermissionModeEnum } from '~/constants'
@ -13,21 +12,26 @@ export const useRouteStore = defineStore('ROUTES', () => {
/**
*
*/
function initRoutes() {
/**
*
*/
function initRoutes(routes: RouteRecordRaw[]) {
// 过滤配置了 meta -> ignore: true 路由
const routeIgnoreFilter = (route: RouteRecordRaw) => {
const { meta } = route
const { ignore } = meta || {}
return !ignore
}
const routes: RouteRecordRaw[] = []
routes.push(PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE)
routes.push(...pageRoutes)
// 过滤空children存在且长度为0的路由
const cleanEmptyChildrenFilter = (route: RouteRecordRaw) => {
return route.children ? route.children.length > 0 : true
}
let tmpRoutes: RouteRecordRaw[] = []
tmpRoutes.push(PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE)
tmpRoutes.push(...routes)
tmpRoutes = filterTree(tmpRoutes, routeIgnoreFilter)
routesRef.value = filterTree(tmpRoutes, cleanEmptyChildrenFilter)
routesRef.value = filterTree(routes, routeIgnoreFilter)
return routesRef.value
}
@ -115,4 +119,4 @@ export const useRouteStore = defineStore('ROUTES', () => {
})
if (import.meta.hot)
import.meta.hot.accept(acceptHMRUpdate(useRouteStore as any, import.meta.hot))
import.meta.hot.accept(acceptHMRUpdate(useRouteStore, import.meta.hot))

@ -0,0 +1,34 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-router. ‼️ DO NOT MODIFY THIS FILE ‼️
// It's recommended to commit this file.
// Make sure to add this file to your tsconfig.json file as an "includes" or "files" entry.
declare module 'vue-router/auto-routes' {
import type {
RouteRecordInfo,
ParamValue,
ParamValueOneOrMore,
ParamValueZeroOrMore,
ParamValueZeroOrOne,
} from 'unplugin-vue-router/types'
/**
* Route name map generated by unplugin-vue-router
*/
export interface RouteNamedMap {
'/': RouteRecordInfo<'/', '/', Record<never, never>, Record<never, never>>,
'/about': RouteRecordInfo<'/about', '/about', Record<never, never>, Record<never, never>>,
'/login': RouteRecordInfo<'/login', '/login', Record<never, never>, Record<never, never>>,
'/login/': RouteRecordInfo<'/login/', '/login', Record<never, never>, Record<never, never>>,
'/login/components/account': RouteRecordInfo<'/login/components/account', '/login/components/account', Record<never, never>, Record<never, never>>,
'/login/components/sms': RouteRecordInfo<'/login/components/sms', '/login/components/sms', Record<never, never>, Record<never, never>>,
'/README': RouteRecordInfo<'/README', '/README', Record<never, never>, Record<never, never>>,
'/register': RouteRecordInfo<'/register', '/register', Record<never, never>, Record<never, never>>,
'/register/': RouteRecordInfo<'/register/', '/register', Record<never, never>, Record<never, never>>,
'/register/components/account': RouteRecordInfo<'/register/components/account', '/register/components/account', Record<never, never>, Record<never, never>>,
'/register/components/credential-popover': RouteRecordInfo<'/register/components/credential-popover', '/register/components/credential-popover', Record<never, never>, Record<never, never>>,
'/register/components/sms': RouteRecordInfo<'/register/components/sms', '/register/components/sms', Record<never, never>, Record<never, never>>,
}
}

58
src/types/env.d.ts vendored

@ -1,41 +1,21 @@
/// <reference types="vite/client" />
declare module 'nenv' {
interface ENV {
VITE_BASE_URL: string
VITE_APP_NAME: string
VITE_APP_TITLE: string
VITE_APP_DESC: string
VITE_API_URL: string
VITE_UPLOAD_URL: string
VITE_API_URL_PREFIX: number
VITE_ICON_LOCAL_PREFIX: string
VITE_ICON_UNOCSS_PREFIX: string
VITE_HTTP_PROXY: boolean
VITE_COMPRESS: string
VITE_PWA: boolean
VITE_MARKDOWN: boolean
VITE_USE_MOCK: boolean
}
interface ImportMetaEnv {
/** 项目基本地址 */
readonly VITE_BASE_URL: string
/** 项目名称 */
readonly VITE_APP_NAME: string
/** 项目标题 */
readonly VITE_APP_TITLE: string
/** 项目描述 */
readonly VITE_APP_DESC: string
/** API访问地址 */
readonly VITE_API_URL: string
/** 上传地址 */
readonly VITE_UPLOAD_URL: string
/** API前缀 */
readonly VITE_API_URL_PREFIX: string
/** 本地ICON前缀 */
readonly VITE_ICON_LOCAL_PREFIX: string
/** UnoCSS ICON 前缀 */
readonly VITE_ICON_UNOCSS_PREFIX: string
/** 开启请求代理 */
readonly VITE_HTTP_PROXY: boolean
/** 是否开启打包文件大小结果分析 */
readonly VITE_VISUALIZER: boolean
/** 打包压缩 */
readonly VITE_COMPRESS: 'gzip' | 'brotliCompress' | 'deflate' | 'deflateRaw' | 'none'
/** 是否应用pwa */
readonly VITE_PWA: boolean
/** 是否启用Markdown插件,markdown生成html */
readonly VITE_MARKDOWN: boolean
// 是否开启Mock
readonly VITE_USE_MOCK: boolean
// 是否使用ViteSSG
readonly VITE_USE_SSG: boolean
const env: ENV
export default env
}
interface ImportMeta { readonly env: ImportMetaEnv }

@ -1,4 +1,4 @@
import type { RouteMeta } from 'vue-router'
import type { RouteMeta } from 'vue-router/auto'
declare global {
interface MenuTag {

@ -6,12 +6,13 @@ export function getAllParentPath<T = Recordable<any>>(
treeData: T[],
path: string,
) {
const menuList = findParentPath(treeData, n => n.path === path) as Menu[]
const menuList = findParentPath(treeData, n => n.path === path) as unknown as Menu[]
return (menuList || []).map(item => item.path)
}
export function hideFilter(menu: Menu) {
return !(menu.meta?.hideInMenu || menu.hideInMenu)
// console.log('hideFilter', menu, !(menu.meta?.hideInMenu || menu.hideInMenu))
return !menu.hideInMenu
}
export function basicFilter(routes: RouteRecordNormalized[]) {
@ -36,7 +37,7 @@ export function basicFilter(routes: RouteRecordNormalized[]) {
}
}
function joinParentPath(menus: RouteRecordRaw[], parentPath = '') {
function joinParentPath(menus: Menu[], parentPath = '') {
for (let index = 0; index < menus.length; index++) {
const menu = menus[index]
// https://next.router.vuejs.org/guide/essentials/nested-routes.html
@ -85,6 +86,8 @@ export function transformRouteToMenu(routes: RouteRecordRaw[], routerMapping: bo
}
},
})
joinParentPath(list)
return cloneDeep(list) as Menu[]
}

@ -150,8 +150,10 @@ export function filterTree<T = any>(
return list
.map((node: any) => ({ ...node }))
.filter((node) => {
// 递归调用 对含有children项 进行再次调用自身函数 listFilter
node[children] = node[children] && listFilter(node[children])
return func(node) || (node[children] && node[children].length)
// 执行传入的回调 func 进行过滤
return func(node)
})
}
return listFilter(tree)
@ -179,7 +181,7 @@ export function forEachTree<T = any>(
*/
export function mapTree<T = any>(
treeData: any[],
opt: { children?: string; conversion: AnyFunction<T> },
opt: { children?: string, conversion: AnyFunction<T> },
): T[] {
return treeData.map(item => doMapTree(item, opt))
}
@ -207,7 +209,7 @@ function doMapTree(
{
children = 'children',
conversion,
}: { children?: string; conversion: AnyFunction<any> },
}: { children?: string, conversion: AnyFunction<any> },
) {
const haveChildren
= Array.isArray(data[children]) && data[children].length > 0

@ -8,7 +8,7 @@
],
"baseUrl": ".",
"module": "ESNext",
"moduleResolution": "node",
"moduleResolution": "Bundler",
"paths": {
"~/*": [
"src/*"
@ -21,17 +21,13 @@
"types": [
"vitest",
"vite/client",
"vue/ref-macros",
"vite-plugin-pages/client",
"vite-plugin-vue-component-preview/client",
"vite-plugin-vue-layouts/client",
"vite-plugin-pwa/client",
"unplugin-vue-macros/macros-global",
"unplugin-vue-router/client",
"naive-ui",
"naive-ui/volar",
"pinia-plugin-persistedstate",
"vue-router",
"build/**"
"pinia-plugin-persistedstate"
],
"allowJs": true,
"strict": true,

@ -17,7 +17,7 @@ export default defineConfig({
presetAttributify(),
presetIcons({
autoInstall: false,
scale: 1.0,
scale: 1.2,
warn: true,
cdn: 'https://esm.sh/',
prefix: `${import.meta.env.VITE_ICON_UNOCSS_PREFIX || 'i'}-`,
@ -109,5 +109,5 @@ export default defineConfig({
dark: '#18181c',
},
},
safelist: 'prose m-auto text-left'.split(' '),
safelist: 'prose prose-sm m-auto text-left'.split(' '),
})

@ -3,6 +3,7 @@ import process from 'node:process'
import type { ConfigEnv } from 'vite'
import { defineConfig, loadEnv } from 'vite'
import Vue from '@vitejs/plugin-vue'
import EnvCaster from '@niku/vite-env-caster/dist/index'
// banner
import Banner from 'vite-plugin-banner'
@ -15,12 +16,13 @@ import { unheadVueComposablesImports } from '@unhead/vue'
// vue macros
import VueMacros from 'unplugin-vue-macros/vite'
// // pages
import Pages from 'vite-plugin-pages'
// layout
import Layouts from 'vite-plugin-vue-layouts'
// vue-router
import VueRouter from 'unplugin-vue-router/vite'
import { VueRouterAutoImports } from 'unplugin-vue-router'
import WebFontDownload from 'vite-plugin-webfont-dl'
import VueDevTools from 'vite-plugin-vue-devtools'
@ -28,7 +30,6 @@ import VueDevTools from 'vite-plugin-vue-devtools'
import Unocss from 'unocss/vite'
import VueI18n from '@intlify/unplugin-vue-i18n/vite'
import Components from 'unplugin-vue-components/vite'
import { visualizer } from 'rollup-plugin-visualizer'
// svg
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
@ -40,33 +41,65 @@ import ViteCompression from 'vite-plugin-compression'
import { VitePWA } from 'vite-plugin-pwa'
// markdown
import Markdown from 'vite-plugin-vue-markdown'
import Markdown from 'unplugin-vue-markdown/vite'
import LinkAttributes from 'markdown-it-link-attributes'
import Shiki from 'markdown-it-shiki'
import Shiki from '@shikijs/markdown-it'
import { NaiveUiResolver } from 'unplugin-vue-components/resolvers'
// import { PrimeVueResolver } from './build/primevue'
import pkg from './package.json'
type Algorithm = 'gzip' | 'brotliCompress' | 'deflate' | 'deflateRaw'
export default defineConfig(({ command, mode }: ConfigEnv) => {
console.log('command', command)
const viteEnv = loadEnv(mode, process.cwd()) as unknown as ImportMetaEnv
const viteEnv = loadEnv(mode, process.cwd())
const plugins = [
EnvCaster({
moduleName: 'nenv',
exportName: 'env',
declaration: 'src/types/env.d.ts',
}),
Banner({ outDir: '', content: `/**\n * name: ${pkg.name}\n * version: v${pkg.version}\n * description: ${pkg.description}\n * author: ${pkg.author.name}\n */` }),
// https://github.com/posva/unplugin-vue-router
VueRouter({
extensions: ['.vue', '.md'],
// 忽略 pages 中的所有 components 下的组件路由
// exclude: ['**/components/*'],
dts: 'src/typed-router.d.ts',
}),
VueMacros({
plugins: {
vue: Vue({
include: [/\.vue$/, /\.md$/],
template: {
compilerOptions: {
nodeTransforms: [
transformShortVmodel({ prefix: '$' }),
],
},
},
}),
},
}),
// https://github.com/JohnCampionJr/vite-plugin-vue-layouts
Layouts(),
// https://github.com/hannoeru/vite-plugin-pages
Pages({
extensions: ['vue', 'md'],
}),
// https://github.com/antfu/unplugin-auto-import
AutoImport({
imports: [
'vue-router',
'vue',
'vue-i18n',
'vue/macros',
'@vueuse/core',
VueRouterAutoImports,
// {
// // add any other imports you were relying on
// 'vue-router/auto': ['useLink', 'createRouter', 'createWebHistory', 'Router'],
// },
unheadVueComposablesImports,
{
'naive-ui': [
@ -87,35 +120,59 @@ export default defineConfig(({ command, mode }: ConfigEnv) => {
vueTemplate: true,
resolvers: [
NaiveUiResolver(),
// PrimeVueResolver(),
],
}),
VueMacros({
plugins: {
vue: Vue({
include: [/\.vue$/, /\.md$/],
reactivityTransform: true,
template: {
compilerOptions: {
nodeTransforms: [
transformShortVmodel({ prefix: '$' }),
],
},
},
}),
},
// https://github.com/antfu/unplugin-vue-components
Components({
// allow auto load markdown components under `./src/components/`
extensions: ['vue', 'md', 'ts'],
// allow auto import and register components used in markdown
include: [/\.vue$/, /\.vue\?vue/, /\.md$/, /\.ts$/],
directoryAsNamespace: true,
collapseSamePrefixes: true,
dts: 'src/components.d.ts',
resolvers: [
NaiveUiResolver(),
// PrimeVueResolver({
// // importTheme: 'mira',
// importStyle: false,
// importIcons: true,
// prefix: 'P'
// }),
// (name) => {
// if (name.startsWith('L')) {
// const importName = name.slice(2)
// console.log("🚀 ~ defineConfig ~ importName:", importName)
// const from = 'src/components'
// return {
// name,
// from: `${from}/${importName}`,
// }
// }
// },
],
}),
// https://github.com/antfu/unocss
// see uno.config.ts for config
Unocss(),
// https://github.com/feat-agency/vite-plugin-webfont-dl
WebFontDownload(),
// https://github.com/webfansplz/vite-plugin-vue-devtools
VueDevTools(),
// https://github.com/vbenjs/vite-plugin-svg-icons/blob/main/README.md
createSvgIconsPlugin({
iconDirs: [path.resolve(process.cwd(), 'assets/svg')],
symbolId: 'nl-[dir]-[name]',
}),
// https://github.com/antfu/unocss
// see uno.config.ts for config
Unocss(),
// https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n
VueI18n({
runtimeOnly: true,
@ -123,45 +180,23 @@ export default defineConfig(({ command, mode }: ConfigEnv) => {
fullInstall: true,
include: [path.resolve(__dirname, 'locales/**')],
}),
// https://github.com/antfu/unplugin-vue-components
Components({
// allow auto load markdown components under `./src/components/`
extensions: ['vue', 'md', 'ts'],
// allow auto import and register components used in markdown
include: [/\.vue$/, /\.vue\?vue/, /\.md$/, /\.ts$/],
directoryAsNamespace: true,
collapseSamePrefixes: true,
dts: 'src/components.d.ts',
resolvers: [
NaiveUiResolver(),
(name) => {
if (name.startsWith('L')) {
const importName = name.slice(2)
const from = 'src/components'
return {
name,
from: `${from}/${importName}`,
}
}
},
],
}),
]
if (viteEnv.VITE_VISUALIZER) {
plugins.push(visualizer({
gzipSize: true,
brotliSize: true,
open: true,
}))
}
// if (viteEnv.VITE_VISUALIZER == 'true') {
// plugins.push(visualizer({
// gzipSize: true,
// brotliSize: true,
// open: true,
// }))
// }
// compress
if (viteEnv.VITE_COMPRESS !== 'none') {
plugins.push(ViteCompression({ algorithm: viteEnv.VITE_COMPRESS }))
plugins.push(ViteCompression({ algorithm: viteEnv.VITE_COMPRESS as Algorithm }))
}
// https://github.com/antfu/vite-plugin-pwa
if (viteEnv.VITE_PWA) {
if (viteEnv.VITE_PWA === 'true') {
plugins.push(VitePWA({
registerType: 'autoUpdate',
includeAssets: ['favicon.svg', 'safari-pinned-tab.svg'],
@ -193,17 +228,11 @@ export default defineConfig(({ command, mode }: ConfigEnv) => {
// https://github.com/antfu/vite-plugin-vue-markdown
// Don't need this? Try vitesse-lite: https://github.com/antfu/vitesse-lite
if (viteEnv.VITE_MARKDOWN) {
if (viteEnv.VITE_MARKDOWN === 'true') {
plugins.push(Markdown({
wrapperClasses: 'prose prose-sm m-auto text-left',
markdownItSetup(md) {
// https://prismjs.com/
md.use(Shiki, {
theme: {
light: 'vitesse-light',
dark: 'vitesse-dark',
},
})
headEnabled: true,
async markdownItSetup(md) {
md.use(LinkAttributes, {
matcher: (link: string) => /^https?:\/\//.test(link),
attrs: {
@ -211,6 +240,13 @@ export default defineConfig(({ command, mode }: ConfigEnv) => {
rel: 'noopener',
},
})
md.use(await Shiki({
defaultColor: false,
themes: {
light: 'vitesse-light',
dark: 'vitesse-dark',
},
}))
},
}))
}
@ -226,8 +262,6 @@ export default defineConfig(({ command, mode }: ConfigEnv) => {
},
server: {
host: '0.0.0.0',
port: 3200,
proxy: {
'^/api': {
target: 'http://127.0.0.1:19999',

Loading…
Cancel
Save