提交 9a8e590a 作者: 方治民

合并分支 '3.x' 到 'dev'

3.x

查看合并请求 !15
...@@ -30,12 +30,7 @@ export function getThemeColors(color?: string) { ...@@ -30,12 +30,7 @@ export function getThemeColors(color?: string) {
return [...lightColors, ...modeColors] return [...lightColors, ...modeColors]
} }
export function generateColors({ export function generateColors({ color = primaryColor, mixLighten, mixDarken, tinycolor }: GenerateColorsParams) {
color = primaryColor,
mixLighten,
mixDarken,
tinycolor,
}: GenerateColorsParams) {
const arr = new Array(19).fill(0) const arr = new Array(19).fill(0)
const lightens = arr.map((_t, i) => { const lightens = arr.map((_t, i) => {
return mixLighten(color, i / 5) return mixLighten(color, i / 5)
......
...@@ -2,5 +2,3 @@ ...@@ -2,5 +2,3 @@
* The name of the configuration file entered in the production environment * The name of the configuration file entered in the production environment
*/ */
export const GLOB_CONFIG_FILE_NAME = '_app.config.js' export const GLOB_CONFIG_FILE_NAME = '_app.config.js'
export const OUTPUT_DIR = 'dist'
import { resolve } from 'node:path'
import { getThemeVariables } from 'ant-design-vue/dist/theme.js'
import { generateAntColors, primaryColor } from '../config/themeConfig' import { generateAntColors, primaryColor } from '../config/themeConfig'
import { getThemeVariables } from 'ant-design-vue/dist/theme'
import { resolve } from 'path'
/** /**
* less global variable * less global variable
...@@ -28,7 +28,7 @@ export function generateModifyVars(dark = false) { ...@@ -28,7 +28,7 @@ export function generateModifyVars(dark = false) {
'success-color': '#55D187', // Success color 'success-color': '#55D187', // Success color
'error-color': '#ED6F6F', // False color 'error-color': '#ED6F6F', // False color
'warning-color': '#EFBD47', // Warning color 'warning-color': '#EFBD47', // Warning color
//'border-color-base': '#EEEEEE', // 'border-color-base': '#EEEEEE',
'font-size-base': '14px', // Main font size 'font-size-base': '14px', // Main font size
'border-radius-base': '2px', // Component/float fillet 'border-radius-base': '2px', // Component/float fillet
'link-color': primary, // Link color 'link-color': primary, // Link color
......
import path from 'path' import path from 'node:path'
import fs from 'fs-extra' import fs from 'fs-extra'
import inquirer from 'inquirer' import inquirer from 'inquirer'
import colors from 'picocolors' import colors from 'picocolors'
...@@ -30,7 +30,7 @@ async function generateIcon() { ...@@ -30,7 +30,7 @@ async function generateIcon() {
{ {
type: 'list', type: 'list',
name: 'iconSet', name: 'iconSet',
choices: choices, choices,
message: 'Select the icon set that needs to be generated?', message: 'Select the icon set that needs to be generated?',
}, },
{ {
...@@ -51,25 +51,17 @@ async function generateIcon() { ...@@ -51,25 +51,17 @@ async function generateIcon() {
if (data) { if (data) {
const { prefix } = data const { prefix } = data
const isLocal = useType === 'local' const isLocal = useType === 'local'
const icons = Object.keys(data.icons).map( const icons = Object.keys(data.icons).map((item) => `${isLocal ? `${prefix}:` : ''}${item}`)
(item) => `${isLocal ? prefix + ':' : ''}${item}`,
)
await fs.writeFileSync( await fs.writeFileSync(
path.join(output, `icons.data.ts`), path.join(output, `icons.data.ts`),
`export default ${ `export default ${isLocal ? JSON.stringify(icons) : JSON.stringify({ prefix, icons })}`,
isLocal ? JSON.stringify(icons) : JSON.stringify({ prefix, icons })
}`,
) )
prefixSet.push(prefix) prefixSet.push(prefix)
} }
} }
fs.emptyDir(path.join(process.cwd(), 'node_modules/.vite')) fs.emptyDir(path.join(process.cwd(), 'node_modules/.vite'))
console.log( console.log(`✨ ${colors.cyan(`[${pkg.name}]`)}` + ' - Icon generated successfully:' + `[${prefixSet}]`)
`✨ ${colors.cyan(`[${pkg.name}]`)}` +
' - Icon generated successfully:' +
`[${prefixSet}]`,
)
}) })
} }
......
/**
* Generate additional configuration files when used for packaging. The file can be configured with some global variables, so that it can be changed directly externally without repackaging
*/
import { GLOB_CONFIG_FILE_NAME, OUTPUT_DIR } from '../constant'
import fs, { writeFileSync } from 'fs-extra'
import colors from 'picocolors'
import { getEnvConfig, getRootPath } from '../utils'
import { getConfigFileName } from '../getConfigFileName'
import pkg from '../../package.json'
interface CreateConfigParams {
configName: string
config: any
configFileName?: string
}
function createConfig(params: CreateConfigParams) {
const { configName, config, configFileName } = params
try {
const windowConf = `window.${configName}`
// Ensure that the variable will not be modified
let configStr = `${windowConf}=${JSON.stringify(config)};`
configStr += `
Object.freeze(${windowConf});
Object.defineProperty(window, "${configName}", {
configurable: false,
writable: false,
});
`.replace(/\s/g, '')
fs.mkdirp(getRootPath(OUTPUT_DIR))
writeFileSync(getRootPath(`${OUTPUT_DIR}/${configFileName}`), configStr)
console.log(colors.cyan(`✨ [${pkg.name}]`) + ` - configuration file is build successfully:`)
console.log(colors.gray(OUTPUT_DIR + '/' + colors.green(configFileName)) + '\n')
} catch (error) {
console.log(colors.red('configuration file configuration file failed to package:\n' + error))
}
}
export function runBuildConfig() {
const config = getEnvConfig()
const configFileName = getConfigFileName(config)
createConfig({ config, configName: configFileName, configFileName: GLOB_CONFIG_FILE_NAME })
}
// #!/usr/bin/env node
import { runBuildConfig } from './buildConf'
import colors from 'picocolors'
import pkg from '../../package.json'
export const runBuild = async () => {
try {
const argvList = process.argv.splice(2)
// Generate configuration file
if (!argvList.includes('disabled-config')) {
runBuildConfig()
}
console.log(`✨ ${colors.cyan(`[${pkg.name}]`)}` + ' - build successfully!')
} catch (error) {
console.log(colors.red('vite build error:\n' + error))
process.exit(1)
}
}
runBuild()
import fs from 'fs' import fs from 'node:fs'
import path from 'path' import path from 'node:path'
import dotenv from 'dotenv' import dotenv from 'dotenv'
export function isDevFn(mode: string): boolean { export function isDevFn(mode: string): boolean {
...@@ -50,7 +50,7 @@ export function wrapperEnv(envConf: Recordable): ViteEnv { ...@@ -50,7 +50,7 @@ export function wrapperEnv(envConf: Recordable): ViteEnv {
*/ */
function getConfFiles() { function getConfFiles() {
const script = process.env.npm_lifecycle_script const script = process.env.npm_lifecycle_script
const reg = new RegExp('--mode ([a-z_\\d]+)') const reg = /--mode ([a-z_\d]+)/
const result = reg.exec(script as string) as any const result = reg.exec(script as string) as any
if (result) { if (result) {
const mode = result[1] as string const mode = result[1] as string
......
import path from 'node:path'
import fs from 'node:fs'
import colors from 'picocolors'
import type { Plugin, ResolvedConfig } from 'vite'
import { getEnvConfig, getRootPath } from '../../utils'
import { getConfigFileName } from '../../getConfigFileName'
import { GLOB_CONFIG_FILE_NAME } from '../../constant'
import pkg from '../../../package.json'
export function configBuildPlugin(): Plugin {
let outputPath: string
let config: ResolvedConfig
return {
name: 'vite:app:config',
apply: 'build',
enforce: 'post',
configResolved(resolvedConfig: ResolvedConfig) {
config = resolvedConfig
outputPath = path.isAbsolute(config.build.outDir)
? config.build.outDir
: path.join(config.root, config.build.outDir)
},
async closeBundle() {
const config = getEnvConfig()
const configName = getConfigFileName(config)
const windowConf = `window.${configName}`
// Ensure that the variable will not be modified
let configStr = `${windowConf}=${JSON.stringify(config)};`
configStr += `
Object.freeze(${windowConf});
Object.defineProperty(window, "${configName}", {
configurable: false,
writable: false,
});
`.replace(/\s/g, '')
fs.writeFileSync(getRootPath(`${outputPath}/${GLOB_CONFIG_FILE_NAME}`), configStr)
console.log(`${colors.cyan(`✨ [${pkg.name}]`)} configuration file is build successfully:`)
console.log(`${colors.gray(`${outputPath}/${colors.green(GLOB_CONFIG_FILE_NAME)}`)}\n`)
},
} as Plugin
}
import { PluginOption } from 'vite' import type { PluginOption } from 'vite'
import vue from '@vitejs/plugin-vue' import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx' import vueJsx from '@vitejs/plugin-vue-jsx'
import legacy from '@vitejs/plugin-legacy' import legacy from '@vitejs/plugin-legacy'
...@@ -15,6 +15,7 @@ import { configVisualizerConfig } from './visualizer' ...@@ -15,6 +15,7 @@ import { configVisualizerConfig } from './visualizer'
import { configThemePlugin } from './theme' import { configThemePlugin } from './theme'
import { configSvgIconsPlugin } from './svgSprite' import { configSvgIconsPlugin } from './svgSprite'
import { configAutoImportPlugin } from './autoImport' import { configAutoImportPlugin } from './autoImport'
import { configBuildPlugin } from './config'
export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) { export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
const { VITE_USE_MOCK, VITE_LEGACY, VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE } = viteEnv const { VITE_USE_MOCK, VITE_LEGACY, VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE } = viteEnv
...@@ -63,13 +64,16 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) { ...@@ -63,13 +64,16 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
// The following plugins only work in the production environment // The following plugins only work in the production environment
if (isBuild) { if (isBuild) {
// vite-plugin-imagemin // config
vitePlugins.push(configBuildPlugin())
// rollup-plugin-gzip if (process.env.RUNTIME !== 'electron') {
vitePlugins.push(configCompressPlugin(VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE)) // rollup-plugin-gzip
vitePlugins.push(configCompressPlugin(VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE))
// vite-plugin-pwa // vite-plugin-pwa
vitePlugins.push(configPwaConfig(viteEnv)) vitePlugins.push(configPwaConfig(viteEnv))
}
} }
return vitePlugins return vitePlugins
......
...@@ -70,7 +70,7 @@ export function configStyleImportPlugin(_isBuild: boolean) { ...@@ -70,7 +70,7 @@ export function configStyleImportPlugin(_isBuild: boolean) {
return ignoreList.includes(name) return ignoreList.includes(name)
? '' ? ''
: replaceList.hasOwnProperty(name) : Object.prototype.hasOwnProperty.call(replaceList, name)
? `ant-design-vue/es/${replaceList[name]}/style/index` ? `ant-design-vue/es/${replaceList[name]}/style/index`
: `ant-design-vue/es/${name}/style/index` : `ant-design-vue/es/${name}/style/index`
}, },
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
* https://github.com/anncwb/vite-plugin-svg-icons * https://github.com/anncwb/vite-plugin-svg-icons
*/ */
import path from 'node:path'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons' import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import path from 'path'
export function configSvgIconsPlugin(isBuild: boolean) { export function configSvgIconsPlugin(isBuild: boolean) {
const svgIconsPlugin = createSvgIconsPlugin({ const svgIconsPlugin = createSvgIconsPlugin({
......
...@@ -2,16 +2,10 @@ ...@@ -2,16 +2,10 @@
* Vite plugin for website theme color switching * Vite plugin for website theme color switching
* https://github.com/anncwb/vite-plugin-theme * https://github.com/anncwb/vite-plugin-theme
*/ */
import path from 'node:path'
import type { PluginOption } from 'vite' import type { PluginOption } from 'vite'
import path from 'path' import { antdDarkThemePlugin, mixDarken, mixLighten, tinycolor, viteThemePlugin } from 'vite-plugin-theme'
import { import { generateColors, getThemeColors } from '../../config/themeConfig'
viteThemePlugin,
antdDarkThemePlugin,
mixLighten,
mixDarken,
tinycolor,
} from 'vite-plugin-theme'
import { getThemeColors, generateColors } from '../../config/themeConfig'
import { generateModifyVars } from '../../generate/generateModifyVars' import { generateModifyVars } from '../../generate/generateModifyVars'
export function configThemePlugin(isBuild: boolean): PluginOption[] { export function configThemePlugin(isBuild: boolean): PluginOption[] {
...@@ -48,7 +42,7 @@ export function configThemePlugin(isBuild: boolean): PluginOption[] { ...@@ -48,7 +42,7 @@ export function configThemePlugin(isBuild: boolean): PluginOption[] {
antdDarkThemePlugin({ antdDarkThemePlugin({
preloadFiles: [ preloadFiles: [
path.resolve(process.cwd(), 'node_modules/ant-design-vue/dist/antd.less'), path.resolve(process.cwd(), 'node_modules/ant-design-vue/dist/antd.less'),
//path.resolve(process.cwd(), 'node_modules/ant-design-vue/dist/antd.dark.less'), // path.resolve(process.cwd(), 'node_modules/ant-design-vue/dist/antd.dark.less'),
path.resolve(process.cwd(), 'src/design/index.less'), path.resolve(process.cwd(), 'src/design/index.less'),
], ],
filter: (id) => (isBuild ? !id.endsWith('antd.less') : true), filter: (id) => (isBuild ? !id.endsWith('antd.less') : true),
......
...@@ -22,7 +22,7 @@ export function createProxy(list: ProxyList = []) { ...@@ -22,7 +22,7 @@ export function createProxy(list: ProxyList = []) {
// https://github.com/http-party/node-http-proxy#options // https://github.com/http-party/node-http-proxy#options
ret[prefix] = { ret[prefix] = {
target: target, target,
changeOrigin: true, changeOrigin: true,
ws: true, ws: true,
rewrite: (path) => path.replace(new RegExp(`^${prefix}`), ''), rewrite: (path) => path.replace(new RegExp(`^${prefix}`), ''),
......
...@@ -8,14 +8,14 @@ ...@@ -8,14 +8,14 @@
name="viewport" name="viewport"
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
/> />
<title><%= title %></title> <title>%VITE_GLOB_APP_TITLE%</title>
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon.ico" />
</head> </head>
<body> <body>
<script> <script>
;(() => { ;(() => {
var htmlRoot = document.getElementById('htmlRoot') let htmlRoot = document.getElementById('htmlRoot')
var theme = window.localStorage.getItem('__APP__DARK__MODE__') let theme = window.localStorage.getItem('__APP__DARK__MODE__')
if (htmlRoot && theme) { if (htmlRoot && theme) {
htmlRoot.setAttribute('data-theme', theme) htmlRoot.setAttribute('data-theme', theme)
theme = htmlRoot = null theme = htmlRoot = null
...@@ -150,7 +150,7 @@ ...@@ -150,7 +150,7 @@
<div class="app-loading-dots"> <div class="app-loading-dots">
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span> <span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
</div> </div>
<div class="app-loading-title"><%= title %></div> <div class="app-loading-title">%VITE_GLOB_APP_TITLE%</div>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -68,7 +68,7 @@ export class Response { ...@@ -68,7 +68,7 @@ export class Response {
export class Request { export class Request {
method: string method: string
body: any body: any
headers?: { authorization?: string } headers?: { ['app-token']?: string }
query: any query: any
/** /**
...@@ -77,6 +77,6 @@ export class Request { ...@@ -77,6 +77,6 @@ export class Request {
* @returns token * @returns token
*/ */
static getRequestToken({ headers }: Request): string | undefined { static getRequestToken({ headers }: Request): string | undefined {
return headers?.authorization return headers?.['app-token']
} }
} }
...@@ -25,9 +25,9 @@ ...@@ -25,9 +25,9 @@
"bootstrap": "pnpm install", "bootstrap": "pnpm install",
"serve": "npm run dev", "serve": "npm run dev",
"dev": "vite", "dev": "vite",
"build": "cross-env NODE_ENV=production vite build && esno ./build/script/postBuild.ts", "build": "vite build",
"build:test": "cross-env vite build --mode test && esno ./build/script/postBuild.ts", "build:test": "vite build --mode test",
"build:preview": "cross-env vite build --mode preview && esno ./build/script/postBuild.ts", "build:preview": "vite build --mode preview",
"build:no-cache": "pnpm clean:cache && npm run build", "build:no-cache": "pnpm clean:cache && npm run build",
"report": "cross-env REPORT=true npm run build", "report": "cross-env REPORT=true npm run build",
"type:check": "vue-tsc --noEmit --skipLibCheck", "type:check": "vue-tsc --noEmit --skipLibCheck",
...@@ -104,7 +104,7 @@ ...@@ -104,7 +104,7 @@
}, },
"devDependencies": { "devDependencies": {
"@antfu/eslint-config": "^0.37.0", "@antfu/eslint-config": "^0.37.0",
"@commitlint/cli": "^17.5.0", "@commitlint/cli": "^17.5.1",
"@commitlint/config-conventional": "^17.4.4", "@commitlint/config-conventional": "^17.4.4",
"@iconify/json": "^2.2.40", "@iconify/json": "^2.2.40",
"@purge-icons/generated": "^0.9.0", "@purge-icons/generated": "^0.9.0",
......
// import * as Pont from 'pont-engine' // import * as Pont from 'pont-engine'
import { Interface, BaseClass, Property, CodeGenerator } from 'pont-engine' import type { BaseClass, Interface } from 'pont-engine'
import { CodeGenerator, Property } from 'pont-engine'
// 接口 API 前缀 // 接口 API 前缀
// 通常与项目的 env 配置中的 VITE_GLOB_API_URL_PREFIX 相同 // 通常与项目的 env 配置中的 VITE_GLOB_API_URL_PREFIX 相同
...@@ -38,7 +39,7 @@ export default class BasicGenerator extends CodeGenerator { ...@@ -38,7 +39,7 @@ export default class BasicGenerator extends CodeGenerator {
return `${requestParams.replace( return `${requestParams.replace(
'options?: any', 'options?: any',
`config?: http.RequestConfig<${ `config?: http.RequestConfig<${
bodyTypeDef ? bodyTypeDef : `Params${requestParams.includes('form') ? ' | FormData' : ''}` bodyTypeDef || `Params${requestParams.includes('form') ? ' | FormData' : ''}`
}>`, }>`,
)}, options?: http.RequestOptions` )}, options?: http.RequestOptions`
} }
......
import { StandardDataSource } from 'pont-engine' import type { StandardDataSource } from 'pont-engine'
export default function transform(dataSource: StandardDataSource): StandardDataSource { export default function transform(dataSource: StandardDataSource): StandardDataSource {
console.log(dataSource) console.log(dataSource)
......
...@@ -157,7 +157,7 @@ const transform: AxiosTransform = { ...@@ -157,7 +157,7 @@ const transform: AxiosTransform = {
const token = getToken() const token = getToken()
if (token && (config as Recordable)?.requestOptions?.withToken !== false) { if (token && (config as Recordable)?.requestOptions?.withToken !== false) {
// jwt token // jwt token
;(config as Recordable).headers.Authorization = options.authenticationScheme ;(config as Recordable).headers['App-Token'] = options.authenticationScheme
? `${options.authenticationScheme} ${token}` ? `${options.authenticationScheme} ${token}`
: token : token
} }
......
import type { UserConfig, ConfigEnv } from 'vite' import { resolve } from 'node:path'
import pkg from './package.json' import type { ConfigEnv, UserConfig } from 'vite'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { loadEnv } from 'vite' import { loadEnv } from 'vite'
import { resolve } from 'path' import pkg from './package.json'
import { generateModifyVars } from './build/generate/generateModifyVars' import { generateModifyVars } from './build/generate/generateModifyVars'
import { createProxy } from './build/vite/proxy' import { createProxy } from './build/vite/proxy'
import { wrapperEnv } from './build/utils' import { wrapperEnv } from './build/utils'
import { createVitePlugins } from './build/vite/plugin' import { createVitePlugins } from './build/vite/plugin'
import { OUTPUT_DIR } from './build/constant'
function pathResolve(dir: string) { function pathResolve(dir: string) {
return resolve(process.cwd(), '.', dir) return resolve(process.cwd(), '.', dir)
...@@ -43,12 +42,12 @@ export default ({ command, mode }: ConfigEnv): UserConfig => { ...@@ -43,12 +42,12 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
// /@/xxxx => src/xxxx // /@/xxxx => src/xxxx
{ {
find: /\/?@\//, find: /\/?@\//,
replacement: pathResolve('src') + '/', replacement: `${pathResolve('src')}/`,
}, },
// /#/xxxx => types/xxxx // /#/xxxx => types/xxxx
{ {
find: /\/#\//, find: /\/#\//,
replacement: pathResolve('types') + '/', replacement: `${pathResolve('types')}/`,
}, },
], ],
}, },
...@@ -60,24 +59,20 @@ export default ({ command, mode }: ConfigEnv): UserConfig => { ...@@ -60,24 +59,20 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
// Load proxy configuration from .env // Load proxy configuration from .env
proxy: createProxy(VITE_PROXY), proxy: createProxy(VITE_PROXY),
}, },
esbuild: {
pure: VITE_DROP_CONSOLE ? ['console.log', 'debugger'] : [],
},
build: { build: {
target: 'es2015', target: 'es2015',
cssTarget: 'chrome80', cssTarget: 'chrome80',
outDir: OUTPUT_DIR, minify: 'terser',
// minify: 'terser',
/** /**
* 当 minify=“minify:'terser'” 解开注释 * 当 minify=“minify:'terser'” 解开注释
* Uncomment when minify="minify:'terser'" * Uncomment when minify="minify:'terser'"
*/ */
// terserOptions: { terserOptions: {
// compress: { compress: {
// keep_infinity: true, keep_infinity: true,
// drop_console: VITE_DROP_CONSOLE, drop_console: VITE_DROP_CONSOLE,
// }, },
// }, },
// Turning off brotliSize display can slightly reduce packaging time // Turning off brotliSize display can slightly reduce packaging time
reportCompressedSize: false, reportCompressedSize: false,
chunkSizeWarningLimit: 2000, chunkSizeWarningLimit: 2000,
...@@ -115,13 +110,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig => { ...@@ -115,13 +110,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
optimizeDeps: { optimizeDeps: {
// @iconify/iconify: The dependency is dynamically and virtually loaded by @purge-icons/generated, so it needs to be specified explicitly // @iconify/iconify: The dependency is dynamically and virtually loaded by @purge-icons/generated, so it needs to be specified explicitly
include: [ include: ['@iconify/iconify', 'ant-design-vue/es/locale/zh_CN', 'ant-design-vue/es/locale/en_US'],
'@vue/runtime-core',
'@vue/shared',
'@iconify/iconify',
'ant-design-vue/es/locale/zh_CN',
'ant-design-vue/es/locale/en_US',
],
}, },
} }
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论