Commit 99ac309fa9eed36f8444b8bbab7b18275c5aa5aa

Authored by vben
1 parent 1d3007f0

wip: support vite

Showing 100 changed files with 397 additions and 1129 deletions

Too many changes to show.

To preserve performance only 100 of 105 files are displayed.

.env.production
@@ -23,5 +23,5 @@ VITE_GLOB_API_URL_PREFIX= @@ -23,5 +23,5 @@ VITE_GLOB_API_URL_PREFIX=
23 # use pwa 23 # use pwa
24 VITE_USE_PWA = false 24 VITE_USE_PWA = false
25 25
26 -# TODO use Cdn  
27 -VITE_USE_CDN = true 26 +# Is it compatible with older browsers
  27 +VITE_LEGACY = false
build/script/changelog.ts deleted 100644 → 0
1 -// #!/usr/bin/env node  
2 -  
3 -import { sh } from 'tasksfile';  
4 -import { errorConsole, successConsole } from '../utils';  
5 -  
6 -export const runChangeLog = async () => {  
7 - try {  
8 - let cmd = `conventional-changelog -p custom-config -i CHANGELOG.md -s -r 0 `;  
9 -  
10 - await sh(cmd, {  
11 - async: true,  
12 - nopipe: true,  
13 - });  
14 - await sh('prettier --write **/CHANGELOG.md ', {  
15 - async: true,  
16 - nopipe: true,  
17 - });  
18 - successConsole('CHANGE_LOG.md generated successfully!');  
19 - } catch (error) {  
20 - errorConsole('CHANGE_LOG.md generated error\n' + error);  
21 -  
22 - process.exit(1);  
23 - }  
24 -};  
25 -  
26 -runChangeLog();  
build/script/postBuild.ts
@@ -3,7 +3,6 @@ @@ -3,7 +3,6 @@
3 import { argv } from 'yargs'; 3 import { argv } from 'yargs';
4 import { runBuildConfig } from './buildConf'; 4 import { runBuildConfig } from './buildConf';
5 import { errorConsole, successConsole } from '../utils'; 5 import { errorConsole, successConsole } from '../utils';
6 -import { startGzipStyle } from '../vite/plugin/gzip/compress';  
7 6
8 export const runBuild = async () => { 7 export const runBuild = async () => {
9 try { 8 try {
@@ -13,8 +12,6 @@ export const runBuild = async () => { @@ -13,8 +12,6 @@ export const runBuild = async () => {
13 if (!argvList.includes('no-conf')) { 12 if (!argvList.includes('no-conf')) {
14 await runBuildConfig(); 13 await runBuildConfig();
15 } 14 }
16 - // await runUpdateHtml();  
17 - await startGzipStyle();  
18 successConsole('Vite Build successfully!'); 15 successConsole('Vite Build successfully!');
19 } catch (error) { 16 } catch (error) {
20 errorConsole('Vite Build Error\n' + error); 17 errorConsole('Vite Build Error\n' + error);
build/utils.ts
@@ -63,11 +63,11 @@ export function getIPAddress() { @@ -63,11 +63,11 @@ export function getIPAddress() {
63 return ''; 63 return '';
64 } 64 }
65 65
66 -export function isDevFn(mode: 'development' | 'production'): boolean { 66 +export function isDevFn(mode: string): boolean {
67 return mode === 'development'; 67 return mode === 'development';
68 } 68 }
69 69
70 -export function isProdFn(mode: 'development' | 'production'): boolean { 70 +export function isProdFn(mode: string): boolean {
71 return mode === 'production'; 71 return mode === 'production';
72 } 72 }
73 73
@@ -85,13 +85,6 @@ export function isBuildGzip(): boolean { @@ -85,13 +85,6 @@ export function isBuildGzip(): boolean {
85 return process.env.VITE_BUILD_GZIP === 'true'; 85 return process.env.VITE_BUILD_GZIP === 'true';
86 } 86 }
87 87
88 -/**  
89 - * Whether to generate package site  
90 - */  
91 -export function isSiteMode(): boolean {  
92 - return process.env.SITE === 'true';  
93 -}  
94 -  
95 export interface ViteEnv { 88 export interface ViteEnv {
96 VITE_PORT: number; 89 VITE_PORT: number;
97 VITE_USE_MOCK: boolean; 90 VITE_USE_MOCK: boolean;
@@ -99,10 +92,12 @@ export interface ViteEnv { @@ -99,10 +92,12 @@ export interface ViteEnv {
99 VITE_PUBLIC_PATH: string; 92 VITE_PUBLIC_PATH: string;
100 VITE_PROXY: [string, string][]; 93 VITE_PROXY: [string, string][];
101 VITE_GLOB_APP_TITLE: string; 94 VITE_GLOB_APP_TITLE: string;
  95 + VITE_GLOB_APP_SHORT_NAME: string;
102 VITE_USE_CDN: boolean; 96 VITE_USE_CDN: boolean;
103 VITE_DROP_CONSOLE: boolean; 97 VITE_DROP_CONSOLE: boolean;
104 VITE_BUILD_GZIP: boolean; 98 VITE_BUILD_GZIP: boolean;
105 VITE_DYNAMIC_IMPORT: boolean; 99 VITE_DYNAMIC_IMPORT: boolean;
  100 + VITE_LEGACY: boolean;
106 } 101 }
107 102
108 // Read all environment variable configuration files to process.env 103 // Read all environment variable configuration files to process.env
build/vite/hm.ts deleted 100644 → 0
1 -// Baidu statistics code for site deployment  
2 -// Only open in build:site  
3 -export const hmScript = `<script>  
4 -var _hmt = _hmt || [];  
5 -(function() {  
6 - var hm = document.createElement("script");  
7 - hm.src = "https://hm.baidu.com/hm.js?384d6046e02f6ac4ea075357bd0e9b43";  
8 - var s = document.getElementsByTagName("script")[0];  
9 - s.parentNode.insertBefore(hm, s);  
10 -})();  
11 -</script>  
12 -`;  
build/vite/plugin/gzip.ts 0 → 100644
  1 +import gzipPlugin from 'rollup-plugin-gzip';
  2 +import { isBuildGzip } from '../../utils';
  3 +import { Plugin } from 'vite';
  4 +export function configGzipPlugin(isBuild: boolean): Plugin | Plugin[] {
  5 + const useGzip = isBuild && isBuildGzip;
  6 +
  7 + if (useGzip) {
  8 + return gzipPlugin();
  9 + }
  10 +
  11 + return [];
  12 +}
build/vite/plugin/gzip/compress.ts deleted 100644 → 0
1 -import { gzip } from 'zlib';  
2 -import { readFileSync, writeFileSync } from 'fs';  
3 -import { GzipPluginOptions } from './types';  
4 -import { readAllFile, getCwdPath, isBuildGzip, isSiteMode } from '../../../utils';  
5 -  
6 -export function startGzip(  
7 - fileContent: string | Buffer,  
8 - options: GzipPluginOptions = {}  
9 -): Promise<Buffer> {  
10 - return new Promise((resolve, reject) => {  
11 - gzip(fileContent, options.gzipOptions || {}, (err, result) => {  
12 - if (err) {  
13 - reject(err);  
14 - } else {  
15 - resolve(result);  
16 - }  
17 - });  
18 - });  
19 -}  
20 -  
21 -// 手动压缩css  
22 -export async function startGzipStyle() {  
23 - if (isBuildGzip() || isSiteMode()) {  
24 - const outDir = 'dist';  
25 - const assets = '_assets';  
26 - const allCssFile = readAllFile(getCwdPath(outDir, assets), /\.(css)$/);  
27 - for (const path of allCssFile) {  
28 - const source = readFileSync(path);  
29 - const content = await startGzip(source);  
30 - const ds = path.split('/');  
31 - const fileName = ds[ds.length - 1];  
32 - writeFileSync(getCwdPath(outDir, assets, `${fileName}.gz`), content);  
33 - }  
34 - }  
35 -}  
build/vite/plugin/gzip/index.ts deleted 100644 → 0
1 -// 修改自https://github.com/kryops/rollup-plugin-gzip  
2 -// 因为rollup-plugin-gzip不支持vite  
3 -// vite对css打包独立的。所以不能在打包的时候顺带打包css  
4 -// TODO rc.9会支持 configurBuild 配置项。到时候重新修改  
5 -  
6 -import { readFile, writeFile } from 'fs';  
7 -import { basename } from 'path';  
8 -import { promisify } from 'util';  
9 -import { gzip } from 'zlib';  
10 -  
11 -import { OutputAsset, OutputChunk, OutputOptions, Plugin } from 'rollup';  
12 -import { GzipPluginOptions } from './types';  
13 -  
14 -const isFunction = (arg: unknown): arg is (...args: any[]) => any => typeof arg === 'function';  
15 -const isRegExp = (arg: unknown): arg is RegExp =>  
16 - Object.prototype.toString.call(arg) === '[object RegExp]';  
17 -  
18 -export type StringMappingOption = (originalString: string) => string;  
19 -export type CustomCompressionOption = (  
20 - content: string | Buffer  
21 -) => string | Buffer | Promise<string | Buffer>;  
22 -  
23 -const readFilePromise = promisify(readFile);  
24 -const writeFilePromise = promisify(writeFile);  
25 -  
26 -// functionality partially copied from rollup  
27 -  
28 -/**  
29 - * copied from https://github.com/rollup/rollup/blob/master/src/rollup/index.ts#L450  
30 - */  
31 -function isOutputChunk(file: OutputAsset | OutputChunk): file is OutputChunk {  
32 - return typeof (file as OutputChunk).code === 'string';  
33 -}  
34 -  
35 -/**  
36 - * Gets the string/buffer content from a file object.  
37 - * Important for adding source map comments  
38 - *  
39 - * Copied partially from rollup.writeOutputFile  
40 - * https://github.com/rollup/rollup/blob/master/src/rollup/index.ts#L454  
41 - */  
42 -function getOutputFileContent(  
43 - outputFileName: string,  
44 - outputFile: OutputAsset | OutputChunk,  
45 - outputOptions: OutputOptions  
46 -): string | Buffer {  
47 - if (isOutputChunk(outputFile)) {  
48 - let source: string | Buffer;  
49 - source = outputFile.code;  
50 - if (outputOptions.sourcemap && outputFile.map) {  
51 - const url =  
52 - outputOptions.sourcemap === 'inline'  
53 - ? outputFile.map.toUrl()  
54 - : `${basename(outputFileName)}.map`;  
55 -  
56 - // https://github.com/rollup/rollup/blob/master/src/utils/sourceMappingURL.ts#L1  
57 - source += `//# source` + `MappingURL=${url}\n`;  
58 - }  
59 - return source;  
60 - } else {  
61 - return typeof outputFile.source === 'string'  
62 - ? outputFile.source  
63 - : // just to be sure, as it is typed string | Uint8Array in rollup 2.0.0  
64 - Buffer.from(outputFile.source);  
65 - }  
66 -}  
67 -  
68 -// actual plugin code  
69 -  
70 -function gzipPlugin(options: GzipPluginOptions = {}): Plugin {  
71 - // check for old options  
72 - if ('algorithm' in options) {  
73 - console.warn(  
74 - '[rollup-plugin-gzip] The "algorithm" option is not supported any more! ' +  
75 - 'Use "customCompression" instead to specify a different compression algorithm.'  
76 - );  
77 - }  
78 - if ('options' in options) {  
79 - console.warn('[rollup-plugin-gzip] The "options" option was renamed to "gzipOptions"!');  
80 - }  
81 - if ('additional' in options) {  
82 - console.warn('[rollup-plugin-gzip] The "additional" option was renamed to "additionalFiles"!');  
83 - }  
84 - if ('delay' in options) {  
85 - console.warn('[rollup-plugin-gzip] The "delay" option was renamed to "additionalFilesDelay"!');  
86 - }  
87 -  
88 - const compressGzip: CustomCompressionOption = (fileContent) => {  
89 - return new Promise((resolve, reject) => {  
90 - gzip(fileContent, options.gzipOptions || {}, (err, result) => {  
91 - if (err) {  
92 - reject(err);  
93 - } else {  
94 - resolve(result);  
95 - }  
96 - });  
97 - });  
98 - };  
99 -  
100 - const doCompress = options.customCompression || compressGzip;  
101 -  
102 - const mapFileName: StringMappingOption = isFunction(options.fileName)  
103 - ? (options.fileName as StringMappingOption)  
104 - : (fileName: string) => fileName + (options.fileName || '.gz');  
105 -  
106 - const plugin: Plugin = {  
107 - name: 'gzip',  
108 -  
109 - generateBundle(outputOptions, bundle) {  
110 - return Promise.all(  
111 - Object.keys(bundle)  
112 - .map((fileName) => {  
113 - const fileEntry = bundle[fileName];  
114 -  
115 - // file name filter option check  
116 -  
117 - const fileNameFilter = options.filter || /\.(js|mjs|json|css|html)$/;  
118 -  
119 - if (isRegExp(fileNameFilter) && !fileName.match(fileNameFilter)) {  
120 - return Promise.resolve();  
121 - }  
122 -  
123 - if (  
124 - isFunction(fileNameFilter) &&  
125 - !(fileNameFilter as (x: string) => boolean)(fileName)  
126 - ) {  
127 - return Promise.resolve();  
128 - }  
129 -  
130 - const fileContent = getOutputFileContent(fileName, fileEntry, outputOptions);  
131 -  
132 - // minSize option check  
133 - if (options.minSize && options.minSize > fileContent.length) {  
134 - return Promise.resolve();  
135 - }  
136 -  
137 - return Promise.resolve(doCompress(fileContent))  
138 - .then((compressedContent) => {  
139 - const compressedFileName = mapFileName(fileName);  
140 - bundle[compressedFileName] = {  
141 - type: 'asset', // Rollup >= 1.21  
142 - name: compressedFileName,  
143 - fileName: compressedFileName,  
144 - isAsset: true, // Rollup < 1.21  
145 - source: compressedContent,  
146 - };  
147 - })  
148 - .catch((err: any) => {  
149 - console.error(err);  
150 - return Promise.reject('[rollup-plugin-gzip] Error compressing file ' + fileName);  
151 - });  
152 - })  
153 - .concat([  
154 - (() => {  
155 - if (!options.additionalFiles || !options.additionalFiles.length)  
156 - return Promise.resolve();  
157 -  
158 - const compressAdditionalFiles = () =>  
159 - Promise.all(  
160 - options.additionalFiles!.map((filePath) =>  
161 - readFilePromise(filePath)  
162 - .then((fileContent) => doCompress(fileContent))  
163 - .then((compressedContent) => {  
164 - return writeFilePromise(mapFileName(filePath), compressedContent);  
165 - })  
166 - .catch(() => {  
167 - return Promise.reject(  
168 - '[rollup-plugin-gzip] Error compressing additional file ' +  
169 - filePath +  
170 - '. Please check the spelling of your configured additionalFiles. ' +  
171 - 'You might also have to increase the value of the additionalFilesDelay option.'  
172 - );  
173 - })  
174 - )  
175 - ) as Promise<any>;  
176 -  
177 - // additional files can be processed outside of rollup after a delay  
178 - // for older plugins or plugins that write to disk (curcumventing rollup) without awaiting  
179 - const additionalFilesDelay = options.additionalFilesDelay || 0;  
180 -  
181 - if (additionalFilesDelay) {  
182 - setTimeout(compressAdditionalFiles, additionalFilesDelay);  
183 - return Promise.resolve();  
184 - } else {  
185 - return compressAdditionalFiles();  
186 - }  
187 - })(),  
188 - ])  
189 - ) as Promise<any>;  
190 - },  
191 - };  
192 -  
193 - return plugin;  
194 -}  
195 -  
196 -export default gzipPlugin;  
build/vite/plugin/gzip/types.ts deleted 100644 → 0
1 -import type { ZlibOptions } from 'zlib';  
2 -  
3 -export type StringMappingOption = (originalString: string) => string;  
4 -export type CustomCompressionOption = (  
5 - content: string | Buffer  
6 -) => string | Buffer | Promise<string | Buffer>;  
7 -  
8 -export interface GzipPluginOptions {  
9 - /**  
10 - * Control which of the output files to compress  
11 - *  
12 - * Defaults to `/\.(js|mjs|json|css|html)$/`  
13 - */  
14 - filter?: RegExp | ((fileName: string) => boolean);  
15 -  
16 - /**  
17 - * GZIP compression options, see https://nodejs.org/api/zlib.html#zlib_class_options  
18 - */  
19 - gzipOptions?: ZlibOptions;  
20 -  
21 - /**  
22 - * Specified the minimum size in Bytes for a file to get compressed.  
23 - * Files that are smaller than this threshold will not be compressed.  
24 - * This does not apply to the files specified through `additionalFiles`!  
25 - */  
26 - minSize?: number;  
27 -  
28 - /**  
29 - * This option allows you to compress additional files outside of the main rollup bundling process.  
30 - * The processing is delayed to make sure the files are written on disk; the delay is controlled  
31 - * through `additionalFilesDelay`.  
32 - */  
33 - additionalFiles?: string[];  
34 -  
35 - /**  
36 - * This options sets a delay (ms) before the plugin compresses the files specified through `additionalFiles`.  
37 - * Increase this value if your artifacts take a long time to generate.  
38 - *  
39 - * Defaults to `2000`  
40 - */  
41 - additionalFilesDelay?: number;  
42 -  
43 - /**  
44 - * Set a custom compression algorithm. The function can either return the compressed contents synchronously,  
45 - * or otherwise return a promise for asynchronous processing.  
46 - */  
47 - customCompression?: CustomCompressionOption;  
48 -  
49 - /**  
50 - * Set a custom file name convention for the compressed files. Can be a suffix string or a function  
51 - * returning the file name.  
52 - *  
53 - * Defaults to `.gz`  
54 - */  
55 - fileName?: string | StringMappingOption;  
56 -}  
build/vite/plugin/html.ts
1 import type { Plugin } from 'vite'; 1 import type { Plugin } from 'vite';
2 -import ViteHtmlPlugin from 'vite-plugin-html';  
3 -import { isProdFn, isSiteMode, ViteEnv } from '../../utils'; 2 +import html from 'vite-plugin-html';
  3 +import { ViteEnv } from '../../utils';
4 4
5 -import { hmScript } from '../hm';  
6 // @ts-ignore 5 // @ts-ignore
7 import pkg from '../../../package.json'; 6 import pkg from '../../../package.json';
8 import { GLOB_CONFIG_FILE_NAME } from '../../constant'; 7 import { GLOB_CONFIG_FILE_NAME } from '../../constant';
9 8
10 -export function setupHtmlPlugin(  
11 - plugins: Plugin[],  
12 - env: ViteEnv,  
13 - mode: 'development' | 'production'  
14 -) { 9 +export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) {
15 const { VITE_GLOB_APP_TITLE, VITE_PUBLIC_PATH } = env; 10 const { VITE_GLOB_APP_TITLE, VITE_PUBLIC_PATH } = env;
16 -  
17 - const htmlPlugin = ViteHtmlPlugin({  
18 - // html title  
19 - title: VITE_GLOB_APP_TITLE,  
20 - minify: isProdFn(mode),  
21 - options: {  
22 - publicPath: VITE_PUBLIC_PATH,  
23 - // Package and insert additional configuration files  
24 - injectConfig: isProdFn(mode)  
25 - ? `<script src='${VITE_PUBLIC_PATH || './'}${GLOB_CONFIG_FILE_NAME}?v=${  
26 - pkg.version  
27 - }-${new Date().getTime()}'></script>`  
28 - : '',  
29 - // Insert Baidu statistics code  
30 - hmScript: isSiteMode() ? hmScript : '',  
31 - title: VITE_GLOB_APP_TITLE, 11 + const htmlPlugin: Plugin[] = html({
  12 + minify: isBuild,
  13 + inject: {
  14 + injectData: {
  15 + title: VITE_GLOB_APP_TITLE,
  16 + },
  17 + tags: isBuild
  18 + ? [
  19 + {
  20 + tag: 'script',
  21 + attrs: {
  22 + src: `${VITE_PUBLIC_PATH || './'}${GLOB_CONFIG_FILE_NAME}?v=${
  23 + pkg.version
  24 + }-${new Date().getTime()}`,
  25 + },
  26 + },
  27 + ]
  28 + : [],
32 }, 29 },
33 }); 30 });
34 -  
35 - plugins.push(htmlPlugin);  
36 - return plugins; 31 + return htmlPlugin;
37 } 32 }
build/vite/plugin/importContext.ts 0 → 100644
  1 +import dynamicImport from 'vite-plugin-import-context';
  2 +import type { ViteEnv } from '../../utils';
  3 +import type { Plugin } from 'vite';
  4 +
  5 +export function configDynamicImport(env: ViteEnv) {
  6 + const { VITE_DYNAMIC_IMPORT } = env;
  7 + const dynamicImportPlugin: Plugin = dynamicImport({
  8 + include: ['**/*.ts'],
  9 + autoImportRoute: VITE_DYNAMIC_IMPORT,
  10 + });
  11 + return dynamicImportPlugin;
  12 +}
build/vite/plugin/index.ts
1 -import type { Plugin as VitePlugin } from 'vite';  
2 -import type { Plugin as rollupPlugin } from 'rollup'; 1 +import type { Plugin } from 'vite';
3 2
4 import PurgeIcons from 'vite-plugin-purge-icons'; 3 import PurgeIcons from 'vite-plugin-purge-icons';
5 4
6 import visualizer from 'rollup-plugin-visualizer'; 5 import visualizer from 'rollup-plugin-visualizer';
7 -import gzipPlugin from './gzip/index';  
8 6
9 // @ts-ignore 7 // @ts-ignore
10 import pkg from '../../../package.json'; 8 import pkg from '../../../package.json';
11 -import { isSiteMode, ViteEnv, isReportMode, isBuildGzip } from '../../utils';  
12 -import { setupHtmlPlugin } from './html';  
13 -import { setupPwaPlugin } from './pwa';  
14 -import { setupMockPlugin } from './mock'; 9 +import { ViteEnv, isReportMode } from '../../utils';
  10 +import { configHtmlPlugin } from './html';
  11 +import { configPwaConfig } from './pwa';
  12 +import { configMockPlugin } from './mock';
  13 +import { configDynamicImport } from './importContext';
  14 +import { configGzipPlugin } from './gzip';
15 15
16 // gen vite plugins 16 // gen vite plugins
17 -export function createVitePlugins(viteEnv: ViteEnv, mode: 'development' | 'production') {  
18 - const vitePlugins: VitePlugin[] = []; 17 +export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean, mode: string) {
  18 + const vitePlugins: (Plugin | Plugin[])[] = [];
19 19
20 // vite-plugin-html 20 // vite-plugin-html
21 - setupHtmlPlugin(vitePlugins, viteEnv, mode); 21 + vitePlugins.push(configHtmlPlugin(viteEnv, isBuild));
  22 +
22 // vite-plugin-pwa 23 // vite-plugin-pwa
23 - setupPwaPlugin(vitePlugins, viteEnv, mode); 24 + vitePlugins.push(configPwaConfig(viteEnv, isBuild));
  25 +
24 // vite-plugin-mock 26 // vite-plugin-mock
25 - setupMockPlugin(vitePlugins, viteEnv, mode); 27 + vitePlugins.push(configMockPlugin(viteEnv, isBuild));
  28 +
  29 + // vite-plugin-import-context
  30 + vitePlugins.push(configDynamicImport(viteEnv));
26 31
27 // vite-plugin-purge-icons 32 // vite-plugin-purge-icons
28 vitePlugins.push(PurgeIcons()); 33 vitePlugins.push(PurgeIcons());
29 34
30 - return vitePlugins;  
31 -}  
32 -  
33 -// gen rollup plugins  
34 -export function createRollupPlugin() {  
35 - const rollupPlugins: rollupPlugin[] = []; 35 + // rollup-plugin-gzip
  36 + vitePlugins.push(configGzipPlugin(isBuild));
36 37
  38 + // rollup-plugin-visualizer
37 if (isReportMode()) { 39 if (isReportMode()) {
38 - // rollup-plugin-visualizer  
39 - rollupPlugins.push(visualizer({ filename: './build/.cache/stats.html', open: true }) as Plugin);  
40 - }  
41 - if (isBuildGzip() || isSiteMode()) {  
42 - // rollup-plugin-gizp  
43 - rollupPlugins.push(gzipPlugin()); 40 + vitePlugins.push(visualizer({ filename: './build/.cache/stats.html', open: true }) as Plugin);
44 } 41 }
45 42
46 - return rollupPlugins; 43 + return vitePlugins;
47 } 44 }
build/vite/plugin/mock.ts
1 -import { createMockServer } from 'vite-plugin-mock';  
2 -import type { Plugin } from 'vite';  
3 -import { isDevFn, ViteEnv } from '../../utils'; 1 +import { viteMockServe } from 'vite-plugin-mock';
  2 +import { ViteEnv } from '../../utils';
4 3
5 -export function setupMockPlugin(  
6 - plugins: Plugin[],  
7 - env: ViteEnv,  
8 - mode: 'development' | 'production'  
9 -) { 4 +export function configMockPlugin(env: ViteEnv, isBuild: boolean) {
10 const { VITE_USE_MOCK } = env; 5 const { VITE_USE_MOCK } = env;
11 6
12 - const useMock = isDevFn(mode) && VITE_USE_MOCK; 7 + const useMock = !isBuild && VITE_USE_MOCK;
13 8
14 if (useMock) { 9 if (useMock) {
15 - const mockPlugin = createMockServer({ 10 + const mockPlugin = viteMockServe({
16 ignore: /^\_/, 11 ignore: /^\_/,
17 mockPath: 'mock', 12 mockPath: 'mock',
18 showTime: true, 13 showTime: true,
19 localEnabled: useMock, 14 localEnabled: useMock,
20 }); 15 });
21 - plugins.push(mockPlugin); 16 + return mockPlugin;
22 } 17 }
23 - return plugins; 18 + return [];
24 } 19 }
build/vite/plugin/pwa.ts
1 import { VitePWA } from 'vite-plugin-pwa'; 1 import { VitePWA } from 'vite-plugin-pwa';
2 -import type { Plugin } from 'vite'; 2 +
3 import { ViteEnv } from '../../utils'; 3 import { ViteEnv } from '../../utils';
4 4
5 -export function setupPwaPlugin(  
6 - plugins: Plugin[],  
7 - env: ViteEnv,  
8 - // @ts-ignore  
9 - mode: 'development' | 'production'  
10 -) {  
11 - const { VITE_USE_PWA } = env; 5 +export function configPwaConfig(env: ViteEnv, isBulid: boolean) {
  6 + const { VITE_USE_PWA, VITE_GLOB_APP_TITLE, VITE_GLOB_APP_SHORT_NAME } = env;
12 7
13 - const pwaPlugin = VitePWA({  
14 - manifest: {  
15 - name: 'Vben Admin',  
16 - short_name: 'vben_admin',  
17 - icons: [  
18 - {  
19 - src: './resource/img/pwa-192x192.png',  
20 - sizes: '192x192',  
21 - type: 'image/png',  
22 - },  
23 - {  
24 - src: './resource/img/pwa-512x512.png',  
25 - sizes: '512x512',  
26 - type: 'image/png',  
27 - },  
28 - ],  
29 - },  
30 - });  
31 - if (VITE_USE_PWA) {  
32 - plugins.push(pwaPlugin); 8 + if (VITE_USE_PWA && isBulid) {
  9 + // vite-plugin-pwa
  10 + const pwaPlugin = VitePWA({
  11 + manifest: {
  12 + name: VITE_GLOB_APP_TITLE,
  13 + short_name: VITE_GLOB_APP_SHORT_NAME,
  14 + icons: [
  15 + {
  16 + src: './resource/img/pwa-192x192.png',
  17 + sizes: '192x192',
  18 + type: 'image/png',
  19 + },
  20 + {
  21 + src: './resource/img/pwa-512x512.png',
  22 + sizes: '512x512',
  23 + type: 'image/png',
  24 + },
  25 + ],
  26 + },
  27 + });
  28 + return pwaPlugin;
33 } 29 }
34 - return plugins; 30 + return [];
35 } 31 }
build/vite/plugin/transform/dynamic-import/index.ts deleted 100644 → 0
1 -// Used to import all files under `src/views`  
2 -// The built-in dynamic import of vite cannot meet the needs of importing all files under views  
3 -// Special usage ,Only for this project  
4 -import glob from 'glob';  
5 -import { Transform } from 'vite/dist/node/transform.js';  
6 -  
7 -function getPath(path: string) {  
8 - const lastIndex = path.lastIndexOf('.');  
9 - if (lastIndex !== -1) {  
10 - path = path.substring(0, lastIndex);  
11 - }  
12 - return path.replace('src/views', '');  
13 -}  
14 -  
15 -const dynamicImportTransform = function (enableDynamicImport: boolean): Transform {  
16 - return {  
17 - test({ path }) {  
18 - // Only convert the file  
19 - return (  
20 - path.includes('/src/router/helper/dynamicImport.ts') ||  
21 - path.includes(`\\src\\router\\helper\\dynamicImport.ts`)  
22 - );  
23 - },  
24 - transform({ code }) {  
25 - if (!enableDynamicImport) {  
26 - return code;  
27 - }  
28 -  
29 - // Only convert the dir  
30 - try {  
31 - const files = glob.sync('src/views/**/**.{vue,tsx}', { cwd: process.cwd() });  
32 -  
33 - return `  
34 - export default function (id) {  
35 - switch (id) {  
36 - ${files  
37 - .map((p) =>  
38 - ` case '${getPath(p)}': return () => import('${p  
39 - .replace('src/views', '/@/views')  
40 - .replace(/\/\//g, '/')}');`.replace('.tsx', '')  
41 - )  
42 - .join('\n ')}  
43 - default: return Promise.reject(new Error("Unknown variable dynamic import: " + id));  
44 - }  
45 - }\n\n  
46 - `;  
47 - } catch (error) {  
48 - console.error(error);  
49 - return code;  
50 - }  
51 - },  
52 - };  
53 -};  
54 -export default dynamicImportTransform;  
build/vite/plugin/transform/globby/index.ts deleted 100644 → 0
1 -// Modified from  
2 -// https://github.com/luxueyan/vite-transform-globby-import/blob/master/src/index.ts  
3 -  
4 -// TODO Deleting files requires re-running the project  
5 -import { join } from 'path';  
6 -import { lstatSync } from 'fs';  
7 -import glob from 'glob';  
8 -import globrex from 'globrex';  
9 -import dotProp from 'dot-prop';  
10 -import { createResolver, Resolver } from 'vite/dist/node/resolver.js';  
11 -import { Transform } from 'vite/dist/node/transform.js';  
12 -  
13 -const modulesDir: string = join(process.cwd(), '/node_modules/');  
14 -  
15 -interface SharedConfig {  
16 - root?: string;  
17 - alias?: Record<string, string>;  
18 - resolvers?: Resolver[];  
19 -  
20 - includes?: string[];  
21 -}  
22 -  
23 -function template(template: string) {  
24 - return (data: { [x: string]: any }) => {  
25 - return template.replace(/#([^#]+)#/g, (_, g1) => data[g1] || g1);  
26 - };  
27 -}  
28 -  
29 -// TODO support hmr  
30 -function hmr(isBuild = false) {  
31 - if (isBuild) return '';  
32 - return `  
33 - if (import.meta.hot) {  
34 - import.meta.hot.accept();  
35 - }`;  
36 -}  
37 -  
38 -// handle includes  
39 -function fileInclude(includes: string | string[] | undefined, filePath: string) {  
40 - return !includes || !Array.isArray(includes)  
41 - ? true  
42 - : includes.some((item) => filePath.startsWith(item));  
43 -}  
44 -  
45 -// Bare exporter  
46 -function compareString(modify: any, data: string[][]) {  
47 - return modify ? '\n' + data.map((v) => `${v[0]}._path = ${v[1]}`).join('\n') : '';  
48 -}  
49 -  
50 -function varTemplate(data: string[][], name: string) {  
51 - //prepare deep data (for locales)  
52 - let deepData: Record<string, object | string> = {};  
53 - let hasDeepData = false;  
54 -  
55 - //data modify  
56 - data.map((v) => {  
57 - //check for has deep data  
58 - if (v[0].includes('/')) {  
59 - hasDeepData = true;  
60 - }  
61 -  
62 - // lastKey is a data  
63 - let pathValue = v[0].replace(/\//g, '.').split('.');  
64 - // let scopeKey = '';  
65 - // const len=pathValue.length  
66 - // const scope=pathValue[len-2]  
67 - let lastKey: string | undefined = pathValue.pop();  
68 -  
69 - let deepValue: Record<any, any> = {};  
70 - if (lastKey) {  
71 - // Solve the problem of files with the same name in different folders  
72 - const lastKeyList = lastKey.replace('_' + pathValue[0], '').split('_');  
73 - const key = lastKeyList.pop();  
74 - if (key) {  
75 - deepValue[key] = lastKey;  
76 - }  
77 - }  
78 - // Set Deep Value  
79 - deepValue = Object.assign(deepValue, dotProp.get(deepData, pathValue.join('.')));  
80 - dotProp.set(deepData, pathValue.join('.'), deepValue);  
81 - });  
82 -  
83 - if (hasDeepData) {  
84 - return `const ${name} = ` + JSON.stringify(deepData).replace(/\"|\'/g, '');  
85 - }  
86 -  
87 - return `const ${name} = { ${data.map((v) => v[0]).join(',')} }`;  
88 -}  
89 -  
90 -const globTransform = function (config: SharedConfig): Transform {  
91 - const resolver = createResolver(  
92 - config.root || process.cwd(),  
93 - config.resolvers || [],  
94 - config.alias || {}  
95 - );  
96 - const { includes } = config;  
97 - const cache = new Map();  
98 - const urlMap = new Map();  
99 - return {  
100 - test({ path }) {  
101 - const filePath = path.replace('\u0000', ''); // why some path startsWith '\u0000'?  
102 -  
103 - try {  
104 - return (  
105 - !filePath.startsWith(modulesDir) &&  
106 - /\.(vue|js|jsx|ts|tsx)$/.test(filePath) &&  
107 - fileInclude(includes, filePath) &&  
108 - lstatSync(filePath).isFile()  
109 - );  
110 - } catch {  
111 - return false;  
112 - }  
113 - },  
114 - transform({ code, path, isBuild }) {  
115 - let result = cache.get(path);  
116 - if (!result) {  
117 - const reg = /import\s+([\w\s{}*]+)\s+from\s+(['"])globby(\?locale)?(\?path)?!([^'"]+)\2/g;  
118 - const match = code.match(reg);  
119 - if (!match) return code;  
120 - const lastImport = urlMap.get(path);  
121 - if (lastImport && match) {  
122 - code = code.replace(lastImport, match[0]);  
123 - }  
124 - result = code.replace(  
125 - reg,  
126 - (  
127 - _,  
128 - // variable to export  
129 - exportName,  
130 - // bare export or not  
131 - bareExporter,  
132 - // is locale import  
133 - isLocale,  
134 - // inject _path attr  
135 - injectPath,  
136 - // path export  
137 - globPath  
138 - ) => {  
139 - const filePath = path.replace('\u0000', ''); // why some path startsWith '\u0000'?  
140 - // resolve path  
141 -  
142 - const resolvedFilePath = globPath.startsWith('.')  
143 - ? resolver.resolveRelativeRequest(filePath, globPath)  
144 - : { pathname: resolver.requestToFile(globPath) };  
145 -  
146 - const files = glob.sync(resolvedFilePath.pathname, { dot: true });  
147 -  
148 - let templateStr = 'import #name# from #file#'; // import default  
149 - let name = exportName;  
150 - const m = exportName.match(/\{\s*(\w+)(\s+as\s+(\w+))?\s*\}/); // import module  
151 - const m2 = exportName.match(/\*\s+as\s+(\w+)/); // import * as all module  
152 - if (m) {  
153 - templateStr = `import { ${m[1]} as #name# } from #file#`;  
154 - name = m[3] || m[1];  
155 - } else if (m2) {  
156 - templateStr = 'import * as #name# from #file#';  
157 - name = m2[1];  
158 - }  
159 -  
160 - const templateRender = template(templateStr);  
161 -  
162 - const groups: Array<string>[] = [];  
163 - const replaceFiles = files.map((f, i) => {  
164 - const filePath = resolver.fileToRequest(f);  
165 - const file = bareExporter + filePath + bareExporter;  
166 -  
167 - if (isLocale) {  
168 - const globrexRes = globrex(globPath, { extended: true, globstar: true });  
169 -  
170 - // Get segments for files like an en/system ch/modules for:  
171 - // ['en', 'system'] ['ch', 'modules']  
172 -  
173 - // TODO The window system and mac system path are inconsistent?  
174 - const fileNameWithAlias = filePath.replace(/^(\/src\/)/, '/@/');  
175 - const matchedGroups = globrexRes.regex.exec(fileNameWithAlias);  
176 -  
177 - if (matchedGroups && matchedGroups.length) {  
178 - const matchedSegments = matchedGroups[1]; //first everytime "Full Match"  
179 - const matchList = matchedSegments.split('/').filter(Boolean);  
180 - const lang = matchList.shift();  
181 - const scope = matchList.pop();  
182 -  
183 - // Solve the problem of files with the same name in different folders  
184 - const scopeKey = scope ? `${scope}_` : '';  
185 - const fileName = matchedGroups[2];  
186 - const name = scopeKey + fileName + '_' + lang;  
187 -  
188 - //send deep way like an (en/modules/system/dashboard) into groups  
189 - groups.push([matchedSegments + name, file]);  
190 - return templateRender({  
191 - name,  
192 - file,  
193 - });  
194 - }  
195 - } else {  
196 - groups.push([name + i, file]);  
197 - return templateRender({ name: name + i, file });  
198 - }  
199 - });  
200 - // save in memory used result  
201 - const filesJoined = replaceFiles.join('\n');  
202 -  
203 - urlMap.set(path, filesJoined);  
204 -  
205 - // console.log('======================');  
206 - // console.log(filesJoined, varTemplate(groups, name));  
207 - // console.log('======================');  
208 - return [  
209 - filesJoined,  
210 - compareString(injectPath, groups),  
211 - varTemplate(groups, name),  
212 - '',  
213 - ].join('\n');  
214 - }  
215 - );  
216 - if (isBuild) cache.set(path, result);  
217 - }  
218 - return `${result}${hmr(isBuild)}`;  
219 - },  
220 - };  
221 -};  
222 -export default globTransform;  
build/vite/proxy.ts
  1 +import type { ServerOptions } from 'http-proxy';
  2 +
1 type ProxyItem = [string, string]; 3 type ProxyItem = [string, string];
2 4
3 type ProxyList = ProxyItem[]; 5 type ProxyList = ProxyItem[];
4 6
5 -type ProxyTargetList = Record<  
6 - string,  
7 - {  
8 - target: string;  
9 - changeOrigin: boolean;  
10 - rewrite: (path: string) => any;  
11 - secure?: boolean;  
12 - }  
13 ->; 7 +type ProxyTargetList = Record<string, ServerOptions & { rewrite: (path: string) => string }>;
14 8
15 const httpsRE = /^https:\/\//; 9 const httpsRE = /^https:\/\//;
16 10
@@ -23,9 +17,11 @@ export function createProxy(list: ProxyList = []) { @@ -23,9 +17,11 @@ export function createProxy(list: ProxyList = []) {
23 for (const [prefix, target] of list) { 17 for (const [prefix, target] of list) {
24 const isHttps = httpsRE.test(target); 18 const isHttps = httpsRE.test(target);
25 19
  20 + // https://github.com/http-party/node-http-proxy#options
26 ret[prefix] = { 21 ret[prefix] = {
27 target: target, 22 target: target,
28 changeOrigin: true, 23 changeOrigin: true,
  24 + ws: true,
29 rewrite: (path) => path.replace(new RegExp(`^${prefix}`), ''), 25 rewrite: (path) => path.replace(new RegExp(`^${prefix}`), ''),
30 // https is require secure=false 26 // https is require secure=false
31 ...(isHttps ? { secure: false } : {}), 27 ...(isHttps ? { secure: false } : {}),
index.html
1 <!DOCTYPE html> 1 <!DOCTYPE html>
2 <html lang="en"> 2 <html lang="en">
3 <head> 3 <head>
4 - <%= viteHtmlPluginOptions.hmScript %>  
5 <meta charset="UTF-8" /> 4 <meta charset="UTF-8" />
6 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
7 <meta name="renderer" content="webkit" /> 6 <meta name="renderer" content="webkit" />
@@ -10,9 +9,8 @@ @@ -10,9 +9,8 @@
10 content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0" 9 content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
11 /> 10 />
12 11
13 - <title></title> 12 + <title><%= title %></title>
14 <link rel="icon" href="/favicon.ico" /> 13 <link rel="icon" href="/favicon.ico" />
15 - <%= viteHtmlPluginOptions.injectConfig %>  
16 </head> 14 </head>
17 <body> 15 <body>
18 <div id="app"> 16 <div id="app">
@@ -137,15 +135,11 @@ @@ -137,15 +135,11 @@
137 </style> 135 </style>
138 <div class="app-loading"> 136 <div class="app-loading">
139 <div class="app-loading-wrap"> 137 <div class="app-loading-wrap">
140 - <img  
141 - src="<%= viteHtmlPluginOptions.publicPath %>resource/img/logo.png"  
142 - class="app-loading-logo"  
143 - alt="Logo"  
144 - /> 138 + <img src="/resource/img/logo.png" class="app-loading-logo" alt="Logo" />
145 <div class="app-loading-dots"> 139 <div class="app-loading-dots">
146 <span class="dot dot-spin"><i></i><i></i><i></i><i></i></span> 140 <span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
147 </div> 141 </div>
148 - <div class="app-loading-title"><%= viteHtmlPluginOptions.title %></div> 142 + <div class="app-loading-title"><%= title %></div>
149 </div> 143 </div>
150 </div> 144 </div>
151 </div> 145 </div>
package.json
1 { 1 {
2 "name": "vben-admin", 2 "name": "vben-admin",
3 - "version": "2.0.0-rc.15", 3 + "version": "2.0.0-rc.16",
4 "scripts": { 4 "scripts": {
5 "bootstrap": "yarn install", 5 "bootstrap": "yarn install",
6 - "serve": "cross-env vite --mode=development",  
7 - "build": "cross-env vite build --mode=production && esno ./build/script/postBuild.ts",  
8 - "build:site": "cross-env SITE=true npm run build ", 6 + "serve": "cross-env vite ",
  7 + "build": "cross-env vite build && esno ./build/script/postBuild.ts",
9 "build:no-cache": "yarn clean:cache && npm run build", 8 "build:no-cache": "yarn clean:cache && npm run build",
10 - "typecheck": "vuedx-typecheck .",  
11 "report": "cross-env REPORT=true npm run build ", 9 "report": "cross-env REPORT=true npm run build ",
12 "preview": "npm run build && esno ./build/script/preview.ts", 10 "preview": "npm run build && esno ./build/script/preview.ts",
13 "preview:dist": "esno ./build/script/preview.ts", 11 "preview:dist": "esno ./build/script/preview.ts",
14 - "log": "esno ./build/script/changelog.ts", 12 + "log": "conventional-changelog -p custom-config -i CHANGELOG.md -s -r 0",
15 "clean:cache": "rimraf node_modules/.cache/ && rimraf node_modules/.vite_opt_cache", 13 "clean:cache": "rimraf node_modules/.cache/ && rimraf node_modules/.vite_opt_cache",
16 "clean:lib": "npx rimraf node_modules", 14 "clean:lib": "npx rimraf node_modules",
17 - "ls-lint": "npx ls-lint",  
18 "lint:eslint": "eslint --fix --ext \"src/**/*.{vue,less,css,scss}\"", 15 "lint:eslint": "eslint --fix --ext \"src/**/*.{vue,less,css,scss}\"",
19 "lint:prettier": "prettier --write --loglevel warn \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"", 16 "lint:prettier": "prettier --write --loglevel warn \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
20 "lint:stylelint": "stylelint --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/", 17 "lint:stylelint": "stylelint --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
@@ -22,7 +19,7 @@ @@ -22,7 +19,7 @@
22 }, 19 },
23 "dependencies": { 20 "dependencies": {
24 "@iconify/iconify": "^2.0.0-rc.5", 21 "@iconify/iconify": "^2.0.0-rc.5",
25 - "@vueuse/core": "^4.0.2", 22 + "@vueuse/core": "^4.0.5",
26 "ant-design-vue": "^2.0.0-rc.8", 23 "ant-design-vue": "^2.0.0-rc.8",
27 "apexcharts": "^3.23.1", 24 "apexcharts": "^3.23.1",
28 "axios": "^0.21.1", 25 "axios": "^0.21.1",
@@ -34,26 +31,27 @@ @@ -34,26 +31,27 @@
34 "nprogress": "^0.2.0", 31 "nprogress": "^0.2.0",
35 "path-to-regexp": "^6.2.0", 32 "path-to-regexp": "^6.2.0",
36 "qrcode": "^1.4.4", 33 "qrcode": "^1.4.4",
37 - "sortablejs": "^1.12.0", 34 + "sortablejs": "^1.13.0",
38 "vditor": "^3.7.5", 35 "vditor": "^3.7.5",
39 "vue": "^3.0.5", 36 "vue": "^3.0.5",
40 - "vue-i18n": "9.0.0-beta.14", 37 + "vue-i18n": "^9.0.0-rc.1",
41 "vue-router": "^4.0.2", 38 "vue-router": "^4.0.2",
42 "vue-types": "^3.0.1", 39 "vue-types": "^3.0.1",
43 "vuex": "^4.0.0-rc.2", 40 "vuex": "^4.0.0-rc.2",
44 "vuex-module-decorators": "^1.0.1", 41 "vuex-module-decorators": "^1.0.1",
45 - "xlsx": "^0.16.9",  
46 "zxcvbn": "^4.4.2" 42 "zxcvbn": "^4.4.2"
47 }, 43 },
48 "devDependencies": { 44 "devDependencies": {
  45 + "@babel/core": "^7.12.10",
49 "@commitlint/cli": "^11.0.0", 46 "@commitlint/cli": "^11.0.0",
50 "@commitlint/config-conventional": "^11.0.0", 47 "@commitlint/config-conventional": "^11.0.0",
51 - "@iconify/json": "^1.1.282", 48 + "@iconify/json": "^1.1.283",
52 "@ls-lint/ls-lint": "^1.9.2", 49 "@ls-lint/ls-lint": "^1.9.2",
53 - "@purge-icons/generated": "^0.4.1", 50 + "@purge-icons/generated": "^0.5.0",
54 "@types/echarts": "^4.9.3", 51 "@types/echarts": "^4.9.3",
55 "@types/fs-extra": "^9.0.6", 52 "@types/fs-extra": "^9.0.6",
56 "@types/globrex": "^0.1.0", 53 "@types/globrex": "^0.1.0",
  54 + "@types/http-proxy": "^1.17.4",
57 "@types/koa-static": "^4.0.1", 55 "@types/koa-static": "^4.0.1",
58 "@types/lodash-es": "^4.17.4", 56 "@types/lodash-es": "^4.17.4",
59 "@types/mockjs": "^1.0.3", 57 "@types/mockjs": "^1.0.3",
@@ -65,10 +63,13 @@ @@ -65,10 +63,13 @@
65 "@types/zxcvbn": "^4.4.0", 63 "@types/zxcvbn": "^4.4.0",
66 "@typescript-eslint/eslint-plugin": "^4.12.0", 64 "@typescript-eslint/eslint-plugin": "^4.12.0",
67 "@typescript-eslint/parser": "^4.12.0", 65 "@typescript-eslint/parser": "^4.12.0",
  66 + "@vitejs/plugin-legacy": "^1.1.0",
  67 + "@vitejs/plugin-vue": "^1.0.4",
  68 + "@vitejs/plugin-vue-jsx": "^1.0.1",
68 "@vue/compiler-sfc": "^3.0.5", 69 "@vue/compiler-sfc": "^3.0.5",
69 "@vuedx/typecheck": "^0.4.1", 70 "@vuedx/typecheck": "^0.4.1",
70 "@vuedx/typescript-plugin-vue": "^0.4.1", 71 "@vuedx/typescript-plugin-vue": "^0.4.1",
71 - "autoprefixer": "^9.8.6", 72 + "autoprefixer": "^10.2.1",
72 "commitizen": "^4.2.2", 73 "commitizen": "^4.2.2",
73 "conventional-changelog-cli": "^2.1.1", 74 "conventional-changelog-cli": "^2.1.1",
74 "conventional-changelog-custom-config": "^0.3.1", 75 "conventional-changelog-custom-config": "^0.3.1",
@@ -82,14 +83,15 @@ @@ -82,14 +83,15 @@
82 "esno": "^0.4.0", 83 "esno": "^0.4.0",
83 "fs-extra": "^9.0.1", 84 "fs-extra": "^9.0.1",
84 "globrex": "^0.1.2", 85 "globrex": "^0.1.2",
85 - "husky": "^4.3.6", 86 + "husky": "^4.3.7",
86 "koa-static": "^5.0.0", 87 "koa-static": "^5.0.0",
87 "less": "^4.0.0", 88 "less": "^4.0.0",
88 "lint-staged": "^10.5.3", 89 "lint-staged": "^10.5.3",
89 "portfinder": "^1.0.28", 90 "portfinder": "^1.0.28",
90 - "postcss-import": "^12.0.1", 91 + "postcss-import": "^14.0.0",
91 "prettier": "^2.2.1", 92 "prettier": "^2.2.1",
92 "rimraf": "^3.0.2", 93 "rimraf": "^3.0.2",
  94 + "rollup-plugin-gzip": "^2.5.0",
93 "rollup-plugin-visualizer": "^4.1.2", 95 "rollup-plugin-visualizer": "^4.1.2",
94 "stylelint": "^13.8.0", 96 "stylelint": "^13.8.0",
95 "stylelint-config-prettier": "^8.0.2", 97 "stylelint-config-prettier": "^8.0.2",
@@ -98,11 +100,12 @@ @@ -98,11 +100,12 @@
98 "tasksfile": "^5.1.1", 100 "tasksfile": "^5.1.1",
99 "ts-node": "^9.1.0", 101 "ts-node": "^9.1.0",
100 "typescript": "^4.1.3", 102 "typescript": "^4.1.3",
101 - "vite": "^1.0.0-rc.13",  
102 - "vite-plugin-html": "^1.0.0-beta.2",  
103 - "vite-plugin-mock": "^1.0.9",  
104 - "vite-plugin-purge-icons": "^0.4.5",  
105 - "vite-plugin-pwa": "^0.2.1", 103 + "vite": "^2.0.0-beta.15",
  104 + "vite-plugin-html": "^2.0.0-beta.5",
  105 + "vite-plugin-import-context": "^1.0.0-rc.1",
  106 + "vite-plugin-mock": "^2.0.0-beta.1",
  107 + "vite-plugin-purge-icons": "^0.5.0",
  108 + "vite-plugin-pwa": "^0.3.2",
106 "vue-eslint-parser": "^7.3.0", 109 "vue-eslint-parser": "^7.3.0",
107 "yargs": "^16.2.0" 110 "yargs": "^16.2.0"
108 }, 111 },
src/App.vue
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 import { initAppConfigStore } from '/@/setup/App'; 13 import { initAppConfigStore } from '/@/setup/App';
14 14
15 import { useLockPage } from '/@/hooks/web/useLockPage'; 15 import { useLockPage } from '/@/hooks/web/useLockPage';
16 - import { useLocale } from '/@/hooks/web/useLocale'; 16 + import { useLocale } from '/@/locales/useLocale';
17 17
18 import { AppProvider } from '/@/components/Application'; 18 import { AppProvider } from '/@/components/Application';
19 19
@@ -21,6 +21,9 @@ @@ -21,6 +21,9 @@
21 name: 'App', 21 name: 'App',
22 components: { ConfigProvider, AppProvider }, 22 components: { ConfigProvider, AppProvider },
23 setup() { 23 setup() {
  24 + const { antConfigLocale, setLocale } = useLocale();
  25 + setLocale();
  26 +
24 // Initialize vuex internal system configuration 27 // Initialize vuex internal system configuration
25 initAppConfigStore(); 28 initAppConfigStore();
26 29
@@ -28,7 +31,6 @@ @@ -28,7 +31,6 @@
28 const lockEvent = useLockPage(); 31 const lockEvent = useLockPage();
29 32
30 // support Multi-language 33 // support Multi-language
31 - const { antConfigLocale } = useLocale();  
32 34
33 return { 35 return {
34 antConfigLocale, 36 antConfigLocale,
src/components/Application/src/AppLocalePicker.vue
@@ -22,7 +22,7 @@ @@ -22,7 +22,7 @@
22 import { Dropdown, DropMenu } from '/@/components/Dropdown'; 22 import { Dropdown, DropMenu } from '/@/components/Dropdown';
23 import { GlobalOutlined } from '@ant-design/icons-vue'; 23 import { GlobalOutlined } from '@ant-design/icons-vue';
24 24
25 - import { useLocale } from '/@/hooks/web/useLocale'; 25 + import { useLocale } from '/@/locales/useLocale';
26 import { useLocaleSetting } from '/@/hooks/setting/useLocaleSetting'; 26 import { useLocaleSetting } from '/@/hooks/setting/useLocaleSetting';
27 27
28 import { LocaleType } from '/@/locales/types'; 28 import { LocaleType } from '/@/locales/types';
@@ -75,7 +75,6 @@ @@ -75,7 +75,6 @@
75 </script> 75 </script>
76 76
77 <style lang="less" scoped> 77 <style lang="less" scoped>
78 - @import (reference) '../../../design/index.less';  
79 @prefix-cls: ~'@{namespace}-app-locale-picker'; 78 @prefix-cls: ~'@{namespace}-app-locale-picker';
80 79
81 :global(.@{prefix-cls}-overlay) { 80 :global(.@{prefix-cls}-overlay) {
src/components/Application/src/AppLogo.vue
@@ -59,7 +59,6 @@ @@ -59,7 +59,6 @@
59 }); 59 });
60 </script> 60 </script>
61 <style lang="less" scoped> 61 <style lang="less" scoped>
62 - @import (reference) '../../../design/index.less';  
63 @prefix-cls: ~'@{namespace}-app-logo'; 62 @prefix-cls: ~'@{namespace}-app-logo';
64 63
65 .@{prefix-cls} { 64 .@{prefix-cls} {
src/components/Application/src/search/AppSearch.vue
@@ -44,7 +44,6 @@ @@ -44,7 +44,6 @@
44 }); 44 });
45 </script> 45 </script>
46 <style lang="less" scoped> 46 <style lang="less" scoped>
47 - @import (reference) '../../../../design/index.less';  
48 @prefix-cls: ~'@{namespace}-app-search'; 47 @prefix-cls: ~'@{namespace}-app-search';
49 48
50 .@{prefix-cls} { 49 .@{prefix-cls} {
src/components/Application/src/search/AppSearchFooter.vue
@@ -37,7 +37,6 @@ @@ -37,7 +37,6 @@
37 }); 37 });
38 </script> 38 </script>
39 <style lang="less" scoped> 39 <style lang="less" scoped>
40 - @import (reference) '../../../../design/index.less';  
41 @prefix-cls: ~'@{namespace}-app-search-footer'; 40 @prefix-cls: ~'@{namespace}-app-search-footer';
42 41
43 .@{prefix-cls} { 42 .@{prefix-cls} {
src/components/Application/src/search/AppSearchModal.vue
@@ -123,7 +123,6 @@ @@ -123,7 +123,6 @@
123 }); 123 });
124 </script> 124 </script>
125 <style lang="less" scoped> 125 <style lang="less" scoped>
126 - @import (reference) '../../../../design/index.less';  
127 @prefix-cls: ~'@{namespace}-app-search-modal'; 126 @prefix-cls: ~'@{namespace}-app-search-modal';
128 @footer-prefix-cls: ~'@{namespace}-app-search-footer'; 127 @footer-prefix-cls: ~'@{namespace}-app-search-footer';
129 .@{prefix-cls} { 128 .@{prefix-cls} {
src/components/Basic/src/BasicArrow.vue
@@ -46,7 +46,6 @@ @@ -46,7 +46,6 @@
46 }); 46 });
47 </script> 47 </script>
48 <style lang="less" scoped> 48 <style lang="less" scoped>
49 - @import (reference) '../../../design/index.less';  
50 @prefix-cls: ~'@{namespace}-basic-arrow'; 49 @prefix-cls: ~'@{namespace}-basic-arrow';
51 50
52 .@{prefix-cls} { 51 .@{prefix-cls} {
src/components/Basic/src/BasicHelp.vue
@@ -112,7 +112,6 @@ @@ -112,7 +112,6 @@
112 }); 112 });
113 </script> 113 </script>
114 <style lang="less"> 114 <style lang="less">
115 - @import (reference) '../../../design/index.less';  
116 @prefix-cls: ~'@{namespace}-basic-help'; 115 @prefix-cls: ~'@{namespace}-basic-help';
117 116
118 .@{prefix-cls} { 117 .@{prefix-cls} {
src/components/Basic/src/BasicTitle.vue
@@ -30,7 +30,6 @@ @@ -30,7 +30,6 @@
30 }); 30 });
31 </script> 31 </script>
32 <style lang="less" scoped> 32 <style lang="less" scoped>
33 - @import (reference) '../../../design/index.less';  
34 @prefix-cls: ~'@{namespace}-basic-title'; 33 @prefix-cls: ~'@{namespace}-basic-title';
35 34
36 .@{prefix-cls} { 35 .@{prefix-cls} {
src/components/Container/src/LazyContainer.vue
@@ -140,7 +140,6 @@ @@ -140,7 +140,6 @@
140 }); 140 });
141 </script> 141 </script>
142 <style lang="less"> 142 <style lang="less">
143 - @import (reference) '../../../design/index.less';  
144 @prefix-cls: ~'@{namespace}-lazy-container'; 143 @prefix-cls: ~'@{namespace}-lazy-container';
145 144
146 .@{prefix-cls} { 145 .@{prefix-cls} {
src/components/Container/src/ScrollContainer.vue
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
12 12
13 export default defineComponent({ 13 export default defineComponent({
14 name: 'ScrollContainer', 14 name: 'ScrollContainer',
15 - inheritAttrs: false, 15 + // inheritAttrs: false,
16 components: { Scrollbar }, 16 components: { Scrollbar },
17 setup() { 17 setup() {
18 const scrollbarRef = ref<Nullable<ScrollbarType>>(null); 18 const scrollbarRef = ref<Nullable<ScrollbarType>>(null);
src/components/Container/src/collapse/CollapseContainer.vue
@@ -87,7 +87,6 @@ @@ -87,7 +87,6 @@
87 }); 87 });
88 </script> 88 </script>
89 <style lang="less"> 89 <style lang="less">
90 - @import (reference) '../../../../design/index.less';  
91 @prefix-cls: ~'@{namespace}-collapse-container'; 90 @prefix-cls: ~'@{namespace}-collapse-container';
92 91
93 .@{prefix-cls} { 92 .@{prefix-cls} {
src/components/ContextMenu/src/index.less
1 -@import (reference) '../../../design/index.less';  
2 -  
3 @default-height: 42px !important; 1 @default-height: 42px !important;
4 2
5 @small-height: 36px !important; 3 @small-height: 36px !important;
src/components/ContextMenu/src/index.tsx
@@ -76,9 +76,7 @@ export default defineComponent({ @@ -76,9 +76,7 @@ export default defineComponent({
76 return ( 76 return (
77 <> 77 <>
78 <Menu.Item disabled={disabled} class={`${prefixCls}__item`} key={label}> 78 <Menu.Item disabled={disabled} class={`${prefixCls}__item`} key={label}>
79 - {() => [  
80 - <ItemContent showIcon={props.showIcon} item={item} handler={handleAction} />,  
81 - ]} 79 + <ItemContent showIcon={props.showIcon} item={item} handler={handleAction} />
82 </Menu.Item> 80 </Menu.Item>
83 {DividerComp} 81 {DividerComp}
84 </> 82 </>
@@ -109,7 +107,7 @@ export default defineComponent({ @@ -109,7 +107,7 @@ export default defineComponent({
109 ref={wrapRef} 107 ref={wrapRef}
110 style={unref(getStyle)} 108 style={unref(getStyle)}
111 > 109 >
112 - {() => renderMenuItem(items)} 110 + {renderMenuItem(items)}
113 </Menu> 111 </Menu>
114 ); 112 );
115 }; 113 };
src/components/Description/src/index.tsx
@@ -114,7 +114,7 @@ export default defineComponent({ @@ -114,7 +114,7 @@ export default defineComponent({
114 const renderDesc = () => { 114 const renderDesc = () => {
115 return ( 115 return (
116 <Descriptions class={`${prefixCls}`} {...(unref(getDescriptionsProps) as any)}> 116 <Descriptions class={`${prefixCls}`} {...(unref(getDescriptionsProps) as any)}>
117 - {() => renderItem()} 117 + {renderItem()}
118 </Descriptions> 118 </Descriptions>
119 ); 119 );
120 }; 120 };
src/components/Drawer/src/BasicDrawer.vue
@@ -199,7 +199,6 @@ @@ -199,7 +199,6 @@
199 }); 199 });
200 </script> 200 </script>
201 <style lang="less"> 201 <style lang="less">
202 - @import (reference) '../../../design/index.less';  
203 @header-height: 60px; 202 @header-height: 60px;
204 @detail-header-height: 40px; 203 @detail-header-height: 40px;
205 @prefix-cls: ~'@{namespace}-basic-drawer'; 204 @prefix-cls: ~'@{namespace}-basic-drawer';
src/components/Drawer/src/components/DrawerFooter.vue
@@ -66,7 +66,6 @@ @@ -66,7 +66,6 @@
66 </script> 66 </script>
67 67
68 <style lang="less"> 68 <style lang="less">
69 - @import (reference) '../../../../design/index.less';  
70 @prefix-cls: ~'@{namespace}-basic-drawer-footer'; 69 @prefix-cls: ~'@{namespace}-basic-drawer-footer';
71 @footer-height: 60px; 70 @footer-height: 60px;
72 .@{prefix-cls} { 71 .@{prefix-cls} {
src/components/Drawer/src/components/DrawerHeader.vue
@@ -45,7 +45,6 @@ @@ -45,7 +45,6 @@
45 </script> 45 </script>
46 46
47 <style lang="less"> 47 <style lang="less">
48 - @import (reference) '../../../../design/index.less';  
49 @prefix-cls: ~'@{namespace}-basic-drawer-header'; 48 @prefix-cls: ~'@{namespace}-basic-drawer-header';
50 @footer-height: 60px; 49 @footer-height: 60px;
51 .@{prefix-cls} { 50 .@{prefix-cls} {
src/components/Form/src/BasicForm.vue
@@ -247,7 +247,6 @@ @@ -247,7 +247,6 @@
247 }); 247 });
248 </script> 248 </script>
249 <style lang="less"> 249 <style lang="less">
250 - @import (reference) '../../../design/index.less';  
251 @prefix-cls: ~'@{namespace}-basic-form'; 250 @prefix-cls: ~'@{namespace}-basic-form';
252 251
253 .@{prefix-cls} { 252 .@{prefix-cls} {
src/components/Form/src/components/FormItem.tsx
@@ -173,7 +173,8 @@ export default defineComponent({ @@ -173,7 +173,8 @@ export default defineComponent({
173 const characterInx = rules.findIndex((val) => val.max); 173 const characterInx = rules.findIndex((val) => val.max);
174 if (characterInx !== -1 && !rules[characterInx].validator) { 174 if (characterInx !== -1 && !rules[characterInx].validator) {
175 rules[characterInx].message = 175 rules[characterInx].message =
176 - rules[characterInx].message || t('component.form.maxTip', [rules[characterInx].max]); 176 + rules[characterInx].message ||
  177 + t('component.form.maxTip', [rules[characterInx].max] as Recordable);
177 } 178 }
178 return rules; 179 return rules;
179 } 180 }
@@ -294,12 +295,10 @@ export default defineComponent({ @@ -294,12 +295,10 @@ export default defineComponent({
294 labelCol={labelCol} 295 labelCol={labelCol}
295 wrapperCol={wrapperCol} 296 wrapperCol={wrapperCol}
296 > 297 >
297 - {() => (  
298 - <>  
299 - {getContent()}  
300 - {showSuffix && <span class="suffix">{getSuffix}</span>}  
301 - </>  
302 - )} 298 + <>
  299 + {getContent()}
  300 + {showSuffix && <span class="suffix">{getSuffix}</span>}
  301 + </>
303 </Form.Item> 302 </Form.Item>
304 ); 303 );
305 } 304 }
@@ -323,7 +322,7 @@ export default defineComponent({ @@ -323,7 +322,7 @@ export default defineComponent({
323 return ( 322 return (
324 isIfShow && ( 323 isIfShow && (
325 <Col {...realColProps} class={{ hidden: !isShow }}> 324 <Col {...realColProps} class={{ hidden: !isShow }}>
326 - {() => getContent()} 325 + {getContent()}
327 </Col> 326 </Col>
328 ) 327 )
329 ); 328 );
src/components/Icon/src/index.vue
@@ -83,8 +83,6 @@ @@ -83,8 +83,6 @@
83 }); 83 });
84 </script> 84 </script>
85 <style lang="less"> 85 <style lang="less">
86 - @import (reference) '../../../design/index.less';  
87 -  
88 .app-iconify { 86 .app-iconify {
89 display: inline-block; 87 display: inline-block;
90 vertical-align: middle; 88 vertical-align: middle;
src/components/Markdown/src/index.vue
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 import 'vditor/dist/index.css'; 7 import 'vditor/dist/index.css';
8 8
9 import { propTypes } from '/@/utils/propTypes'; 9 import { propTypes } from '/@/utils/propTypes';
10 - import { useLocale } from '/@/hooks/web/useLocale'; 10 + import { useLocale } from '/@/locales/useLocale';
11 import { useModalContext } from '../../Modal'; 11 import { useModalContext } from '../../Modal';
12 12
13 type Lang = 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' | undefined; 13 type Lang = 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' | undefined;
src/components/Menu/src/index.less
1 -@import (reference) '../../../design/index.less';  
2 -  
3 @basic-menu-prefix-cls: ~'@{namespace}-basic-menu'; 1 @basic-menu-prefix-cls: ~'@{namespace}-basic-menu';
4 @basic-menu-content-prefix-cls: ~'@{namespace}-basic-menu-item-content'; 2 @basic-menu-content-prefix-cls: ~'@{namespace}-basic-menu-item-content';
5 @basic-menu-tag-prefix-cls: ~'@{namespace}-basic-menu-item-tag'; 3 @basic-menu-tag-prefix-cls: ~'@{namespace}-basic-menu-item-tag';
src/components/Modal/src/components/ModalClose.vue
@@ -54,7 +54,6 @@ @@ -54,7 +54,6 @@
54 }); 54 });
55 </script> 55 </script>
56 <style lang="less"> 56 <style lang="less">
57 - @import (reference) '../../../../design/index.less';  
58 @prefix-cls: ~'@{namespace}-basic-modal-close'; 57 @prefix-cls: ~'@{namespace}-basic-modal-close';
59 .@{prefix-cls} { 58 .@{prefix-cls} {
60 display: flex; 59 display: flex;
src/components/Modal/src/index.less
1 -@import (reference) '../../../design/index.less';  
2 -  
3 .fullscreen-modal { 1 .fullscreen-modal {
4 overflow: hidden; 2 overflow: hidden;
5 3
@@ -79,7 +77,7 @@ @@ -79,7 +77,7 @@
79 77
80 &-confirm-body { 78 &-confirm-body {
81 .ant-modal-confirm-content { 79 .ant-modal-confirm-content {
82 - color: #fff; 80 + // color: #fff;
83 81
84 > * { 82 > * {
85 color: @text-color-help-dark; 83 color: @text-color-help-dark;
src/components/Preview/index.ts
1 -export { createImgPreview } from './src/functional'; 1 +// export { createImgPreview } from './src/functional';
2 2
3 -import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';  
4 -export const ImagePreview = createAsyncComponent(() => import('./src/index.vue')); 3 +export const createImgPreview = () => {};
  4 +
  5 +// import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
  6 +// export const ImagePreview = createAsyncComponent(() => import('./src/index.vue'));
  7 +
  8 +export { default as ImagePreview } from './src/index.vue';
src/components/Preview/src/index.less
1 -@import (reference) '../../../design/index.less';  
2 -  
3 .img-preview { 1 .img-preview {
4 position: fixed; 2 position: fixed;
5 top: 0; 3 top: 0;
src/components/Preview/src/index.vue
@@ -58,7 +58,6 @@ @@ -58,7 +58,6 @@
58 }); 58 });
59 </script> 59 </script>
60 <style lang="less"> 60 <style lang="less">
61 - @import (reference) '../../../design/index.less';  
62 @prefix-cls: ~'@{namespace}-image-preview'; 61 @prefix-cls: ~'@{namespace}-image-preview';
63 62
64 .@{prefix-cls} { 63 .@{prefix-cls} {
src/components/Scrollbar/src/index.vue
@@ -34,7 +34,7 @@ @@ -34,7 +34,7 @@
34 34
35 export default defineComponent({ 35 export default defineComponent({
36 name: 'Scrollbar', 36 name: 'Scrollbar',
37 - inheritAttrs: false, 37 + // inheritAttrs: false,
38 components: { Bar }, 38 components: { Bar },
39 props: { 39 props: {
40 native: { 40 native: {
src/components/StrengthMeter/src/index.vue
@@ -83,7 +83,6 @@ @@ -83,7 +83,6 @@
83 }); 83 });
84 </script> 84 </script>
85 <style lang="less" scoped> 85 <style lang="less" scoped>
86 - @import (reference) '../../../design/index.less';  
87 @prefix-cls: ~'@{namespace}-strength-meter'; 86 @prefix-cls: ~'@{namespace}-strength-meter';
88 87
89 .@{prefix-cls} { 88 .@{prefix-cls} {
src/components/Upload/src/FileList.less
1 -@import (reference) '../../../design/index.less';  
2 -  
3 .file-table { 1 .file-table {
4 width: 100%; 2 width: 100%;
5 border-collapse: collapse; 3 border-collapse: collapse;
src/components/Verify/src/DragVerify.less
1 -@import (reference) '../../../design/index.less';  
2 -  
3 @radius: 4px; 1 @radius: 4px;
4 2
5 .darg-verify { 3 .darg-verify {
src/components/Verify/src/ImgRotate.less
1 -@import (reference) '../../../design/index.less';  
2 -  
3 .ir-dv { 1 .ir-dv {
4 position: relative; 2 position: relative;
5 display: flex; 3 display: flex;
src/components/registerGlobComp.ts
@@ -35,25 +35,21 @@ import { @@ -35,25 +35,21 @@ import {
35 Menu, 35 Menu,
36 Breadcrumb, 36 Breadcrumb,
37 } from 'ant-design-vue'; 37 } from 'ant-design-vue';
38 -import { getApp } from '/@/setup/App'; 38 +import { App } from 'vue';
39 39
40 const compList = [Icon, Button, AntButton.Group]; 40 const compList = [Icon, Button, AntButton.Group];
41 41
42 // Fix hmr multiple registered components 42 // Fix hmr multiple registered components
43 -let registered = false;  
44 -export function registerGlobComp() {  
45 - if (registered) return; 43 +export function registerGlobComp(app: App) {
46 compList.forEach((comp: any) => { 44 compList.forEach((comp: any) => {
47 - getApp().component(comp.name, comp); 45 + app.component(comp.name, comp);
48 }); 46 });
49 47
50 - registered = true;  
51 -  
52 // Optional 48 // Optional
53 // Why register here: The main reason for registering here is not to increase the size of the first screen code 49 // Why register here: The main reason for registering here is not to increase the size of the first screen code
54 // If you need to customize global components, you can write here 50 // If you need to customize global components, you can write here
55 // If you don’t need it, you can delete it 51 // If you don’t need it, you can delete it
56 - getApp() 52 + app
57 .use(Select) 53 .use(Select)
58 .use(Alert) 54 .use(Alert)
59 .use(Breadcrumb) 55 .use(Breadcrumb)
src/hooks/setting/useLocaleSetting.ts
@@ -4,7 +4,7 @@ import { computed, unref } from &#39;vue&#39;; @@ -4,7 +4,7 @@ import { computed, unref } from &#39;vue&#39;;
4 import { appStore } from '/@/store/modules/app'; 4 import { appStore } from '/@/store/modules/app';
5 5
6 import getProjectSetting from '/@/settings/projectSetting'; 6 import getProjectSetting from '/@/settings/projectSetting';
7 -import { localeList } from '/@/locales'; 7 +import { localeList } from '/@/locales/constant';
8 8
9 // Get locale configuration 9 // Get locale configuration
10 const getLocale = computed(() => appStore.getProjectConfig.locale || getProjectSetting.locale); 10 const getLocale = computed(() => appStore.getProjectConfig.locale || getProjectSetting.locale);
src/hooks/web/useI18n.ts
1 -import { getI18n } from '/@/setup/i18n'; 1 +import { i18n } from '/@/locales/setupI18n';
2 2
3 export function useI18n(namespace?: string) { 3 export function useI18n(namespace?: string) {
4 function getKey(key: string) { 4 function getKey(key: string) {
@@ -16,18 +16,19 @@ export function useI18n(namespace?: string) { @@ -16,18 +16,19 @@ export function useI18n(namespace?: string) {
16 }, 16 },
17 }; 17 };
18 18
19 - if (!getI18n()) { 19 + if (!i18n) {
20 return normalFn; 20 return normalFn;
21 } 21 }
22 22
23 - const { t, ...methods } = getI18n().global; 23 + const { t, ...methods } = i18n.global;
24 24
  25 + const tFn = function (...arg: Parameters<typeof t>) {
  26 + if (!arg[0]) return '';
  27 + return t(getKey(arg[0]), ...(arg as Parameters<typeof t>));
  28 + };
25 return { 29 return {
26 ...methods, 30 ...methods,
27 - t: (key: string, ...arg: any): string => {  
28 - if (!key) return '';  
29 - return t(getKey(key), ...(arg as Parameters<typeof t>));  
30 - }, 31 + t: tFn,
31 }; 32 };
32 } 33 }
33 34
src/hooks/web/useMessage.tsx
@@ -59,7 +59,7 @@ function createConfirm(options: ModalOptionsEx): ConfirmOptions { @@ -59,7 +59,7 @@ function createConfirm(options: ModalOptionsEx): ConfirmOptions {
59 icon: getIcon(iconType), 59 icon: getIcon(iconType),
60 ...options, 60 ...options,
61 }; 61 };
62 - return Modal.confirm(opt) as any; 62 + return (Modal.confirm(opt) as unknown) as ConfirmOptions;
63 } 63 }
64 64
65 const baseOptions = { 65 const baseOptions = {
src/layouts/default/content/index.vue
@@ -18,7 +18,7 @@ @@ -18,7 +18,7 @@
18 import { useDesign } from '/@/hooks/web/useDesign'; 18 import { useDesign } from '/@/hooks/web/useDesign';
19 import { useRootSetting } from '/@/hooks/setting/useRootSetting'; 19 import { useRootSetting } from '/@/hooks/setting/useRootSetting';
20 import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting'; 20 import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
21 - import PageLayout from '/@/layouts/page/index'; 21 + import PageLayout from '/@/layouts/page/index.vue';
22 import { useContentViewHeight } from './useContentViewHeight'; 22 import { useContentViewHeight } from './useContentViewHeight';
23 import { Loading } from '/@/components/Loading'; 23 import { Loading } from '/@/components/Loading';
24 24
@@ -41,7 +41,6 @@ @@ -41,7 +41,6 @@
41 }); 41 });
42 </script> 42 </script>
43 <style lang="less"> 43 <style lang="less">
44 - @import (reference) '../../../design/index.less';  
45 @prefix-cls: ~'@{namespace}-layout-content'; 44 @prefix-cls: ~'@{namespace}-layout-content';
46 45
47 .@{prefix-cls} { 46 .@{prefix-cls} {
src/layouts/default/footer/index.vue
@@ -40,7 +40,6 @@ @@ -40,7 +40,6 @@
40 }); 40 });
41 </script> 41 </script>
42 <style lang="less" scoped> 42 <style lang="less" scoped>
43 - @import (reference) '../../../design/index.less';  
44 @prefix-cls: ~'@{namespace}-layout-footer'; 43 @prefix-cls: ~'@{namespace}-layout-footer';
45 44
46 @normal-color: rgba(0, 0, 0, 0.45); 45 @normal-color: rgba(0, 0, 0, 0.45);
src/layouts/default/header/MultipleHeader.vue
@@ -109,7 +109,6 @@ @@ -109,7 +109,6 @@
109 }); 109 });
110 </script> 110 </script>
111 <style lang="less" scoped> 111 <style lang="less" scoped>
112 - @import (reference) '../../../design/index.less';  
113 @prefix-cls: ~'@{namespace}-layout-multiple-header'; 112 @prefix-cls: ~'@{namespace}-layout-multiple-header';
114 113
115 .@{prefix-cls} { 114 .@{prefix-cls} {
src/layouts/default/header/components/Breadcrumb.vue
@@ -147,7 +147,6 @@ @@ -147,7 +147,6 @@
147 }); 147 });
148 </script> 148 </script>
149 <style lang="less"> 149 <style lang="less">
150 - @import (reference) '../../../../design/index.less';  
151 @prefix-cls: ~'@{namespace}-layout-breadcrumb'; 150 @prefix-cls: ~'@{namespace}-layout-breadcrumb';
152 151
153 .@{prefix-cls} { 152 .@{prefix-cls} {
src/layouts/default/header/components/lock/LockModal.vue
@@ -80,7 +80,6 @@ @@ -80,7 +80,6 @@
80 }); 80 });
81 </script> 81 </script>
82 <style lang="less"> 82 <style lang="less">
83 - @import (reference) '../../../../../design/index.less';  
84 @prefix-cls: ~'@{namespace}-header-lock-modal'; 83 @prefix-cls: ~'@{namespace}-header-lock-modal';
85 84
86 .@{prefix-cls} { 85 .@{prefix-cls} {
src/layouts/default/header/components/notify/NoticeList.vue
@@ -49,7 +49,6 @@ @@ -49,7 +49,6 @@
49 }); 49 });
50 </script> 50 </script>
51 <style lang="less" scoped> 51 <style lang="less" scoped>
52 - @import (reference) '../../../../../design/index.less';  
53 @prefix-cls: ~'@{namespace}-header-notify-list'; 52 @prefix-cls: ~'@{namespace}-header-notify-list';
54 53
55 .@{prefix-cls} { 54 .@{prefix-cls} {
src/layouts/default/header/components/notify/index.vue
@@ -49,7 +49,6 @@ @@ -49,7 +49,6 @@
49 }); 49 });
50 </script> 50 </script>
51 <style lang="less"> 51 <style lang="less">
52 - @import (reference) '../../../../../design/index.less';  
53 @prefix-cls: ~'@{namespace}-header-notify'; 52 @prefix-cls: ~'@{namespace}-header-notify';
54 53
55 .@{prefix-cls} { 54 .@{prefix-cls} {
src/layouts/default/header/components/user-dropdown/index.vue
@@ -99,7 +99,6 @@ @@ -99,7 +99,6 @@
99 }); 99 });
100 </script> 100 </script>
101 <style lang="less"> 101 <style lang="less">
102 - @import (reference) '../../../../../design/index.less';  
103 @prefix-cls: ~'@{namespace}-header-user-dropdown'; 102 @prefix-cls: ~'@{namespace}-header-user-dropdown';
104 103
105 .@{prefix-cls} { 104 .@{prefix-cls} {
src/layouts/default/header/index.less
1 -@import (reference) '../../../design/index.less';  
2 @header-trigger-prefix-cls: ~'@{namespace}-layout-header-trigger'; 1 @header-trigger-prefix-cls: ~'@{namespace}-layout-header-trigger';
3 @header-prefix-cls: ~'@{namespace}-layout-header'; 2 @header-prefix-cls: ~'@{namespace}-layout-header';
4 @locale-prefix-cls: ~'@{namespace}-app-locale-picker'; 3 @locale-prefix-cls: ~'@{namespace}-app-locale-picker';
src/layouts/default/index.vue
@@ -31,7 +31,6 @@ @@ -31,7 +31,6 @@
31 import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; 31 import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
32 import { useDesign } from '/@/hooks/web/useDesign'; 32 import { useDesign } from '/@/hooks/web/useDesign';
33 33
34 - import { registerGlobComp } from '/@/components/registerGlobComp';  
35 import { useAppInject } from '/@/hooks/web/useAppInject'; 34 import { useAppInject } from '/@/hooks/web/useAppInject';
36 35
37 export default defineComponent({ 36 export default defineComponent({
@@ -46,11 +45,6 @@ @@ -46,11 +45,6 @@
46 Layout, 45 Layout,
47 }, 46 },
48 setup() { 47 setup() {
49 - // ! Only register global components here  
50 - // ! Can reduce the size of the first screen code  
51 - // default layout It is loaded after login. So it won’t be packaged to the first screen  
52 - registerGlobComp();  
53 -  
54 const { prefixCls } = useDesign('default-layout'); 48 const { prefixCls } = useDesign('default-layout');
55 49
56 const { getIsMobile } = useAppInject(); 50 const { getIsMobile } = useAppInject();
@@ -70,7 +64,6 @@ @@ -70,7 +64,6 @@
70 }); 64 });
71 </script> 65 </script>
72 <style lang="less"> 66 <style lang="less">
73 - @import (reference) '../../design/index.less';  
74 @prefix-cls: ~'@{namespace}-default-layout'; 67 @prefix-cls: ~'@{namespace}-default-layout';
75 68
76 .@{prefix-cls} { 69 .@{prefix-cls} {
src/layouts/default/menu/index.less
1 -@import (reference) '../../../design/index.less';  
2 -  
3 @prefix-cls: ~'@{namespace}-layout-menu'; 1 @prefix-cls: ~'@{namespace}-layout-menu';
4 @logo-prefix-cls: ~'@{namespace}-app-logo'; 2 @logo-prefix-cls: ~'@{namespace}-app-logo';
5 3
src/layouts/default/setting/SettingDrawer.tsx
@@ -389,26 +389,20 @@ export default defineComponent({ @@ -389,26 +389,20 @@ export default defineComponent({
389 width={330} 389 width={330}
390 wrapClassName="setting-drawer" 390 wrapClassName="setting-drawer"
391 > 391 >
392 - {{  
393 - default: () => (  
394 - <>  
395 - <Divider>{() => t('layout.setting.navMode')}</Divider>  
396 - {renderSidebar()}  
397 - <Divider>{() => t('layout.setting.headerTheme')}</Divider>  
398 - {renderHeaderTheme()}  
399 - <Divider>{() => t('layout.setting.sidebarTheme')}</Divider>  
400 - {renderSiderTheme()}  
401 - <Divider>{() => t('layout.setting.interfaceFunction')}</Divider>  
402 - {renderFeatures()}  
403 - <Divider>{() => t('layout.setting.interfaceDisplay')}</Divider>  
404 - {renderContent()}  
405 - <Divider>{() => t('layout.setting.animation')}</Divider>  
406 - {renderTransition()}  
407 - <Divider />  
408 - <SettingFooter />  
409 - </>  
410 - ),  
411 - }} 392 + <Divider>{() => t('layout.setting.navMode')}</Divider>
  393 + {renderSidebar()}
  394 + <Divider>{() => t('layout.setting.headerTheme')}</Divider>
  395 + {renderHeaderTheme()}
  396 + <Divider>{() => t('layout.setting.sidebarTheme')}</Divider>
  397 + {renderSiderTheme()}
  398 + <Divider>{() => t('layout.setting.interfaceFunction')}</Divider>
  399 + {renderFeatures()}
  400 + <Divider>{() => t('layout.setting.interfaceDisplay')}</Divider>
  401 + {renderContent()}
  402 + <Divider>{() => t('layout.setting.animation')}</Divider>
  403 + {renderTransition()}
  404 + <Divider />
  405 + <SettingFooter />
412 </BasicDrawer> 406 </BasicDrawer>
413 ); 407 );
414 }, 408 },
src/layouts/default/setting/components/InputNumberItem.vue
@@ -43,7 +43,6 @@ @@ -43,7 +43,6 @@
43 }); 43 });
44 </script> 44 </script>
45 <style lang="less" scoped> 45 <style lang="less" scoped>
46 - @import (reference) '../../../../design/index.less';  
47 @prefix-cls: ~'@{namespace}-setting-input-number-item'; 46 @prefix-cls: ~'@{namespace}-setting-input-number-item';
48 47
49 .@{prefix-cls} { 48 .@{prefix-cls} {
src/layouts/default/setting/components/SelectItem.vue
@@ -62,7 +62,6 @@ @@ -62,7 +62,6 @@
62 }); 62 });
63 </script> 63 </script>
64 <style lang="less" scoped> 64 <style lang="less" scoped>
65 - @import (reference) '../../../../design/index.less';  
66 @prefix-cls: ~'@{namespace}-setting-select-item'; 65 @prefix-cls: ~'@{namespace}-setting-select-item';
67 66
68 .@{prefix-cls} { 67 .@{prefix-cls} {
src/layouts/default/setting/components/SettingFooter.vue
@@ -75,7 +75,6 @@ @@ -75,7 +75,6 @@
75 }); 75 });
76 </script> 76 </script>
77 <style lang="less" scoped> 77 <style lang="less" scoped>
78 - @import (reference) '../../../../design/index.less';  
79 @prefix-cls: ~'@{namespace}-setting-footer'; 78 @prefix-cls: ~'@{namespace}-setting-footer';
80 79
81 .@{prefix-cls} { 80 .@{prefix-cls} {
src/layouts/default/setting/components/SwitchItem.vue
@@ -57,7 +57,6 @@ @@ -57,7 +57,6 @@
57 }); 57 });
58 </script> 58 </script>
59 <style lang="less" scoped> 59 <style lang="less" scoped>
60 - @import (reference) '../../../../design/index.less';  
61 @prefix-cls: ~'@{namespace}-setting-switch-item'; 60 @prefix-cls: ~'@{namespace}-setting-switch-item';
62 61
63 .@{prefix-cls} { 62 .@{prefix-cls} {
src/layouts/default/setting/components/ThemePicker.vue
@@ -55,7 +55,6 @@ @@ -55,7 +55,6 @@
55 }); 55 });
56 </script> 56 </script>
57 <style lang="less"> 57 <style lang="less">
58 - @import (reference) '../../../../design/index.less';  
59 @prefix-cls: ~'@{namespace}-setting-theme-picker'; 58 @prefix-cls: ~'@{namespace}-setting-theme-picker';
60 59
61 .@{prefix-cls} { 60 .@{prefix-cls} {
src/layouts/default/setting/components/TypePicker.vue
@@ -51,7 +51,6 @@ @@ -51,7 +51,6 @@
51 }); 51 });
52 </script> 52 </script>
53 <style lang="less" scoped> 53 <style lang="less" scoped>
54 - @import (reference) '../../../../design/index.less';  
55 @prefix-cls: ~'@{namespace}-setting-menu-type-picker'; 54 @prefix-cls: ~'@{namespace}-setting-menu-type-picker';
56 55
57 .@{prefix-cls} { 56 .@{prefix-cls} {
src/layouts/default/setting/index.vue
@@ -28,7 +28,6 @@ @@ -28,7 +28,6 @@
28 }); 28 });
29 </script> 29 </script>
30 <style lang="less"> 30 <style lang="less">
31 - @import (reference) '../../../design/index.less';  
32 @prefix-cls: ~'@{namespace}-setting-button'; 31 @prefix-cls: ~'@{namespace}-setting-button';
33 32
34 .@{prefix-cls} { 33 .@{prefix-cls} {
src/layouts/default/sider/DragBar.vue
@@ -41,7 +41,6 @@ @@ -41,7 +41,6 @@
41 }); 41 });
42 </script> 42 </script>
43 <style lang="less" scoped> 43 <style lang="less" scoped>
44 - @import (reference) '../../../design/index.less';  
45 @prefix-cls: ~'@{namespace}-darg-bar'; 44 @prefix-cls: ~'@{namespace}-darg-bar';
46 45
47 .@{prefix-cls} { 46 .@{prefix-cls} {
src/layouts/default/sider/LayoutSider.vue
@@ -128,7 +128,6 @@ @@ -128,7 +128,6 @@
128 }); 128 });
129 </script> 129 </script>
130 <style lang="less"> 130 <style lang="less">
131 - @import (reference) '../../../design/index.less';  
132 @prefix-cls: ~'@{namespace}-layout-sideBar'; 131 @prefix-cls: ~'@{namespace}-layout-sideBar';
133 132
134 .@{prefix-cls} { 133 .@{prefix-cls} {
src/layouts/default/sider/MixSider.vue
@@ -333,7 +333,6 @@ @@ -333,7 +333,6 @@
333 }); 333 });
334 </script> 334 </script>
335 <style lang="less"> 335 <style lang="less">
336 - @import (reference) '../../../design/index.less';  
337 @prefix-cls: ~'@{namespace}-layout-mix-sider'; 336 @prefix-cls: ~'@{namespace}-layout-mix-sider';
338 @tag-prefix-cls: ~'@{namespace}-basic-menu-item-tag'; 337 @tag-prefix-cls: ~'@{namespace}-basic-menu-item-tag';
339 @width: 80px; 338 @width: 80px;
src/layouts/default/sider/index.vue
@@ -41,7 +41,6 @@ @@ -41,7 +41,6 @@
41 }); 41 });
42 </script> 42 </script>
43 <style lang="less"> 43 <style lang="less">
44 - @import (reference) '../../../design/index.less';  
45 @prefix-cls: ~'@{namespace}-layout-sider-wrapper'; 44 @prefix-cls: ~'@{namespace}-layout-sider-wrapper';
46 .@{prefix-cls} { 45 .@{prefix-cls} {
47 .ant-drawer-body { 46 .ant-drawer-body {
src/layouts/default/tabs/index.less
1 -@import (reference) '../../../design/index.less';  
2 @prefix-cls: ~'@{namespace}-multiple-tabs'; 1 @prefix-cls: ~'@{namespace}-multiple-tabs';
3 2
4 .@{prefix-cls} { 3 .@{prefix-cls} {
src/layouts/page/index.tsx deleted 100644 → 0
1 -import type { DefaultContext } from './transition';  
2 -  
3 -import { computed, defineComponent, unref, Transition, KeepAlive } from 'vue';  
4 -import { RouterView } from 'vue-router';  
5 -  
6 -import FrameLayout from '/@/layouts/iframe/index.vue';  
7 -  
8 -import { useRootSetting } from '/@/hooks/setting/useRootSetting';  
9 -  
10 -import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';  
11 -import { useCache } from './useCache';  
12 -import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';  
13 -import { getTransitionName } from './transition';  
14 -  
15 -export default defineComponent({  
16 - name: 'PageLayout',  
17 - setup() {  
18 - const { getCaches } = useCache(true);  
19 - const { getShowMultipleTab } = useMultipleTabSetting();  
20 -  
21 - const { getOpenKeepAlive, getCanEmbedIFramePage } = useRootSetting();  
22 -  
23 - const { getBasicTransition, getEnableTransition } = useTransitionSetting();  
24 -  
25 - const openCache = computed(() => unref(getOpenKeepAlive) && unref(getShowMultipleTab));  
26 -  
27 - return () => {  
28 - return (  
29 - <>  
30 - <RouterView>  
31 - {{  
32 - default: ({ Component, route }: DefaultContext) => {  
33 - // No longer show animations that are already in the tab  
34 - const cacheTabs = unref(getCaches);  
35 -  
36 - const name = getTransitionName({  
37 - route,  
38 - openCache: unref(openCache),  
39 - enableTransition: unref(getEnableTransition),  
40 - cacheTabs,  
41 - def: unref(getBasicTransition),  
42 - });  
43 -  
44 - // When the child element is the parentView, adding the key will cause the component to be executed multiple times. When it is not parentView, you need to add a key, because it needs to be compatible with the same route carrying different parameters  
45 - const isParentView = Component?.type.parentView;  
46 - const componentKey = isParentView ? {} : { key: route.fullPath };  
47 -  
48 - const renderComp = () => <Component {...componentKey} />;  
49 -  
50 - const PageContent = unref(openCache) ? (  
51 - <KeepAlive include={cacheTabs}>{renderComp()}</KeepAlive>  
52 - ) : (  
53 - renderComp()  
54 - );  
55 -  
56 - if (!unref(getEnableTransition)) {  
57 - return PageContent;  
58 - }  
59 - return (  
60 - <Transition name={name} mode="out-in" appear={true}>  
61 - {() => PageContent}  
62 - </Transition>  
63 - );  
64 - },  
65 - }}  
66 - </RouterView>  
67 - {unref(getCanEmbedIFramePage) && <FrameLayout />}  
68 - </>  
69 - );  
70 - };  
71 - },  
72 -});  
src/layouts/page/index.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <router-view>
  4 + <template v-slot="{ Component, route }">
  5 + <transition
  6 + :name="
  7 + getTransitionName({
  8 + route,
  9 + openCache,
  10 + enableTransition: getEnableTransition,
  11 + cacheTabs: getCaches,
  12 + def: getBasicTransition,
  13 + })
  14 + "
  15 + mode="out-in"
  16 + appear
  17 + >
  18 + <keep-alive v-if="openCache" :include="getCaches">
  19 + <component :is="Component" v-bind="getKey(Component, route)" />
  20 + </keep-alive>
  21 + <component v-else :is="Component" v-bind="getKey(Component, route)" />
  22 + </transition>
  23 + </template>
  24 + </router-view>
  25 + <FrameLayout v-if="getCanEmbedIFramePage" />
  26 + </div>
  27 +</template>
  28 +
  29 +<script lang="ts">
  30 + import type { FunctionalComponent } from 'vue';
  31 + import type { RouteLocation } from 'vue-router';
  32 +
  33 + import { computed, defineComponent, unref } from 'vue';
  34 +
  35 + import FrameLayout from '/@/layouts/iframe/index.vue';
  36 +
  37 + import { useRootSetting } from '/@/hooks/setting/useRootSetting';
  38 +
  39 + import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
  40 + import { useCache } from './useCache';
  41 + import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
  42 + import { getTransitionName } from './transition';
  43 +
  44 + export default defineComponent({
  45 + name: 'PageLayout',
  46 + components: { FrameLayout },
  47 + setup() {
  48 + const { getCaches } = useCache(true);
  49 + const { getShowMultipleTab } = useMultipleTabSetting();
  50 +
  51 + const { getOpenKeepAlive, getCanEmbedIFramePage } = useRootSetting();
  52 +
  53 + const { getBasicTransition, getEnableTransition } = useTransitionSetting();
  54 +
  55 + const openCache = computed(() => unref(getOpenKeepAlive) && unref(getShowMultipleTab));
  56 +
  57 + function getKey(component: FunctionalComponent & { type: Indexable }, route: RouteLocation) {
  58 + return !!component?.type.parentView ? {} : { key: route.fullPath };
  59 + }
  60 +
  61 + return {
  62 + getTransitionName,
  63 + openCache,
  64 + getEnableTransition,
  65 + getBasicTransition,
  66 + getCaches,
  67 + getCanEmbedIFramePage,
  68 + getKey,
  69 + };
  70 + },
  71 + });
  72 +</script>
src/locales/index.ts renamed to src/locales/constant.ts
1 -import messages from 'globby?locale!/@/locales/lang/**/*.@(ts)';  
2 -  
3 import type { DropMenu } from '/@/components/Dropdown'; 1 import type { DropMenu } from '/@/components/Dropdown';
4 2
5 // locale list 3 // locale list
@@ -13,4 +11,3 @@ export const localeList: DropMenu[] = [ @@ -13,4 +11,3 @@ export const localeList: DropMenu[] = [
13 event: 'en', 11 event: 'en',
14 }, 12 },
15 ]; 13 ];
16 -export default messages;  
src/locales/getMessage.ts 0 → 100644
  1 +import { genMessage } from './helper';
  2 +import modules from 'glob:./lang/**/*.ts';
  3 +
  4 +export default genMessage(modules);
src/locales/helper.ts 0 → 100644
  1 +import { set } from 'lodash-es';
  2 +
  3 +export function genMessage(langs: Record<string, Record<string, any>>, prefix = 'lang') {
  4 + const obj: Recordable = {};
  5 +
  6 + Object.keys(langs).forEach((key) => {
  7 + const mod = langs[key].default;
  8 + let k = key.replace(`./${prefix}/`, '').replace(/^\.\//, '');
  9 + const lastIndex = k.lastIndexOf('.');
  10 + k = k.substring(0, lastIndex);
  11 + const keyList = k.split('/');
  12 + const lang = keyList.shift();
  13 + const objKey = keyList.join('.');
  14 + if (lang) {
  15 + set(obj, lang, obj[lang] || {});
  16 + set(obj[lang], objKey, mod);
  17 + }
  18 + });
  19 + return obj;
  20 +}
src/setup/i18n/index.ts renamed to src/locales/setupI18n.ts
1 -import { App } from 'vue'; 1 +import type { App } from 'vue';
2 import type { I18n, I18nOptions } from 'vue-i18n'; 2 import type { I18n, I18nOptions } from 'vue-i18n';
3 3
4 import { createI18n } from 'vue-i18n'; 4 import { createI18n } from 'vue-i18n';
5 -import localeMessages from '/@/locales';  
6 -import { useLocale } from '/@/hooks/web/useLocale'; 5 +
  6 +import 'moment/dist/locale/zh-cn';
  7 +
7 import projectSetting from '/@/settings/projectSetting'; 8 import projectSetting from '/@/settings/projectSetting';
8 -const { setupLocale } = useLocale(); 9 +
  10 +import messages from './getMessage';
9 11
10 const { lang, availableLocales, fallback } = projectSetting?.locale; 12 const { lang, availableLocales, fallback } = projectSetting?.locale;
  13 +
11 const localeData: I18nOptions = { 14 const localeData: I18nOptions = {
12 legacy: false, 15 legacy: false,
13 locale: lang, 16 locale: lang,
14 fallbackLocale: fallback, 17 fallbackLocale: fallback,
15 - messages: localeMessages, 18 + messages,
16 availableLocales: availableLocales, 19 availableLocales: availableLocales,
17 sync: true, //If you don’t want to inherit locale from global scope, you need to set sync of i18n component option to false. 20 sync: true, //If you don’t want to inherit locale from global scope, you need to set sync of i18n component option to false.
18 silentTranslationWarn: true, // true - warning off 21 silentTranslationWarn: true, // true - warning off
19 missingWarn: false, 22 missingWarn: false,
20 silentFallbackWarn: true, 23 silentFallbackWarn: true,
21 }; 24 };
22 -  
23 -let i18n: I18n; 25 +export let i18n: I18n;
24 26
25 // setup i18n instance with glob 27 // setup i18n instance with glob
26 export function setupI18n(app: App) { 28 export function setupI18n(app: App) {
27 i18n = createI18n(localeData) as I18n; 29 i18n = createI18n(localeData) as I18n;
28 - setupLocale();  
29 app.use(i18n); 30 app.use(i18n);
30 } 31 }
31 -  
32 -export function getI18n(): I18n {  
33 - return i18n;  
34 -}  
src/hooks/web/useLocale.ts renamed to src/locales/useLocale.ts
@@ -2,18 +2,16 @@ @@ -2,18 +2,16 @@
2 * Multi-language related operations 2 * Multi-language related operations
3 */ 3 */
4 import type { LocaleType } from '/@/locales/types'; 4 import type { LocaleType } from '/@/locales/types';
  5 +import type { Ref } from 'vue';
5 6
6 import { unref, ref } from 'vue'; 7 import { unref, ref } from 'vue';
7 -  
8 -import { getI18n } from '/@/setup/i18n';  
9 -  
10 import { useLocaleSetting } from '/@/hooks/setting/useLocaleSetting'; 8 import { useLocaleSetting } from '/@/hooks/setting/useLocaleSetting';
11 9
12 import moment from 'moment'; 10 import moment from 'moment';
13 11
14 import 'moment/dist/locale/zh-cn'; 12 import 'moment/dist/locale/zh-cn';
15 13
16 -moment.locale('zh-cn'); 14 +import { i18n } from './setupI18n';
17 15
18 const antConfigLocaleRef = ref<any>(null); 16 const antConfigLocaleRef = ref<any>(null);
19 17
@@ -23,7 +21,11 @@ export function useLocale() { @@ -23,7 +21,11 @@ export function useLocale() {
23 // Switching the language will change the locale of useI18n 21 // Switching the language will change the locale of useI18n
24 // And submit to configuration modification 22 // And submit to configuration modification
25 function changeLocale(lang: LocaleType): void { 23 function changeLocale(lang: LocaleType): void {
26 - (getI18n().global.locale as any).value = lang; 24 + if (i18n.mode === 'legacy') {
  25 + i18n.global.locale = lang;
  26 + } else {
  27 + ((i18n.global.locale as unknown) as Ref<string>).value = lang;
  28 + }
27 setLocalSetting({ lang }); 29 setLocalSetting({ lang });
28 // i18n.global.setLocaleMessage(locale, messages); 30 // i18n.global.setLocaleMessage(locale, messages);
29 31
@@ -51,13 +53,13 @@ export function useLocale() { @@ -51,13 +53,13 @@ export function useLocale() {
51 } 53 }
52 54
53 // initialization 55 // initialization
54 - function setupLocale() { 56 + function setLocale() {
55 const lang = unref(getLang); 57 const lang = unref(getLang);
56 lang && changeLocale(lang); 58 lang && changeLocale(lang);
57 } 59 }
58 60
59 return { 61 return {
60 - setupLocale, 62 + setLocale,
61 getLocale, 63 getLocale,
62 getLang, 64 getLang,
63 changeLocale, 65 changeLocale,
src/main.ts
@@ -6,18 +6,19 @@ import { setupStore } from &#39;/@/store&#39;; @@ -6,18 +6,19 @@ import { setupStore } from &#39;/@/store&#39;;
6 import { setupAntd } from '/@/setup/ant-design-vue'; 6 import { setupAntd } from '/@/setup/ant-design-vue';
7 import { setupErrorHandle } from '/@/setup/error-handle'; 7 import { setupErrorHandle } from '/@/setup/error-handle';
8 import { setupGlobDirectives } from '/@/directives'; 8 import { setupGlobDirectives } from '/@/directives';
9 -import { setupI18n } from '/@/setup/i18n'; 9 +import { setupI18n } from '/@/locales/setupI18n';
10 import { setupProdMockServer } from '../mock/_createProductionServer'; 10 import { setupProdMockServer } from '../mock/_createProductionServer';
11 -import { setApp } from '/@/setup/App'; 11 +
  12 +import { registerGlobComp } from '/@/components/registerGlobComp';
12 13
13 import { isDevMode, isProdMode, isUseMock } from '/@/utils/env'; 14 import { isDevMode, isProdMode, isUseMock } from '/@/utils/env';
14 15
15 import '/@/design/index.less'; 16 import '/@/design/index.less';
16 17
17 -import '/@/locales/index';  
18 -  
19 const app = createApp(App); 18 const app = createApp(App);
20 19
  20 +registerGlobComp(app);
  21 +
21 // Configure component library 22 // Configure component library
22 setupAntd(app); 23 setupAntd(app);
23 24
@@ -51,5 +52,3 @@ if (isDevMode()) { @@ -51,5 +52,3 @@ if (isDevMode()) {
51 if (isProdMode() && isUseMock()) { 52 if (isProdMode() && isUseMock()) {
52 setupProdMockServer(); 53 setupProdMockServer();
53 } 54 }
54 -// Used to share app instances in other modules  
55 -setApp(app);  
src/router/helper/dynamicImport.ts deleted 100644 → 0
1 -// The content here is just for type approval. The actual file content is overwritten by transform  
2 -// For specific coverage, see build/vite/plugin/transform/dynamic-import/index.ts  
3 -export default function (name: string) {  
4 - return name as any;  
5 -}  
src/router/helper/routeHelper.ts
@@ -2,8 +2,8 @@ import type { AppRouteModule, AppRouteRecordRaw } from &#39;/@/router/types&#39;; @@ -2,8 +2,8 @@ import type { AppRouteModule, AppRouteRecordRaw } from &#39;/@/router/types&#39;;
2 import type { RouteLocationNormalized, RouteRecordNormalized } from 'vue-router'; 2 import type { RouteLocationNormalized, RouteRecordNormalized } from 'vue-router';
3 3
4 import { getParentLayout, LAYOUT } from '/@/router/constant'; 4 import { getParentLayout, LAYOUT } from '/@/router/constant';
5 -import dynamicImport from './dynamicImport';  
6 import { cloneDeep } from 'lodash-es'; 5 import { cloneDeep } from 'lodash-es';
  6 +import { warn } from '/@/utils/log';
7 7
8 export type LayoutMapKey = 'LAYOUT'; 8 export type LayoutMapKey = 'LAYOUT';
9 9
@@ -11,12 +11,20 @@ const LayoutMap = new Map&lt;LayoutMapKey, () =&gt; Promise&lt;typeof import(&#39;*.vue&#39;)&gt;&gt;() @@ -11,12 +11,20 @@ const LayoutMap = new Map&lt;LayoutMapKey, () =&gt; Promise&lt;typeof import(&#39;*.vue&#39;)&gt;&gt;()
11 11
12 // 动态引入 12 // 动态引入
13 function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) { 13 function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) {
  14 + // TODO Because xlsx does not support vite2.0 temporarily. So filter the excel example first
  15 + const dynamicViewsModules = importContext({
  16 + dir: '/@/views',
  17 + deep: true,
  18 + regexp: /^(?!.*\/demo\/excel).*\.(tsx?|vue)$/,
  19 + dynamicImport: true,
  20 + dynamicEnabled: 'autoImportRoute',
  21 + });
14 if (!routes) return; 22 if (!routes) return;
15 routes.forEach((item) => { 23 routes.forEach((item) => {
16 const { component, name } = item; 24 const { component, name } = item;
17 const { children } = item; 25 const { children } = item;
18 if (component) { 26 if (component) {
19 - item.component = dynamicImport(component as string); 27 + item.component = dynamicImport(dynamicViewsModules, component as string);
20 } else if (name) { 28 } else if (name) {
21 item.component = getParentLayout(name); 29 item.component = getParentLayout(name);
22 } 30 }
@@ -24,6 +32,24 @@ function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) { @@ -24,6 +32,24 @@ function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) {
24 }); 32 });
25 } 33 }
26 34
  35 +function dynamicImport(dynamicViewsModules: DynamicImportContextResult, component: string) {
  36 + const keys = dynamicViewsModules.keys();
  37 + const matchKeys = keys.filter((key) => {
  38 + const k = key.substr(1);
  39 + return k.startsWith(component) || k.startsWith(`/${component}`);
  40 + });
  41 + if (matchKeys?.length === 1) {
  42 + const matchKey = matchKeys[0];
  43 + return dynamicViewsModules(matchKey);
  44 + }
  45 + if (matchKeys?.length > 1) {
  46 + warn(
  47 + 'Please do not create `.vue` and `.TSX` files with the same file name in the same hierarchical directory under the views folder. This will cause dynamic introduction failure'
  48 + );
  49 + return;
  50 + }
  51 +}
  52 +
27 // Turn background objects into routing objects 53 // Turn background objects into routing objects
28 export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModule[]): T[] { 54 export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModule[]): T[] {
29 LayoutMap.set('LAYOUT', LAYOUT); 55 LayoutMap.set('LAYOUT', LAYOUT);
src/router/menus/index.ts
@@ -9,18 +9,18 @@ import router from &#39;/@/router&#39;; @@ -9,18 +9,18 @@ import router from &#39;/@/router&#39;;
9 import { PermissionModeEnum } from '/@/enums/appEnum'; 9 import { PermissionModeEnum } from '/@/enums/appEnum';
10 import { pathToRegexp } from 'path-to-regexp'; 10 import { pathToRegexp } from 'path-to-regexp';
11 11
12 -import modules from 'globby!/@/router/menus/modules/**/*.@(ts)';  
13 -  
14 -const reg = /(((https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/; 12 +import modules from 'glob:./modules/**/*.ts';
15 13
16 const menuModules: MenuModule[] = []; 14 const menuModules: MenuModule[] = [];
17 15
18 Object.keys(modules).forEach((key) => { 16 Object.keys(modules).forEach((key) => {
19 - const moduleItem = modules[key];  
20 - const menuModule = Array.isArray(moduleItem) ? [...moduleItem] : [moduleItem];  
21 - menuModules.push(...menuModule); 17 + const mod = modules[key].default || {};
  18 + const modList = Array.isArray(mod) ? [...mod] : [mod];
  19 + menuModules.push(...modList);
22 }); 20 });
23 21
  22 +const reg = /(((https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/;
  23 +
24 // =========================== 24 // ===========================
25 // ==========Helper=========== 25 // ==========Helper===========
26 // =========================== 26 // ===========================
src/router/routes/index.ts
@@ -2,17 +2,18 @@ import type { AppRouteRecordRaw, AppRouteModule } from &#39;/@/router/types&#39;; @@ -2,17 +2,18 @@ import type { AppRouteRecordRaw, AppRouteModule } from &#39;/@/router/types&#39;;
2 2
3 import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '../constant'; 3 import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '../constant';
4 4
5 -import modules from 'globby!/@/router/routes/modules/**/*.@(ts)';  
6 import { mainOutRoutes } from './mainOut'; 5 import { mainOutRoutes } from './mainOut';
7 import { PageEnum } from '/@/enums/pageEnum'; 6 import { PageEnum } from '/@/enums/pageEnum';
8 -  
9 import { t } from '/@/hooks/web/useI18n'; 7 import { t } from '/@/hooks/web/useI18n';
10 8
  9 +import modules from 'glob:./modules/**/*.ts';
  10 +
11 const routeModuleList: AppRouteModule[] = []; 11 const routeModuleList: AppRouteModule[] = [];
12 12
13 Object.keys(modules).forEach((key) => { 13 Object.keys(modules).forEach((key) => {
14 - const mod = Array.isArray(modules[key]) ? [...modules[key]] : [modules[key]];  
15 - routeModuleList.push(...mod); 14 + const mod = modules[key].default || {};
  15 + const modList = Array.isArray(mod) ? [...mod] : [mod];
  16 + routeModuleList.push(...modList);
16 }); 17 });
17 18
18 export const asyncRoutes = [PAGE_NOT_FOUND_ROUTE, ...routeModuleList]; 19 export const asyncRoutes = [PAGE_NOT_FOUND_ROUTE, ...routeModuleList];
src/router/routes/modules/demo/feat.ts
@@ -172,51 +172,51 @@ const feat: AppRouteModule = { @@ -172,51 +172,51 @@ const feat: AppRouteModule = {
172 title: t('routes.demo.feat.errorLog'), 172 title: t('routes.demo.feat.errorLog'),
173 }, 173 },
174 }, 174 },
175 - {  
176 - path: 'excel',  
177 - name: 'Excel',  
178 - redirect: '/feat/excel/customExport',  
179 - component: getParentLayout('Excel'),  
180 - meta: {  
181 - // icon: 'mdi:microsoft-excel',  
182 - title: t('routes.demo.excel.excel'),  
183 - }, 175 + // {
  176 + // path: 'excel',
  177 + // name: 'Excel',
  178 + // redirect: '/feat/excel/customExport',
  179 + // component: getParentLayout('Excel'),
  180 + // meta: {
  181 + // // icon: 'mdi:microsoft-excel',
  182 + // title: t('routes.demo.excel.excel'),
  183 + // },
184 184
185 - children: [  
186 - {  
187 - path: 'customExport',  
188 - name: 'CustomExport',  
189 - component: () => import('/@/views/demo/excel/CustomExport.vue'),  
190 - meta: {  
191 - title: t('routes.demo.excel.customExport'),  
192 - },  
193 - },  
194 - {  
195 - path: 'jsonExport',  
196 - name: 'JsonExport',  
197 - component: () => import('/@/views/demo/excel/JsonExport.vue'),  
198 - meta: {  
199 - title: t('routes.demo.excel.jsonExport'),  
200 - },  
201 - },  
202 - {  
203 - path: 'arrayExport',  
204 - name: 'ArrayExport',  
205 - component: () => import('/@/views/demo/excel/ArrayExport.vue'),  
206 - meta: {  
207 - title: t('routes.demo.excel.arrayExport'),  
208 - },  
209 - },  
210 - {  
211 - path: 'importExcel',  
212 - name: 'ImportExcel',  
213 - component: () => import('/@/views/demo/excel/ImportExcel.vue'),  
214 - meta: {  
215 - title: t('routes.demo.excel.importExcel'),  
216 - },  
217 - },  
218 - ],  
219 - }, 185 + // children: [
  186 + // {
  187 + // path: 'customExport',
  188 + // name: 'CustomExport',
  189 + // component: () => import('/@/views/demo/excel/CustomExport.vue'),
  190 + // meta: {
  191 + // title: t('routes.demo.excel.customExport'),
  192 + // },
  193 + // },
  194 + // {
  195 + // path: 'jsonExport',
  196 + // name: 'JsonExport',
  197 + // component: () => import('/@/views/demo/excel/JsonExport.vue'),
  198 + // meta: {
  199 + // title: t('routes.demo.excel.jsonExport'),
  200 + // },
  201 + // },
  202 + // {
  203 + // path: 'arrayExport',
  204 + // name: 'ArrayExport',
  205 + // component: () => import('/@/views/demo/excel/ArrayExport.vue'),
  206 + // meta: {
  207 + // title: t('routes.demo.excel.arrayExport'),
  208 + // },
  209 + // },
  210 + // {
  211 + // path: 'importExcel',
  212 + // name: 'ImportExcel',
  213 + // component: () => import('/@/views/demo/excel/ImportExcel.vue'),
  214 + // meta: {
  215 + // title: t('routes.demo.excel.importExcel'),
  216 + // },
  217 + // },
  218 + // ],
  219 + // },
220 { 220 {
221 path: 'testTab/:id', 221 path: 'testTab/:id',
222 name: 'TestTab', 222 name: 'TestTab',
src/settings/projectSetting.ts
@@ -172,7 +172,7 @@ const setting: ProjectConfig = { @@ -172,7 +172,7 @@ const setting: ProjectConfig = {
172 172
173 // Whether to cancel the http request that has been sent but not responded when switching the interface. 173 // Whether to cancel the http request that has been sent but not responded when switching the interface.
174 // If it is enabled, I want to overwrite a single interface. Can be set in a separate interface 174 // If it is enabled, I want to overwrite a single interface. Can be set in a separate interface
175 - removeAllHttpPending: true, 175 + removeAllHttpPending: false,
176 }; 176 };
177 177
178 export default setting; 178 export default setting;
src/setup/App.ts
@@ -3,7 +3,6 @@ @@ -3,7 +3,6 @@
3 */ 3 */
4 4
5 import type { ProjectConfig } from '/@/types/config'; 5 import type { ProjectConfig } from '/@/types/config';
6 -import type { App } from 'vue';  
7 import { computed, ref } from 'vue'; 6 import { computed, ref } from 'vue';
8 7
9 import { ThemeModeEnum } from '/@/enums/appEnum'; 8 import { ThemeModeEnum } from '/@/enums/appEnum';
@@ -21,17 +20,6 @@ import { @@ -21,17 +20,6 @@ import {
21 import { appStore } from '/@/store/modules/app'; 20 import { appStore } from '/@/store/modules/app';
22 import { deepMerge } from '/@/utils'; 21 import { deepMerge } from '/@/utils';
23 22
24 -// Used to share global app instances  
25 -let app: App;  
26 -  
27 -export function setApp(_app: App): void {  
28 - app = _app;  
29 -}  
30 -  
31 -export function getApp(): App {  
32 - return app;  
33 -}  
34 -  
35 // TODO Theme switching 23 // TODO Theme switching
36 export function useThemeMode(mode: ThemeModeEnum) { 24 export function useThemeMode(mode: ThemeModeEnum) {
37 const modeRef = ref(mode); 25 const modeRef = ref(mode);
src/types/vue-app-env.d.ts
@@ -23,81 +23,3 @@ declare namespace NodeJS { @@ -23,81 +23,3 @@ declare namespace NodeJS {
23 } 23 }
24 24
25 declare let process: NodeJS.Process; 25 declare let process: NodeJS.Process;
26 -  
27 -declare module '*.bmp' {  
28 - const src: string;  
29 - export default src;  
30 -}  
31 -  
32 -declare module '*.gif' {  
33 - const src: string;  
34 - export default src;  
35 -}  
36 -  
37 -declare module '*.jpg' {  
38 - const src: string;  
39 - export default src;  
40 -}  
41 -  
42 -declare module '*.jpeg' {  
43 - const src: string;  
44 - export default src;  
45 -}  
46 -  
47 -declare module '*.png' {  
48 - const src: string;  
49 - export default src;  
50 -}  
51 -  
52 -declare module '*.webp' {  
53 - const src: string;  
54 - export default src;  
55 -}  
56 -  
57 -declare module '*.svg' {  
58 - const src: string;  
59 - export default src;  
60 -}  
61 -  
62 -declare module '*.json' {  
63 - const content: any | any[];  
64 - export default content;  
65 -}  
66 -  
67 -declare module '*.scss' {  
68 - const content: {  
69 - readonly [className: string]: string;  
70 - };  
71 - export default content;  
72 -}  
73 -declare module '*.less' {  
74 - const content: {  
75 - readonly [className: string]: string;  
76 - };  
77 - export default content;  
78 -}  
79 -declare module '*.styl' {  
80 - const content: {  
81 - readonly [className: string]: string;  
82 - };  
83 - export default content;  
84 -}  
85 -declare module '*.css' {  
86 - const content: any;  
87 - export default content;  
88 -}  
89 -  
90 -declare module '*.module.css' {  
91 - const classes: { readonly [key: string]: string };  
92 - export default classes;  
93 -}  
94 -  
95 -declare module '*.module.scss' {  
96 - const classes: { readonly [key: string]: string };  
97 - export default classes;  
98 -}  
99 -  
100 -declare module '*.module.sass' {  
101 - const classes: { readonly [key: string]: string };  
102 - export default classes;  
103 -}  
src/types/window.d.ts
@@ -4,5 +4,6 @@ declare global { @@ -4,5 +4,6 @@ declare global {
4 declare interface Window { 4 declare interface Window {
5 // Global vue app instance 5 // Global vue app instance
6 __APP__: App<Element>; 6 __APP__: App<Element>;
  7 + __VERSION__: string;
7 } 8 }
8 } 9 }
src/views/dashboard/analysis/components/GrowCard.vue
@@ -41,8 +41,6 @@ @@ -41,8 +41,6 @@
41 }); 41 });
42 </script> 42 </script>
43 <style lang="less"> 43 <style lang="less">
44 - @import (reference) '../../../../design/index.less';  
45 -  
46 .grow-card { 44 .grow-card {
47 display: flex; 45 display: flex;
48 width: calc(100% - 12px); 46 width: calc(100% - 12px);
src/views/dashboard/analysis/index.vue
@@ -68,8 +68,6 @@ @@ -68,8 +68,6 @@
68 }); 68 });
69 </script> 69 </script>
70 <style lang="less" scoped> 70 <style lang="less" scoped>
71 - @import (reference) '../../../design/index.less';  
72 -  
73 .analysis { 71 .analysis {
74 width: 100%; 72 width: 100%;
75 73
src/views/dashboard/house/index.less
1 -@import (reference) '../../../design/index.less';  
2 -  
3 .house-wrap { 1 .house-wrap {
4 position: relative; 2 position: relative;
5 width: 600px; 3 width: 600px;