👌 新的依赖和vue开发工具

This commit is contained in:
bunny 2025-05-15 22:49:56 +08:00
parent f116067708
commit 0587b8ddd8
30 changed files with 1046 additions and 119 deletions

View File

@ -33,6 +33,7 @@ export const buildEnv = (): BuildOptions => {
rollupOptions: { rollupOptions: {
external: ['md-editor-v3', 'echarts'], external: ['md-editor-v3', 'echarts'],
input: { input: {
// @ts-ignore
index: pathResolve('../index.html', import.meta.url), index: pathResolve('../index.html', import.meta.url),
}, },
// 静态资源分类打包 // 静态资源分类打包

View File

@ -1,12 +1,18 @@
import type { AcceptedPlugin } from 'postcss';
import postCssPxToViewport8plugin from 'postcss-px-to-viewport-8-plugin'; import postCssPxToViewport8plugin from 'postcss-px-to-viewport-8-plugin';
import type { CSSOptions, Plugin } from 'vite'; import type { CSSOptions } from 'vite';
import { wrapperEnv } from './utils'; import { wrapperEnv } from './utils';
export const css = (mode): CSSOptions => { export const css = (mode: string): CSSOptions => {
const plugins: Plugin[] = [usePostCssPxToViewport8plugin(mode)]; const plugins: AcceptedPlugin[] = [usePostCssPxToViewport8plugin(mode)];
return { return {
preprocessorOptions: {
scss: {
additionalData: `@use "@/assets/styles/minix/sidebar" as *;`,
},
},
postcss: { postcss: {
plugins: plugins.filter(Boolean), plugins: plugins.filter(Boolean),
}, },
@ -14,7 +20,7 @@ export const css = (mode): CSSOptions => {
}; };
/** 是否启用px转换vw插件 */ /** 是否启用px转换vw插件 */
const usePostCssPxToViewport8plugin = (mode): Plugin => { const usePostCssPxToViewport8plugin = (mode: string): AcceptedPlugin => {
const { VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN } = wrapperEnv(mode, 'VITE'); const { VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN } = wrapperEnv(mode, 'VITE');
const cssPxToVw = postCssPxToViewport8plugin({ const cssPxToVw = postCssPxToViewport8plugin({

View File

@ -3,7 +3,7 @@ import dayjs, { type Dayjs } from 'dayjs';
import duration from 'dayjs/plugin/duration'; import duration from 'dayjs/plugin/duration';
import gradientString from 'gradient-string'; import gradientString from 'gradient-string';
import { wrapperEnv } from './utils'; import { logOutputSize, wrapperEnv } from './utils';
dayjs.extend(duration); dayjs.extend(duration);
@ -17,13 +17,12 @@ const boxenOptions: BoxenOptions = {
/* 输出日志信息 */ /* 输出日志信息 */
const printLogMessage = (VITE_PORT: number) => { const printLogMessage = (VITE_PORT: number) => {
return gradientString('cyan', 'magenta').multiline( return gradientString('cyan', 'magenta').multiline(
`保存成功!服务器重新启动... `欢迎使用此项目,项目访问地址如下:
访
http://localhost:${VITE_PORT}` http://localhost:${VITE_PORT}`
); );
}; };
export const viteConsoleLog = (mode) => { export const viteConsoleLog = (mode: string) => {
const { VITE_PORT } = wrapperEnv(mode); const { VITE_PORT } = wrapperEnv(mode);
let config: { command: string }; let config: { command: string };
@ -44,9 +43,12 @@ export const viteConsoleLog = (mode) => {
if (config.command === 'build') { if (config.command === 'build') {
endTime = dayjs(new Date()); endTime = dayjs(new Date());
const format = dayjs.duration(endTime.diff(startTime)).format('mm分ss秒'); const format = dayjs.duration(endTime.diff(startTime)).format('mm分ss秒');
console.log( console.log(
boxen( boxen(
gradientString('cyan', 'magenta').multiline(`🎉 恭喜打包完成(总用时${format}`), gradientString('cyan', 'magenta').multiline(
`🎉 恭喜打包完成(总用时${format})打包大小(${logOutputSize()}`
),
boxenOptions boxenOptions
) )
); );

View File

@ -9,6 +9,6 @@ const include = ['vue', 'vue-router', 'dayjs', 'axios', 'pinia', 'vue-types', 'j
/** /**
* *
*/ */
const exclude = []; const exclude: string[] = [];
export { include, exclude }; export { include, exclude };

View File

@ -1,24 +1,26 @@
import UnoCssIcons from '@unocss/preset-icons'; import UnoCssIcons from '@unocss/preset-icons';
import vue from '@vitejs/plugin-vue'; import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx'; import vueJsx from '@vitejs/plugin-vue-jsx';
import { presetIcons, presetUno } from 'unocss'; import { presetIcons } from 'unocss';
import UnoCSS from 'unocss/vite'; import UnoCSS from 'unocss/vite';
import type { PluginOption } from 'vite'; import type { PluginOption } from 'vite';
import { vitePluginFakeServer } from 'vite-plugin-fake-server'; import { vitePluginFakeServer } from 'vite-plugin-fake-server';
import removeConsole from 'vite-plugin-remove-console'; import removeConsole from 'vite-plugin-remove-console';
import vueDevTools from 'vite-plugin-vue-devtools';
import Inspector from 'vite-plugin-vue-inspector'; import Inspector from 'vite-plugin-vue-inspector';
import { useCDN } from './cdn'; import { useCDN } from './cdn';
import { viteConsoleLog } from './info'; import { viteConsoleLog } from './info';
import { compressPack, report, wrapperEnv } from './utils'; import { compressPack, report, wrapperEnv } from './utils';
export const plugins = (mode): PluginOption[] => { export const plugins = (mode: string): PluginOption[] => {
return [ return [
vue(), vue(),
vueJsx(), vueJsx(),
Inspector(), Inspector(),
report(), report(),
removeConsole(), removeConsole(),
vueDevTools(),
useCDN(mode), useCDN(mode),
viteConsoleLog(mode), viteConsoleLog(mode),
UnoCSS({ UnoCSS({
@ -26,18 +28,19 @@ export const plugins = (mode): PluginOption[] => {
inspector: true, // 控制台是否打印 UnoCSS inspector inspector: true, // 控制台是否打印 UnoCSS inspector
presets: [ presets: [
presetIcons({ presetIcons({
prefix: '',
extraProperties: { extraProperties: {
display: 'inline-block', display: 'inline-block',
'vertical-align': 'middle', 'vertical-align': 'middle',
}, },
}), }),
UnoCssIcons({ UnoCssIcons({
prefix: 'i-', prefix: '',
extraProperties: { extraProperties: {
display: 'inline-block', display: 'inline-block',
'vertical-align': 'middle',
}, },
}), }),
presetUno(),
], ],
}), }),
compressPack(mode), compressPack(mode),
@ -46,7 +49,7 @@ export const plugins = (mode): PluginOption[] => {
}; };
/** MOCK 服务 */ /** MOCK 服务 */
const useMock = (mode) => { const useMock = (mode: string) => {
const { VITE_MOCK_DEV_SERVER } = wrapperEnv(mode); const { VITE_MOCK_DEV_SERVER } = wrapperEnv(mode);
return VITE_MOCK_DEV_SERVER return VITE_MOCK_DEV_SERVER

View File

@ -4,7 +4,7 @@ export const resolve = () => {
return { return {
alias: { alias: {
'@': pathResolve('../src'), '@': pathResolve('../src'),
'@build': pathResolve(), // '@build': pathResolve(),
}, },
}; };
}; };

View File

@ -3,7 +3,7 @@ import type { ServerOptions } from 'vite';
import { wrapperEnv } from './utils'; import { wrapperEnv } from './utils';
/* 开发服务配置 */ /* 开发服务配置 */
export const server = (mode) => { export const server = (mode: string) => {
const { VITE_PORT, VITE_APP_URL, VITE_STRICT_PORT } = wrapperEnv(mode); const { VITE_PORT, VITE_APP_URL, VITE_STRICT_PORT } = wrapperEnv(mode);
const options: ServerOptions = { const options: ServerOptions = {

View File

@ -1,10 +1,14 @@
import { dirname, resolve } from 'node:path'; import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url'; import { fileURLToPath } from 'node:url';
import fs from 'fs';
import path from 'path';
import { visualizer } from 'rollup-plugin-visualizer'; import { visualizer } from 'rollup-plugin-visualizer';
import { loadEnv } from 'vite'; import { loadEnv } from 'vite';
import viteCompression from 'vite-plugin-compression'; import viteCompression from 'vite-plugin-compression';
import { buildEnv } from './buildEnv';
export const root: string = process.cwd(); export const root: string = process.cwd();
/** /**
@ -12,6 +16,7 @@ export const root: string = process.cwd();
* @param dir `build` * @param dir `build`
* @param metaUrl `url``build``import.meta.url` * @param metaUrl `url``build``import.meta.url`
*/ */
// @ts-ignore
export const pathResolve = (dir = '.', metaUrl = import.meta.url) => { export const pathResolve = (dir = '.', metaUrl = import.meta.url) => {
// 当前文件目录的绝对路径 // 当前文件目录的绝对路径
const currentFileDir = dirname(fileURLToPath(metaUrl)); const currentFileDir = dirname(fileURLToPath(metaUrl));
@ -34,18 +39,20 @@ export const pathResolve = (dir = '.', metaUrl = import.meta.url) => {
* @param prefix * @param prefix
* @link https://cn.vite.dev/config/#using-environment-variables-in-config * @link https://cn.vite.dev/config/#using-environment-variables-in-config
*/ */
export const wrapperEnv = (mode, prefix: string = ''): ViteEnv => { // @ts-ignore
const env = loadEnv(mode, root, prefix); export const wrapperEnv = (mode: string, prefix: string = ''): ViteEnv => {
const env: any = loadEnv(mode, root, prefix);
// 将变量转换指定类型 // 将变量转换指定类型
for (const envName of Object.keys(env)) { for (const envName of Object.keys(env)) {
let realName = env[envName].replace(/\\n/g, '\n'); let realName: string | boolean | number = env[envName].replace(/\\n/g, '\n');
realName = realName === 'true' ? true : realName === 'false' ? false : realName; realName = realName === 'true' ? true : realName === 'false' ? false : realName;
if (envName === 'VITE_PORT') { if (envName === 'VITE_PORT') {
realName = Number(realName); realName = Number(realName);
} }
env[envName] = realName; env[envName] = realName;
// @ts-ignore
process.env[envName] = realName; process.env[envName] = realName;
} }
return env; return env;
@ -60,8 +67,52 @@ export const report = () => {
}; };
/* 启用gzip压缩 */ /* 启用gzip压缩 */
export const compressPack = (mode) => { export const compressPack = (mode: string) => {
const { VITE_COMPRESSION } = wrapperEnv(mode); const { VITE_COMPRESSION } = wrapperEnv(mode);
return VITE_COMPRESSION == 'gzip' ? viteCompression({ threshold: 1024000 }) : null; return VITE_COMPRESSION == 'gzip' ? viteCompression({ threshold: 1024000 }) : null;
}; };
/**
*
* @returns
*/
export const logOutputSize = (): string => {
const outDir = `../${buildEnv().outDir}`;
function convertSize(size: number) {
const units: Array<string> = ['byte', 'KB', 'MB', 'GB'];
// 输入的单位是否存在
let index = 0;
while (size >= 1024) {
size /= 1024;
index++;
}
return `${size.toFixed(2)} ${units[index]}`;
}
// 计算文件夹字节大小
function getFolderSize(folderPath: string) {
let size = 0;
fs.readdirSync(folderPath).forEach((fileName: string) => {
const filePath = path.join(folderPath, fileName);
const stats = fs.statSync(filePath);
if (stats.isFile()) {
size += stats.size;
} else if (stats.isDirectory()) {
size += getFolderSize(filePath);
}
});
return size;
}
const folderSize = getFolderSize(path.resolve(__dirname, outDir));
return convertSize(folderSize);
};

View File

@ -1,29 +1,39 @@
{ {
"name": "dashboard-template", "name": "screen-template",
"private": true, "private": true,
"version": "1.0.0", "version": "1.0.0",
"type": "module", "type": "module",
"author": {
"name": "Bunny",
"url": "https://github.com/BunnyMaster"
},
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build",
"preview": "vite preview", "preview": "vite preview",
"report": "rimraf dist && vite build", "report": "rimraf dist && vite build",
"lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock,build}/**/*.{vue,js,ts,tsx}\" --fix",
"lint:prettier": "prettier --write \"src/**/*.{js,ts,json,tsx,css,scss,vue,html,md}\"",
"lint:stylelint": "stylelint --cache --fix \"**/*.{html,vue,css,scss}\" --cache-location node_modules/.cache/stylelint/", "lint:stylelint": "stylelint --cache --fix \"**/*.{html,vue,css,scss}\" --cache-location node_modules/.cache/stylelint/",
"lint": "pnpm lint:eslint && pnpm lint:prettier && pnpm lint:stylelint" "lint": "pnpm lint:eslint && pnpm lint:prettier && pnpm lint:stylelint"
}, },
"dependencies": { "dependencies": {
"@eslint/js": "^9.21.0", "@eslint/js": "^9.21.0",
"@parcel/watcher": "^2.5.1",
"@types/node": "^22.13.10",
"@typescript-eslint/eslint-plugin": "^8.24.1", "@typescript-eslint/eslint-plugin": "^8.24.1",
"@typescript-eslint/parser": "^8.24.1", "@typescript-eslint/parser": "^8.24.1",
"@unocss/preset-icons": "^66.0.0", "@unocss/preset-icons": "^66.0.0",
"@unocss/reset": "^66.0.0", "@unocss/reset": "^66.0.0",
"@vitejs/plugin-vue-jsx": "^4.1.1", "@vitejs/plugin-vue-jsx": "^4.1.1",
"@vueuse/core": "^12.8.2",
"animate.css": "^4.1.1", "animate.css": "^4.1.1",
"autofit.js": "^3.2.4", "autofit.js": "^3.2.4",
"axios": "^1.7.9", "axios": "^1.7.9",
"boxen": "^8.0.1", "boxen": "^8.0.1",
"dayjs": "^1.11.13", "dayjs": "^1.11.13",
"echarts": "^5.6.0", "echarts": "^5.6.0",
"esbuild": "^0.25.1",
"eslint": "^9.9.1", "eslint": "^9.9.1",
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"eslint-define-config": "^2.1.0", "eslint-define-config": "^2.1.0",
@ -35,6 +45,7 @@
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"pinia": "^2.3.1", "pinia": "^2.3.1",
"pinia-plugin-persistedstate": "^3.2.3", "pinia-plugin-persistedstate": "^3.2.3",
"postcss": "^8.5.3",
"postcss-px-to-viewport-8-plugin": "^1.2.5", "postcss-px-to-viewport-8-plugin": "^1.2.5",
"prettier": "^3.3.3", "prettier": "^3.3.3",
"qs": "^6.14.0", "qs": "^6.14.0",
@ -53,19 +64,24 @@
"vite-plugin-remove-console": "^2.2.0", "vite-plugin-remove-console": "^2.2.0",
"vite-plugin-vue-inspector": "^5.3.1", "vite-plugin-vue-inspector": "^5.3.1",
"vue": "^3.5.13", "vue": "^3.5.13",
"vue-demi": "^0.14.10",
"vue-eslint-parser": "^9.4.3", "vue-eslint-parser": "^9.4.3",
"vue-router": "^4.4.3", "vue-router": "^4.4.3",
"vue-types": "^6.0.0" "vue-types": "^6.0.0"
}, },
"devDependencies": { "devDependencies": {
"@iconify/json": "^2.2.310", "@iconify/json": "^2.2.310",
"@types/nprogress": "^0.2.3",
"@types/qs": "^6.9.18",
"@vitejs/plugin-vue": "^5.2.1", "@vitejs/plugin-vue": "^5.2.1",
"@vue/tsconfig": "^0.7.0", "@vue/tsconfig": "^0.7.0",
"eslint-plugin-simple-import-sort": "^12.1.1", "eslint-plugin-simple-import-sort": "^12.1.1",
"typescript": "~5.7.2", "typescript": "~5.7.2",
"vite": "^6.1.0", "vite": "^6.1.0",
"vite-plugin-compression": "^0.5.1", "vite-plugin-compression": "^0.5.1",
"vue-tsc": "^2.2.0" "vue-tsc": "^2.2.0",
"vite-plugin-vue-devtools": "^7.7.2",
"jiti": "^2.4.2"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0", "node": "^18.18.0 || ^20.9.0 || >=21.1.0",
@ -85,4 +101,4 @@
} }
} }
} }
} }

File diff suppressed because it is too large Load Diff

5
push.sh Normal file
View File

@ -0,0 +1,5 @@
git checkout master
git merge dev
git push --all
git push --tags
git checkout dev

View File

@ -1,7 +1,28 @@
<template> <template>
<router-view v-slot="{ Component, route }"> <router-view v-slot="{ Component, route }">
<transition :name="route.meta.transition || 'fade-transform'" mode="out-in"> <transition
:enter-active-class="
route.meta.transition?.enter
? `animate__animated ${route.meta.transition.enter}`
: 'animate__animated animate__fadeInLeft animate__faster'
"
:leave-active-class="
route.meta.transition?.leave
? `animate__animated ${route.meta.transition.leave}`
: 'animate__animated animate__fadeOutLeft animate__faster'
"
mode="out-in"
>
<component :is="Component" :key="route.path" /> <component :is="Component" :key="route.path" />
</transition> </transition>
</router-view> </router-view>
</template> </template>
<script lang="ts" setup></script>
<style lang="scss">
#app {
width: 100%;
//height: 1080px;
height: 100%;
}
</style>

View File

@ -44,7 +44,7 @@ service.interceptors.response.use(
} }
// ElMessage.error(msg || '系统出错'); // ElMessage.error(msg || '系统出错');
return Promise.reject(msg || 'Error'); return Promise.reject(response.data.message || 'Error');
}, },
(error: any) => { (error: any) => {
// 异常处理 // 异常处理

View File

@ -44,7 +44,7 @@ service.interceptors.response.use(
} }
// ElMessage.error(msg || '系统出错'); // ElMessage.error(msg || '系统出错');
return Promise.reject(msg || 'Error'); return Promise.reject(response.data.message || 'Error');
}, },
(error: any) => { (error: any) => {
// 异常处理 // 异常处理

View File

@ -0,0 +1,50 @@
@mixin view-style-default($sidebar-width,$content-width) {
&__sidebar {
display: flex;
flex-wrap: wrap;
flex-direction: column;
justify-content: space-between;
align-items: center;
width: $sidebar-width;
height: 100%;
color: #fff;
&-item {
padding: 9px 15px;
width: 100%;
background: rgba(14, 95, 255, 0.2);
}
&-tag {
float: left;
margin: 0 7px 0 0;
width: 62px;
height: 26px;
line-height: 26px;
font-size: 14px;
text-align: center;
background: rgba(24, 69, 135, 0.55);
color: #fff;
cursor: default;
}
&-title {
width: 172px;
height: 42px;
font-size: 22px;
color: #fff;
background: url('@/assets/images/business-supervision/bg/sidebar/bg-frame-4.png') no-repeat;
background-size: cover;
}
&-title-describe {
font-size: 12px;
color: var(--color-info-secondary-1);
}
}
&__content {
width: $content-width;
height: 100%;
}
}

View File

@ -2,6 +2,7 @@ import 'animate.css';
import '@unocss/reset/tailwind-compat.css'; import '@unocss/reset/tailwind-compat.css';
import 'uno.css'; import 'uno.css';
import 'virtual:unocss-devtools'; import 'virtual:unocss-devtools';
import '@/assets/styles/global.scss';
import { createApp } from 'vue'; import { createApp } from 'vue';

View File

@ -1,4 +1,4 @@
import { BarChart, LineChart, PieChart } from 'echarts/charts'; import { BarChart, GaugeChart, LineChart, PictorialBarChart, PieChart } from 'echarts/charts';
import { import {
DataZoomComponent, DataZoomComponent,
GraphicComponent, GraphicComponent,
@ -15,7 +15,6 @@ import { CanvasRenderer, SVGRenderer } from 'echarts/renderers';
import type { App } from 'vue'; import type { App } from 'vue';
const { use } = echarts; const { use } = echarts;
use([ use([
PieChart, PieChart,
BarChart, BarChart,
@ -31,6 +30,8 @@ use([
TooltipComponent, TooltipComponent,
DataZoomComponent, DataZoomComponent,
VisualMapComponent, VisualMapComponent,
PictorialBarChart,
GaugeChart,
]); ]);
/** /**

View File

@ -3,19 +3,20 @@ import type { App } from 'vue';
import { setupDirective } from '@/directive'; import { setupDirective } from '@/directive';
import { autoFit } from '@/plugins/autofit'; import { autoFit } from '@/plugins/autofit';
import { useEcharts } from '@/plugins/echarts'; import { useEcharts } from '@/plugins/echarts';
import { setUpRouter } from '@/router'; import { setupRouter } from '@/router';
import { setupStore } from '@/store'; import { setupStore } from '@/store';
export default { export default {
install(app: App<Element>) { install(app: App<Element>) {
// 设置路由 // 设置路由
setUpRouter(app); setupRouter(app);
// 设置状态管理 // 设置状态管理
setupStore(app); setupStore(app);
// 设置指令 // 设置指令
setupDirective(app); setupDirective(app);
// 根据需求引入echarts // 根据需求引入echarts
useEcharts(app); useEcharts(app);
// 使用autoFit在环境配置文件中设置
autoFit(); autoFit();
}, },
}; };

View File

@ -6,15 +6,15 @@ import home from '@/router/modules/home';
import remaining from '@/router/modules/remaining'; import remaining from '@/router/modules/remaining';
// 静态路由 // 静态路由
const routes: RouteRecordRaw[] = [...remaining, ...home, ...error]; const routes: RouteRecordRaw[] = [...remaining, ...home, ...error] as RouteRecordRaw[];
const router = createRouter({ const router = createRouter({
history: createWebHashHistory(), history: createWebHashHistory(),
routes, routes,
scrollBehavior: () => ({ x: 0, y: 0 }), scrollBehavior: () => ({ left: 0, top: 0, behavior: 'smooth' }),
}); });
/** 全局注册 router */ /** 全局注册 router */
export const setUpRouter = (app: App<Element>) => { export const setupRouter = (app: App<Element>) => {
app.use(router); app.use(router);
}; };
@ -23,4 +23,10 @@ export const resetRouter = () => {
router.replace({ path: '/' }).then(); router.replace({ path: '/' }).then();
}; };
// router.afterEach((to, from) => {
// const toDepth = to.path.split('/').length;
// const fromDepth = from.path.split('/').length;
// to.meta.transition = toDepth < fromDepth ? 'slide-right' : 'slide-left';
// });
export default router; export default router;

View File

@ -1,6 +1,8 @@
import type { RouteRecordRaw } from 'vue-router'; import type { RouteRecordRaw } from 'vue-router';
const routes: RouteRecordRaw[] = [ import type { RouteConfigsTable } from '@/types/router/Route';
const routes: RouteRecordRaw[] | RouteConfigsTable[] = [
{ {
path: '/error', path: '/error',
component: () => import('@/views/error-page/404.vue'), component: () => import('@/views/error-page/404.vue'),

View File

@ -1,13 +1,13 @@
import type { RouteRecordRaw } from 'vue-router'; import type { RouteRecordRaw } from 'vue-router';
import Layout from '@/layout/index.vue'; import Layout from '@/layout/index.vue';
import type { RouteConfigsTable } from '@/types/router/Route';
const routes: RouteRecordRaw[] = [ const routes: RouteRecordRaw[] | RouteConfigsTable[] = [
{ {
path: '/', path: '/',
name: '/', name: '/',
component: Layout, component: Layout,
meta: { transition: 'fade' },
}, },
]; ];

View File

@ -1,8 +1,9 @@
import type { RouteRecordRaw } from 'vue-router'; import type { RouteRecordRaw } from 'vue-router';
import Layout from '@/layout/index.vue'; import Layout from '@/layout/index.vue';
import type { RouteConfigsTable } from '@/types/router/Route';
const routes: RouteRecordRaw[] = [ const routes: RouteRecordRaw[] | RouteConfigsTable[] = [
{ {
path: '/redirect', path: '/redirect',
component: Layout, component: Layout,

27
src/store/app.ts Normal file
View File

@ -0,0 +1,27 @@
import { defineStore } from 'pinia';
import { isCSSColor, isPath } from '@/utils/regexp/regexpBackground';
const useAppStore = defineStore('appStore', {
state() {
return {
background: '',
};
},
getters: {},
actions: {
setBackground(background: string) {
if (isCSSColor(background)) {
this.background = background;
} else if (isPath(background)) {
const href = new URL(background, import.meta.url).href;
this.background = `url(${href})`;
} else {
const href = new URL('@/assets/images/common/bg/bg-layout.png', import.meta.url).href;
this.background = `url(${href})`;
}
},
},
});
export { useAppStore };

11
src/types/router.d.ts vendored Normal file
View File

@ -0,0 +1,11 @@
// types/router.d.ts
import 'vue-router';
declare module 'vue-router' {
interface RouteMeta {
transition?: {
enter: string;
leave: string;
};
}
}

View File

@ -1,18 +1,29 @@
import type { RouteComponent } from 'vue-router'; import type { RouteComponent } from 'vue-router';
/**
* @description
*/
interface Transition {
enter?: string;
leave?: string;
}
/** /**
* @description `meta` * @description `meta`
*/ */
interface CustomizeRouteMeta { interface CustomizeRouteMeta {
title: string; title?: string;
subtitle: string; subtitle?: string;
transition: string; transition?: Transition;
hidden?: boolean;
/* 头部类型 */
headerType?: any;
} }
/** /**
* @description * @description
*/ */
interface RouteConfigsTable { export interface RouteConfigsTable {
/** 路由地址 `必填` */ /** 路由地址 `必填` */
path: string; path: string;
/** 路由名字(保持唯一)`可选` */ /** 路由名字(保持唯一)`可选` */
@ -25,5 +36,3 @@ interface RouteConfigsTable {
/** 子路由配置项 */ /** 子路由配置项 */
children?: Array<RouteConfigsTable>; children?: Array<RouteConfigsTable>;
} }
export { RouteConfigsTable };

View File

@ -1,20 +1,18 @@
import { useEventListener } from '@vueuse/core'; import { useDebounceFn, useEventListener } from '@vueuse/core';
import type { EChartsType } from 'echarts';
import echarts from '@/plugins/echarts';
/** 通用重置图表样式 */ /** 通用重置图表样式 */
export const debounceChart = (myChart: EChartsType) => { export const debounceChart = (myChart: echarts.ECharts | undefined) => {
useEventListener( const debounceFn = useDebounceFn(() => {
window, myChart!.resize();
'resize', }, 500);
() => {
myChart.resize(); useEventListener(window, 'resize', debounceFn);
},
500
);
}; };
/** 数字格式化 */ /** 数字格式化 */
export const formatter = (number) => { export const formatter = (number: any) => {
const numbers = number.toString().split('').reverse(); const numbers = number.toString().split('').reverse();
const segs = []; const segs = [];
@ -22,3 +20,21 @@ export const formatter = (number) => {
return segs.join(',').split('').reverse().join(''); return segs.join(',').split('').reverse().join('');
}; };
/** 颜色渲染 */
export const graphicLinearGradient = (
color1: string,
color2: string,
coordinate: Array<number> = [0, 0, 0, 1]
) => {
return new echarts.graphic.LinearGradient(
coordinate[0],
coordinate[1],
coordinate[2],
coordinate[3],
[
{ offset: 0, color: color1 },
{ offset: 1, color: color2 },
]
);
};

View File

@ -25,7 +25,7 @@ export const downloadBlob = (response: any) => {
const contentDisposition = response.headers['content-disposition']; const contentDisposition = response.headers['content-disposition'];
let fileName = 'download.zip'; let fileName = 'download.zip';
if (contentDisposition) { if (contentDisposition) {
const fileNameMatch = contentDisposition.match(/filename="?(.+)"?/); const fileNameMatch = contentDisposition.match(/filename="?(.+)"/);
if (fileNameMatch && fileNameMatch[1]) { if (fileNameMatch && fileNameMatch[1]) {
fileName = fileNameMatch[1]; fileName = fileNameMatch[1];
} }

View File

@ -1,5 +1,5 @@
/** 判断是否是CSS颜色 */ /** 判断是否是CSS颜色 */
function isCSSColor(str) { function isCSSColor(str: string) {
// 匹配十六进制颜色(如 #fff, #ffffff // 匹配十六进制颜色(如 #fff, #ffffff
const hexColor = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/; const hexColor = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
@ -16,7 +16,7 @@ function isCSSColor(str) {
} }
/** 判断是否是相对路径或绝对路径 */ /** 判断是否是相对路径或绝对路径 */
function isPath(str) { function isPath(str: string) {
// 匹配相对路径(如 ./path, ../path, path/to/file // 匹配相对路径(如 ./path, ../path, path/to/file
const relativePath = /^\.{0,2}\/[^\/].*$/; const relativePath = /^\.{0,2}\/[^\/].*$/;

View File

@ -1,49 +1,49 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "esnext", "target": "ESNext",
"useDefineForClassFields": true, "module": "ESNext",
"module": "esnext", "moduleResolution": "bundler",
"moduleResolution": "node", "strict": false,
"strict": true, "jsx": "preserve",
"noLib": false, "importHelpers": true,
"sourceMap": true, "experimentalDecorators": true,
"resolveJsonModule": true, "strictFunctionTypes": false,
"esModuleInterop": true,
"lib": [
"esnext",
"dom"
],
"baseUrl": ".",
"allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"esModuleInterop": true,
"isolatedModules": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"jsx": "preserve", "sourceMap": true,
"jsxFactory": "h", "baseUrl": ".",
"jsxFragmentFactory": "Fragment", "allowJs": false,
"resolveJsonModule": true,
"lib": [
"ESNext",
"DOM"
],
"paths": { "paths": {
"@/*": [ "@/*": [
"src/*" "src/*"
],
"@build/*": [
"build/*"
] ]
}, },
"types": [ "types": [
"vite/client", "node",
"unplugin-icons/types/vue", "vite/client"
"element-plus/global"
] ]
}, },
"files": [],
"include": [ "include": [
"mock/*.ts", "mock/*.ts",
"src/**/*.ts", "src/**/*.ts",
"src/**/*.tsx", "src/**/*.tsx",
"src/**/*.vue", "src/**/*.vue",
"src/types/*.d.ts", "vite.config.ts",
"vite.config.ts" "src/**/*.d.ts"
], ],
"exclude": [ "exclude": [
"dist", "dist",
"**/*.js",
"node_modules" "node_modules"
] ]
} }

View File

@ -10,7 +10,8 @@ import { server } from './build/server';
import { root, wrapperEnv } from './build/utils'; import { root, wrapperEnv } from './build/utils';
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig(({ command, mode, isSsrBuild, isPreview }) => { // export default defineConfig(({ command, mode, isSsrBuild, isPreview }) => {
export default defineConfig(({ mode }) => {
const env = wrapperEnv(mode, 'VITE'); const env = wrapperEnv(mode, 'VITE');
return { return {