初始化
This commit is contained in:
58
build/config/cli-helper.ts
Normal file
58
build/config/cli-helper.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
/* eslint-disable */
|
||||
import process from 'node:process'
|
||||
import readline from 'node:readline'
|
||||
|
||||
function clearScreen() {
|
||||
const repeatCount = process.stdout.rows - 2
|
||||
const blank = repeatCount > 0 ? '\n'.repeat(repeatCount) : ''
|
||||
console.log(blank)
|
||||
readline.cursorTo(process.stdout, 0, 0)
|
||||
readline.clearScreenDown(process.stdout)
|
||||
}
|
||||
|
||||
function formatter(open: string, close: string, replace = open) {
|
||||
return (input: string) => {
|
||||
const string = `${input}`
|
||||
const index = string.indexOf(close, open.length)
|
||||
return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close
|
||||
}
|
||||
}
|
||||
|
||||
function replaceClose(string: string, close: string, replace: string, index: number): string {
|
||||
const start = string.substring(0, index) + replace
|
||||
const end = string.substring(index + close.length)
|
||||
const nextIndex = end.indexOf(close)
|
||||
return ~nextIndex ? start + replaceClose(end, close, replace, nextIndex) : start + end
|
||||
}
|
||||
|
||||
function createColors() {
|
||||
return {
|
||||
bgBlack: formatter('\x1B[40m', '\x1B[49m'),
|
||||
bgBlue: formatter('\x1B[44m', '\x1B[49m'),
|
||||
bgCyan: formatter('\x1B[46m', '\x1B[49m'),
|
||||
bgGreen: formatter('\x1B[42m', '\x1B[49m'),
|
||||
bgMagenta: formatter('\x1B[45m', '\x1B[49m'),
|
||||
bgRed: formatter('\x1B[41m', '\x1B[49m', '\x1B[22m\x1B[1m'),
|
||||
bgWhite: formatter('\x1B[47m', '\x1B[49m'),
|
||||
bgYellow: formatter('\x1B[43m', '\x1B[49m'),
|
||||
black: formatter('\x1B[30m', '\x1B[39m'),
|
||||
blue: formatter('\x1B[34m', '\x1B[39m'),
|
||||
bold: formatter('\x1B[1m', '\x1B[22m', '\x1B[22m\x1B[1m'),
|
||||
cyan: formatter('\x1B[36m', '\x1B[39m'),
|
||||
dim: formatter('\x1B[2m', '\x1B[22m', '\x1B[22m\x1B[2m'),
|
||||
gray: formatter('\x1B[90m', '\x1B[39m'),
|
||||
green: formatter('\x1B[32m', '\x1B[39m'),
|
||||
hidden: formatter('\x1B[8m', '\x1B[28m'),
|
||||
inverse: formatter('\x1B[7m', '\x1B[27m'),
|
||||
italic: formatter('\x1B[3m', '\x1B[23m'),
|
||||
magenta: formatter('\x1B[35m', '\x1B[39m'),
|
||||
red: formatter('\x1B[31m', '\x1B[39m'),
|
||||
reset: (s: string) => `\x1B[0m${s}\x1B[0m`,
|
||||
strikethrough: formatter('\x1B[9m', '\x1B[29m'),
|
||||
underline: formatter('\x1B[4m', '\x1B[24m'),
|
||||
white: formatter('\x1B[37m', '\x1B[39m'),
|
||||
yellow: formatter('\x1B[33m', '\x1B[39m'),
|
||||
}
|
||||
}
|
||||
|
||||
export { clearScreen, createColors }
|
||||
2
build/config/index.ts
Normal file
2
build/config/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './proxy';
|
||||
export * from './time';
|
||||
57
build/config/proxy.ts
Normal file
57
build/config/proxy.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import type { ProxyOptions } from 'vite';
|
||||
import { bgRed, bgYellow, green, lightBlue } from 'kolorist';
|
||||
import { consola } from 'consola';
|
||||
import { createServiceConfig } from '../../src/utils/service';
|
||||
|
||||
/**
|
||||
* Set http proxy
|
||||
*
|
||||
* @param env - The current env
|
||||
* @param enable - If enable http proxy
|
||||
*/
|
||||
export function createViteProxy(env: Env.ImportMeta, enable: boolean) {
|
||||
const isEnableHttpProxy = enable && env.VITE_HTTP_PROXY === 'Y';
|
||||
|
||||
if (!isEnableHttpProxy) return undefined;
|
||||
|
||||
const isEnableProxyLog = env.VITE_PROXY_LOG === 'Y';
|
||||
|
||||
const { baseURL, proxyPattern, other } = createServiceConfig(env);
|
||||
|
||||
const proxy: Record<string, ProxyOptions> = createProxyItem({ baseURL, proxyPattern }, isEnableProxyLog);
|
||||
|
||||
other.forEach(item => {
|
||||
Object.assign(proxy, createProxyItem(item, isEnableProxyLog));
|
||||
});
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
function createProxyItem(item: App.Service.ServiceConfigItem, enableLog: boolean) {
|
||||
const proxy: Record<string, ProxyOptions> = {};
|
||||
|
||||
proxy[item.proxyPattern] = {
|
||||
target: item.baseURL,
|
||||
changeOrigin: true,
|
||||
configure: (_proxy, options) => {
|
||||
_proxy.on('proxyReq', (_proxyReq, req, _res) => {
|
||||
if (!enableLog) return;
|
||||
|
||||
const requestUrl = `${lightBlue('[proxy url]')}: ${bgYellow(` ${req.method} `)} ${green(
|
||||
`${item.proxyPattern}${req.url}`
|
||||
)}`;
|
||||
|
||||
const proxyUrl = `${lightBlue('[real request url]')}: ${green(`${options.target}${req.url}`)}`;
|
||||
|
||||
consola.log(`${requestUrl}\n${proxyUrl}`);
|
||||
});
|
||||
_proxy.on('error', (_err, req, _res) => {
|
||||
if (!enableLog) return;
|
||||
consola.log(bgRed(`Error: ${req.method} `), green(`${options.target}${req.url}`));
|
||||
});
|
||||
},
|
||||
rewrite: path => path.replace(new RegExp(`^${item.proxyPattern}`), '')
|
||||
};
|
||||
|
||||
return proxy;
|
||||
}
|
||||
12
build/config/time.ts
Normal file
12
build/config/time.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import dayjs from 'dayjs';
|
||||
import utc from 'dayjs/plugin/utc';
|
||||
import timezone from 'dayjs/plugin/timezone';
|
||||
|
||||
export function getBuildTime() {
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(timezone);
|
||||
|
||||
const buildTime = dayjs.tz(Date.now(), 'Asia/Shanghai').format('YYYY-MM-DD HH:mm:ss');
|
||||
|
||||
return buildTime;
|
||||
}
|
||||
13
build/plugins/devtools.ts
Normal file
13
build/plugins/devtools.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import VueDevtools from 'vite-plugin-vue-devtools';
|
||||
|
||||
export function setupDevtoolsPlugin(viteEnv: Env.ImportMeta) {
|
||||
const { VITE_DEVTOOLS_ENABLED, VITE_DEVTOOLS_LAUNCH_EDITOR } = viteEnv;
|
||||
|
||||
if (VITE_DEVTOOLS_ENABLED !== 'Y') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return VueDevtools({
|
||||
launchEditor: VITE_DEVTOOLS_LAUNCH_EDITOR
|
||||
});
|
||||
}
|
||||
13
build/plugins/html.ts
Normal file
13
build/plugins/html.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { Plugin } from 'vite';
|
||||
|
||||
export function setupHtmlPlugin(buildTime: string) {
|
||||
const plugin: Plugin = {
|
||||
name: 'html-plugin',
|
||||
apply: 'build',
|
||||
transformIndexHtml(html) {
|
||||
return html.replace('<head>', `<head>\n <meta name="buildTime" content="${buildTime}">`);
|
||||
}
|
||||
};
|
||||
|
||||
return plugin;
|
||||
}
|
||||
24
build/plugins/index.ts
Normal file
24
build/plugins/index.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import type { PluginOption } from 'vite';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx';
|
||||
import progress from 'vite-plugin-progress';
|
||||
import { setupElegantRouter } from './router';
|
||||
import { setupUnocss } from './unocss';
|
||||
import { setupUnplugin } from './unplugin';
|
||||
import { setupHtmlPlugin } from './html';
|
||||
import { setupDevtoolsPlugin } from './devtools';
|
||||
|
||||
export function setupVitePlugins(viteEnv: Env.ImportMeta, buildTime: string) {
|
||||
const plugins: PluginOption = [
|
||||
vue(),
|
||||
vueJsx(),
|
||||
setupDevtoolsPlugin(viteEnv),
|
||||
setupElegantRouter(),
|
||||
setupUnocss(viteEnv),
|
||||
...setupUnplugin(viteEnv),
|
||||
progress(),
|
||||
setupHtmlPlugin(buildTime)
|
||||
];
|
||||
|
||||
return plugins;
|
||||
}
|
||||
79
build/plugins/router.ts
Normal file
79
build/plugins/router.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import type { RouteMeta } from 'vue-router';
|
||||
import ElegantVueRouter from '@elegant-router/vue/vite';
|
||||
import type { RouteKey } from '@elegant-router/types';
|
||||
|
||||
export function setupElegantRouter() {
|
||||
return ElegantVueRouter({
|
||||
layouts: {
|
||||
base: 'src/layouts/base-layout/index.vue',
|
||||
blank: 'src/layouts/blank-layout/index.vue'
|
||||
},
|
||||
customRoutes: {
|
||||
names: ['exception_403', 'exception_404', 'exception_500']
|
||||
},
|
||||
routePathTransformer(routeName, routePath) {
|
||||
const key = routeName as RouteKey;
|
||||
|
||||
if (key === 'login') {
|
||||
const modules: UnionKey.LoginModule[] = ['pwd-login', 'reset-pwd'];
|
||||
|
||||
const moduleReg = modules.join('|');
|
||||
|
||||
return `/login/:module(${moduleReg})?`;
|
||||
}
|
||||
|
||||
return routePath;
|
||||
},
|
||||
onRouteMetaGen(routeName) {
|
||||
const key = routeName as RouteKey;
|
||||
|
||||
const constantRoutes: RouteKey[] = ['login', '403', '404', '500'];
|
||||
const routeMetaMap: Partial<Record<RouteKey, Partial<RouteMeta>>> = {
|
||||
system: {
|
||||
icon: 'carbon:cloud-service-management',
|
||||
order: 9,
|
||||
roles: ['R_ADMIN']
|
||||
},
|
||||
system_menu: {
|
||||
icon: 'material-symbols:route',
|
||||
order: 3,
|
||||
roles: ['R_ADMIN'],
|
||||
keepAlive: true
|
||||
},
|
||||
system_dict: {
|
||||
icon: 'mdi:book-open-page-variant-outline',
|
||||
order: 4,
|
||||
roles: ['R_ADMIN'],
|
||||
keepAlive: true
|
||||
},
|
||||
system_role: {
|
||||
icon: 'carbon:user-role',
|
||||
order: 2,
|
||||
roles: ['R_SUPER']
|
||||
},
|
||||
system_user: {
|
||||
icon: 'ic:round-manage-accounts',
|
||||
order: 1,
|
||||
roles: ['R_ADMIN']
|
||||
},
|
||||
'system_user-detail': {
|
||||
hideInMenu: true,
|
||||
roles: ['R_ADMIN'],
|
||||
activeMenu: 'system_user'
|
||||
}
|
||||
};
|
||||
|
||||
const meta: Partial<RouteMeta> = {
|
||||
title: key,
|
||||
i18nKey: `route.${key}` as App.I18n.I18nKey,
|
||||
...routeMetaMap[key]
|
||||
};
|
||||
|
||||
if (constantRoutes.includes(key)) {
|
||||
meta.constant = true;
|
||||
}
|
||||
|
||||
return meta;
|
||||
}
|
||||
});
|
||||
}
|
||||
32
build/plugins/unocss.ts
Normal file
32
build/plugins/unocss.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import process from 'node:process';
|
||||
import path from 'node:path';
|
||||
import unocss from '@unocss/vite';
|
||||
import presetIcons from '@unocss/preset-icons';
|
||||
import { FileSystemIconLoader } from '@iconify/utils/lib/loader/node-loaders';
|
||||
|
||||
export function setupUnocss(viteEnv: Env.ImportMeta) {
|
||||
const { VITE_ICON_PREFIX, VITE_ICON_LOCAL_PREFIX } = viteEnv;
|
||||
|
||||
const localIconPath = path.join(process.cwd(), 'src/assets/svg-icon');
|
||||
|
||||
/** The name of the local icon collection */
|
||||
const collectionName = VITE_ICON_LOCAL_PREFIX.replace(`${VITE_ICON_PREFIX}-`, '');
|
||||
|
||||
return unocss({
|
||||
presets: [
|
||||
presetIcons({
|
||||
prefix: `${VITE_ICON_PREFIX}-`,
|
||||
scale: 1,
|
||||
extraProperties: {
|
||||
display: 'inline-block'
|
||||
},
|
||||
collections: {
|
||||
[collectionName]: FileSystemIconLoader(localIconPath, svg =>
|
||||
svg.replace(/^<svg\s/, '<svg width="1em" height="1em" ')
|
||||
)
|
||||
},
|
||||
warn: true
|
||||
})
|
||||
]
|
||||
});
|
||||
}
|
||||
51
build/plugins/unplugin.ts
Normal file
51
build/plugins/unplugin.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import process from 'node:process';
|
||||
import path from 'node:path';
|
||||
import type { PluginOption } from 'vite';
|
||||
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
|
||||
import Icons from 'unplugin-icons/vite';
|
||||
import IconsResolver from 'unplugin-icons/resolver';
|
||||
import Components from 'unplugin-vue-components/vite';
|
||||
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
|
||||
import { FileSystemIconLoader } from 'unplugin-icons/loaders';
|
||||
|
||||
export function setupUnplugin(viteEnv: Env.ImportMeta) {
|
||||
const { VITE_ICON_PREFIX, VITE_ICON_LOCAL_PREFIX } = viteEnv;
|
||||
|
||||
const localIconPath = path.join(process.cwd(), 'src/assets/svg-icon');
|
||||
|
||||
/** The name of the local icon collection */
|
||||
const collectionName = VITE_ICON_LOCAL_PREFIX.replace(`${VITE_ICON_PREFIX}-`, '');
|
||||
|
||||
const plugins: PluginOption[] = [
|
||||
Icons({
|
||||
compiler: 'vue3',
|
||||
customCollections: {
|
||||
[collectionName]: FileSystemIconLoader(localIconPath, svg =>
|
||||
svg.replace(/^<svg\s/, '<svg width="1em" height="1em" ')
|
||||
)
|
||||
},
|
||||
scale: 1,
|
||||
defaultClass: 'inline-block'
|
||||
}),
|
||||
Components({
|
||||
dts: 'src/typings/components.d.ts',
|
||||
types: [{ from: 'vue-router', names: ['RouterLink', 'RouterView'] }],
|
||||
resolvers: [
|
||||
// auto import Element Plus components。 full import to see /src/plugins/ui.ts
|
||||
ElementPlusResolver({
|
||||
// no to import style, full import to see /src/plugins/assets.ts
|
||||
importStyle: false
|
||||
}),
|
||||
IconsResolver({ customCollections: [collectionName], componentPrefix: VITE_ICON_PREFIX })
|
||||
]
|
||||
}),
|
||||
createSvgIconsPlugin({
|
||||
iconDirs: [localIconPath],
|
||||
symbolId: `${VITE_ICON_LOCAL_PREFIX}-[dir]-[name]`,
|
||||
inject: 'body-last',
|
||||
customDomId: '__SVG_ICON_LOCAL__'
|
||||
})
|
||||
];
|
||||
|
||||
return plugins;
|
||||
}
|
||||
Reference in New Issue
Block a user