Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
418ca2405e
|
|
@ -1,6 +1,4 @@
|
||||||
// @ts-check
|
module.exports = {
|
||||||
const { defineConfig } = require('eslint-define-config');
|
|
||||||
module.exports = defineConfig({
|
|
||||||
root: true,
|
root: true,
|
||||||
env: {
|
env: {
|
||||||
browser: true,
|
browser: true,
|
||||||
|
|
@ -20,9 +18,7 @@ module.exports = defineConfig({
|
||||||
extends: [
|
extends: [
|
||||||
'plugin:vue/vue3-recommended',
|
'plugin:vue/vue3-recommended',
|
||||||
'plugin:@typescript-eslint/recommended',
|
'plugin:@typescript-eslint/recommended',
|
||||||
'prettier',
|
|
||||||
'plugin:prettier/recommended',
|
'plugin:prettier/recommended',
|
||||||
'plugin:jest/recommended',
|
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
'vue/script-setup-uses-vars': 'error',
|
'vue/script-setup-uses-vars': 'error',
|
||||||
|
|
@ -77,4 +73,4 @@ module.exports = defineConfig({
|
||||||
],
|
],
|
||||||
'vue/multi-word-component-names': 'off',
|
'vue/multi-word-component-names': 'off',
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
"**/yarn.lock": true
|
"**/yarn.lock": true
|
||||||
},
|
},
|
||||||
"stylelint.enable": true,
|
"stylelint.enable": true,
|
||||||
"stylelint.packageManager": "yarn",
|
"stylelint.validate": ["css", "less", "postcss", "scss", "vue", "sass"],
|
||||||
"path-intellisense.mappings": {
|
"path-intellisense.mappings": {
|
||||||
"/@/": "${workspaceRoot}/src"
|
"/@/": "${workspaceRoot}/src"
|
||||||
},
|
},
|
||||||
|
|
@ -88,7 +88,8 @@
|
||||||
},
|
},
|
||||||
"[vue]": {
|
"[vue]": {
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll.eslint": false
|
"source.fixAll.eslint": true,
|
||||||
|
"source.fixAll.stylelint": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"i18n-ally.localesPaths": ["src/locales/lang"],
|
"i18n-ally.localesPaths": ["src/locales/lang"],
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import inquirer from 'inquirer';
|
import inquirer from 'inquirer';
|
||||||
import chalk from 'chalk';
|
import colors from 'picocolors';
|
||||||
import pkg from '../../../package.json';
|
import pkg from '../../../package.json';
|
||||||
|
|
||||||
async function generateIcon() {
|
async function generateIcon() {
|
||||||
|
|
@ -64,7 +64,7 @@ async function generateIcon() {
|
||||||
}
|
}
|
||||||
fs.emptyDir(path.join(process.cwd(), 'node_modules/.vite'));
|
fs.emptyDir(path.join(process.cwd(), 'node_modules/.vite'));
|
||||||
console.log(
|
console.log(
|
||||||
`✨ ${chalk.cyan(`[${pkg.name}]`)}` + ' - Icon generated successfully:' + `[${prefixSet}]`,
|
`✨ ${colors.cyan(`[${pkg.name}]`)}` + ' - Icon generated successfully:' + `[${prefixSet}]`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
*/
|
*/
|
||||||
import { GLOB_CONFIG_FILE_NAME, OUTPUT_DIR } from '../constant';
|
import { GLOB_CONFIG_FILE_NAME, OUTPUT_DIR } from '../constant';
|
||||||
import fs, { writeFileSync } from 'fs-extra';
|
import fs, { writeFileSync } from 'fs-extra';
|
||||||
import chalk from 'chalk';
|
import colors from 'picocolors';
|
||||||
|
|
||||||
import { getEnvConfig, getRootPath } from '../utils';
|
import { getEnvConfig, getRootPath } from '../utils';
|
||||||
import { getConfigFileName } from '../getConfigFileName';
|
import { getConfigFileName } from '../getConfigFileName';
|
||||||
|
|
@ -31,10 +31,10 @@ function createConfig(params: CreateConfigParams) {
|
||||||
fs.mkdirp(getRootPath(OUTPUT_DIR));
|
fs.mkdirp(getRootPath(OUTPUT_DIR));
|
||||||
writeFileSync(getRootPath(`${OUTPUT_DIR}/${configFileName}`), configStr);
|
writeFileSync(getRootPath(`${OUTPUT_DIR}/${configFileName}`), configStr);
|
||||||
|
|
||||||
console.log(chalk.cyan(`✨ [${pkg.name}]`) + ` - configuration file is build successfully:`);
|
console.log(colors.cyan(`✨ [${pkg.name}]`) + ` - configuration file is build successfully:`);
|
||||||
console.log(chalk.gray(OUTPUT_DIR + '/' + chalk.green(configFileName)) + '\n');
|
console.log(colors.gray(OUTPUT_DIR + '/' + colors.green(configFileName)) + '\n');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(chalk.red('configuration file configuration file failed to package:\n' + error));
|
console.log(colors.red('configuration file configuration file failed to package:\n' + error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// #!/usr/bin/env node
|
// #!/usr/bin/env node
|
||||||
|
|
||||||
import { runBuildConfig } from './buildConf';
|
import { runBuildConfig } from './buildConf';
|
||||||
import chalk from 'chalk';
|
import colors from 'picocolors';
|
||||||
|
|
||||||
import pkg from '../../package.json';
|
import pkg from '../../package.json';
|
||||||
|
|
||||||
|
|
@ -14,9 +14,9 @@ export const runBuild = async () => {
|
||||||
runBuildConfig();
|
runBuildConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`✨ ${chalk.cyan(`[${pkg.name}]`)}` + ' - build successfully!');
|
console.log(`✨ ${colors.cyan(`[${pkg.name}]`)}` + ' - build successfully!');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(chalk.red('vite build error:\n' + error));
|
console.log(colors.red('vite build error:\n' + error));
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,16 @@
|
||||||
* Used to package and output gzip. Note that this does not work properly in Vite, the specific reason is still being investigated
|
* Used to package and output gzip. Note that this does not work properly in Vite, the specific reason is still being investigated
|
||||||
* https://github.com/anncwb/vite-plugin-compression
|
* https://github.com/anncwb/vite-plugin-compression
|
||||||
*/
|
*/
|
||||||
import type { Plugin } from 'vite';
|
import type { PluginOption } from 'vite';
|
||||||
import compressPlugin from 'vite-plugin-compression';
|
import compressPlugin from 'vite-plugin-compression';
|
||||||
|
|
||||||
export function configCompressPlugin(
|
export function configCompressPlugin(
|
||||||
compress: 'gzip' | 'brotli' | 'none',
|
compress: 'gzip' | 'brotli' | 'none',
|
||||||
deleteOriginFile = false,
|
deleteOriginFile = false,
|
||||||
): Plugin | Plugin[] {
|
): PluginOption | PluginOption[] {
|
||||||
const compressList = compress.split(',');
|
const compressList = compress.split(',');
|
||||||
|
|
||||||
const plugins: Plugin[] = [];
|
const plugins: PluginOption[] = [];
|
||||||
|
|
||||||
if (compressList.includes('gzip')) {
|
if (compressList.includes('gzip')) {
|
||||||
plugins.push(
|
plugins.push(
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
* Plugin to minimize and use ejs template syntax in index.html.
|
* Plugin to minimize and use ejs template syntax in index.html.
|
||||||
* https://github.com/anncwb/vite-plugin-html
|
* https://github.com/anncwb/vite-plugin-html
|
||||||
*/
|
*/
|
||||||
import type { Plugin } from 'vite';
|
import type { PluginOption } from 'vite';
|
||||||
import html from 'vite-plugin-html';
|
import { createHtmlPlugin } from 'vite-plugin-html';
|
||||||
import pkg from '../../../package.json';
|
import pkg from '../../../package.json';
|
||||||
import { GLOB_CONFIG_FILE_NAME } from '../../constant';
|
import { GLOB_CONFIG_FILE_NAME } from '../../constant';
|
||||||
|
|
||||||
|
|
@ -16,7 +16,7 @@ export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) {
|
||||||
return `${path || '/'}${GLOB_CONFIG_FILE_NAME}?v=${pkg.version}-${new Date().getTime()}`;
|
return `${path || '/'}${GLOB_CONFIG_FILE_NAME}?v=${pkg.version}-${new Date().getTime()}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const htmlPlugin: Plugin[] = html({
|
const htmlPlugin: PluginOption[] = createHtmlPlugin({
|
||||||
minify: isBuild,
|
minify: isBuild,
|
||||||
inject: {
|
inject: {
|
||||||
// Inject data into ejs template
|
// Inject data into ejs template
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import type { Plugin } from 'vite';
|
import { 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';
|
||||||
import purgeIcons from 'vite-plugin-purge-icons';
|
import purgeIcons from 'vite-plugin-purge-icons';
|
||||||
import windiCSS from 'vite-plugin-windicss';
|
import windiCSS from 'vite-plugin-windicss';
|
||||||
|
import VitePluginCertificate from 'vite-plugin-mkcert';
|
||||||
import vueSetupExtend from 'vite-plugin-vue-setup-extend';
|
import vueSetupExtend from 'vite-plugin-vue-setup-extend';
|
||||||
import { configHtmlPlugin } from './html';
|
import { configHtmlPlugin } from './html';
|
||||||
import { configPwaConfig } from './pwa';
|
import { configPwaConfig } from './pwa';
|
||||||
|
|
@ -24,13 +25,16 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
|
||||||
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE,
|
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE,
|
||||||
} = viteEnv;
|
} = viteEnv;
|
||||||
|
|
||||||
const vitePlugins: (Plugin | Plugin[])[] = [
|
const vitePlugins: (PluginOption | PluginOption[])[] = [
|
||||||
// have to
|
// have to
|
||||||
vue(),
|
vue(),
|
||||||
// have to
|
// have to
|
||||||
vueJsx(),
|
vueJsx(),
|
||||||
// support name
|
// support name
|
||||||
vueSetupExtend(),
|
vueSetupExtend(),
|
||||||
|
VitePluginCertificate({
|
||||||
|
source: 'coding',
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
// vite-plugin-windicss
|
// vite-plugin-windicss
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@
|
||||||
* Introduces component library styles on demand.
|
* Introduces component library styles on demand.
|
||||||
* https://github.com/anncwb/vite-plugin-style-import
|
* https://github.com/anncwb/vite-plugin-style-import
|
||||||
*/
|
*/
|
||||||
import styleImport from 'vite-plugin-style-import';
|
import { createStyleImportPlugin } from 'vite-plugin-style-import';
|
||||||
|
|
||||||
export function configStyleImportPlugin(_isBuild: boolean) {
|
export function configStyleImportPlugin(_isBuild: boolean) {
|
||||||
// if (!isBuild) {
|
// if (!isBuild) {
|
||||||
// return [];
|
// return [];
|
||||||
// }
|
// }
|
||||||
const styleImportPlugin = styleImport({
|
const styleImportPlugin = createStyleImportPlugin({
|
||||||
libs: [
|
libs: [
|
||||||
{
|
{
|
||||||
libraryName: 'ant-design-vue',
|
libraryName: 'ant-design-vue',
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,11 @@
|
||||||
* https://github.com/anncwb/vite-plugin-svg-icons
|
* https://github.com/anncwb/vite-plugin-svg-icons
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import SvgIconsPlugin from 'vite-plugin-svg-icons';
|
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
export function configSvgIconsPlugin(isBuild: boolean) {
|
export function configSvgIconsPlugin(isBuild: boolean) {
|
||||||
const svgIconsPlugin = SvgIconsPlugin({
|
const svgIconsPlugin = createSvgIconsPlugin({
|
||||||
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
|
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
|
||||||
svgoOptions: isBuild,
|
svgoOptions: isBuild,
|
||||||
// default
|
// default
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
* 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 type { Plugin } from 'vite';
|
import type { PluginOption } from 'vite';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import {
|
import {
|
||||||
viteThemePlugin,
|
viteThemePlugin,
|
||||||
|
|
@ -14,7 +14,7 @@ import {
|
||||||
import { getThemeColors, generateColors } from '../../config/themeConfig';
|
import { getThemeColors, generateColors } from '../../config/themeConfig';
|
||||||
import { generateModifyVars } from '../../generate/generateModifyVars';
|
import { generateModifyVars } from '../../generate/generateModifyVars';
|
||||||
|
|
||||||
export function configThemePlugin(isBuild: boolean): Plugin[] {
|
export function configThemePlugin(isBuild: boolean): PluginOption[] {
|
||||||
const colors = generateColors({
|
const colors = generateColors({
|
||||||
mixDarken,
|
mixDarken,
|
||||||
mixLighten,
|
mixLighten,
|
||||||
|
|
@ -85,5 +85,5 @@ export function configThemePlugin(isBuild: boolean): Plugin[] {
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
return plugin as unknown as Plugin[];
|
return plugin as unknown as PluginOption[];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
export default {
|
|
||||||
preset: 'ts-jest',
|
|
||||||
roots: ['<rootDir>/tests/'],
|
|
||||||
clearMocks: true,
|
|
||||||
moduleDirectories: ['node_modules', 'src'],
|
|
||||||
moduleFileExtensions: ['js', 'ts', 'vue', 'tsx', 'jsx', 'json', 'node'],
|
|
||||||
modulePaths: ['<rootDir>/src', '<rootDir>/node_modules'],
|
|
||||||
testMatch: [
|
|
||||||
'**/tests/**/*.[jt]s?(x)',
|
|
||||||
'**/?(*.)+(spec|test).[tj]s?(x)',
|
|
||||||
'(/__tests__/.*|(\\.|/)(test|spec))\\.(js|ts)$',
|
|
||||||
],
|
|
||||||
testPathIgnorePatterns: [
|
|
||||||
'<rootDir>/tests/server/',
|
|
||||||
'<rootDir>/tests/__mocks__/',
|
|
||||||
'/node_modules/',
|
|
||||||
],
|
|
||||||
transform: {
|
|
||||||
'^.+\\.tsx?$': 'ts-jest',
|
|
||||||
},
|
|
||||||
transformIgnorePatterns: ['<rootDir>/tests/__mocks__/', '/node_modules/'],
|
|
||||||
// A map from regular expressions to module names that allow to stub out resources with a single module
|
|
||||||
moduleNameMapper: {
|
|
||||||
'\\.(vs|fs|vert|frag|glsl|jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
|
|
||||||
'<rootDir>/tests/__mocks__/fileMock.ts',
|
|
||||||
'\\.(sass|s?css|less)$': '<rootDir>/tests/__mocks__/styleMock.ts',
|
|
||||||
'\\?worker$': '<rootDir>/tests/__mocks__/workerMock.ts',
|
|
||||||
'^/@/(.*)$': '<rootDir>/src/$1',
|
|
||||||
},
|
|
||||||
testEnvironment: 'jsdom',
|
|
||||||
verbose: true,
|
|
||||||
collectCoverage: false,
|
|
||||||
coverageDirectory: 'coverage',
|
|
||||||
collectCoverageFrom: ['src/**/*.{js,ts,vue}'],
|
|
||||||
coveragePathIgnorePatterns: ['^.+\\.d\\.ts$'],
|
|
||||||
};
|
|
||||||
|
|
@ -111,4 +111,12 @@ export default [
|
||||||
return resultSuccess(undefined, { message: 'Token has been destroyed' });
|
return resultSuccess(undefined, { message: 'Token has been destroyed' });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
url: '/basic-api/testRetry',
|
||||||
|
statusCode: 405,
|
||||||
|
method: 'get',
|
||||||
|
response: () => {
|
||||||
|
return resultError('Error!');
|
||||||
|
},
|
||||||
|
},
|
||||||
] as MockMethod[];
|
] as MockMethod[];
|
||||||
|
|
|
||||||
149
package.json
149
package.json
|
|
@ -25,7 +25,6 @@
|
||||||
"lint:stylelint": "stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
|
"lint:stylelint": "stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
|
||||||
"lint:lint-staged": "lint-staged",
|
"lint:lint-staged": "lint-staged",
|
||||||
"test:unit": "jest",
|
"test:unit": "jest",
|
||||||
"test:unit-coverage": "jest --coverage",
|
|
||||||
"test:gzip": "npx http-server dist --cors --gzip -c-1",
|
"test:gzip": "npx http-server dist --cors --gzip -c-1",
|
||||||
"test:br": "npx http-server dist --cors --brotli -c-1",
|
"test:br": "npx http-server dist --cors --brotli -c-1",
|
||||||
"reinstall": "rimraf pnpm-lock.yaml && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
|
"reinstall": "rimraf pnpm-lock.yaml && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
|
||||||
|
|
@ -34,117 +33,115 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/colors": "^6.0.0",
|
"@ant-design/colors": "^6.0.0",
|
||||||
"@ant-design/icons-vue": "^6.0.1",
|
"@ant-design/icons-vue": "^6.1.0",
|
||||||
"@iconify/iconify": "^2.1.0",
|
"@iconify/iconify": "^2.1.2",
|
||||||
"@logicflow/core": "^0.7.16",
|
"@logicflow/core": "^1.1.7",
|
||||||
"@logicflow/extension": "^0.7.16",
|
"@logicflow/extension": "^1.1.7",
|
||||||
"@vue/runtime-core": "^3.2.26",
|
"@vue/runtime-core": "^3.2.31",
|
||||||
"@vue/shared": "^3.2.26",
|
"@vue/shared": "^3.2.31",
|
||||||
"@vueuse/core": "^7.4.1",
|
"@vueuse/core": "^8.1.1",
|
||||||
"@vueuse/shared": "^7.4.1",
|
"@vueuse/shared": "^8.1.1",
|
||||||
"@zxcvbn-ts/core": "^1.2.0",
|
"@zxcvbn-ts/core": "^2.0.1",
|
||||||
"ant-design-vue": "3.0.0-beta.3",
|
"ant-design-vue": "3.1.0-rc.1",
|
||||||
"axios": "^0.24.0",
|
"axios": "^0.26.1",
|
||||||
"codemirror": "^5.65.0",
|
"codemirror": "^5.65.2",
|
||||||
"cropperjs": "^1.5.12",
|
"cropperjs": "^1.5.12",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"dayjs": "^1.10.7",
|
"dayjs": "^1.11.0",
|
||||||
"echarts": "^5.2.2",
|
"echarts": "^5.3.1",
|
||||||
"intro.js": "^4.3.0",
|
"intro.js": "^5.0.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"mockjs": "^1.1.0",
|
"mockjs": "^1.1.0",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"path-to-regexp": "^6.2.0",
|
"path-to-regexp": "^6.2.0",
|
||||||
"pinia": "2.0.9",
|
"pinia": "2.0.12",
|
||||||
"print-js": "^1.6.0",
|
"print-js": "^1.6.0",
|
||||||
"qrcode": "^1.5.0",
|
"qrcode": "^1.5.0",
|
||||||
"qs": "^6.10.2",
|
"qs": "^6.10.3",
|
||||||
"resize-observer-polyfill": "^1.5.1",
|
"resize-observer-polyfill": "^1.5.1",
|
||||||
"showdown": "^1.9.1",
|
"showdown": "^2.0.3",
|
||||||
"sortablejs": "^1.14.0",
|
"sortablejs": "^1.14.0",
|
||||||
"tinymce": "^5.10.2",
|
"tinymce": "^5.10.3",
|
||||||
"vditor": "^3.8.10",
|
"vditor": "^3.8.12",
|
||||||
"vue": "^3.2.26",
|
"vue": "^3.2.31",
|
||||||
"vue-i18n": "^9.1.9",
|
"vue-i18n": "^9.1.9",
|
||||||
"vue-json-pretty": "^1.8.2",
|
"vue-json-pretty": "^2.0.6",
|
||||||
"vue-router": "^4.0.12",
|
"vue-router": "^4.0.14",
|
||||||
"vue-types": "^4.1.1",
|
"vue-types": "^4.1.1",
|
||||||
"xlsx": "^0.17.4"
|
"xlsx": "^0.18.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^16.0.1",
|
"@commitlint/cli": "^16.2.3",
|
||||||
"@commitlint/config-conventional": "^16.0.0",
|
"@commitlint/config-conventional": "^16.2.1",
|
||||||
"@iconify/json": "^2.0.16",
|
"@iconify/json": "^2.1.17",
|
||||||
"@purge-icons/generated": "^0.7.0",
|
"@purge-icons/generated": "^0.8.1",
|
||||||
"@types/codemirror": "^5.60.5",
|
"@types/codemirror": "^5.60.5",
|
||||||
"@types/crypto-js": "^4.0.2",
|
"@types/crypto-js": "^4.1.1",
|
||||||
"@types/fs-extra": "^9.0.13",
|
"@types/fs-extra": "^9.0.13",
|
||||||
"@types/inquirer": "^8.1.3",
|
"@types/inquirer": "^8.2.0",
|
||||||
"@types/intro.js": "^3.0.2",
|
"@types/intro.js": "^3.0.2",
|
||||||
"@types/jest": "^27.0.3",
|
"@types/lodash-es": "^4.17.6",
|
||||||
"@types/lodash-es": "^4.17.5",
|
"@types/mockjs": "^1.0.6",
|
||||||
"@types/mockjs": "^1.0.4",
|
"@types/node": "^17.0.21",
|
||||||
"@types/node": "^17.0.5",
|
|
||||||
"@types/nprogress": "^0.2.0",
|
"@types/nprogress": "^0.2.0",
|
||||||
"@types/qrcode": "^1.4.2",
|
"@types/qrcode": "^1.4.2",
|
||||||
"@types/qs": "^6.9.7",
|
"@types/qs": "^6.9.7",
|
||||||
"@types/showdown": "^1.9.4",
|
"@types/showdown": "^1.9.4",
|
||||||
"@types/sortablejs": "^1.10.7",
|
"@types/sortablejs": "^1.10.7",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.8.1",
|
"@typescript-eslint/eslint-plugin": "^5.15.0",
|
||||||
"@typescript-eslint/parser": "^5.8.1",
|
"@typescript-eslint/parser": "^5.15.0",
|
||||||
"@vitejs/plugin-legacy": "^1.6.4",
|
"@vitejs/plugin-legacy": "^1.7.1",
|
||||||
"@vitejs/plugin-vue": "^2.0.1",
|
"@vitejs/plugin-vue": "^2.2.4",
|
||||||
"@vitejs/plugin-vue-jsx": "^1.3.3",
|
"@vitejs/plugin-vue-jsx": "^1.3.8",
|
||||||
"@vue/compiler-sfc": "3.2.26",
|
"@vue/compiler-sfc": "3.2.31",
|
||||||
"@vue/test-utils": "^2.0.0-rc.18",
|
"@vue/test-utils": "^2.0.0-rc.18",
|
||||||
"autoprefixer": "^10.4.0",
|
"autoprefixer": "^10.4.4",
|
||||||
"commitizen": "^4.2.4",
|
"commitizen": "^4.2.4",
|
||||||
"conventional-changelog-cli": "^2.2.2",
|
"conventional-changelog-cli": "^2.2.2",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"dotenv": "^10.0.0",
|
"dotenv": "^16.0.0",
|
||||||
"eslint": "^8.5.0",
|
"eslint": "^8.11.0",
|
||||||
"eslint-config-prettier": "^8.3.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
"eslint-define-config": "^1.2.1",
|
|
||||||
"eslint-plugin-jest": "^25.3.2",
|
|
||||||
"eslint-plugin-prettier": "^4.0.0",
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
"eslint-plugin-vue": "^8.2.0",
|
"eslint-plugin-vue": "^8.5.0",
|
||||||
"esno": "^0.13.0",
|
"esno": "^0.14.1",
|
||||||
"fs-extra": "^10.0.0",
|
"fs-extra": "^10.0.1",
|
||||||
"husky": "^7.0.4",
|
"husky": "^7.0.4",
|
||||||
"inquirer": "^8.2.0",
|
"inquirer": "^8.2.1",
|
||||||
"jest": "^27.4.5",
|
|
||||||
"less": "^4.1.2",
|
"less": "^4.1.2",
|
||||||
"lint-staged": "12.1.4",
|
"lint-staged": "12.3.7",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"postcss": "^8.4.5",
|
"picocolors": "^1.0.0",
|
||||||
|
"postcss": "^8.4.12",
|
||||||
"postcss-html": "^1.3.0",
|
"postcss-html": "^1.3.0",
|
||||||
"postcss-less": "^5.0.0",
|
"postcss-less": "^6.0.0",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.6.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"rollup-plugin-visualizer": "^5.5.2",
|
"rollup": "^2.70.1",
|
||||||
"stylelint": "^14.2.0",
|
"rollup-plugin-visualizer": "^5.6.0",
|
||||||
"stylelint-config-html": "^1.0.0",
|
"stylelint": "^14.6.0",
|
||||||
"stylelint-config-prettier": "^9.0.3",
|
"stylelint-config-prettier": "^9.0.3",
|
||||||
"stylelint-config-recommended": "^6.0.0",
|
"stylelint-config-recommended": "^7.0.0",
|
||||||
"stylelint-config-standard": "^24.0.0",
|
"stylelint-config-recommended-vue": "^1.3.0",
|
||||||
|
"stylelint-config-standard": "^25.0.0",
|
||||||
"stylelint-order": "^5.0.0",
|
"stylelint-order": "^5.0.0",
|
||||||
"ts-jest": "^27.1.2",
|
"ts-node": "^10.7.0",
|
||||||
"ts-node": "^10.4.0",
|
"typescript": "^4.6.2",
|
||||||
"typescript": "^4.5.4",
|
"vite": "^2.9.0-beta.3",
|
||||||
"vite": "^2.7.8",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
"vite-plugin-compression": "^0.4.0",
|
"vite-plugin-html": "^3.2.0",
|
||||||
"vite-plugin-html": "^2.1.2",
|
"vite-plugin-imagemin": "^0.6.1",
|
||||||
"vite-plugin-imagemin": "^0.5.1",
|
"vite-plugin-mkcert": "^1.6.0",
|
||||||
"vite-plugin-mock": "^2.9.6",
|
"vite-plugin-mock": "^2.9.6",
|
||||||
"vite-plugin-purge-icons": "^0.7.0",
|
"vite-plugin-purge-icons": "^0.8.1",
|
||||||
"vite-plugin-pwa": "^0.11.12",
|
"vite-plugin-pwa": "^0.11.13",
|
||||||
"vite-plugin-style-import": "^1.4.1",
|
"vite-plugin-style-import": "^2.0.0",
|
||||||
"vite-plugin-svg-icons": "^1.0.5",
|
"vite-plugin-svg-icons": "^2.0.1",
|
||||||
"vite-plugin-theme": "^0.8.1",
|
"vite-plugin-theme": "^0.8.1",
|
||||||
"vite-plugin-vue-setup-extend": "^0.3.0",
|
"vite-plugin-vue-setup-extend": "^0.4.0",
|
||||||
"vite-plugin-windicss": "^1.6.1",
|
"vite-plugin-windicss": "^1.8.3",
|
||||||
"vue-eslint-parser": "^8.0.1",
|
"vue-eslint-parser": "^8.3.0",
|
||||||
"vue-tsc": "^0.30.1"
|
"vue-tsc": "^0.33.2"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"bin-wrapper": "npm:bin-wrapper-china",
|
"bin-wrapper": "npm:bin-wrapper-china",
|
||||||
|
|
|
||||||
6673
pnpm-lock.yaml
6673
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
|
@ -8,6 +8,7 @@ enum Api {
|
||||||
Logout = '/logout',
|
Logout = '/logout',
|
||||||
GetUserInfo = '/getUserInfo',
|
GetUserInfo = '/getUserInfo',
|
||||||
GetPermCode = '/getPermCode',
|
GetPermCode = '/getPermCode',
|
||||||
|
TestRetry = '/testRetry',
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -39,3 +40,16 @@ export function getPermCode() {
|
||||||
export function doLogout() {
|
export function doLogout() {
|
||||||
return defHttp.get({ url: Api.Logout });
|
return defHttp.get({ url: Api.Logout });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function testRetry() {
|
||||||
|
return defHttp.get(
|
||||||
|
{ url: Api.TestRetry },
|
||||||
|
{
|
||||||
|
retryRequest: {
|
||||||
|
isOpenRetry: true,
|
||||||
|
count: 5,
|
||||||
|
waitTime: 1000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@
|
||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
placement="bottomCenter"
|
placement="bottom"
|
||||||
:trigger="['click']"
|
:trigger="['click']"
|
||||||
:dropMenuList="localeList"
|
:dropMenuList="localeList"
|
||||||
:selectedKeys="selectedKeys"
|
:selectedKeys="selectedKeys"
|
||||||
@menuEvent="handleMenuEvent"
|
@menu-event="handleMenuEvent"
|
||||||
overlayClassName="app-locale-picker-overlay"
|
overlayClassName="app-locale-picker-overlay"
|
||||||
>
|
>
|
||||||
<span class="cursor-pointer flex items-center">
|
<span class="cursor-pointer flex items-center">
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
<div class="p-4 mb-2 bg-white">
|
<div class="p-4 mb-2 bg-white">
|
||||||
<BasicForm @register="registerForm" />
|
<BasicForm @register="registerForm" />
|
||||||
</div>
|
</div>
|
||||||
{{ sliderProp.width }}
|
|
||||||
<div class="p-2 bg-white">
|
<div class="p-2 bg-white">
|
||||||
<List
|
<List
|
||||||
:grid="{ gutter: 5, xs: 1, sm: 2, md: 4, lg: 4, xl: 6, xxl: grid }"
|
:grid="{ gutter: 5, xs: 1, sm: 2, md: 4, lg: 4, xl: 6, xxl: grid }"
|
||||||
|
|
@ -39,7 +38,7 @@
|
||||||
<Image :src="item.imgs[0]" />
|
<Image :src="item.imgs[0]" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template class="ant-card-actions" #actions>
|
<template #actions>
|
||||||
<!-- <SettingOutlined key="setting" />-->
|
<!-- <SettingOutlined key="setting" />-->
|
||||||
<EditOutlined key="edit" />
|
<EditOutlined key="edit" />
|
||||||
<Dropdown
|
<Dropdown
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@
|
||||||
width: `${width}px`,
|
width: `${width}px`,
|
||||||
left: `${left + 1}px`,
|
left: `${left + 1}px`,
|
||||||
top: `${top + 1}px`,
|
top: `${top + 1}px`,
|
||||||
|
zIndex: 9999,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
<CopperModal
|
<CopperModal
|
||||||
@register="register"
|
@register="register"
|
||||||
@uploadSuccess="handleUploadSuccess"
|
@upload-success="handleUploadSuccess"
|
||||||
:uploadApi="uploadApi"
|
:uploadApi="uploadApi"
|
||||||
:src="sourceValue"
|
:src="sourceValue"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import xlsx from 'xlsx';
|
import * as xlsx from 'xlsx';
|
||||||
import type { WorkBook } from 'xlsx';
|
import type { WorkBook } from 'xlsx';
|
||||||
import type { JsonToSheet, AoAToSheet } from './typing';
|
import type { JsonToSheet, AoAToSheet } from './typing';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, ref, unref } from 'vue';
|
import { defineComponent, ref, unref } from 'vue';
|
||||||
import XLSX from 'xlsx';
|
import * as XLSX from 'xlsx';
|
||||||
import { dateUtil } from '/@/utils/dateUtil';
|
import { dateUtil } from '/@/utils/dateUtil';
|
||||||
|
|
||||||
import type { ExcelData } from './typing';
|
import type { ExcelData } from './typing';
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ export { useForm } from './src/hooks/useForm';
|
||||||
export { default as ApiSelect } from './src/components/ApiSelect.vue';
|
export { default as ApiSelect } from './src/components/ApiSelect.vue';
|
||||||
export { default as RadioButtonGroup } from './src/components/RadioButtonGroup.vue';
|
export { default as RadioButtonGroup } from './src/components/RadioButtonGroup.vue';
|
||||||
export { default as ApiTreeSelect } from './src/components/ApiTreeSelect.vue';
|
export { default as ApiTreeSelect } from './src/components/ApiTreeSelect.vue';
|
||||||
|
export { default as ApiTree } from './src/components/ApiTree.vue';
|
||||||
export { default as ApiRadioGroup } from './src/components/ApiRadioGroup.vue';
|
export { default as ApiRadioGroup } from './src/components/ApiRadioGroup.vue';
|
||||||
export { default as ApiCascader } from './src/components/ApiCascader.vue';
|
export { default as ApiCascader } from './src/components/ApiCascader.vue';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import {
|
||||||
import ApiRadioGroup from './components/ApiRadioGroup.vue';
|
import ApiRadioGroup from './components/ApiRadioGroup.vue';
|
||||||
import RadioButtonGroup from './components/RadioButtonGroup.vue';
|
import RadioButtonGroup from './components/RadioButtonGroup.vue';
|
||||||
import ApiSelect from './components/ApiSelect.vue';
|
import ApiSelect from './components/ApiSelect.vue';
|
||||||
|
import ApiTree from './components/ApiTree.vue';
|
||||||
import ApiTreeSelect from './components/ApiTreeSelect.vue';
|
import ApiTreeSelect from './components/ApiTreeSelect.vue';
|
||||||
import ApiCascader from './components/ApiCascader.vue';
|
import ApiCascader from './components/ApiCascader.vue';
|
||||||
import { BasicUpload } from '/@/components/Upload';
|
import { BasicUpload } from '/@/components/Upload';
|
||||||
|
|
@ -43,6 +44,7 @@ componentMap.set('AutoComplete', AutoComplete);
|
||||||
|
|
||||||
componentMap.set('Select', Select);
|
componentMap.set('Select', Select);
|
||||||
componentMap.set('ApiSelect', ApiSelect);
|
componentMap.set('ApiSelect', ApiSelect);
|
||||||
|
componentMap.set('ApiTree', ApiTree);
|
||||||
componentMap.set('TreeSelect', TreeSelect);
|
componentMap.set('TreeSelect', TreeSelect);
|
||||||
componentMap.set('ApiTreeSelect', ApiTreeSelect);
|
componentMap.set('ApiTreeSelect', ApiTreeSelect);
|
||||||
componentMap.set('ApiRadioGroup', ApiRadioGroup);
|
componentMap.set('ApiRadioGroup', ApiRadioGroup);
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
import { get, omit } from 'lodash-es';
|
import { get, omit } from 'lodash-es';
|
||||||
import { useRuleFormItem } from '/@/hooks/component/useFormItem';
|
import { useRuleFormItem } from '/@/hooks/component/useFormItem';
|
||||||
import { LoadingOutlined } from '@ant-design/icons-vue';
|
import { LoadingOutlined } from '@ant-design/icons-vue';
|
||||||
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
interface Option {
|
interface Option {
|
||||||
value: string;
|
value: string;
|
||||||
label: string;
|
label: string;
|
||||||
|
|
@ -76,7 +76,7 @@
|
||||||
const loading = ref<boolean>(false);
|
const loading = ref<boolean>(false);
|
||||||
const emitData = ref<any[]>([]);
|
const emitData = ref<any[]>([]);
|
||||||
const isFirstLoad = ref(true);
|
const isFirstLoad = ref(true);
|
||||||
|
const { t } = useI18n();
|
||||||
// Embedded in the form, just use the hook binding to perform form verification
|
// Embedded in the form, just use the hook binding to perform form verification
|
||||||
const [state] = useRuleFormItem(props, 'value', 'change', emitData);
|
const [state] = useRuleFormItem(props, 'value', 'change', emitData);
|
||||||
|
|
||||||
|
|
@ -188,6 +188,7 @@
|
||||||
state,
|
state,
|
||||||
options,
|
options,
|
||||||
loading,
|
loading,
|
||||||
|
t,
|
||||||
handleChange,
|
handleChange,
|
||||||
loadData,
|
loadData,
|
||||||
handleRenderDisplay,
|
handleRenderDisplay,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
<template>
|
||||||
|
<a-tree v-bind="getAttrs" @change="handleChange">
|
||||||
|
<template #[item]="data" v-for="item in Object.keys($slots)">
|
||||||
|
<slot :name="item" v-bind="data || {}"></slot>
|
||||||
|
</template>
|
||||||
|
<template #suffixIcon v-if="loading">
|
||||||
|
<LoadingOutlined spin />
|
||||||
|
</template>
|
||||||
|
</a-tree>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { computed, defineComponent, watch, ref, onMounted, unref } from 'vue';
|
||||||
|
import { Tree } from 'ant-design-vue';
|
||||||
|
import { isArray, isFunction } from '/@/utils/is';
|
||||||
|
import { get } from 'lodash-es';
|
||||||
|
import { propTypes } from '/@/utils/propTypes';
|
||||||
|
import { LoadingOutlined } from '@ant-design/icons-vue';
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'ApiTree',
|
||||||
|
components: { ATree: Tree, LoadingOutlined },
|
||||||
|
props: {
|
||||||
|
api: { type: Function as PropType<(arg?: Recordable) => Promise<Recordable>> },
|
||||||
|
params: { type: Object },
|
||||||
|
immediate: { type: Boolean, default: true },
|
||||||
|
resultField: propTypes.string.def(''),
|
||||||
|
},
|
||||||
|
emits: ['options-change', 'change'],
|
||||||
|
setup(props, { attrs, emit }) {
|
||||||
|
const treeData = ref<Recordable[]>([]);
|
||||||
|
const isFirstLoaded = ref<Boolean>(false);
|
||||||
|
const loading = ref(false);
|
||||||
|
const getAttrs = computed(() => {
|
||||||
|
return {
|
||||||
|
...(props.api ? { treeData: unref(treeData) } : {}),
|
||||||
|
...attrs,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleChange(...args) {
|
||||||
|
emit('change', ...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.params,
|
||||||
|
() => {
|
||||||
|
!unref(isFirstLoaded) && fetch();
|
||||||
|
},
|
||||||
|
{ deep: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.immediate,
|
||||||
|
(v) => {
|
||||||
|
v && !isFirstLoaded.value && fetch();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
props.immediate && fetch();
|
||||||
|
});
|
||||||
|
|
||||||
|
async function fetch() {
|
||||||
|
const { api } = props;
|
||||||
|
if (!api || !isFunction(api)) return;
|
||||||
|
loading.value = true;
|
||||||
|
treeData.value = [];
|
||||||
|
let result;
|
||||||
|
try {
|
||||||
|
result = await api(props.params);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
loading.value = false;
|
||||||
|
if (!result) return;
|
||||||
|
if (!isArray(result)) {
|
||||||
|
result = get(result, props.resultField);
|
||||||
|
}
|
||||||
|
treeData.value = (result as Recordable[]) || [];
|
||||||
|
isFirstLoaded.value = true;
|
||||||
|
emit('options-change', treeData.value);
|
||||||
|
}
|
||||||
|
return { getAttrs, loading, handleChange };
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -2,7 +2,7 @@ import type { ComputedRef, Ref } from 'vue';
|
||||||
import type { FormProps, FormSchema, FormActionType } from '../types/form';
|
import type { FormProps, FormSchema, FormActionType } from '../types/form';
|
||||||
import type { NamePath } from 'ant-design-vue/lib/form/interface';
|
import type { NamePath } from 'ant-design-vue/lib/form/interface';
|
||||||
import { unref, toRaw, nextTick } from 'vue';
|
import { unref, toRaw, nextTick } from 'vue';
|
||||||
import { isArray, isFunction, isObject, isString } from '/@/utils/is';
|
import { isArray, isFunction, isNullOrUnDef, isObject, isString } from '/@/utils/is';
|
||||||
import { deepMerge } from '/@/utils';
|
import { deepMerge } from '/@/utils';
|
||||||
import { dateItemType, handleInputNumberValue, defaultValueComponents } from '../helper';
|
import { dateItemType, handleInputNumberValue, defaultValueComponents } from '../helper';
|
||||||
import { dateUtil } from '/@/utils/dateUtil';
|
import { dateUtil } from '/@/utils/dateUtil';
|
||||||
|
|
@ -132,11 +132,14 @@ export function useFormEvents({
|
||||||
if (!prefixField || index === -1 || first) {
|
if (!prefixField || index === -1 || first) {
|
||||||
first ? schemaList.unshift(schema) : schemaList.push(schema);
|
first ? schemaList.unshift(schema) : schemaList.push(schema);
|
||||||
schemaRef.value = schemaList;
|
schemaRef.value = schemaList;
|
||||||
|
_setDefaultValue(schema);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
schemaList.splice(index + 1, 0, schema);
|
schemaList.splice(index + 1, 0, schema);
|
||||||
}
|
}
|
||||||
|
_setDefaultValue(schema);
|
||||||
|
|
||||||
schemaRef.value = schemaList;
|
schemaRef.value = schemaList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -192,9 +195,34 @@ export function useFormEvents({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
_setDefaultValue(schema);
|
||||||
|
|
||||||
schemaRef.value = uniqBy(schema, 'field');
|
schemaRef.value = uniqBy(schema, 'field');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _setDefaultValue(data: FormSchema | FormSchema[]) {
|
||||||
|
let schemas: FormSchema[] = [];
|
||||||
|
if (isObject(data)) {
|
||||||
|
schemas.push(data as FormSchema);
|
||||||
|
}
|
||||||
|
if (isArray(data)) {
|
||||||
|
schemas = [...data];
|
||||||
|
}
|
||||||
|
|
||||||
|
const obj: Recordable = {};
|
||||||
|
schemas.forEach((item) => {
|
||||||
|
if (
|
||||||
|
item.component != 'Divider' &&
|
||||||
|
Reflect.has(item, 'field') &&
|
||||||
|
item.field &&
|
||||||
|
!isNullOrUnDef(item.defaultValue)
|
||||||
|
) {
|
||||||
|
obj[item.field] = item.defaultValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setFieldsValue(obj);
|
||||||
|
}
|
||||||
|
|
||||||
function getFieldsValue(): Recordable {
|
function getFieldsValue(): Recordable {
|
||||||
const formEl = unref(formElRef);
|
const formEl = unref(formElRef);
|
||||||
if (!formEl) return {};
|
if (!formEl) return {};
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,43 @@ interface UseFormValuesContext {
|
||||||
getProps: ComputedRef<FormProps>;
|
getProps: ComputedRef<FormProps>;
|
||||||
formModel: Recordable;
|
formModel: Recordable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @desription deconstruct array-link key. This method will mutate the target.
|
||||||
|
*/
|
||||||
|
function tryDeconstructArray(key: string, value: any, target: Recordable) {
|
||||||
|
const pattern = /^\[(.+)\]$/;
|
||||||
|
if (pattern.test(key)) {
|
||||||
|
const match = key.match(pattern);
|
||||||
|
if (match && match[1]) {
|
||||||
|
const keys = match[1].split(',');
|
||||||
|
value = Array.isArray(value) ? value : [value];
|
||||||
|
keys.forEach((k, index) => {
|
||||||
|
set(target, k.trim(), value[index]);
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @desription deconstruct object-link key. This method will mutate the target.
|
||||||
|
*/
|
||||||
|
function tryDeconstructObject(key: string, value: any, target: Recordable) {
|
||||||
|
const pattern = /^\{(.+)\}$/;
|
||||||
|
if (pattern.test(key)) {
|
||||||
|
const match = key.match(pattern);
|
||||||
|
if (match && match[1]) {
|
||||||
|
const keys = match[1].split(',');
|
||||||
|
value = isObject(value) ? value : {};
|
||||||
|
keys.forEach((k) => {
|
||||||
|
set(target, k.trim(), value[k.trim()]);
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function useFormValues({
|
export function useFormValues({
|
||||||
defaultValueRef,
|
defaultValueRef,
|
||||||
getSchema,
|
getSchema,
|
||||||
|
|
@ -41,8 +78,11 @@ export function useFormValues({
|
||||||
if (isString(value)) {
|
if (isString(value)) {
|
||||||
value = value.trim();
|
value = value.trim();
|
||||||
}
|
}
|
||||||
|
if (!tryDeconstructArray(key, value, res) && !tryDeconstructObject(key, value, res)) {
|
||||||
|
// 没有解构成功的,按原样赋值
|
||||||
set(res, key, value);
|
set(res, key, value);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return handleRangeTimeValue(res);
|
return handleRangeTimeValue(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@ export type ComponentType =
|
||||||
| 'Select'
|
| 'Select'
|
||||||
| 'ApiSelect'
|
| 'ApiSelect'
|
||||||
| 'TreeSelect'
|
| 'TreeSelect'
|
||||||
|
| 'ApiTree'
|
||||||
| 'ApiTreeSelect'
|
| 'ApiTreeSelect'
|
||||||
| 'ApiRadioGroup'
|
| 'ApiRadioGroup'
|
||||||
| 'RadioButtonGroup'
|
| 'RadioButtonGroup'
|
||||||
|
|
|
||||||
|
|
@ -31,18 +31,7 @@
|
||||||
v-for="icon in getPaginationList"
|
v-for="icon in getPaginationList"
|
||||||
:key="icon"
|
:key="icon"
|
||||||
:class="currentSelect === icon ? 'border border-primary' : ''"
|
:class="currentSelect === icon ? 'border border-primary' : ''"
|
||||||
class="
|
class="p-2 w-1/8 cursor-pointer mr-1 mt-1 flex justify-center items-center border border-solid hover:border-primary"
|
||||||
p-2
|
|
||||||
w-1/8
|
|
||||||
cursor-pointer
|
|
||||||
mr-1
|
|
||||||
mt-1
|
|
||||||
flex
|
|
||||||
justify-center
|
|
||||||
items-center
|
|
||||||
border border-solid
|
|
||||||
hover:border-primary
|
|
||||||
"
|
|
||||||
@click="handleClick(icon)"
|
@click="handleClick(icon)"
|
||||||
:title="icon"
|
:title="icon"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
:openKeys="getOpenKeys"
|
:openKeys="getOpenKeys"
|
||||||
:inlineIndent="inlineIndent"
|
:inlineIndent="inlineIndent"
|
||||||
:theme="theme"
|
:theme="theme"
|
||||||
@openChange="handleOpenChange"
|
@open-change="handleOpenChange"
|
||||||
:class="getMenuClass"
|
:class="getMenuClass"
|
||||||
@click="handleMenuClick"
|
@click="handleMenuClick"
|
||||||
:subMenuOpenDelay="0.2"
|
:subMenuOpenDelay="0.2"
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
:overlayClassName="`${prefixCls}-menu-popover`"
|
:overlayClassName="`${prefixCls}-menu-popover`"
|
||||||
v-else
|
v-else
|
||||||
:visible="getIsOpend"
|
:visible="getIsOpend"
|
||||||
@visibleChange="handleVisibleChange"
|
@visible-change="handleVisibleChange"
|
||||||
:overlayStyle="getOverlayStyle"
|
:overlayStyle="getOverlayStyle"
|
||||||
:align="{ offset: [0, 0] }"
|
:align="{ offset: [0, 0] }"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
display: block;
|
display: block;
|
||||||
width: 2px;
|
width: 2px;
|
||||||
background-color: @primary-color;
|
|
||||||
content: '';
|
content: '';
|
||||||
|
background-color: @primary-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -45,8 +45,8 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
right: 18px;
|
right: 18px;
|
||||||
transform: translateY(-50%) rotate(-90deg);
|
|
||||||
transition: transform @transition-time @ease-in-out;
|
transition: transform @transition-time @ease-in-out;
|
||||||
|
transform: translateY(-50%) rotate(-90deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,12 +128,12 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
font-size: @font-size-base;
|
font-size: @font-size-base;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
outline: none;
|
outline: none;
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:active {
|
&:active {
|
||||||
|
|
@ -178,8 +178,8 @@
|
||||||
&-vertical &-submenu-collapse {
|
&-vertical &-submenu-collapse {
|
||||||
.@{submenu-popup-prefix-cls} {
|
.@{submenu-popup-prefix-cls} {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
.@{menu-prefix-cls}-submenu-collapsed-show-tit {
|
.@{menu-prefix-cls}-submenu-collapsed-show-tit {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
@ -244,8 +244,8 @@
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 3px;
|
width: 3px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: @primary-color;
|
|
||||||
content: '';
|
content: '';
|
||||||
|
background-color: @primary-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -276,8 +276,8 @@
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 3px;
|
width: 3px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: @primary-color;
|
|
||||||
content: '';
|
content: '';
|
||||||
|
background-color: @primary-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.@{menu-prefix-cls}-submenu-collapse {
|
.@{menu-prefix-cls}-submenu-collapse {
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,12 @@
|
||||||
<template #[item]="data" v-for="item in Object.keys($slots)" :key="item">
|
<template #[item]="data" v-for="item in Object.keys($slots)" :key="item">
|
||||||
<slot :name="item" v-bind="data || {}"></slot>
|
<slot :name="item" v-bind="data || {}"></slot>
|
||||||
</template>
|
</template>
|
||||||
|
<template #headerCell="{ column }">
|
||||||
<template #[`header-${column.dataIndex}`] v-for="(column, index) in columns" :key="index">
|
|
||||||
<HeaderCell :column="column" />
|
<HeaderCell :column="column" />
|
||||||
</template>
|
</template>
|
||||||
|
<!-- <template #[`header-${column.dataIndex}`] v-for="(column, index) in columns" :key="index">-->
|
||||||
|
<!-- <HeaderCell :column="column" />-->
|
||||||
|
<!-- </template>-->
|
||||||
</Table>
|
</Table>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
const { prefixCls } = useDesign('basic-table-header-cell');
|
const { prefixCls } = useDesign('basic-table-header-cell');
|
||||||
|
|
||||||
const getIsEdit = computed(() => !!props.column?.edit);
|
const getIsEdit = computed(() => !!props.column?.edit);
|
||||||
const getTitle = computed(() => props.column?.customTitle);
|
const getTitle = computed(() => props.column?.customTitle || props.column?.title);
|
||||||
const getHelpMessage = computed(() => props.column?.helpMessage);
|
const getHelpMessage = computed(() => props.column?.helpMessage);
|
||||||
|
|
||||||
return { prefixCls, getIsEdit, getTitle, getHelpMessage };
|
return { prefixCls, getIsEdit, getTitle, getHelpMessage };
|
||||||
|
|
|
||||||
|
|
@ -1,40 +1,4 @@
|
||||||
<template>
|
<script lang="tsx">
|
||||||
<div :class="prefixCls">
|
|
||||||
<div
|
|
||||||
v-show="!isEdit"
|
|
||||||
:class="{ [`${prefixCls}__normal`]: true, 'ellipsis-cell': column.ellipsis }"
|
|
||||||
@click="handleEdit"
|
|
||||||
>
|
|
||||||
<div class="cell-content" :title="column.ellipsis ? getValues ?? '' : ''">
|
|
||||||
{{ getValues || getValues === 0 ? getValues : ' ' }}
|
|
||||||
</div>
|
|
||||||
<FormOutlined :class="`${prefixCls}__normal-icon`" v-if="!column.editRow" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<a-spin v-if="isEdit" :spinning="spinning">
|
|
||||||
<div :class="`${prefixCls}__wrapper`" v-click-outside="onClickOutside">
|
|
||||||
<CellComponent
|
|
||||||
v-bind="getComponentProps"
|
|
||||||
:component="getComponent"
|
|
||||||
:style="getWrapperStyle"
|
|
||||||
:popoverVisible="getRuleVisible"
|
|
||||||
:rule="getRule"
|
|
||||||
:ruleMessage="ruleMessage"
|
|
||||||
:class="getWrapperClass"
|
|
||||||
ref="elRef"
|
|
||||||
@change="handleChange"
|
|
||||||
@options-change="handleOptionsChange"
|
|
||||||
@pressEnter="handleEnter"
|
|
||||||
/>
|
|
||||||
<div :class="`${prefixCls}__action`" v-if="!getRowEditable">
|
|
||||||
<CheckOutlined :class="[`${prefixCls}__icon`, 'mx-2']" @click="handleSubmitClick" />
|
|
||||||
<CloseOutlined :class="`${prefixCls}__icon `" @click="handleCancel" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a-spin>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script lang="ts">
|
|
||||||
import type { CSSProperties, PropType } from 'vue';
|
import type { CSSProperties, PropType } from 'vue';
|
||||||
import { computed, defineComponent, nextTick, ref, toRaw, unref, watchEffect } from 'vue';
|
import { computed, defineComponent, nextTick, ref, toRaw, unref, watchEffect } from 'vue';
|
||||||
import type { BasicColumn } from '../../types/table';
|
import type { BasicColumn } from '../../types/table';
|
||||||
|
|
@ -56,7 +20,7 @@
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'EditableCell',
|
name: 'EditableCell',
|
||||||
components: { FormOutlined, CloseOutlined, CheckOutlined, CellComponent, ASpin: Spin },
|
components: { FormOutlined, CloseOutlined, CheckOutlined, CellComponent, Spin },
|
||||||
directives: {
|
directives: {
|
||||||
clickOutside,
|
clickOutside,
|
||||||
},
|
},
|
||||||
|
|
@ -100,13 +64,6 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
const getComponentProps = computed(() => {
|
const getComponentProps = computed(() => {
|
||||||
const compProps = props.column?.editComponentProps ?? {};
|
|
||||||
const component = unref(getComponent);
|
|
||||||
const apiSelectProps: Recordable = {};
|
|
||||||
if (component === 'ApiSelect') {
|
|
||||||
apiSelectProps.cache = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const isCheckValue = unref(getIsCheckComp);
|
const isCheckValue = unref(getIsCheckComp);
|
||||||
|
|
||||||
const valueField = isCheckValue ? 'checked' : 'value';
|
const valueField = isCheckValue ? 'checked' : 'value';
|
||||||
|
|
@ -114,19 +71,30 @@
|
||||||
|
|
||||||
const value = isCheckValue ? (isNumber(val) && isBoolean(val) ? val : !!val) : val;
|
const value = isCheckValue ? (isNumber(val) && isBoolean(val) ? val : !!val) : val;
|
||||||
|
|
||||||
|
let compProps = props.column?.editComponentProps ?? {};
|
||||||
|
const { record, column, index } = props;
|
||||||
|
|
||||||
|
if (isFunction(compProps)) {
|
||||||
|
compProps = compProps({ text: val, record, column, index }) ?? {};
|
||||||
|
}
|
||||||
|
const component = unref(getComponent);
|
||||||
|
const apiSelectProps: Recordable = {};
|
||||||
|
if (component === 'ApiSelect') {
|
||||||
|
apiSelectProps.cache = true;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
size: 'small',
|
size: 'small',
|
||||||
getPopupContainer: () => unref(table?.wrapRef.value) ?? document.body,
|
getPopupContainer: () => unref(table?.wrapRef.value) ?? document.body,
|
||||||
getCalendarContainer: () => unref(table?.wrapRef.value) ?? document.body,
|
|
||||||
placeholder: createPlaceholderMessage(unref(getComponent)),
|
placeholder: createPlaceholderMessage(unref(getComponent)),
|
||||||
...apiSelectProps,
|
...apiSelectProps,
|
||||||
...omit(compProps, 'onChange'),
|
...omit(compProps, 'onChange'),
|
||||||
[valueField]: value,
|
[valueField]: value,
|
||||||
};
|
} as any;
|
||||||
});
|
});
|
||||||
|
|
||||||
const getValues = computed(() => {
|
const getValues = computed(() => {
|
||||||
const { editComponentProps, editValueMap } = props.column;
|
const { editValueMap } = props.column;
|
||||||
|
|
||||||
const value = unref(currentValueRef);
|
const value = unref(currentValueRef);
|
||||||
|
|
||||||
|
|
@ -139,7 +107,8 @@
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const options: LabelValueOptions = editComponentProps?.options ?? (unref(optionsRef) || []);
|
const options: LabelValueOptions =
|
||||||
|
unref(getComponentProps)?.options ?? (unref(optionsRef) || []);
|
||||||
const option = options.find((item) => `${item.value}` === `${value}`);
|
const option = options.find((item) => `${item.value}` === `${value}`);
|
||||||
|
|
||||||
return option?.label ?? value;
|
return option?.label ?? value;
|
||||||
|
|
@ -199,7 +168,7 @@
|
||||||
} else if (isString(e) || isBoolean(e) || isNumber(e)) {
|
} else if (isString(e) || isBoolean(e) || isNumber(e)) {
|
||||||
currentValueRef.value = e;
|
currentValueRef.value = e;
|
||||||
}
|
}
|
||||||
const onChange = props.column?.editComponentProps?.onChange;
|
const onChange = unref(getComponentProps)?.onChange;
|
||||||
if (onChange && isFunction(onChange)) onChange(...arguments);
|
if (onChange && isFunction(onChange)) onChange(...arguments);
|
||||||
|
|
||||||
table.emit?.('edit-change', {
|
table.emit?.('edit-change', {
|
||||||
|
|
@ -267,7 +236,7 @@
|
||||||
result = await beforeEditSubmit({
|
result = await beforeEditSubmit({
|
||||||
record: pick(record, keys),
|
record: pick(record, keys),
|
||||||
index,
|
index,
|
||||||
key: key as string,
|
key: dataKey as string,
|
||||||
value,
|
value,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -283,7 +252,7 @@
|
||||||
|
|
||||||
set(record, dataKey, value);
|
set(record, dataKey, value);
|
||||||
//const record = await table.updateTableData(index, dataKey, value);
|
//const record = await table.updateTableData(index, dataKey, value);
|
||||||
needEmit && table.emit?.('edit-end', { record, index, key, value });
|
needEmit && table.emit?.('edit-end', { record, index, key: dataKey, value });
|
||||||
isEdit.value = false;
|
isEdit.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -324,7 +293,7 @@
|
||||||
|
|
||||||
// only ApiSelect or TreeSelect
|
// only ApiSelect or TreeSelect
|
||||||
function handleOptionsChange(options: LabelValueOptions) {
|
function handleOptionsChange(options: LabelValueOptions) {
|
||||||
const { replaceFields } = props.column?.editComponentProps ?? {};
|
const { replaceFields } = unref(getComponentProps);
|
||||||
const component = unref(getComponent);
|
const component = unref(getComponent);
|
||||||
if (component === 'ApiTreeSelect') {
|
if (component === 'ApiTreeSelect') {
|
||||||
const { title = 'title', value = 'value', children = 'children' } = replaceFields || {};
|
const { title = 'title', value = 'value', children = 'children' } = replaceFields || {};
|
||||||
|
|
@ -357,7 +326,7 @@
|
||||||
|
|
||||||
if (props.column.dataIndex) {
|
if (props.column.dataIndex) {
|
||||||
if (!props.record.editValueRefs) props.record.editValueRefs = {};
|
if (!props.record.editValueRefs) props.record.editValueRefs = {};
|
||||||
props.record.editValueRefs[props.column.dataIndex] = currentValueRef;
|
props.record.editValueRefs[props.column.dataIndex as any] = currentValueRef;
|
||||||
}
|
}
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
props.record.onCancelEdit = () => {
|
props.record.onCancelEdit = () => {
|
||||||
|
|
@ -400,6 +369,59 @@
|
||||||
spinning,
|
spinning,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div class={this.prefixCls}>
|
||||||
|
<div
|
||||||
|
v-show={!this.isEdit}
|
||||||
|
class={{ [`${this.prefixCls}__normal`]: true, 'ellipsis-cell': this.column.ellipsis }}
|
||||||
|
onClick={this.handleEdit}
|
||||||
|
>
|
||||||
|
<div class="cell-content" title={this.column.ellipsis ? this.getValues ?? '' : ''}>
|
||||||
|
{this.column.editRender
|
||||||
|
? this.column.editRender({
|
||||||
|
text: this.value,
|
||||||
|
record: this.record as Recordable,
|
||||||
|
column: this.column,
|
||||||
|
index: this.index,
|
||||||
|
})
|
||||||
|
: this.getValues
|
||||||
|
? this.getValues
|
||||||
|
: '\u00A0'}
|
||||||
|
</div>
|
||||||
|
{!this.column.editRow && <FormOutlined class={`${this.prefixCls}__normal-icon`} />}
|
||||||
|
</div>
|
||||||
|
{this.isEdit && (
|
||||||
|
<Spin spinning={this.spinning}>
|
||||||
|
<div class={`${this.prefixCls}__wrapper`} v-click-outside={this.onClickOutside}>
|
||||||
|
<CellComponent
|
||||||
|
{...this.getComponentProps}
|
||||||
|
component={this.getComponent}
|
||||||
|
style={this.getWrapperStyle}
|
||||||
|
popoverVisible={this.getRuleVisible}
|
||||||
|
rule={this.getRule}
|
||||||
|
ruleMessage={this.ruleMessage}
|
||||||
|
class={this.getWrapperClass}
|
||||||
|
ref="elRef"
|
||||||
|
onChange={this.handleChange}
|
||||||
|
onOptionsChange={this.handleOptionsChange}
|
||||||
|
onPressEnter={this.handleEnter}
|
||||||
|
/>
|
||||||
|
{!this.getRowEditable && (
|
||||||
|
<div class={`${this.prefixCls}__action`}>
|
||||||
|
<CheckOutlined
|
||||||
|
class={[`${this.prefixCls}__icon`, 'mx-2']}
|
||||||
|
onClick={this.handleSubmitClick}
|
||||||
|
/>
|
||||||
|
<CloseOutlined class={`${this.prefixCls}__icon `} onClick={this.handleCancel} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Spin>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<Popover
|
<Popover
|
||||||
placement="bottomLeft"
|
placement="bottomLeft"
|
||||||
trigger="click"
|
trigger="click"
|
||||||
@visibleChange="handleVisibleChange"
|
@visible-change="handleVisibleChange"
|
||||||
:overlayClassName="`${prefixCls}__cloumn-list`"
|
:overlayClassName="`${prefixCls}__cloumn-list`"
|
||||||
:getPopupContainer="getPopupContainer"
|
:getPopupContainer="getPopupContainer"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<span>{{ t('component.table.settingDens') }}</span>
|
<span>{{ t('component.table.settingDens') }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<Dropdown placement="bottomCenter" :trigger="['click']" :getPopupContainer="getPopupContainer">
|
<Dropdown placement="bottom" :trigger="['click']" :getPopupContainer="getPopupContainer">
|
||||||
<ColumnHeightOutlined />
|
<ColumnHeightOutlined />
|
||||||
<template #overlay>
|
<template #overlay>
|
||||||
<Menu @click="handleTitleClick" selectable v-model:selectedKeys="selectedKeysRef">
|
<Menu @click="handleTitleClick" selectable v-model:selectedKeys="selectedKeysRef">
|
||||||
|
|
|
||||||
|
|
@ -152,10 +152,10 @@ export function useColumns(
|
||||||
return hasPermission(column.auth) && isIfShow(column);
|
return hasPermission(column.auth) && isIfShow(column);
|
||||||
})
|
})
|
||||||
.map((column) => {
|
.map((column) => {
|
||||||
const { slots, dataIndex, customRender, format, edit, editRow, flag } = column;
|
const { slots, customRender, format, edit, editRow, flag } = column;
|
||||||
|
|
||||||
if (!slots || !slots?.title) {
|
if (!slots || !slots?.title) {
|
||||||
column.slots = { title: `header-${dataIndex}`, ...(slots || {}) };
|
// column.slots = { title: `header-${dataIndex}`, ...(slots || {}) };
|
||||||
column.customTitle = column.title;
|
column.customTitle = column.title;
|
||||||
Reflect.deleteProperty(column, 'title');
|
Reflect.deleteProperty(column, 'title');
|
||||||
}
|
}
|
||||||
|
|
@ -197,7 +197,7 @@ export function useColumns(
|
||||||
* set columns
|
* set columns
|
||||||
* @param columnList key|column
|
* @param columnList key|column
|
||||||
*/
|
*/
|
||||||
function setColumns(columnList: Partial<BasicColumn>[] | string[]) {
|
function setColumns(columnList: Partial<BasicColumn>[] | (string | string[])[]) {
|
||||||
const columns = cloneDeep(columnList);
|
const columns = cloneDeep(columnList);
|
||||||
if (!isArray(columns)) return;
|
if (!isArray(columns)) return;
|
||||||
|
|
||||||
|
|
@ -210,23 +210,23 @@ export function useColumns(
|
||||||
|
|
||||||
const cacheKeys = cacheColumns.map((item) => item.dataIndex);
|
const cacheKeys = cacheColumns.map((item) => item.dataIndex);
|
||||||
|
|
||||||
if (!isString(firstColumn)) {
|
if (!isString(firstColumn) && !isArray(firstColumn)) {
|
||||||
columnsRef.value = columns as BasicColumn[];
|
columnsRef.value = columns as BasicColumn[];
|
||||||
} else {
|
} else {
|
||||||
const columnKeys = columns as string[];
|
const columnKeys = (columns as (string | string[])[]).map(m => m.toString());
|
||||||
const newColumns: BasicColumn[] = [];
|
const newColumns: BasicColumn[] = [];
|
||||||
cacheColumns.forEach((item) => {
|
cacheColumns.forEach((item) => {
|
||||||
newColumns.push({
|
newColumns.push({
|
||||||
...item,
|
...item,
|
||||||
defaultHidden: !columnKeys.includes(item.dataIndex! || (item.key as string)),
|
defaultHidden: !columnKeys.includes(item.dataIndex?.toString() || (item.key as string))
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// Sort according to another array
|
// Sort according to another array
|
||||||
if (!isEqual(cacheKeys, columns)) {
|
if (!isEqual(cacheKeys, columns)) {
|
||||||
newColumns.sort((prev, next) => {
|
newColumns.sort((prev, next) => {
|
||||||
return (
|
return (
|
||||||
columnKeys.indexOf(prev.dataIndex as string) -
|
columnKeys.indexOf(prev.dataIndex?.toString() as string) -
|
||||||
columnKeys.indexOf(next.dataIndex as string)
|
columnKeys.indexOf(next.dataIndex?.toString() as string)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -292,7 +292,7 @@ export function useDataSource(
|
||||||
const isArrayResult = Array.isArray(res);
|
const isArrayResult = Array.isArray(res);
|
||||||
|
|
||||||
let resultItems: Recordable[] = isArrayResult ? res : get(res, listField);
|
let resultItems: Recordable[] = isArrayResult ? res : get(res, listField);
|
||||||
const resultTotal: number = isArrayResult ? 0 : get(res, totalField);
|
const resultTotal: number = isArrayResult ? res.length : get(res, totalField);
|
||||||
|
|
||||||
// 假如数据变少,导致总页数变少并小于当前选中页码,通过getPaginationRef获取到的页码是不正确的,需获取正确的页码再次执行
|
// 假如数据变少,导致总页数变少并小于当前选中页码,通过getPaginationRef获取到的页码是不正确的,需获取正确的页码再次执行
|
||||||
if (resultTotal) {
|
if (resultTotal) {
|
||||||
|
|
|
||||||
|
|
@ -412,7 +412,7 @@ export type CellFormat =
|
||||||
| Map<string | number, any>;
|
| Map<string | number, any>;
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
export interface BasicColumn extends ColumnProps {
|
export interface BasicColumn extends ColumnProps<Recordable> {
|
||||||
children?: BasicColumn[];
|
children?: BasicColumn[];
|
||||||
filters?: {
|
filters?: {
|
||||||
text: string;
|
text: string;
|
||||||
|
|
@ -441,7 +441,14 @@ export interface BasicColumn extends ColumnProps {
|
||||||
editRow?: boolean;
|
editRow?: boolean;
|
||||||
editable?: boolean;
|
editable?: boolean;
|
||||||
editComponent?: ComponentType;
|
editComponent?: ComponentType;
|
||||||
editComponentProps?: Recordable;
|
editComponentProps?:
|
||||||
|
| ((opt: {
|
||||||
|
text: string | number | boolean | Recordable;
|
||||||
|
record: Recordable;
|
||||||
|
column: BasicColumn;
|
||||||
|
index: number;
|
||||||
|
}) => Recordable)
|
||||||
|
| Recordable;
|
||||||
editRule?: boolean | ((text: string, record: Recordable) => Promise<string>);
|
editRule?: boolean | ((text: string, record: Recordable) => Promise<string>);
|
||||||
editValueMap?: (value: any) => string;
|
editValueMap?: (value: any) => string;
|
||||||
onEditRow?: () => void;
|
onEditRow?: () => void;
|
||||||
|
|
@ -449,6 +456,13 @@ export interface BasicColumn extends ColumnProps {
|
||||||
auth?: RoleEnum | RoleEnum[] | string | string[];
|
auth?: RoleEnum | RoleEnum[] | string | string[];
|
||||||
// 业务控制是否显示
|
// 业务控制是否显示
|
||||||
ifShow?: boolean | ((column: BasicColumn) => boolean);
|
ifShow?: boolean | ((column: BasicColumn) => boolean);
|
||||||
|
// 自定义修改后显示的内容
|
||||||
|
editRender?: (opt: {
|
||||||
|
text: string | number | boolean | Recordable;
|
||||||
|
record: Recordable;
|
||||||
|
column: BasicColumn;
|
||||||
|
index: number;
|
||||||
|
}) => VNodeChild | JSX.Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ColumnChangeParam = {
|
export type ColumnChangeParam = {
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,6 @@
|
||||||
@import './input.less';
|
@import './input.less';
|
||||||
@import './btn.less';
|
@import './btn.less';
|
||||||
|
|
||||||
// TODO beta.11 fix
|
|
||||||
.ant-col {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-image-preview-root {
|
.ant-image-preview-root {
|
||||||
img {
|
img {
|
||||||
display: unset;
|
display: unset;
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,9 @@
|
||||||
{
|
{
|
||||||
field: 'password',
|
field: 'password',
|
||||||
label: t('layout.header.lockScreenPassword'),
|
label: t('layout.header.lockScreenPassword'),
|
||||||
|
colProps: {
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
component: 'InputPassword',
|
component: 'InputPassword',
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
name: 'DropdownMenuItem',
|
name: 'DropdownMenuItem',
|
||||||
components: { MenuItem: Menu.Item, Icon },
|
components: { MenuItem: Menu.Item, Icon },
|
||||||
props: {
|
props: {
|
||||||
|
// eslint-disable-next-line
|
||||||
key: propTypes.string,
|
key: propTypes.string,
|
||||||
text: propTypes.string,
|
text: propTypes.string,
|
||||||
icon: propTypes.string,
|
icon: propTypes.string,
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@
|
||||||
:items="childrenMenus"
|
:items="childrenMenus"
|
||||||
:theme="getMenuTheme"
|
:theme="getMenuTheme"
|
||||||
mixSider
|
mixSider
|
||||||
@menuClick="handleMenuClick"
|
@menu-click="handleMenuClick"
|
||||||
/>
|
/>
|
||||||
</ScrollContainer>
|
</ScrollContainer>
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<Dropdown :dropMenuList="getDropMenuList" :trigger="getTrigger" @menuEvent="handleMenuEvent">
|
<Dropdown
|
||||||
|
:dropMenuList="getDropMenuList"
|
||||||
|
:trigger="getTrigger"
|
||||||
|
placement="bottom"
|
||||||
|
overlayClassName="multiple-tabs__dropdown"
|
||||||
|
@menu-event="handleMenuEvent"
|
||||||
|
>
|
||||||
<div :class="`${prefixCls}__info`" @contextmenu="handleContext" v-if="getIsTabs">
|
<div :class="`${prefixCls}__info`" @contextmenu="handleContext" v-if="getIsTabs">
|
||||||
<span class="ml-1">{{ getTitle }}</span>
|
<span class="ml-1">{{ getTitle }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -180,3 +180,28 @@ html[data-theme='light'] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-tabs-dropdown-menu {
|
||||||
|
&-title-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.@{prefix-cls} {
|
||||||
|
&-content__info {
|
||||||
|
width: auto;
|
||||||
|
margin-left: 0;
|
||||||
|
line-height: 28px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-item-remove {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiple-tabs__dropdown {
|
||||||
|
.ant-dropdown-content {
|
||||||
|
width: 172px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,7 @@ export default {
|
||||||
breadcrumb: 'Breadcrumbs',
|
breadcrumb: 'Breadcrumbs',
|
||||||
breadcrumbFlat: 'Flat Mode',
|
breadcrumbFlat: 'Flat Mode',
|
||||||
breadcrumbFlatDetail: 'Flat mode details',
|
breadcrumbFlatDetail: 'Flat mode details',
|
||||||
|
requestDemo: 'Retry request demo',
|
||||||
|
|
||||||
breadcrumbChildren: 'Level mode',
|
breadcrumbChildren: 'Level mode',
|
||||||
breadcrumbChildrenDetail: 'Level mode detail',
|
breadcrumbChildrenDetail: 'Level mode detail',
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,7 @@ export default {
|
||||||
ws: 'websocket测试',
|
ws: 'websocket测试',
|
||||||
breadcrumb: '面包屑导航',
|
breadcrumb: '面包屑导航',
|
||||||
breadcrumbFlat: '平级模式',
|
breadcrumbFlat: '平级模式',
|
||||||
|
requestDemo: '测试请求重试',
|
||||||
breadcrumbFlatDetail: '平级详情',
|
breadcrumbFlatDetail: '平级详情',
|
||||||
breadcrumbChildren: '层级模式',
|
breadcrumbChildren: '层级模式',
|
||||||
breadcrumbChildrenDetail: '层级详情',
|
breadcrumbChildrenDetail: '层级详情',
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,15 @@ const feat: AppRouteModule = {
|
||||||
title: t('routes.demo.feat.ws'),
|
title: t('routes.demo.feat.ws'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'request',
|
||||||
|
name: 'RequestDemo',
|
||||||
|
// @ts-ignore
|
||||||
|
component: () => import('/@/views/demo/feat/request-demo/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: t('routes.demo.feat.requestDemo'),
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'session-timeout',
|
path: 'session-timeout',
|
||||||
name: 'SessionTimeout',
|
name: 'SessionTimeout',
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,12 @@ export class Memory<T = any, V = any> {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
const now = new Date().getTime();
|
const now = new Date().getTime();
|
||||||
item.time = now + this.alive;
|
/**
|
||||||
|
* Prevent overflow of the setTimeout Maximum delay value
|
||||||
|
* Maximum delay value 2,147,483,647 ms
|
||||||
|
* https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#maximum_delay_value
|
||||||
|
*/
|
||||||
|
item.time = expires > now ? expires : now + expires;
|
||||||
item.timeoutId = setTimeout(
|
item.timeoutId = setTimeout(
|
||||||
() => {
|
() => {
|
||||||
this.remove(key);
|
this.remove(key);
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,10 @@ export class VAxios {
|
||||||
// Response result interceptor error capture
|
// Response result interceptor error capture
|
||||||
responseInterceptorsCatch &&
|
responseInterceptorsCatch &&
|
||||||
isFunction(responseInterceptorsCatch) &&
|
isFunction(responseInterceptorsCatch) &&
|
||||||
this.axiosInstance.interceptors.response.use(undefined, responseInterceptorsCatch);
|
this.axiosInstance.interceptors.response.use(undefined, (error) => {
|
||||||
|
// @ts-ignore
|
||||||
|
responseInterceptorsCatch(this.axiosInstance, error);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { AxiosError, AxiosInstance } from 'axios';
|
||||||
|
/**
|
||||||
|
* 请求重试机制
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class AxiosRetry {
|
||||||
|
/**
|
||||||
|
* 重试
|
||||||
|
*/
|
||||||
|
retry(AxiosInstance: AxiosInstance, error: AxiosError) {
|
||||||
|
// @ts-ignore
|
||||||
|
const { config } = error.response;
|
||||||
|
const { waitTime, count } = config?.requestOptions?.retryRequest;
|
||||||
|
config.__retryCount = config.__retryCount || 0;
|
||||||
|
if (config.__retryCount >= count) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
config.__retryCount += 1;
|
||||||
|
return this.delay(waitTime).then(() => AxiosInstance(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 延迟
|
||||||
|
*/
|
||||||
|
private delay(waitTime: number) {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, waitTime));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -48,5 +48,5 @@ export abstract class AxiosTransform {
|
||||||
/**
|
/**
|
||||||
* @description: 请求之后的拦截器错误处理
|
* @description: 请求之后的拦截器错误处理
|
||||||
*/
|
*/
|
||||||
responseInterceptorsCatch?: (error: Error) => void;
|
responseInterceptorsCatch?: (axiosInstance: AxiosResponse, error: Error) => void;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import { useErrorLogStoreWithOut } from '/@/store/modules/errorLog';
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
import { joinTimestamp, formatRequestDate } from './helper';
|
import { joinTimestamp, formatRequestDate } from './helper';
|
||||||
import { useUserStoreWithOut } from '/@/store/modules/user';
|
import { useUserStoreWithOut } from '/@/store/modules/user';
|
||||||
|
import { AxiosRetry } from '/@/utils/http/axios/axiosRetry';
|
||||||
|
|
||||||
const globSetting = useGlobSetting();
|
const globSetting = useGlobSetting();
|
||||||
const urlPrefix = globSetting.urlPrefix;
|
const urlPrefix = globSetting.urlPrefix;
|
||||||
|
|
@ -158,7 +159,7 @@ const transform: AxiosTransform = {
|
||||||
/**
|
/**
|
||||||
* @description: 响应错误处理
|
* @description: 响应错误处理
|
||||||
*/
|
*/
|
||||||
responseInterceptorsCatch: (error: any) => {
|
responseInterceptorsCatch: (axiosInstance: AxiosResponse, error: any) => {
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const errorLogStore = useErrorLogStoreWithOut();
|
const errorLogStore = useErrorLogStoreWithOut();
|
||||||
errorLogStore.addAjaxErrorInfo(error);
|
errorLogStore.addAjaxErrorInfo(error);
|
||||||
|
|
@ -189,6 +190,14 @@ const transform: AxiosTransform = {
|
||||||
}
|
}
|
||||||
|
|
||||||
checkStatus(error?.response?.status, msg, errorMessageMode);
|
checkStatus(error?.response?.status, msg, errorMessageMode);
|
||||||
|
|
||||||
|
// 添加自动重试机制 保险起见 只针对GET请求
|
||||||
|
const retryRequest = new AxiosRetry();
|
||||||
|
const { isOpenRetry } = config.requestOptions.retryRequest;
|
||||||
|
config.method?.toUpperCase() === RequestEnum.GET &&
|
||||||
|
isOpenRetry &&
|
||||||
|
// @ts-ignore
|
||||||
|
retryRequest.retry(axiosInstance, error);
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -234,6 +243,11 @@ function createAxios(opt?: Partial<CreateAxiosOptions>) {
|
||||||
ignoreCancelToken: true,
|
ignoreCancelToken: true,
|
||||||
// 是否携带token
|
// 是否携带token
|
||||||
withToken: true,
|
withToken: true,
|
||||||
|
retryRequest: {
|
||||||
|
isOpenRetry: true,
|
||||||
|
count: 5,
|
||||||
|
waitTime: 100,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
opt || {},
|
opt || {},
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
:tab-list="tabListTitle"
|
:tab-list="tabListTitle"
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
:active-tab-key="activeKey"
|
:active-tab-key="activeKey"
|
||||||
@tabChange="onTabChange"
|
@tab-change="onTabChange"
|
||||||
>
|
>
|
||||||
<p v-if="activeKey === 'tab1'">
|
<p v-if="activeKey === 'tab1'">
|
||||||
<VisitAnalysis />
|
<VisitAnalysis />
|
||||||
|
|
|
||||||
|
|
@ -39,28 +39,22 @@
|
||||||
splitNumber: 8,
|
splitNumber: 8,
|
||||||
indicator: [
|
indicator: [
|
||||||
{
|
{
|
||||||
text: '电脑',
|
name: '电脑',
|
||||||
max: 100,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '充电器',
|
name: '充电器',
|
||||||
max: 100,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '耳机',
|
name: '耳机',
|
||||||
max: 100,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '手机',
|
name: '手机',
|
||||||
max: 100,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Ipad',
|
name: 'Ipad',
|
||||||
max: 100,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '耳机',
|
name: '耳机',
|
||||||
max: 100,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -39,28 +39,22 @@
|
||||||
splitNumber: 8,
|
splitNumber: 8,
|
||||||
indicator: [
|
indicator: [
|
||||||
{
|
{
|
||||||
text: '2017',
|
name: '2017',
|
||||||
max: 100,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '2017',
|
name: '2017',
|
||||||
max: 100,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '2018',
|
name: '2018',
|
||||||
max: 100,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '2019',
|
name: '2019',
|
||||||
max: 100,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '2020',
|
name: '2020',
|
||||||
max: 100,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '2021',
|
name: '2021',
|
||||||
max: 100,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -43,28 +43,22 @@
|
||||||
splitNumber: 8,
|
splitNumber: 8,
|
||||||
indicator: [
|
indicator: [
|
||||||
{
|
{
|
||||||
text: '2017',
|
name: '2017',
|
||||||
max: 100,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '2017',
|
name: '2017',
|
||||||
max: 100,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '2018',
|
name: '2018',
|
||||||
max: 100,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '2019',
|
name: '2019',
|
||||||
max: 100,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '2020',
|
name: '2020',
|
||||||
max: 100,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '2021',
|
name: '2021',
|
||||||
max: 100,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<PageWrapper title="卡片列表示例" content="基础封装">
|
<PageWrapper title="卡片列表示例" content="基础封装">
|
||||||
<CardList :params="params" :api="demoListApi" @getMethod="getMethod" @delete="handleDel">
|
<CardList :params="params" :api="demoListApi" @get-method="getMethod" @delete="handleDel">
|
||||||
<template #header>
|
<template #header>
|
||||||
<Button type="primary" color="error"> 按钮1 </Button>
|
<Button type="primary" color="error"> 按钮1 </Button>
|
||||||
<Button type="primary" color="success"> 按钮2 </Button>
|
<Button type="primary" color="success"> 按钮2 </Button>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<PageWrapper title="点内外部触发事件">
|
<PageWrapper title="点内外部触发事件">
|
||||||
<ClickOutSide @clickOutside="handleClickOutside" class="flex justify-center">
|
<ClickOutSide @click-outside="handleClickOutside" class="flex justify-center">
|
||||||
<div @click="innerClick" class="demo-box">
|
<div @click="innerClick" class="demo-box">
|
||||||
{{ text }}
|
{{ text }}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<template>
|
||||||
|
<div class="request-box">
|
||||||
|
<a-button @click="handleClick" type="primary"> 点击会重新发起请求5次 </a-button>
|
||||||
|
<p>打开浏览器的network面板,可以看到发出了六次请求</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { testRetry } from '/@/api/sys/user';
|
||||||
|
// @ts-ignore
|
||||||
|
const handleClick = async () => {
|
||||||
|
await testRetry();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.request-box {
|
||||||
|
margin: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -142,6 +142,9 @@
|
||||||
field: 'divider-basic',
|
field: 'divider-basic',
|
||||||
component: 'Divider',
|
component: 'Divider',
|
||||||
label: '基础字段',
|
label: '基础字段',
|
||||||
|
colProps: {
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'field1',
|
field: 'field1',
|
||||||
|
|
@ -340,6 +343,9 @@
|
||||||
field: 'divider-api-select',
|
field: 'divider-api-select',
|
||||||
component: 'Divider',
|
component: 'Divider',
|
||||||
label: '远程下拉演示',
|
label: '远程下拉演示',
|
||||||
|
colProps: {
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'field30',
|
field: 'field30',
|
||||||
|
|
@ -458,6 +464,9 @@
|
||||||
field: 'divider-linked',
|
field: 'divider-linked',
|
||||||
component: 'Divider',
|
component: 'Divider',
|
||||||
label: '字段联动',
|
label: '字段联动',
|
||||||
|
colProps: {
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'province',
|
field: 'province',
|
||||||
|
|
@ -509,6 +518,9 @@
|
||||||
component: 'Divider',
|
component: 'Divider',
|
||||||
label: '互斥多选',
|
label: '互斥多选',
|
||||||
helpMessage: ['两个Select共用数据源', '但不可选择对方已选中的项目'],
|
helpMessage: ['两个Select共用数据源', '但不可选择对方已选中的项目'],
|
||||||
|
colProps: {
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'selectA',
|
field: 'selectA',
|
||||||
|
|
@ -530,10 +542,32 @@
|
||||||
span: 8,
|
span: 8,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
field: 'divider-deconstruct',
|
||||||
|
component: 'Divider',
|
||||||
|
label: '字段解构',
|
||||||
|
helpMessage: ['如果组件的值是 array 或者 object', '可以根据 ES6 的解构语法分别取值'],
|
||||||
|
colProps: {
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: '[startTime, endTime]',
|
||||||
|
label: '时间范围',
|
||||||
|
component: 'RangePicker',
|
||||||
|
componentProps: {
|
||||||
|
format: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
placeholder: ['开始时间', '结束时间'],
|
||||||
|
showTime: { format: 'HH:mm:ss' },
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: 'divider-others',
|
field: 'divider-others',
|
||||||
component: 'Divider',
|
component: 'Divider',
|
||||||
label: '其它',
|
label: '其它',
|
||||||
|
colProps: {
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'field20',
|
field: 'field20',
|
||||||
|
|
@ -602,6 +636,7 @@
|
||||||
keyword.value = '';
|
keyword.value = '';
|
||||||
},
|
},
|
||||||
handleSubmit: (values: any) => {
|
handleSubmit: (values: any) => {
|
||||||
|
console.log('values', values);
|
||||||
createMessage.success('click search,values:' + JSON.stringify(values));
|
createMessage.success('click search,values:' + JSON.stringify(values));
|
||||||
},
|
},
|
||||||
check,
|
check,
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
import { FormSchema } from '/@/components/Form';
|
import { FormSchema } from '/@/components/Form';
|
||||||
|
const colProps = {
|
||||||
|
span: 8,
|
||||||
|
};
|
||||||
|
|
||||||
export const schemas: FormSchema[] = [
|
export const schemas: FormSchema[] = [
|
||||||
{
|
{
|
||||||
field: 'title',
|
field: 'title',
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
label: '标题',
|
label: '标题',
|
||||||
|
colProps,
|
||||||
componentProps: {
|
componentProps: {
|
||||||
placeholder: '给目标起个名字',
|
placeholder: '给目标起个名字',
|
||||||
},
|
},
|
||||||
|
|
@ -14,12 +18,37 @@ export const schemas: FormSchema[] = [
|
||||||
field: 'time',
|
field: 'time',
|
||||||
component: 'RangePicker',
|
component: 'RangePicker',
|
||||||
label: '起止日期',
|
label: '起止日期',
|
||||||
|
colProps,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
field: 'client',
|
||||||
|
component: 'Input',
|
||||||
|
colProps,
|
||||||
|
label: '客户',
|
||||||
|
helpMessage: '目标的服务对象',
|
||||||
|
subLabel: '( 选填 )',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请描述你服务的客户,内部客户直接 @姓名/工号',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'weights',
|
||||||
|
component: 'InputNumber',
|
||||||
|
label: '权重',
|
||||||
|
colProps,
|
||||||
|
subLabel: '( 选填 )',
|
||||||
|
componentProps: {
|
||||||
|
formatter: (value: string) => (value ? `${value}%` : ''),
|
||||||
|
parser: (value: string) => value.replace('%', ''),
|
||||||
|
placeholder: '请输入',
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: 'target',
|
field: 'target',
|
||||||
component: 'InputTextArea',
|
component: 'InputTextArea',
|
||||||
label: '目标描述',
|
label: '目标描述',
|
||||||
|
colProps,
|
||||||
componentProps: {
|
componentProps: {
|
||||||
placeholder: '请输入你的阶段性工作目标',
|
placeholder: '请输入你的阶段性工作目标',
|
||||||
rows: 4,
|
rows: 4,
|
||||||
|
|
@ -30,46 +59,33 @@ export const schemas: FormSchema[] = [
|
||||||
field: 'metrics',
|
field: 'metrics',
|
||||||
component: 'InputTextArea',
|
component: 'InputTextArea',
|
||||||
label: '衡量标准',
|
label: '衡量标准',
|
||||||
|
colProps,
|
||||||
componentProps: {
|
componentProps: {
|
||||||
placeholder: '请输入衡量标准',
|
placeholder: '请输入衡量标准',
|
||||||
rows: 4,
|
rows: 4,
|
||||||
},
|
},
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
field: 'client',
|
|
||||||
component: 'Input',
|
|
||||||
label: '客户',
|
|
||||||
helpMessage: '目标的服务对象',
|
|
||||||
subLabel: '( 选填 )',
|
|
||||||
componentProps: {
|
|
||||||
placeholder: '请描述你服务的客户,内部客户直接 @姓名/工号',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
field: 'inviteer',
|
field: 'inviteer',
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
label: '邀评人',
|
label: '邀评人',
|
||||||
|
colProps: {
|
||||||
|
span: 8,
|
||||||
|
},
|
||||||
subLabel: '( 选填 )',
|
subLabel: '( 选填 )',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
placeholder: '请直接 @姓名/工号,最多可邀请 5 人',
|
placeholder: '请直接 @姓名/工号,最多可邀请 5 人',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
field: 'weights',
|
|
||||||
component: 'InputNumber',
|
|
||||||
label: '权重',
|
|
||||||
subLabel: '( 选填 )',
|
|
||||||
componentProps: {
|
|
||||||
formatter: (value: string) => (value ? `${value}%` : ''),
|
|
||||||
parser: (value: string) => value.replace('%', ''),
|
|
||||||
placeholder: '请输入',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
field: 'disclosure',
|
field: 'disclosure',
|
||||||
component: 'RadioGroup',
|
component: 'RadioGroup',
|
||||||
label: '目标公开',
|
label: '目标公开',
|
||||||
|
colProps: {
|
||||||
|
span: 16,
|
||||||
|
},
|
||||||
itemProps: {
|
itemProps: {
|
||||||
extra: '客户、邀评人默认被分享',
|
extra: '客户、邀评人默认被分享',
|
||||||
},
|
},
|
||||||
|
|
@ -91,9 +107,12 @@ export const schemas: FormSchema[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'disclosurer',
|
field: 'disclosure',
|
||||||
component: 'Select',
|
component: 'Select',
|
||||||
label: ' ',
|
label: ' ',
|
||||||
|
colProps: {
|
||||||
|
span: 8,
|
||||||
|
},
|
||||||
show: ({ model }) => {
|
show: ({ model }) => {
|
||||||
return model.disclosure === '2';
|
return model.disclosure === '2';
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,12 @@
|
||||||
span: 8,
|
span: 8,
|
||||||
},
|
},
|
||||||
wrapperCol: {
|
wrapperCol: {
|
||||||
span: 10,
|
span: 15,
|
||||||
},
|
},
|
||||||
schemas: schemas,
|
schemas: schemas,
|
||||||
actionColOptions: {
|
actionColOptions: {
|
||||||
offset: 8,
|
offset: 8,
|
||||||
span: 12,
|
span: 23,
|
||||||
},
|
},
|
||||||
submitButtonOptions: {
|
submitButtonOptions: {
|
||||||
text: '提交',
|
text: '提交',
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
const tableRef = ref<{ getDataSource: () => any } | null>(null);
|
const tableRef = ref<{ getDataSource: () => any } | null>(null);
|
||||||
|
|
||||||
const [register, { validate }] = useForm({
|
const [register, { validate }] = useForm({
|
||||||
|
layout: 'vertical',
|
||||||
baseColProps: {
|
baseColProps: {
|
||||||
span: 6,
|
span: 6,
|
||||||
},
|
},
|
||||||
|
|
@ -42,6 +43,7 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
const [registerTask, { validate: validateTaskForm }] = useForm({
|
const [registerTask, { validate: validateTaskForm }] = useForm({
|
||||||
|
layout: 'vertical',
|
||||||
baseColProps: {
|
baseColProps: {
|
||||||
span: 6,
|
span: 6,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,9 @@ export const step1Schemas: FormSchema[] = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
colProps: {
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'fac',
|
field: 'fac',
|
||||||
|
|
@ -23,6 +26,9 @@ export const step1Schemas: FormSchema[] = [
|
||||||
required: true,
|
required: true,
|
||||||
defaultValue: 'test@example.com',
|
defaultValue: 'test@example.com',
|
||||||
slot: 'fac',
|
slot: 'fac',
|
||||||
|
colProps: {
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'pay',
|
field: 'pay',
|
||||||
|
|
@ -37,6 +43,9 @@ export const step1Schemas: FormSchema[] = [
|
||||||
label: '收款人姓名',
|
label: '收款人姓名',
|
||||||
defaultValue: 'Vben',
|
defaultValue: 'Vben',
|
||||||
required: true,
|
required: true,
|
||||||
|
colProps: {
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'money',
|
field: 'money',
|
||||||
|
|
@ -49,6 +58,9 @@ export const step1Schemas: FormSchema[] = [
|
||||||
prefix: () => '¥',
|
prefix: () => '¥',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
colProps: {
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -59,5 +71,8 @@ export const step2Schemas: FormSchema[] = [
|
||||||
label: '支付密码',
|
label: '支付密码',
|
||||||
required: true,
|
required: true,
|
||||||
defaultValue: '123456',
|
defaultValue: '123456',
|
||||||
|
colProps: {
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -32,13 +32,13 @@
|
||||||
{
|
{
|
||||||
title: 'ID',
|
title: 'ID',
|
||||||
dataIndex: 'id',
|
dataIndex: 'id',
|
||||||
slots: { customRender: 'id' },
|
// slots: { customRender: 'id' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '头像',
|
title: '头像',
|
||||||
dataIndex: 'avatar',
|
dataIndex: 'avatar',
|
||||||
width: 100,
|
width: 100,
|
||||||
slots: { customRender: 'avatar' },
|
// slots: { customRender: 'avatar' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '分类',
|
title: '分类',
|
||||||
|
|
@ -46,7 +46,7 @@
|
||||||
width: 80,
|
width: 80,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
defaultHidden: true,
|
defaultHidden: true,
|
||||||
slots: { customRender: 'category' },
|
// slots: { customRender: 'category' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '姓名',
|
title: '姓名',
|
||||||
|
|
@ -58,13 +58,13 @@
|
||||||
dataIndex: 'imgArr',
|
dataIndex: 'imgArr',
|
||||||
helpMessage: ['这是简单模式的图片列表', '只会显示一张在表格中', '但点击可预览多张图片'],
|
helpMessage: ['这是简单模式的图片列表', '只会显示一张在表格中', '但点击可预览多张图片'],
|
||||||
width: 140,
|
width: 140,
|
||||||
slots: { customRender: 'img' },
|
// slots: { customRender: 'img' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '照片列表2',
|
title: '照片列表2',
|
||||||
dataIndex: 'imgs',
|
dataIndex: 'imgs',
|
||||||
width: 160,
|
width: 160,
|
||||||
slots: { customRender: 'imgs' },
|
// slots: { customRender: 'imgs' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '地址',
|
title: '地址',
|
||||||
|
|
@ -73,7 +73,7 @@
|
||||||
{
|
{
|
||||||
title: '编号',
|
title: '编号',
|
||||||
dataIndex: 'no',
|
dataIndex: 'no',
|
||||||
slots: { customRender: 'no' },
|
// slots: { customRender: 'no' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '开始时间',
|
title: '开始时间',
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,14 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent, h } from 'vue';
|
||||||
import { BasicTable, useTable, BasicColumn } from '/@/components/Table';
|
import { BasicTable, useTable, BasicColumn } from '/@/components/Table';
|
||||||
import { optionsListApi } from '/@/api/demo/select';
|
import { optionsListApi } from '/@/api/demo/select';
|
||||||
|
|
||||||
import { demoListApi } from '/@/api/demo/table';
|
import { demoListApi } from '/@/api/demo/table';
|
||||||
import { treeOptionsListApi } from '/@/api/demo/tree';
|
import { treeOptionsListApi } from '/@/api/demo/tree';
|
||||||
import { useMessage } from '/@/hooks/web/useMessage';
|
import { useMessage } from '/@/hooks/web/useMessage';
|
||||||
|
import { Progress } from 'ant-design-vue';
|
||||||
const columns: BasicColumn[] = [
|
const columns: BasicColumn[] = [
|
||||||
{
|
{
|
||||||
title: '输入框',
|
title: '输入框',
|
||||||
|
|
@ -60,6 +61,15 @@
|
||||||
editRule: true,
|
editRule: true,
|
||||||
editComponent: 'InputNumber',
|
editComponent: 'InputNumber',
|
||||||
width: 200,
|
width: 200,
|
||||||
|
editComponentProps: () => {
|
||||||
|
return {
|
||||||
|
max: 100,
|
||||||
|
min: 0,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
editRender: ({ text }) => {
|
||||||
|
return h(Progress, { percent: Number(text) });
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '下拉框',
|
title: '下拉框',
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@
|
||||||
actionColumn: {
|
actionColumn: {
|
||||||
width: 160,
|
width: 160,
|
||||||
title: 'Action',
|
title: 'Action',
|
||||||
slots: { customRender: 'action' },
|
// slots: { customRender: 'action' },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
function handleDelete(record: Recordable) {
|
function handleDelete(record: Recordable) {
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@
|
||||||
width: 160,
|
width: 160,
|
||||||
title: 'Action',
|
title: 'Action',
|
||||||
dataIndex: 'action',
|
dataIndex: 'action',
|
||||||
slots: { customRender: 'action' },
|
// slots: { customRender: 'action' },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
function handleDelete(record: Recordable) {
|
function handleDelete(record: Recordable) {
|
||||||
|
|
|
||||||
|
|
@ -123,13 +123,13 @@ export function getCustomHeaderColumns(): BasicColumn[] {
|
||||||
// title: '姓名',
|
// title: '姓名',
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
width: 120,
|
width: 120,
|
||||||
slots: { title: 'customTitle' },
|
// slots: { title: 'customTitle' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// title: '地址',
|
// title: '地址',
|
||||||
dataIndex: 'address',
|
dataIndex: 'address',
|
||||||
width: 120,
|
width: 120,
|
||||||
slots: { title: 'customAddress' },
|
// slots: { title: 'customAddress' },
|
||||||
sorter: true,
|
sorter: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,23 +5,7 @@
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
:class="`${prefixCls}__unlock`"
|
:class="`${prefixCls}__unlock`"
|
||||||
class="
|
class="absolute top-0 left-1/2 flex pt-5 h-16 items-center justify-center sm:text-md xl:text-xl text-white flex-col cursor-pointer transform translate-x-1/2"
|
||||||
absolute
|
|
||||||
top-0
|
|
||||||
left-1/2
|
|
||||||
flex
|
|
||||||
pt-5
|
|
||||||
h-16
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
sm:text-md
|
|
||||||
xl:text-xl
|
|
||||||
text-white
|
|
||||||
flex-col
|
|
||||||
cursor-pointer
|
|
||||||
transform
|
|
||||||
translate-x-1/2
|
|
||||||
"
|
|
||||||
@click="handleShowForm(false)"
|
@click="handleShowForm(false)"
|
||||||
v-show="showDate"
|
v-show="showDate"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -32,23 +32,7 @@
|
||||||
<div class="flex w-full h-full py-5 xl:h-auto xl:py-0 xl:my-0 xl:w-6/12">
|
<div class="flex w-full h-full py-5 xl:h-auto xl:py-0 xl:my-0 xl:w-6/12">
|
||||||
<div
|
<div
|
||||||
:class="`${prefixCls}-form`"
|
:class="`${prefixCls}-form`"
|
||||||
class="
|
class="relative w-full px-5 py-8 mx-auto my-auto rounded-md shadow-md xl:ml-16 xl:bg-transparent sm:px-8 xl:p-4 xl:shadow-none sm:w-3/4 lg:w-2/4 xl:w-auto enter-x"
|
||||||
relative
|
|
||||||
w-full
|
|
||||||
px-5
|
|
||||||
py-8
|
|
||||||
mx-auto
|
|
||||||
my-auto
|
|
||||||
rounded-md
|
|
||||||
shadow-md
|
|
||||||
xl:ml-16 xl:bg-transparent
|
|
||||||
sm:px-8
|
|
||||||
xl:p-4 xl:shadow-none
|
|
||||||
sm:w-3/4
|
|
||||||
lg:w-2/4
|
|
||||||
xl:w-auto
|
|
||||||
enter-x
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<LoginForm />
|
<LoginForm />
|
||||||
<ForgetPasswordForm />
|
<ForgetPasswordForm />
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
root: true,
|
root: true,
|
||||||
plugins: ['stylelint-order'],
|
plugins: ['stylelint-order'],
|
||||||
customSyntax: 'postcss-html',
|
|
||||||
extends: ['stylelint-config-standard', 'stylelint-config-prettier'],
|
extends: ['stylelint-config-standard', 'stylelint-config-prettier'],
|
||||||
|
customSyntax: 'postcss-html',
|
||||||
rules: {
|
rules: {
|
||||||
|
'function-no-unknown': null,
|
||||||
'selector-class-pattern': null,
|
'selector-class-pattern': null,
|
||||||
'selector-pseudo-class-no-unknown': [
|
'selector-pseudo-class-no-unknown': [
|
||||||
true,
|
true,
|
||||||
|
|
@ -35,6 +36,7 @@ module.exports = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'no-empty-source': null,
|
'no-empty-source': null,
|
||||||
|
'string-quotes': null,
|
||||||
'named-grid-areas-no-invalid': null,
|
'named-grid-areas-no-invalid': null,
|
||||||
'unicode-bom': 'never',
|
'unicode-bom': 'never',
|
||||||
'no-descending-specificity': null,
|
'no-descending-specificity': null,
|
||||||
|
|
@ -72,7 +74,7 @@ module.exports = {
|
||||||
overrides: [
|
overrides: [
|
||||||
{
|
{
|
||||||
files: ['*.vue', '**/*.vue', '*.html', '**/*.html'],
|
files: ['*.vue', '**/*.vue', '*.html', '**/*.html'],
|
||||||
extends: ['stylelint-config-recommended', 'stylelint-config-html'],
|
extends: ['stylelint-config-recommended'],
|
||||||
rules: {
|
rules: {
|
||||||
'keyframes-name-pattern': null,
|
'keyframes-name-pattern': null,
|
||||||
'selector-pseudo-class-no-unknown': [
|
'selector-pseudo-class-no-unknown': [
|
||||||
|
|
@ -89,5 +91,10 @@ module.exports = {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
files: ['*.less', '**/*.less'],
|
||||||
|
customSyntax: 'postcss-less',
|
||||||
|
extends: ['stylelint-config-standard', 'stylelint-config-recommended-vue'],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
export default '';
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
export default {};
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
export default jest.fn().mockImplementation(() => ({
|
|
||||||
postMessage: jest.fn(),
|
|
||||||
onmessage: jest.fn(),
|
|
||||||
onerror: jest.fn(),
|
|
||||||
}));
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
"stop": "npx pm2 stop ecosystem.config.js"
|
"stop": "npx pm2 stop ecosystem.config.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fs-extra": "^10.0.0",
|
"fs-extra": "^10.0.1",
|
||||||
"koa": "^2.13.4",
|
"koa": "^2.13.4",
|
||||||
"koa-body": "^4.2.0",
|
"koa-body": "^4.2.0",
|
||||||
"koa-bodyparser": "^4.3.0",
|
"koa-bodyparser": "^4.3.0",
|
||||||
|
|
@ -24,13 +24,13 @@
|
||||||
"@types/koa": "^2.13.4",
|
"@types/koa": "^2.13.4",
|
||||||
"@types/koa-bodyparser": "^5.0.2",
|
"@types/koa-bodyparser": "^5.0.2",
|
||||||
"@types/koa-router": "^7.4.4",
|
"@types/koa-router": "^7.4.4",
|
||||||
"@types/node": "^17.0.5",
|
"@types/node": "^17.0.21",
|
||||||
"nodemon": "^2.0.15",
|
"nodemon": "^2.0.15",
|
||||||
"pm2": "^5.1.2",
|
"pm2": "^5.2.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"ts-node": "^10.4.0",
|
"ts-node": "^10.7.0",
|
||||||
"tsconfig-paths": "^3.12.0",
|
"tsconfig-paths": "^3.14.0",
|
||||||
"tsup": "^5.11.9",
|
"tsup": "^5.12.1",
|
||||||
"typescript": "^4.5.4"
|
"typescript": "^4.6.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
// import { mount } from '@vue/test-utils';
|
|
||||||
// import { Button } from '/@/components/Button';
|
|
||||||
|
|
||||||
test('if jest is normal.', async () => {
|
|
||||||
expect('jest').toEqual('jest');
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO Vue component testing is not supported temporarily
|
|
||||||
// test('is a Vue instance.', async () => {
|
|
||||||
// const wrapper = mount(Button, {
|
|
||||||
// slots: {
|
|
||||||
// default: 'Button text',
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
// expect(wrapper.html()).toContain('Button text');
|
|
||||||
// });
|
|
||||||
|
|
@ -23,8 +23,15 @@ export interface RequestOptions {
|
||||||
ignoreCancelToken?: boolean;
|
ignoreCancelToken?: boolean;
|
||||||
// Whether to send token in header
|
// Whether to send token in header
|
||||||
withToken?: boolean;
|
withToken?: boolean;
|
||||||
|
// 请求重试机制
|
||||||
|
retryRequest?: RetryRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface RetryRequest {
|
||||||
|
isOpenRetry: boolean;
|
||||||
|
count: number;
|
||||||
|
waitTime: number;
|
||||||
|
}
|
||||||
export interface Result<T = any> {
|
export interface Result<T = any> {
|
||||||
code: number;
|
code: number;
|
||||||
type: 'success' | 'error' | 'warning';
|
type: 'success' | 'error' | 'warning';
|
||||||
|
|
|
||||||
|
|
@ -53,24 +53,31 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
|
https: true,
|
||||||
// Listening on all local IPs
|
// Listening on all local IPs
|
||||||
host: true,
|
host: true,
|
||||||
port: VITE_PORT,
|
port: VITE_PORT,
|
||||||
// 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: {
|
||||||
minify: false,
|
target: 'es2015',
|
||||||
// target: 'es2015',
|
cssTarget: 'chrome80',
|
||||||
// cssTarget: 'chrome86',
|
|
||||||
outDir: OUTPUT_DIR,
|
outDir: OUTPUT_DIR,
|
||||||
terserOptions: {
|
// minify: 'terser',
|
||||||
compress: {
|
/**
|
||||||
keep_infinity: true,
|
* 当 minify=“minify:'terser'” 解开注释
|
||||||
// Used to delete console in production environment
|
* Uncomment when minify="minify:'terser'"
|
||||||
drop_console: VITE_DROP_CONSOLE,
|
*/
|
||||||
},
|
// terserOptions: {
|
||||||
},
|
// compress: {
|
||||||
|
// keep_infinity: true,
|
||||||
|
// drop_console: VITE_DROP_CONSOLE,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
// Turning off brotliSize display can slightly reduce packaging time
|
// Turning off brotliSize display can slightly reduce packaging time
|
||||||
brotliSize: false,
|
brotliSize: false,
|
||||||
chunkSizeWarningLimit: 2000,
|
chunkSizeWarningLimit: 2000,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue