new-map
parent
dbdc655406
commit
8aaaa449d6
|
|
@ -73,4 +73,4 @@ module.exports = {
|
||||||
],
|
],
|
||||||
'vue/multi-word-component-names': 'off',
|
'vue/multi-word-component-names': 'off',
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# shellcheck source=./_/husky.sh
|
|
||||||
. "$(dirname "$0")/_/husky.sh"
|
|
||||||
|
|
||||||
# npx --no-install commitlint --edit "$1"
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
command_exists () {
|
|
||||||
command -v "$1" >/dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Workaround for Windows 10, Git Bash and Yarn
|
|
||||||
if command_exists winpty && test -t 1; then
|
|
||||||
exec < /dev/tty
|
|
||||||
fi
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
. "$(dirname "$0")/_/husky.sh"
|
|
||||||
. "$(dirname "$0")/common.sh"
|
|
||||||
|
|
||||||
[ -n "$CI" ] && exit 0
|
|
||||||
|
|
||||||
# Format and submit code according to lintstagedrc.js configuration
|
|
||||||
npm run lint:lint-staged
|
|
||||||
|
|
@ -1,33 +1,33 @@
|
||||||
import { generate } from '@ant-design/colors';
|
import { generate } from '@ant-design/colors'
|
||||||
|
|
||||||
export const primaryColor = '#0960bd';
|
export const primaryColor = '#0960bd'
|
||||||
|
|
||||||
export const darkMode = 'light';
|
export const darkMode = 'light'
|
||||||
|
|
||||||
type Fn = (...arg: any) => any;
|
type Fn = (...arg: any) => any
|
||||||
|
|
||||||
type GenerateTheme = 'default' | 'dark';
|
type GenerateTheme = 'default' | 'dark'
|
||||||
|
|
||||||
export interface GenerateColorsParams {
|
export interface GenerateColorsParams {
|
||||||
mixLighten: Fn;
|
mixLighten: Fn
|
||||||
mixDarken: Fn;
|
mixDarken: Fn
|
||||||
tinycolor: any;
|
tinycolor: any
|
||||||
color?: string;
|
color?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateAntColors(color: string, theme: GenerateTheme = 'default') {
|
export function generateAntColors(color: string, theme: GenerateTheme = 'default') {
|
||||||
return generate(color, {
|
return generate(color, {
|
||||||
theme,
|
theme,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getThemeColors(color?: string) {
|
export function getThemeColors(color?: string) {
|
||||||
const tc = color || primaryColor;
|
const tc = color || primaryColor
|
||||||
const lightColors = generateAntColors(tc);
|
const lightColors = generateAntColors(tc)
|
||||||
const primary = lightColors[5];
|
const primary = lightColors[5]
|
||||||
const modeColors = generateAntColors(primary, 'dark');
|
const modeColors = generateAntColors(primary, 'dark')
|
||||||
|
|
||||||
return [...lightColors, ...modeColors];
|
return [...lightColors, ...modeColors]
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateColors({
|
export function generateColors({
|
||||||
|
|
@ -36,38 +36,38 @@ export function generateColors({
|
||||||
mixDarken,
|
mixDarken,
|
||||||
tinycolor,
|
tinycolor,
|
||||||
}: GenerateColorsParams) {
|
}: GenerateColorsParams) {
|
||||||
const arr = new Array(19).fill(0);
|
const arr = new Array(19).fill(0)
|
||||||
const lightens = arr.map((_t, i) => {
|
const lightens = arr.map((_t, i) => {
|
||||||
return mixLighten(color, i / 5);
|
return mixLighten(color, i / 5)
|
||||||
});
|
})
|
||||||
|
|
||||||
const darkens = arr.map((_t, i) => {
|
const darkens = arr.map((_t, i) => {
|
||||||
return mixDarken(color, i / 5);
|
return mixDarken(color, i / 5)
|
||||||
});
|
})
|
||||||
|
|
||||||
const alphaColors = arr.map((_t, i) => {
|
const alphaColors = arr.map((_t, i) => {
|
||||||
return tinycolor(color)
|
return tinycolor(color)
|
||||||
.setAlpha(i / 20)
|
.setAlpha(i / 20)
|
||||||
.toRgbString();
|
.toRgbString()
|
||||||
});
|
})
|
||||||
|
|
||||||
const shortAlphaColors = alphaColors.map((item) => item.replace(/\s/g, '').replace(/0\./g, '.'));
|
const shortAlphaColors = alphaColors.map((item) => item.replace(/\s/g, '').replace(/0\./g, '.'))
|
||||||
|
|
||||||
const tinycolorLightens = arr
|
const tinycolorLightens = arr
|
||||||
.map((_t, i) => {
|
.map((_t, i) => {
|
||||||
return tinycolor(color)
|
return tinycolor(color)
|
||||||
.lighten(i * 5)
|
.lighten(i * 5)
|
||||||
.toHexString();
|
.toHexString()
|
||||||
})
|
})
|
||||||
.filter((item) => item !== '#ffffff');
|
.filter((item) => item !== '#ffffff')
|
||||||
|
|
||||||
const tinycolorDarkens = arr
|
const tinycolorDarkens = arr
|
||||||
.map((_t, i) => {
|
.map((_t, i) => {
|
||||||
return tinycolor(color)
|
return tinycolor(color)
|
||||||
.darken(i * 5)
|
.darken(i * 5)
|
||||||
.toHexString();
|
.toHexString()
|
||||||
})
|
})
|
||||||
.filter((item) => item !== '#000000');
|
.filter((item) => item !== '#000000')
|
||||||
return [
|
return [
|
||||||
...lightens,
|
...lightens,
|
||||||
...darkens,
|
...darkens,
|
||||||
|
|
@ -75,5 +75,5 @@ export function generateColors({
|
||||||
...shortAlphaColors,
|
...shortAlphaColors,
|
||||||
...tinycolorDarkens,
|
...tinycolorDarkens,
|
||||||
...tinycolorLightens,
|
...tinycolorLightens,
|
||||||
].filter((item) => !item.includes('-'));
|
].filter((item) => !item.includes('-'))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
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 colors from 'picocolors';
|
import colors from 'picocolors'
|
||||||
import pkg from '../../../package.json';
|
import pkg from '../../../package.json'
|
||||||
|
|
||||||
async function generateIcon() {
|
async function generateIcon() {
|
||||||
const dir = path.resolve(process.cwd(), 'node_modules/@iconify/json');
|
const dir = path.resolve(process.cwd(), 'node_modules/@iconify/json')
|
||||||
|
|
||||||
const raw = await fs.readJSON(path.join(dir, 'collections.json'));
|
const raw = await fs.readJSON(path.join(dir, 'collections.json'))
|
||||||
|
|
||||||
const collections = Object.entries(raw).map(([id, v]) => ({
|
const collections = Object.entries(raw).map(([id, v]) => ({
|
||||||
...(v as any),
|
...(v as any),
|
||||||
id,
|
id,
|
||||||
}));
|
}))
|
||||||
|
|
||||||
const choices = collections.map((item) => ({ key: item.id, value: item.id, name: item.name }));
|
const choices = collections.map((item) => ({ key: item.id, value: item.id, name: item.name }))
|
||||||
|
|
||||||
inquirer
|
inquirer
|
||||||
.prompt([
|
.prompt([
|
||||||
|
|
@ -41,32 +41,32 @@ async function generateIcon() {
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
.then(async (answers) => {
|
.then(async (answers) => {
|
||||||
const { iconSet, output, useType } = answers;
|
const { iconSet, output, useType } = answers
|
||||||
const outputDir = path.resolve(process.cwd(), output);
|
const outputDir = path.resolve(process.cwd(), output)
|
||||||
fs.ensureDir(outputDir);
|
fs.ensureDir(outputDir)
|
||||||
const genCollections = collections.filter((item) => [iconSet].includes(item.id));
|
const genCollections = collections.filter((item) => [iconSet].includes(item.id))
|
||||||
const prefixSet: string[] = [];
|
const prefixSet: string[] = []
|
||||||
for (const info of genCollections) {
|
for (const info of genCollections) {
|
||||||
const data = await fs.readJSON(path.join(dir, 'json', `${info.id}.json`));
|
const data = await fs.readJSON(path.join(dir, 'json', `${info.id}.json`))
|
||||||
if (data) {
|
if (data) {
|
||||||
const { prefix } = data;
|
const { prefix } = data
|
||||||
const isLocal = useType === 'local';
|
const isLocal = useType === 'local'
|
||||||
const icons = Object.keys(data.icons).map(
|
const icons = Object.keys(data.icons).map(
|
||||||
(item) => `${isLocal ? prefix + ':' : ''}${item}`,
|
(item) => `${isLocal ? prefix + ':' : ''}${item}`,
|
||||||
);
|
)
|
||||||
|
|
||||||
await fs.writeFileSync(
|
await fs.writeFileSync(
|
||||||
path.join(output, `icons.data.ts`),
|
path.join(output, `icons.data.ts`),
|
||||||
`export default ${isLocal ? JSON.stringify(icons) : JSON.stringify({ prefix, icons })}`,
|
`export default ${isLocal ? JSON.stringify(icons) : JSON.stringify({ prefix, icons })}`,
|
||||||
);
|
)
|
||||||
prefixSet.push(prefix);
|
prefixSet.push(prefix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fs.emptyDir(path.join(process.cwd(), 'node_modules/.vite'));
|
fs.emptyDir(path.join(process.cwd(), 'node_modules/.vite'))
|
||||||
console.log(
|
console.log(
|
||||||
`✨ ${colors.cyan(`[${pkg.name}]`)}` + ' - Icon generated successfully:' + `[${prefixSet}]`,
|
`✨ ${colors.cyan(`[${pkg.name}]`)}` + ' - Icon generated successfully:' + `[${prefixSet}]`,
|
||||||
);
|
)
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
generateIcon();
|
generateIcon()
|
||||||
|
|
|
||||||
|
|
@ -1,47 +1,47 @@
|
||||||
/**
|
/**
|
||||||
* Generate additional configuration files when used for packaging. The file can be configured with some global variables, so that it can be changed directly externally without repackaging
|
* Generate additional configuration files when used for packaging. The file can be configured with some global variables, so that it can be changed directly externally without repackaging
|
||||||
*/
|
*/
|
||||||
import { GLOB_CONFIG_FILE_NAME, OUTPUT_DIR } from '../constant';
|
import { GLOB_CONFIG_FILE_NAME, OUTPUT_DIR } from '../constant'
|
||||||
import fs, { writeFileSync } from 'fs-extra';
|
import fs, { writeFileSync } from 'fs-extra'
|
||||||
import colors from 'picocolors';
|
import colors from 'picocolors'
|
||||||
|
|
||||||
import { getEnvConfig, getRootPath } from '../utils';
|
import { getEnvConfig, getRootPath } from '../utils'
|
||||||
import { getConfigFileName } from '../getConfigFileName';
|
import { getConfigFileName } from '../getConfigFileName'
|
||||||
|
|
||||||
import pkg from '../../package.json';
|
import pkg from '../../package.json'
|
||||||
|
|
||||||
interface CreateConfigParams {
|
interface CreateConfigParams {
|
||||||
configName: string;
|
configName: string
|
||||||
config: any;
|
config: any
|
||||||
configFileName?: string;
|
configFileName?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function createConfig(params: CreateConfigParams) {
|
function createConfig(params: CreateConfigParams) {
|
||||||
const { configName, config, configFileName } = params;
|
const { configName, config, configFileName } = params
|
||||||
try {
|
try {
|
||||||
const windowConf = `window.${configName}`;
|
const windowConf = `window.${configName}`
|
||||||
// Ensure that the variable will not be modified
|
// Ensure that the variable will not be modified
|
||||||
let configStr = `${windowConf}=${JSON.stringify(config)};`;
|
let configStr = `${windowConf}=${JSON.stringify(config)};`
|
||||||
configStr += `
|
configStr += `
|
||||||
Object.freeze(${windowConf});
|
Object.freeze(${windowConf});
|
||||||
Object.defineProperty(window, "${configName}", {
|
Object.defineProperty(window, "${configName}", {
|
||||||
configurable: false,
|
configurable: false,
|
||||||
writable: false,
|
writable: false,
|
||||||
});
|
});
|
||||||
`.replace(/\s/g, '');
|
`.replace(/\s/g, '')
|
||||||
|
|
||||||
fs.mkdirp(getRootPath(OUTPUT_DIR));
|
fs.mkdirp(getRootPath(OUTPUT_DIR))
|
||||||
writeFileSync(getRootPath(`${OUTPUT_DIR}/${configFileName}`), configStr);
|
writeFileSync(getRootPath(`${OUTPUT_DIR}/${configFileName}`), configStr)
|
||||||
|
|
||||||
console.log(colors.cyan(`✨ [${pkg.name}]`) + ` - configuration file is build successfully:`);
|
console.log(colors.cyan(`✨ [${pkg.name}]`) + ` - configuration file is build successfully:`)
|
||||||
console.log(colors.gray(OUTPUT_DIR + '/' + colors.green(configFileName)) + '\n');
|
console.log(colors.gray(OUTPUT_DIR + '/' + colors.green(configFileName)) + '\n')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(colors.red('configuration file configuration file failed to package:\n' + error));
|
console.log(colors.red('configuration file configuration file failed to package:\n' + error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function runBuildConfig() {
|
export function runBuildConfig() {
|
||||||
const config = getEnvConfig();
|
const config = getEnvConfig()
|
||||||
const configFileName = getConfigFileName(config);
|
const configFileName = getConfigFileName(config)
|
||||||
createConfig({ config, configName: configFileName, configFileName: GLOB_CONFIG_FILE_NAME });
|
createConfig({ config, configName: configFileName, configFileName: GLOB_CONFIG_FILE_NAME })
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,23 @@
|
||||||
// #!/usr/bin/env node
|
// #!/usr/bin/env node
|
||||||
|
|
||||||
import { runBuildConfig } from './buildConf';
|
import { runBuildConfig } from './buildConf'
|
||||||
import colors from 'picocolors';
|
import colors from 'picocolors'
|
||||||
|
|
||||||
import pkg from '../../package.json';
|
import pkg from '../../package.json'
|
||||||
|
|
||||||
export const runBuild = async () => {
|
export const runBuild = async () => {
|
||||||
try {
|
try {
|
||||||
const argvList = process.argv.splice(2);
|
const argvList = process.argv.splice(2)
|
||||||
|
|
||||||
// Generate configuration file
|
// Generate configuration file
|
||||||
if (!argvList.includes('disabled-config')) {
|
if (!argvList.includes('disabled-config')) {
|
||||||
runBuildConfig();
|
runBuildConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`✨ ${colors.cyan(`[${pkg.name}]`)}` + ' - build successfully!');
|
console.log(`✨ ${colors.cyan(`[${pkg.name}]`)}` + ' - build successfully!')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(colors.red('vite build error:\n' + error));
|
console.log(colors.red('vite build error:\n' + error))
|
||||||
process.exit(1);
|
process.exit(1)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
runBuild();
|
runBuild()
|
||||||
|
|
|
||||||
|
|
@ -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 { PluginOption } 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,
|
||||||
): PluginOption | PluginOption[] {
|
): PluginOption | PluginOption[] {
|
||||||
const compressList = compress.split(',');
|
const compressList = compress.split(',')
|
||||||
|
|
||||||
const plugins: PluginOption[] = [];
|
const plugins: PluginOption[] = []
|
||||||
|
|
||||||
if (compressList.includes('gzip')) {
|
if (compressList.includes('gzip')) {
|
||||||
plugins.push(
|
plugins.push(
|
||||||
|
|
@ -19,7 +19,7 @@ export function configCompressPlugin(
|
||||||
ext: '.gz',
|
ext: '.gz',
|
||||||
deleteOriginFile,
|
deleteOriginFile,
|
||||||
}),
|
}),
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compressList.includes('brotli')) {
|
if (compressList.includes('brotli')) {
|
||||||
|
|
@ -29,7 +29,7 @@ export function configCompressPlugin(
|
||||||
algorithm: 'brotliCompress',
|
algorithm: 'brotliCompress',
|
||||||
deleteOriginFile,
|
deleteOriginFile,
|
||||||
}),
|
}),
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
return plugins;
|
return plugins
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,19 +2,19 @@
|
||||||
* 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 { PluginOption } from 'vite';
|
import type { PluginOption } from 'vite'
|
||||||
import { createHtmlPlugin } 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'
|
||||||
|
|
||||||
export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) {
|
export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) {
|
||||||
const { VITE_GLOB_APP_TITLE, VITE_PUBLIC_PATH } = env;
|
const { VITE_GLOB_APP_TITLE, VITE_PUBLIC_PATH } = env
|
||||||
|
|
||||||
const path = VITE_PUBLIC_PATH.endsWith('/') ? VITE_PUBLIC_PATH : `${VITE_PUBLIC_PATH}/`;
|
const path = VITE_PUBLIC_PATH.endsWith('/') ? VITE_PUBLIC_PATH : `${VITE_PUBLIC_PATH}/`
|
||||||
|
|
||||||
const getAppConfigSrc = () => {
|
const getAppConfigSrc = () => {
|
||||||
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: PluginOption[] = createHtmlPlugin({
|
const htmlPlugin: PluginOption[] = createHtmlPlugin({
|
||||||
minify: isBuild,
|
minify: isBuild,
|
||||||
|
|
@ -35,6 +35,6 @@ export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) {
|
||||||
]
|
]
|
||||||
: [],
|
: [],
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
return htmlPlugin;
|
return htmlPlugin
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
* https://github.com/anncwb/vite-plugin-svg-icons
|
* https://github.com/anncwb/vite-plugin-svg-icons
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { createSvgIconsPlugin } 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 = createSvgIconsPlugin({
|
const svgIconsPlugin = createSvgIconsPlugin({
|
||||||
|
|
@ -12,6 +12,6 @@ export function configSvgIconsPlugin(isBuild: boolean) {
|
||||||
svgoOptions: isBuild,
|
svgoOptions: isBuild,
|
||||||
// default
|
// default
|
||||||
symbolId: 'icon-[dir]-[name]',
|
symbolId: 'icon-[dir]-[name]',
|
||||||
});
|
})
|
||||||
return svgIconsPlugin;
|
return svgIconsPlugin
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,46 +2,46 @@
|
||||||
* 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 { PluginOption } from 'vite';
|
import type { PluginOption } from 'vite'
|
||||||
import path from 'path';
|
import path from 'path'
|
||||||
import {
|
import {
|
||||||
viteThemePlugin,
|
viteThemePlugin,
|
||||||
antdDarkThemePlugin,
|
antdDarkThemePlugin,
|
||||||
mixLighten,
|
mixLighten,
|
||||||
mixDarken,
|
mixDarken,
|
||||||
tinycolor,
|
tinycolor,
|
||||||
} from 'vite-plugin-theme';
|
} from 'vite-plugin-theme'
|
||||||
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): PluginOption[] {
|
export function configThemePlugin(isBuild: boolean): PluginOption[] {
|
||||||
const colors = generateColors({
|
const colors = generateColors({
|
||||||
mixDarken,
|
mixDarken,
|
||||||
mixLighten,
|
mixLighten,
|
||||||
tinycolor,
|
tinycolor,
|
||||||
});
|
})
|
||||||
const plugin = [
|
const plugin = [
|
||||||
viteThemePlugin({
|
viteThemePlugin({
|
||||||
resolveSelector: (s) => {
|
resolveSelector: (s) => {
|
||||||
s = s.trim();
|
s = s.trim()
|
||||||
switch (s) {
|
switch (s) {
|
||||||
case '.ant-steps-item-process .ant-steps-item-icon > .ant-steps-icon':
|
case '.ant-steps-item-process .ant-steps-item-icon > .ant-steps-icon':
|
||||||
return '.ant-steps-item-icon > .ant-steps-icon';
|
return '.ant-steps-item-icon > .ant-steps-icon'
|
||||||
case '.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled)':
|
case '.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled)':
|
||||||
case '.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):hover':
|
case '.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):hover':
|
||||||
case '.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):active':
|
case '.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):active':
|
||||||
return s;
|
return s
|
||||||
case '.ant-steps-item-icon > .ant-steps-icon':
|
case '.ant-steps-item-icon > .ant-steps-icon':
|
||||||
return s;
|
return s
|
||||||
case '.ant-select-item-option-selected:not(.ant-select-item-option-disabled)':
|
case '.ant-select-item-option-selected:not(.ant-select-item-option-disabled)':
|
||||||
return s;
|
return s
|
||||||
default:
|
default:
|
||||||
if (s.indexOf('.ant-btn') >= -1) {
|
if (s.indexOf('.ant-btn') >= -1) {
|
||||||
// 按钮被重新定制过,需要过滤掉class防止覆盖
|
// 按钮被重新定制过,需要过滤掉class防止覆盖
|
||||||
return s;
|
return s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s.startsWith('[data-theme') ? s : `[data-theme] ${s}`;
|
return s.startsWith('[data-theme') ? s : `[data-theme] ${s}`
|
||||||
},
|
},
|
||||||
colorVariables: [...getThemeColors(), ...colors],
|
colorVariables: [...getThemeColors(), ...colors],
|
||||||
}),
|
}),
|
||||||
|
|
@ -83,7 +83,7 @@ export function configThemePlugin(isBuild: boolean): PluginOption[] {
|
||||||
'alert-error-icon-color': '#a61d24',
|
'alert-error-icon-color': '#a61d24',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
];
|
]
|
||||||
|
|
||||||
return plugin as unknown as PluginOption[];
|
return plugin as unknown as PluginOption[]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,13 +18,13 @@
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { LocaleType } from '/#/config';
|
import type { LocaleType } from '/#/config'
|
||||||
import type { DropMenu } from '/@/components/Dropdown';
|
import type { DropMenu } from '/@/components/Dropdown'
|
||||||
import { ref, watchEffect, unref, computed } from 'vue';
|
import { ref, watchEffect, unref, computed } from 'vue'
|
||||||
import { Dropdown } from '/@/components/Dropdown';
|
import { Dropdown } from '/@/components/Dropdown'
|
||||||
import { Icon } from '/@/components/Icon';
|
import { Icon } from '/@/components/Icon'
|
||||||
import { useLocale } from '/@/locales/useLocale';
|
import { useLocale } from '/@/locales/useLocale'
|
||||||
import { localeList } from '/@/settings/localeSetting';
|
import { localeList } from '/@/settings/localeSetting'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
/**
|
/**
|
||||||
|
|
@ -35,35 +35,35 @@
|
||||||
* Whether to refresh the interface when changing
|
* Whether to refresh the interface when changing
|
||||||
*/
|
*/
|
||||||
reload: { type: Boolean },
|
reload: { type: Boolean },
|
||||||
});
|
})
|
||||||
|
|
||||||
const selectedKeys = ref<string[]>([]);
|
const selectedKeys = ref<string[]>([])
|
||||||
|
|
||||||
const { changeLocale, getLocale } = useLocale();
|
const { changeLocale, getLocale } = useLocale()
|
||||||
|
|
||||||
const getLocaleText = computed(() => {
|
const getLocaleText = computed(() => {
|
||||||
const key = selectedKeys.value[0];
|
const key = selectedKeys.value[0]
|
||||||
if (!key) {
|
if (!key) {
|
||||||
return '';
|
return ''
|
||||||
}
|
}
|
||||||
return localeList.find((item) => item.event === key)?.text;
|
return localeList.find((item) => item.event === key)?.text
|
||||||
});
|
})
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
selectedKeys.value = [unref(getLocale)];
|
selectedKeys.value = [unref(getLocale)]
|
||||||
});
|
})
|
||||||
|
|
||||||
async function toggleLocale(lang: LocaleType | string) {
|
async function toggleLocale(lang: LocaleType | string) {
|
||||||
await changeLocale(lang as LocaleType);
|
await changeLocale(lang as LocaleType)
|
||||||
selectedKeys.value = [lang as string];
|
selectedKeys.value = [lang as string]
|
||||||
props.reload && location.reload();
|
props.reload && location.reload()
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMenuEvent(menu: DropMenu) {
|
function handleMenuEvent(menu: DropMenu) {
|
||||||
if (unref(getLocale) === menu.event) {
|
if (unref(getLocale) === menu.event) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
toggleLocale(menu.event as string);
|
toggleLocale(menu.event as string)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,17 +23,17 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { PropType } from 'vue';
|
import type { PropType } from 'vue'
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue'
|
||||||
import { isNil } from 'lodash-es';
|
import { isNil } from 'lodash-es'
|
||||||
// component
|
// component
|
||||||
import { Skeleton } from 'ant-design-vue';
|
import { Skeleton } from 'ant-design-vue'
|
||||||
import { CollapseTransition } from '/@/components/Transition';
|
import { CollapseTransition } from '/@/components/Transition'
|
||||||
import CollapseHeader from './CollapseHeader.vue';
|
import CollapseHeader from './CollapseHeader.vue'
|
||||||
import { triggerWindowResize } from '/@/utils/event';
|
import { triggerWindowResize } from '/@/utils/event'
|
||||||
// hook
|
// hook
|
||||||
import { useTimeoutFn } from '/@/hooks/core/useTimeout';
|
import { useTimeoutFn } from '/@/hooks/core/useTimeout'
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
title: { type: String, default: '' },
|
title: { type: String, default: '' },
|
||||||
|
|
@ -58,26 +58,26 @@
|
||||||
* Delayed loading time
|
* Delayed loading time
|
||||||
*/
|
*/
|
||||||
lazyTime: { type: Number, default: 0 },
|
lazyTime: { type: Number, default: 0 },
|
||||||
});
|
})
|
||||||
|
|
||||||
const show = ref(true);
|
const show = ref(true)
|
||||||
|
|
||||||
const { prefixCls } = useDesign('collapse-container');
|
const { prefixCls } = useDesign('collapse-container')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description: Handling development events
|
* @description: Handling development events
|
||||||
*/
|
*/
|
||||||
function handleExpand(val: boolean) {
|
function handleExpand(val: boolean) {
|
||||||
show.value = isNil(val) ? !show.value : val;
|
show.value = isNil(val) ? !show.value : val
|
||||||
if (props.triggerWindowResize) {
|
if (props.triggerWindowResize) {
|
||||||
// 200 milliseconds here is because the expansion has animation,
|
// 200 milliseconds here is because the expansion has animation,
|
||||||
useTimeoutFn(triggerWindowResize, 200);
|
useTimeoutFn(triggerWindowResize, 200)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
handleExpand,
|
handleExpand,
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@prefix-cls: ~'@{namespace}-collapse-container';
|
@prefix-cls: ~'@{namespace}-collapse-container';
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import type { ContextMenuItem, ItemContentProps, Axis } from './typing';
|
import type { ContextMenuItem, ItemContentProps, Axis } from './typing'
|
||||||
import type { FunctionalComponent, CSSProperties, PropType } from 'vue';
|
import type { FunctionalComponent, CSSProperties, PropType } from 'vue'
|
||||||
import { defineComponent, nextTick, onMounted, computed, ref, unref, onUnmounted } from 'vue';
|
import { defineComponent, nextTick, onMounted, computed, ref, unref, onUnmounted } from 'vue'
|
||||||
import Icon from '/@/components/Icon';
|
import Icon from '/@/components/Icon'
|
||||||
import { Menu, Divider } from 'ant-design-vue';
|
import { Menu, Divider } from 'ant-design-vue'
|
||||||
|
|
||||||
const prefixCls = 'context-menu';
|
const prefixCls = 'context-menu'
|
||||||
|
|
||||||
const props = {
|
const props = {
|
||||||
width: { type: Number, default: 156 },
|
width: { type: Number, default: 156 },
|
||||||
|
|
@ -16,20 +16,20 @@
|
||||||
// The position of the right mouse button click
|
// The position of the right mouse button click
|
||||||
type: Object as PropType<Axis>,
|
type: Object as PropType<Axis>,
|
||||||
default() {
|
default() {
|
||||||
return { x: 0, y: 0 };
|
return { x: 0, y: 0 }
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
items: {
|
items: {
|
||||||
// The most important list, if not, will not be displayed
|
// The most important list, if not, will not be displayed
|
||||||
type: Array as PropType<ContextMenuItem[]>,
|
type: Array as PropType<ContextMenuItem[]>,
|
||||||
default() {
|
default() {
|
||||||
return [];
|
return []
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|
||||||
const ItemContent: FunctionalComponent<ItemContentProps> = (props) => {
|
const ItemContent: FunctionalComponent<ItemContentProps> = (props) => {
|
||||||
const { item } = props;
|
const { item } = props
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
style="display: inline-block; width: 100%; "
|
style="display: inline-block; width: 100%; "
|
||||||
|
|
@ -39,25 +39,25 @@
|
||||||
{props.showIcon && item.icon && <Icon class="mr-2" icon={item.icon} />}
|
{props.showIcon && item.icon && <Icon class="mr-2" icon={item.icon} />}
|
||||||
<span>{item.label}</span>
|
<span>{item.label}</span>
|
||||||
</span>
|
</span>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'ContextMenu',
|
name: 'ContextMenu',
|
||||||
props,
|
props,
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const wrapRef = ref(null);
|
const wrapRef = ref(null)
|
||||||
const showRef = ref(false);
|
const showRef = ref(false)
|
||||||
|
|
||||||
const getStyle = computed((): CSSProperties => {
|
const getStyle = computed((): CSSProperties => {
|
||||||
const { axis, items, styles, width } = props;
|
const { axis, items, styles, width } = props
|
||||||
const { x, y } = axis || { x: 0, y: 0 };
|
const { x, y } = axis || { x: 0, y: 0 }
|
||||||
const menuHeight = (items || []).length * 40;
|
const menuHeight = (items || []).length * 40
|
||||||
const menuWidth = width;
|
const menuWidth = width
|
||||||
const body = document.body;
|
const body = document.body
|
||||||
|
|
||||||
const left = body.clientWidth < x + menuWidth ? x - menuWidth : x;
|
const left = body.clientWidth < x + menuWidth ? x - menuWidth : x
|
||||||
const top = body.clientHeight < y + menuHeight ? y - menuHeight : y;
|
const top = body.clientHeight < y + menuHeight ? y - menuHeight : y
|
||||||
return {
|
return {
|
||||||
...styles,
|
...styles,
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
|
@ -65,39 +65,39 @@
|
||||||
left: `${left + 1}px`,
|
left: `${left + 1}px`,
|
||||||
top: `${top + 1}px`,
|
top: `${top + 1}px`,
|
||||||
zIndex: 9999,
|
zIndex: 9999,
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
nextTick(() => (showRef.value = true));
|
nextTick(() => (showRef.value = true))
|
||||||
});
|
})
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
const el = unref(wrapRef);
|
const el = unref(wrapRef)
|
||||||
el && document.body.removeChild(el);
|
el && document.body.removeChild(el)
|
||||||
});
|
})
|
||||||
|
|
||||||
function handleAction(item: ContextMenuItem, e: MouseEvent) {
|
function handleAction(item: ContextMenuItem, e: MouseEvent) {
|
||||||
const { handler, disabled } = item;
|
const { handler, disabled } = item
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
showRef.value = false;
|
showRef.value = false
|
||||||
e?.stopPropagation();
|
e?.stopPropagation()
|
||||||
e?.preventDefault();
|
e?.preventDefault()
|
||||||
handler?.();
|
handler?.()
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderMenuItem(items: ContextMenuItem[]) {
|
function renderMenuItem(items: ContextMenuItem[]) {
|
||||||
const visibleItems = items.filter((item) => !item.hidden);
|
const visibleItems = items.filter((item) => !item.hidden)
|
||||||
return visibleItems.map((item) => {
|
return visibleItems.map((item) => {
|
||||||
const { disabled, label, children, divider = false } = item;
|
const { disabled, label, children, divider = false } = item
|
||||||
|
|
||||||
const contentProps = {
|
const contentProps = {
|
||||||
item,
|
item,
|
||||||
handler: handleAction,
|
handler: handleAction,
|
||||||
showIcon: props.showIcon,
|
showIcon: props.showIcon,
|
||||||
};
|
}
|
||||||
|
|
||||||
if (!children || children.length === 0) {
|
if (!children || children.length === 0) {
|
||||||
return (
|
return (
|
||||||
|
|
@ -107,9 +107,9 @@
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
{divider ? <Divider key={`d-${label}`} /> : null}
|
{divider ? <Divider key={`d-${label}`} /> : null}
|
||||||
</>
|
</>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
if (!unref(showRef)) return null;
|
if (!unref(showRef)) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Menu.SubMenu key={label} disabled={disabled} popupClassName={`${prefixCls}__popup`}>
|
<Menu.SubMenu key={label} disabled={disabled} popupClassName={`${prefixCls}__popup`}>
|
||||||
|
|
@ -118,24 +118,24 @@
|
||||||
default: () => renderMenuItem(children),
|
default: () => renderMenuItem(children),
|
||||||
}}
|
}}
|
||||||
</Menu.SubMenu>
|
</Menu.SubMenu>
|
||||||
);
|
)
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
return () => {
|
return () => {
|
||||||
if (!unref(showRef)) {
|
if (!unref(showRef)) {
|
||||||
return null;
|
return null
|
||||||
}
|
}
|
||||||
const { items } = props;
|
const { items } = props
|
||||||
return (
|
return (
|
||||||
<div class={prefixCls}>
|
<div class={prefixCls}>
|
||||||
<Menu inlineIndent={12} mode="vertical" ref={wrapRef} style={unref(getStyle)}>
|
<Menu inlineIndent={12} mode="vertical" ref={wrapRef} style={unref(getStyle)}>
|
||||||
{renderMenuItem(items)}
|
{renderMenuItem(items)}
|
||||||
</Menu>
|
</Menu>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@default-height: 42px !important;
|
@default-height: 42px !important;
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,36 @@
|
||||||
export interface Axis {
|
export interface Axis {
|
||||||
x: number;
|
x: number
|
||||||
y: number;
|
y: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ContextMenuItem {
|
export interface ContextMenuItem {
|
||||||
label: string;
|
label: string
|
||||||
icon?: string;
|
icon?: string
|
||||||
hidden?: boolean;
|
hidden?: boolean
|
||||||
disabled?: boolean;
|
disabled?: boolean
|
||||||
handler?: Fn;
|
handler?: Fn
|
||||||
divider?: boolean;
|
divider?: boolean
|
||||||
children?: ContextMenuItem[];
|
children?: ContextMenuItem[]
|
||||||
}
|
}
|
||||||
export interface CreateContextOptions {
|
export interface CreateContextOptions {
|
||||||
event: MouseEvent;
|
event: MouseEvent
|
||||||
icon?: string;
|
icon?: string
|
||||||
styles?: any;
|
styles?: any
|
||||||
items?: ContextMenuItem[];
|
items?: ContextMenuItem[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ContextMenuProps {
|
export interface ContextMenuProps {
|
||||||
event?: MouseEvent;
|
event?: MouseEvent
|
||||||
styles?: any;
|
styles?: any
|
||||||
items: ContextMenuItem[];
|
items: ContextMenuItem[]
|
||||||
customEvent?: MouseEvent;
|
customEvent?: MouseEvent
|
||||||
axis?: Axis;
|
axis?: Axis
|
||||||
width?: number;
|
width?: number
|
||||||
showIcon?: boolean;
|
showIcon?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ItemContentProps {
|
export interface ItemContentProps {
|
||||||
showIcon: boolean | undefined;
|
showIcon: boolean | undefined
|
||||||
item: ContextMenuItem;
|
item: ContextMenuItem
|
||||||
handler: Fn;
|
handler: Fn
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,8 @@
|
||||||
</Drawer>
|
</Drawer>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { DrawerInstance, DrawerProps } from './typing';
|
import type { DrawerInstance, DrawerProps } from './typing'
|
||||||
import type { CSSProperties } from 'vue';
|
import type { CSSProperties } from 'vue'
|
||||||
import {
|
import {
|
||||||
defineComponent,
|
defineComponent,
|
||||||
ref,
|
ref,
|
||||||
|
|
@ -42,17 +42,17 @@
|
||||||
nextTick,
|
nextTick,
|
||||||
toRaw,
|
toRaw,
|
||||||
getCurrentInstance,
|
getCurrentInstance,
|
||||||
} from 'vue';
|
} from 'vue'
|
||||||
import { Drawer } from 'ant-design-vue';
|
import { Drawer } from 'ant-design-vue'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
import { isFunction, isNumber } from '/@/utils/is';
|
import { isFunction, isNumber } from '/@/utils/is'
|
||||||
import { deepMerge } from '/@/utils';
|
import { deepMerge } from '/@/utils'
|
||||||
import DrawerFooter from './components/DrawerFooter.vue';
|
import DrawerFooter from './components/DrawerFooter.vue'
|
||||||
import DrawerHeader from './components/DrawerHeader.vue';
|
import DrawerHeader from './components/DrawerHeader.vue'
|
||||||
import { ScrollContainer } from '/@/components/Container';
|
import { ScrollContainer } from '/@/components/Container'
|
||||||
import { basicProps } from './props';
|
import { basicProps } from './props'
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
import { useAttrs } from '/@/hooks/core/useAttrs';
|
import { useAttrs } from '/@/hooks/core/useAttrs'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: { Drawer, ScrollContainer, DrawerFooter, DrawerHeader },
|
components: { Drawer, ScrollContainer, DrawerFooter, DrawerHeader },
|
||||||
|
|
@ -60,25 +60,25 @@
|
||||||
props: basicProps,
|
props: basicProps,
|
||||||
emits: ['visible-change', 'ok', 'close', 'register'],
|
emits: ['visible-change', 'ok', 'close', 'register'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const visibleRef = ref(false);
|
const visibleRef = ref(false)
|
||||||
const attrs = useAttrs();
|
const attrs = useAttrs()
|
||||||
const propsRef = ref<Partial<Nullable<DrawerProps>>>(null);
|
const propsRef = ref<Partial<Nullable<DrawerProps>>>(null)
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
const { prefixVar, prefixCls } = useDesign('basic-drawer');
|
const { prefixVar, prefixCls } = useDesign('basic-drawer')
|
||||||
|
|
||||||
const drawerInstance: DrawerInstance = {
|
const drawerInstance: DrawerInstance = {
|
||||||
setDrawerProps: setDrawerProps,
|
setDrawerProps: setDrawerProps,
|
||||||
emitVisible: undefined,
|
emitVisible: undefined,
|
||||||
};
|
}
|
||||||
|
|
||||||
const instance = getCurrentInstance();
|
const instance = getCurrentInstance()
|
||||||
|
|
||||||
instance && emit('register', drawerInstance, instance.uid);
|
instance && emit('register', drawerInstance, instance.uid)
|
||||||
|
|
||||||
const getMergeProps = computed((): DrawerProps => {
|
const getMergeProps = computed((): DrawerProps => {
|
||||||
return deepMerge(toRaw(props), unref(propsRef));
|
return deepMerge(toRaw(props), unref(propsRef))
|
||||||
});
|
})
|
||||||
|
|
||||||
const getProps = computed((): DrawerProps => {
|
const getProps = computed((): DrawerProps => {
|
||||||
const opt = {
|
const opt = {
|
||||||
|
|
@ -86,95 +86,95 @@
|
||||||
...unref(attrs),
|
...unref(attrs),
|
||||||
...unref(getMergeProps),
|
...unref(getMergeProps),
|
||||||
visible: unref(visibleRef),
|
visible: unref(visibleRef),
|
||||||
};
|
}
|
||||||
opt.title = undefined;
|
opt.title = undefined
|
||||||
const { isDetail, width, wrapClassName, getContainer } = opt;
|
const { isDetail, width, wrapClassName, getContainer } = opt
|
||||||
if (isDetail) {
|
if (isDetail) {
|
||||||
if (!width) {
|
if (!width) {
|
||||||
opt.width = '100%';
|
opt.width = '100%'
|
||||||
}
|
}
|
||||||
const detailCls = `${prefixCls}__detail`;
|
const detailCls = `${prefixCls}__detail`
|
||||||
opt.class = wrapClassName ? `${wrapClassName} ${detailCls}` : detailCls;
|
opt.class = wrapClassName ? `${wrapClassName} ${detailCls}` : detailCls
|
||||||
|
|
||||||
if (!getContainer) {
|
if (!getContainer) {
|
||||||
// TODO type error?
|
// TODO type error?
|
||||||
opt.getContainer = `.${prefixVar}-layout-content` as any;
|
opt.getContainer = `.${prefixVar}-layout-content` as any
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return opt as DrawerProps;
|
return opt as DrawerProps
|
||||||
});
|
})
|
||||||
|
|
||||||
const getBindValues = computed((): DrawerProps => {
|
const getBindValues = computed((): DrawerProps => {
|
||||||
return {
|
return {
|
||||||
...attrs,
|
...attrs,
|
||||||
...unref(getProps),
|
...unref(getProps),
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
// Custom implementation of the bottom button,
|
// Custom implementation of the bottom button,
|
||||||
const getFooterHeight = computed(() => {
|
const getFooterHeight = computed(() => {
|
||||||
const { footerHeight, showFooter } = unref(getProps);
|
const { footerHeight, showFooter } = unref(getProps)
|
||||||
if (showFooter && footerHeight) {
|
if (showFooter && footerHeight) {
|
||||||
return isNumber(footerHeight)
|
return isNumber(footerHeight)
|
||||||
? `${footerHeight}px`
|
? `${footerHeight}px`
|
||||||
: `${footerHeight.replace('px', '')}px`;
|
: `${footerHeight.replace('px', '')}px`
|
||||||
}
|
}
|
||||||
return `0px`;
|
return `0px`
|
||||||
});
|
})
|
||||||
|
|
||||||
const getScrollContentStyle = computed((): CSSProperties => {
|
const getScrollContentStyle = computed((): CSSProperties => {
|
||||||
const footerHeight = unref(getFooterHeight);
|
const footerHeight = unref(getFooterHeight)
|
||||||
return {
|
return {
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
height: `calc(100% - ${footerHeight})`,
|
height: `calc(100% - ${footerHeight})`,
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
const getLoading = computed(() => {
|
const getLoading = computed(() => {
|
||||||
return !!unref(getProps)?.loading;
|
return !!unref(getProps)?.loading
|
||||||
});
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.visible,
|
() => props.visible,
|
||||||
(newVal, oldVal) => {
|
(newVal, oldVal) => {
|
||||||
if (newVal !== oldVal) visibleRef.value = newVal;
|
if (newVal !== oldVal) visibleRef.value = newVal
|
||||||
},
|
},
|
||||||
{ deep: true },
|
{ deep: true },
|
||||||
);
|
)
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => visibleRef.value,
|
() => visibleRef.value,
|
||||||
(visible) => {
|
(visible) => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
emit('visible-change', visible);
|
emit('visible-change', visible)
|
||||||
instance && drawerInstance.emitVisible?.(visible, instance.uid);
|
instance && drawerInstance.emitVisible?.(visible, instance.uid)
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
|
|
||||||
// Cancel event
|
// Cancel event
|
||||||
async function onClose(e: Recordable) {
|
async function onClose(e: Recordable) {
|
||||||
const { closeFunc } = unref(getProps);
|
const { closeFunc } = unref(getProps)
|
||||||
emit('close', e);
|
emit('close', e)
|
||||||
if (closeFunc && isFunction(closeFunc)) {
|
if (closeFunc && isFunction(closeFunc)) {
|
||||||
const res = await closeFunc();
|
const res = await closeFunc()
|
||||||
visibleRef.value = !res;
|
visibleRef.value = !res
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
visibleRef.value = false;
|
visibleRef.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDrawerProps(props: Partial<DrawerProps>): void {
|
function setDrawerProps(props: Partial<DrawerProps>): void {
|
||||||
// Keep the last setDrawerProps
|
// Keep the last setDrawerProps
|
||||||
propsRef.value = deepMerge(unref(propsRef) || ({} as any), props);
|
propsRef.value = deepMerge(unref(propsRef) || ({} as any), props)
|
||||||
|
|
||||||
if (Reflect.has(props, 'visible')) {
|
if (Reflect.has(props, 'visible')) {
|
||||||
visibleRef.value = !!props.visible;
|
visibleRef.value = !!props.visible
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleOk() {
|
function handleOk() {
|
||||||
emit('ok');
|
emit('ok')
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -188,9 +188,9 @@
|
||||||
getBindValues,
|
getBindValues,
|
||||||
getFooterHeight,
|
getFooterHeight,
|
||||||
handleOk,
|
handleOk,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@header-height: 60px;
|
@header-height: 60px;
|
||||||
|
|
|
||||||
|
|
@ -25,11 +25,11 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { CSSProperties } from 'vue';
|
import type { CSSProperties } from 'vue'
|
||||||
import { defineComponent, computed } from 'vue';
|
import { defineComponent, computed } from 'vue'
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
|
|
||||||
import { footerProps } from '../props';
|
import { footerProps } from '../props'
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'BasicDrawerFooter',
|
name: 'BasicDrawerFooter',
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -41,26 +41,26 @@
|
||||||
},
|
},
|
||||||
emits: ['ok', 'close'],
|
emits: ['ok', 'close'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const { prefixCls } = useDesign('basic-drawer-footer');
|
const { prefixCls } = useDesign('basic-drawer-footer')
|
||||||
|
|
||||||
const getStyle = computed((): CSSProperties => {
|
const getStyle = computed((): CSSProperties => {
|
||||||
const heightStr = `${props.height}`;
|
const heightStr = `${props.height}`
|
||||||
return {
|
return {
|
||||||
height: heightStr,
|
height: heightStr,
|
||||||
lineHeight: `calc(${heightStr} - 1px)`,
|
lineHeight: `calc(${heightStr} - 1px)`,
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
function handleOk() {
|
function handleOk() {
|
||||||
emit('ok');
|
emit('ok')
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleClose() {
|
function handleClose() {
|
||||||
emit('close');
|
emit('close')
|
||||||
}
|
}
|
||||||
return { handleOk, prefixCls, handleClose, getStyle };
|
return { handleOk, prefixCls, handleClose, getStyle }
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
|
|
||||||
|
|
@ -1,193 +1,193 @@
|
||||||
import type { ButtonProps } from 'ant-design-vue/lib/button/buttonTypes';
|
import type { ButtonProps } from 'ant-design-vue/lib/button/buttonTypes'
|
||||||
import type { CSSProperties, VNodeChild, ComputedRef } from 'vue';
|
import type { CSSProperties, VNodeChild, ComputedRef } from 'vue'
|
||||||
import type { ScrollContainerOptions } from '/@/components/Container/index';
|
import type { ScrollContainerOptions } from '/@/components/Container/index'
|
||||||
|
|
||||||
export interface DrawerInstance {
|
export interface DrawerInstance {
|
||||||
setDrawerProps: (props: Partial<DrawerProps> | boolean) => void;
|
setDrawerProps: (props: Partial<DrawerProps> | boolean) => void
|
||||||
emitVisible?: (visible: boolean, uid: number) => void;
|
emitVisible?: (visible: boolean, uid: number) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ReturnMethods extends DrawerInstance {
|
export interface ReturnMethods extends DrawerInstance {
|
||||||
openDrawer: <T = any>(visible?: boolean, data?: T, openOnSet?: boolean) => void;
|
openDrawer: <T = any>(visible?: boolean, data?: T, openOnSet?: boolean) => void
|
||||||
closeDrawer: () => void;
|
closeDrawer: () => void
|
||||||
getVisible?: ComputedRef<boolean>;
|
getVisible?: ComputedRef<boolean>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RegisterFn = (drawerInstance: DrawerInstance, uuid?: string) => void;
|
export type RegisterFn = (drawerInstance: DrawerInstance, uuid?: string) => void
|
||||||
|
|
||||||
export interface ReturnInnerMethods extends DrawerInstance {
|
export interface ReturnInnerMethods extends DrawerInstance {
|
||||||
closeDrawer: () => void;
|
closeDrawer: () => void
|
||||||
changeLoading: (loading: boolean) => void;
|
changeLoading: (loading: boolean) => void
|
||||||
changeOkLoading: (loading: boolean) => void;
|
changeOkLoading: (loading: boolean) => void
|
||||||
getVisible?: ComputedRef<boolean>;
|
getVisible?: ComputedRef<boolean>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UseDrawerReturnType = [RegisterFn, ReturnMethods];
|
export type UseDrawerReturnType = [RegisterFn, ReturnMethods]
|
||||||
|
|
||||||
export type UseDrawerInnerReturnType = [RegisterFn, ReturnInnerMethods];
|
export type UseDrawerInnerReturnType = [RegisterFn, ReturnInnerMethods]
|
||||||
|
|
||||||
export interface DrawerFooterProps {
|
export interface DrawerFooterProps {
|
||||||
showOkBtn: boolean;
|
showOkBtn: boolean
|
||||||
showCancelBtn: boolean;
|
showCancelBtn: boolean
|
||||||
/**
|
/**
|
||||||
* Text of the Cancel button
|
* Text of the Cancel button
|
||||||
* @default 'cancel'
|
* @default 'cancel'
|
||||||
* @type string
|
* @type string
|
||||||
*/
|
*/
|
||||||
cancelText: string;
|
cancelText: string
|
||||||
/**
|
/**
|
||||||
* Text of the OK button
|
* Text of the OK button
|
||||||
* @default 'OK'
|
* @default 'OK'
|
||||||
* @type string
|
* @type string
|
||||||
*/
|
*/
|
||||||
okText: string;
|
okText: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Button type of the OK button
|
* Button type of the OK button
|
||||||
* @default 'primary'
|
* @default 'primary'
|
||||||
* @type string
|
* @type string
|
||||||
*/
|
*/
|
||||||
okType: 'primary' | 'danger' | 'dashed' | 'ghost' | 'default';
|
okType: 'primary' | 'danger' | 'dashed' | 'ghost' | 'default'
|
||||||
/**
|
/**
|
||||||
* The ok button props, follow jsx rules
|
* The ok button props, follow jsx rules
|
||||||
* @type object
|
* @type object
|
||||||
*/
|
*/
|
||||||
okButtonProps: { props: ButtonProps; on: {} };
|
okButtonProps: { props: ButtonProps; on: {} }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The cancel button props, follow jsx rules
|
* The cancel button props, follow jsx rules
|
||||||
* @type object
|
* @type object
|
||||||
*/
|
*/
|
||||||
cancelButtonProps: { props: ButtonProps; on: {} };
|
cancelButtonProps: { props: ButtonProps; on: {} }
|
||||||
/**
|
/**
|
||||||
* Whether to apply loading visual effect for OK button or not
|
* Whether to apply loading visual effect for OK button or not
|
||||||
* @default false
|
* @default false
|
||||||
* @type boolean
|
* @type boolean
|
||||||
*/
|
*/
|
||||||
confirmLoading: boolean;
|
confirmLoading: boolean
|
||||||
|
|
||||||
showFooter: boolean;
|
showFooter: boolean
|
||||||
footerHeight: string | number;
|
footerHeight: string | number
|
||||||
}
|
}
|
||||||
export interface DrawerProps extends DrawerFooterProps {
|
export interface DrawerProps extends DrawerFooterProps {
|
||||||
isDetail?: boolean;
|
isDetail?: boolean
|
||||||
loading?: boolean;
|
loading?: boolean
|
||||||
showDetailBack?: boolean;
|
showDetailBack?: boolean
|
||||||
visible?: boolean;
|
visible?: boolean
|
||||||
/**
|
/**
|
||||||
* Built-in ScrollContainer component configuration
|
* Built-in ScrollContainer component configuration
|
||||||
* @type ScrollContainerOptions
|
* @type ScrollContainerOptions
|
||||||
*/
|
*/
|
||||||
scrollOptions?: ScrollContainerOptions;
|
scrollOptions?: ScrollContainerOptions
|
||||||
closeFunc?: () => Promise<any>;
|
closeFunc?: () => Promise<any>
|
||||||
triggerWindowResize?: boolean;
|
triggerWindowResize?: boolean
|
||||||
/**
|
/**
|
||||||
* Whether a close (x) button is visible on top right of the Drawer dialog or not.
|
* Whether a close (x) button is visible on top right of the Drawer dialog or not.
|
||||||
* @default true
|
* @default true
|
||||||
* @type boolean
|
* @type boolean
|
||||||
*/
|
*/
|
||||||
closable?: boolean;
|
closable?: boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to unmount child components on closing drawer or not.
|
* Whether to unmount child components on closing drawer or not.
|
||||||
* @default false
|
* @default false
|
||||||
* @type boolean
|
* @type boolean
|
||||||
*/
|
*/
|
||||||
destroyOnClose?: boolean;
|
destroyOnClose?: boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the mounted node for Drawer.
|
* Return the mounted node for Drawer.
|
||||||
* @default 'body'
|
* @default 'body'
|
||||||
* @type any ( HTMLElement| () => HTMLElement | string)
|
* @type any ( HTMLElement| () => HTMLElement | string)
|
||||||
*/
|
*/
|
||||||
getContainer?: () => HTMLElement | string;
|
getContainer?: () => HTMLElement | string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to show mask or not.
|
* Whether to show mask or not.
|
||||||
* @default true
|
* @default true
|
||||||
* @type boolean
|
* @type boolean
|
||||||
*/
|
*/
|
||||||
mask?: boolean;
|
mask?: boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clicking on the mask (area outside the Drawer) to close the Drawer or not.
|
* Clicking on the mask (area outside the Drawer) to close the Drawer or not.
|
||||||
* @default true
|
* @default true
|
||||||
* @type boolean
|
* @type boolean
|
||||||
*/
|
*/
|
||||||
maskClosable?: boolean;
|
maskClosable?: boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Style for Drawer's mask element.
|
* Style for Drawer's mask element.
|
||||||
* @default {}
|
* @default {}
|
||||||
* @type object
|
* @type object
|
||||||
*/
|
*/
|
||||||
maskStyle?: CSSProperties;
|
maskStyle?: CSSProperties
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The title for Drawer.
|
* The title for Drawer.
|
||||||
* @type any (string | slot)
|
* @type any (string | slot)
|
||||||
*/
|
*/
|
||||||
title?: VNodeChild | JSX.Element;
|
title?: VNodeChild | JSX.Element
|
||||||
/**
|
/**
|
||||||
* The class name of the container of the Drawer dialog.
|
* The class name of the container of the Drawer dialog.
|
||||||
* @type string
|
* @type string
|
||||||
*/
|
*/
|
||||||
wrapClassName?: string;
|
wrapClassName?: string
|
||||||
class?: string;
|
class?: string
|
||||||
/**
|
/**
|
||||||
* Style of wrapper element which **contains mask** compare to `drawerStyle`
|
* Style of wrapper element which **contains mask** compare to `drawerStyle`
|
||||||
* @type object
|
* @type object
|
||||||
*/
|
*/
|
||||||
wrapStyle?: CSSProperties;
|
wrapStyle?: CSSProperties
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Style of the popup layer element
|
* Style of the popup layer element
|
||||||
* @type object
|
* @type object
|
||||||
*/
|
*/
|
||||||
drawerStyle?: CSSProperties;
|
drawerStyle?: CSSProperties
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Style of floating layer, typically used for adjusting its position.
|
* Style of floating layer, typically used for adjusting its position.
|
||||||
* @type object
|
* @type object
|
||||||
*/
|
*/
|
||||||
bodyStyle?: CSSProperties;
|
bodyStyle?: CSSProperties
|
||||||
headerStyle?: CSSProperties;
|
headerStyle?: CSSProperties
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Width of the Drawer dialog.
|
* Width of the Drawer dialog.
|
||||||
* @default 256
|
* @default 256
|
||||||
* @type string | number
|
* @type string | number
|
||||||
*/
|
*/
|
||||||
width?: string | number;
|
width?: string | number
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* placement is top or bottom, height of the Drawer dialog.
|
* placement is top or bottom, height of the Drawer dialog.
|
||||||
* @type string | number
|
* @type string | number
|
||||||
*/
|
*/
|
||||||
height?: string | number;
|
height?: string | number
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The z-index of the Drawer.
|
* The z-index of the Drawer.
|
||||||
* @default 1000
|
* @default 1000
|
||||||
* @type number
|
* @type number
|
||||||
*/
|
*/
|
||||||
zIndex?: number;
|
zIndex?: number
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The placement of the Drawer.
|
* The placement of the Drawer.
|
||||||
* @default 'right'
|
* @default 'right'
|
||||||
* @type string
|
* @type string
|
||||||
*/
|
*/
|
||||||
placement?: 'top' | 'right' | 'bottom' | 'left';
|
placement?: 'top' | 'right' | 'bottom' | 'left'
|
||||||
afterVisibleChange?: (visible?: boolean) => void;
|
afterVisibleChange?: (visible?: boolean) => void
|
||||||
keyboard?: boolean;
|
keyboard?: boolean
|
||||||
/**
|
/**
|
||||||
* Specify a callback that will be called when a user clicks mask, close button or Cancel button.
|
* Specify a callback that will be called when a user clicks mask, close button or Cancel button.
|
||||||
*/
|
*/
|
||||||
onClose?: (e?: Event) => void;
|
onClose?: (e?: Event) => void
|
||||||
}
|
}
|
||||||
export interface DrawerActionType {
|
export interface DrawerActionType {
|
||||||
scrollBottom: () => void;
|
scrollBottom: () => void
|
||||||
scrollTo: (to: number) => void;
|
scrollTo: (to: number) => void
|
||||||
getScrollWrap: () => Element | null;
|
getScrollWrap: () => Element | null
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
import BasicForm from './src/BasicForm.vue';
|
import BasicForm from './src/BasicForm.vue'
|
||||||
|
|
||||||
export * from './src/types/form';
|
export * from './src/types/form'
|
||||||
export * from './src/types/formItem';
|
export * from './src/types/formItem'
|
||||||
|
|
||||||
export { useComponentRegister } from './src/hooks/useComponentRegister';
|
export { useComponentRegister } from './src/hooks/useComponentRegister'
|
||||||
export { useForm } from './src/hooks/useForm';
|
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 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'
|
||||||
export { default as ApiTransfer } from './src/components/ApiTransfer.vue';
|
export { default as ApiTransfer } from './src/components/ApiTransfer.vue'
|
||||||
|
|
||||||
export { BasicForm };
|
export { BasicForm }
|
||||||
|
|
|
||||||
|
|
@ -37,32 +37,32 @@
|
||||||
</Form>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { FormActionType, FormProps, FormSchema } from './types/form';
|
import type { FormActionType, FormProps, FormSchema } from './types/form'
|
||||||
import type { AdvanceState } from './types/hooks';
|
import type { AdvanceState } from './types/hooks'
|
||||||
import type { Ref } from 'vue';
|
import type { Ref } from 'vue'
|
||||||
|
|
||||||
import { defineComponent, reactive, ref, computed, unref, onMounted, watch, nextTick } from 'vue';
|
import { defineComponent, reactive, ref, computed, unref, onMounted, watch, nextTick } from 'vue'
|
||||||
import { Form, Row } from 'ant-design-vue';
|
import { Form, Row } from 'ant-design-vue'
|
||||||
import FormItem from './components/FormItem.vue';
|
import FormItem from './components/FormItem.vue'
|
||||||
import FormAction from './components/FormAction.vue';
|
import FormAction from './components/FormAction.vue'
|
||||||
|
|
||||||
import { dateItemType } from './helper';
|
import { dateItemType } from './helper'
|
||||||
import { dateUtil } from '/@/utils/dateUtil';
|
import { dateUtil } from '/@/utils/dateUtil'
|
||||||
|
|
||||||
// import { cloneDeep } from 'lodash-es';
|
// import { cloneDeep } from 'lodash-es';
|
||||||
import { deepMerge } from '/@/utils';
|
import { deepMerge } from '/@/utils'
|
||||||
|
|
||||||
import { useFormValues } from './hooks/useFormValues';
|
import { useFormValues } from './hooks/useFormValues'
|
||||||
import useAdvanced from './hooks/useAdvanced';
|
import useAdvanced from './hooks/useAdvanced'
|
||||||
import { useFormEvents } from './hooks/useFormEvents';
|
import { useFormEvents } from './hooks/useFormEvents'
|
||||||
import { createFormContext } from './hooks/useFormContext';
|
import { createFormContext } from './hooks/useFormContext'
|
||||||
import { useAutoFocus } from './hooks/useAutoFocus';
|
import { useAutoFocus } from './hooks/useAutoFocus'
|
||||||
import { useModalContext } from '/@/components/Modal';
|
import { useModalContext } from '/@/components/Modal'
|
||||||
import { useDebounceFn } from '@vueuse/core';
|
import { useDebounceFn } from '@vueuse/core'
|
||||||
|
|
||||||
import { basicProps } from './props';
|
import { basicProps } from './props'
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'BasicForm',
|
name: 'BasicForm',
|
||||||
|
|
@ -70,28 +70,28 @@
|
||||||
props: basicProps,
|
props: basicProps,
|
||||||
emits: ['advanced-change', 'reset', 'submit', 'register', 'field-value-change'],
|
emits: ['advanced-change', 'reset', 'submit', 'register', 'field-value-change'],
|
||||||
setup(props, { emit, attrs }) {
|
setup(props, { emit, attrs }) {
|
||||||
const formModel = reactive<Recordable>({});
|
const formModel = reactive<Recordable>({})
|
||||||
const modalFn = useModalContext();
|
const modalFn = useModalContext()
|
||||||
|
|
||||||
const advanceState = reactive<AdvanceState>({
|
const advanceState = reactive<AdvanceState>({
|
||||||
isAdvanced: true,
|
isAdvanced: true,
|
||||||
hideAdvanceBtn: false,
|
hideAdvanceBtn: false,
|
||||||
isLoad: false,
|
isLoad: false,
|
||||||
actionSpan: 6,
|
actionSpan: 6,
|
||||||
});
|
})
|
||||||
|
|
||||||
const defaultValueRef = ref<Recordable>({});
|
const defaultValueRef = ref<Recordable>({})
|
||||||
const isInitedDefaultRef = ref(false);
|
const isInitedDefaultRef = ref(false)
|
||||||
const propsRef = ref<Partial<FormProps>>({});
|
const propsRef = ref<Partial<FormProps>>({})
|
||||||
const schemaRef = ref<Nullable<FormSchema[]>>(null);
|
const schemaRef = ref<Nullable<FormSchema[]>>(null)
|
||||||
const formElRef = ref<Nullable<FormActionType>>(null);
|
const formElRef = ref<Nullable<FormActionType>>(null)
|
||||||
|
|
||||||
const { prefixCls } = useDesign('basic-form');
|
const { prefixCls } = useDesign('basic-form')
|
||||||
|
|
||||||
// Get the basic configuration of the form
|
// Get the basic configuration of the form
|
||||||
const getProps = computed((): FormProps => {
|
const getProps = computed((): FormProps => {
|
||||||
return { ...props, ...unref(propsRef) } as FormProps;
|
return { ...props, ...unref(propsRef) } as FormProps
|
||||||
});
|
})
|
||||||
|
|
||||||
const getFormClass = computed(() => {
|
const getFormClass = computed(() => {
|
||||||
return [
|
return [
|
||||||
|
|
@ -99,47 +99,47 @@
|
||||||
{
|
{
|
||||||
[`${prefixCls}--compact`]: unref(getProps).compact,
|
[`${prefixCls}--compact`]: unref(getProps).compact,
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
});
|
})
|
||||||
|
|
||||||
// Get uniform row style and Row configuration for the entire form
|
// Get uniform row style and Row configuration for the entire form
|
||||||
const getRow = computed((): Recordable => {
|
const getRow = computed((): Recordable => {
|
||||||
const { baseRowStyle = {}, rowProps } = unref(getProps);
|
const { baseRowStyle = {}, rowProps } = unref(getProps)
|
||||||
return {
|
return {
|
||||||
style: baseRowStyle,
|
style: baseRowStyle,
|
||||||
...rowProps,
|
...rowProps,
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
const getBindValue = computed(
|
const getBindValue = computed(
|
||||||
() => ({ ...attrs, ...props, ...unref(getProps) } as Recordable),
|
() => ({ ...attrs, ...props, ...unref(getProps) } as Recordable),
|
||||||
);
|
)
|
||||||
|
|
||||||
const getSchema = computed((): FormSchema[] => {
|
const getSchema = computed((): FormSchema[] => {
|
||||||
const schemas: FormSchema[] = unref(schemaRef) || (unref(getProps).schemas as any);
|
const schemas: FormSchema[] = unref(schemaRef) || (unref(getProps).schemas as any)
|
||||||
for (const schema of schemas) {
|
for (const schema of schemas) {
|
||||||
const { defaultValue, component } = schema;
|
const { defaultValue, component } = schema
|
||||||
// handle date type
|
// handle date type
|
||||||
if (defaultValue && dateItemType.includes(component)) {
|
if (defaultValue && dateItemType.includes(component)) {
|
||||||
if (!Array.isArray(defaultValue)) {
|
if (!Array.isArray(defaultValue)) {
|
||||||
schema.defaultValue = dateUtil(defaultValue);
|
schema.defaultValue = dateUtil(defaultValue)
|
||||||
} else {
|
} else {
|
||||||
const def: any[] = [];
|
const def: any[] = []
|
||||||
defaultValue.forEach((item) => {
|
defaultValue.forEach((item) => {
|
||||||
def.push(dateUtil(item));
|
def.push(dateUtil(item))
|
||||||
});
|
})
|
||||||
schema.defaultValue = def;
|
schema.defaultValue = def
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (unref(getProps).showAdvancedButton) {
|
if (unref(getProps).showAdvancedButton) {
|
||||||
return cloneDeep(
|
return cloneDeep(
|
||||||
schemas.filter((schema) => schema.component !== 'Divider') as FormSchema[],
|
schemas.filter((schema) => schema.component !== 'Divider') as FormSchema[],
|
||||||
);
|
)
|
||||||
} else {
|
} else {
|
||||||
return cloneDeep(schemas as FormSchema[]);
|
return cloneDeep(schemas as FormSchema[])
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
const { handleToggleAdvanced } = useAdvanced({
|
const { handleToggleAdvanced } = useAdvanced({
|
||||||
advanceState,
|
advanceState,
|
||||||
|
|
@ -148,21 +148,21 @@
|
||||||
getSchema,
|
getSchema,
|
||||||
formModel,
|
formModel,
|
||||||
defaultValueRef,
|
defaultValueRef,
|
||||||
});
|
})
|
||||||
|
|
||||||
const { handleFormValues, initDefault } = useFormValues({
|
const { handleFormValues, initDefault } = useFormValues({
|
||||||
getProps,
|
getProps,
|
||||||
defaultValueRef,
|
defaultValueRef,
|
||||||
getSchema,
|
getSchema,
|
||||||
formModel,
|
formModel,
|
||||||
});
|
})
|
||||||
|
|
||||||
useAutoFocus({
|
useAutoFocus({
|
||||||
getSchema,
|
getSchema,
|
||||||
getProps,
|
getProps,
|
||||||
isInitedDefault: isInitedDefaultRef,
|
isInitedDefault: isInitedDefaultRef,
|
||||||
formElRef: formElRef as Ref<FormActionType>,
|
formElRef: formElRef as Ref<FormActionType>,
|
||||||
});
|
})
|
||||||
|
|
||||||
const {
|
const {
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
|
|
@ -186,77 +186,77 @@
|
||||||
formElRef: formElRef as Ref<FormActionType>,
|
formElRef: formElRef as Ref<FormActionType>,
|
||||||
schemaRef: schemaRef as Ref<FormSchema[]>,
|
schemaRef: schemaRef as Ref<FormSchema[]>,
|
||||||
handleFormValues,
|
handleFormValues,
|
||||||
});
|
})
|
||||||
|
|
||||||
createFormContext({
|
createFormContext({
|
||||||
resetAction: resetFields,
|
resetAction: resetFields,
|
||||||
submitAction: handleSubmit,
|
submitAction: handleSubmit,
|
||||||
});
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => unref(getProps).model,
|
() => unref(getProps).model,
|
||||||
() => {
|
() => {
|
||||||
const { model } = unref(getProps);
|
const { model } = unref(getProps)
|
||||||
if (!model) return;
|
if (!model) return
|
||||||
setFieldsValue(model);
|
setFieldsValue(model)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
immediate: true,
|
immediate: true,
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => unref(getProps).schemas,
|
() => unref(getProps).schemas,
|
||||||
(schemas) => {
|
(schemas) => {
|
||||||
resetSchema(schemas ?? []);
|
resetSchema(schemas ?? [])
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => getSchema.value,
|
() => getSchema.value,
|
||||||
(schema) => {
|
(schema) => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
// Solve the problem of modal adaptive height calculation when the form is placed in the modal
|
// Solve the problem of modal adaptive height calculation when the form is placed in the modal
|
||||||
modalFn?.redoModalHeight?.();
|
modalFn?.redoModalHeight?.()
|
||||||
});
|
})
|
||||||
if (unref(isInitedDefaultRef)) {
|
if (unref(isInitedDefaultRef)) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if (schema?.length) {
|
if (schema?.length) {
|
||||||
initDefault();
|
initDefault()
|
||||||
isInitedDefaultRef.value = true;
|
isInitedDefaultRef.value = true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => formModel,
|
() => formModel,
|
||||||
useDebounceFn(() => {
|
useDebounceFn(() => {
|
||||||
unref(getProps).submitOnChange && handleSubmit();
|
unref(getProps).submitOnChange && handleSubmit()
|
||||||
}, 300),
|
}, 300),
|
||||||
{ deep: true },
|
{ deep: true },
|
||||||
);
|
)
|
||||||
|
|
||||||
async function setProps(formProps: Partial<FormProps>): Promise<void> {
|
async function setProps(formProps: Partial<FormProps>): Promise<void> {
|
||||||
propsRef.value = deepMerge(unref(propsRef) || {}, formProps);
|
propsRef.value = deepMerge(unref(propsRef) || {}, formProps)
|
||||||
}
|
}
|
||||||
|
|
||||||
function setFormModel(key: string, value: any) {
|
function setFormModel(key: string, value: any) {
|
||||||
formModel[key] = value;
|
formModel[key] = value
|
||||||
const { validateTrigger } = unref(getBindValue);
|
const { validateTrigger } = unref(getBindValue)
|
||||||
if (!validateTrigger || validateTrigger === 'change') {
|
if (!validateTrigger || validateTrigger === 'change') {
|
||||||
validateFields([key]).catch((_) => {});
|
validateFields([key]).catch((_) => {})
|
||||||
}
|
}
|
||||||
emit('field-value-change', key, value);
|
emit('field-value-change', key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleEnterPress(e: KeyboardEvent) {
|
function handleEnterPress(e: KeyboardEvent) {
|
||||||
const { autoSubmitOnEnter } = unref(getProps);
|
const { autoSubmitOnEnter } = unref(getProps)
|
||||||
if (!autoSubmitOnEnter) return;
|
if (!autoSubmitOnEnter) return
|
||||||
if (e.key === 'Enter' && e.target && e.target instanceof HTMLElement) {
|
if (e.key === 'Enter' && e.target && e.target instanceof HTMLElement) {
|
||||||
const target: HTMLElement = e.target as HTMLElement;
|
const target: HTMLElement = e.target as HTMLElement
|
||||||
if (target && target.tagName && target.tagName.toUpperCase() == 'INPUT') {
|
if (target && target.tagName && target.tagName.toUpperCase() == 'INPUT') {
|
||||||
handleSubmit();
|
handleSubmit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -275,12 +275,12 @@
|
||||||
validate,
|
validate,
|
||||||
submit: handleSubmit,
|
submit: handleSubmit,
|
||||||
scrollToField: scrollToField,
|
scrollToField: scrollToField,
|
||||||
};
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initDefault();
|
initDefault()
|
||||||
emit('register', formActionType);
|
emit('register', formActionType)
|
||||||
});
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getBindValue,
|
getBindValue,
|
||||||
|
|
@ -300,9 +300,9 @@
|
||||||
(): Recordable => ({ ...getProps.value, ...advanceState }),
|
(): Recordable => ({ ...getProps.value, ...advanceState }),
|
||||||
),
|
),
|
||||||
...formActionType,
|
...formActionType,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@prefix-cls: ~'@{namespace}-basic-form';
|
@prefix-cls: ~'@{namespace}-basic-form';
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import type { Component } from 'vue';
|
import type { Component } from 'vue'
|
||||||
import type { ComponentType } from './types/index';
|
import type { ComponentType } from './types/index'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component list, register here to setting it in the form
|
* Component list, register here to setting it in the form
|
||||||
|
|
@ -19,65 +19,65 @@ import {
|
||||||
Slider,
|
Slider,
|
||||||
Rate,
|
Rate,
|
||||||
Divider,
|
Divider,
|
||||||
} from 'ant-design-vue';
|
} from 'ant-design-vue'
|
||||||
|
|
||||||
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 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 ApiTransfer from './components/ApiTransfer.vue';
|
import ApiTransfer from './components/ApiTransfer.vue'
|
||||||
import { BasicUpload } from '/@/components/Upload';
|
import { BasicUpload } from '/@/components/Upload'
|
||||||
import { StrengthMeter } from '/@/components/StrengthMeter';
|
import { StrengthMeter } from '/@/components/StrengthMeter'
|
||||||
import { IconPicker } from '/@/components/Icon';
|
import { IconPicker } from '/@/components/Icon'
|
||||||
import { CountdownInput } from '/@/components/CountDown';
|
import { CountdownInput } from '/@/components/CountDown'
|
||||||
|
|
||||||
const componentMap = new Map<ComponentType, Component>();
|
const componentMap = new Map<ComponentType, Component>()
|
||||||
|
|
||||||
componentMap.set('Input', Input);
|
componentMap.set('Input', Input)
|
||||||
componentMap.set('InputGroup', Input.Group);
|
componentMap.set('InputGroup', Input.Group)
|
||||||
componentMap.set('InputPassword', Input.Password);
|
componentMap.set('InputPassword', Input.Password)
|
||||||
componentMap.set('InputSearch', Input.Search);
|
componentMap.set('InputSearch', Input.Search)
|
||||||
componentMap.set('InputTextArea', Input.TextArea);
|
componentMap.set('InputTextArea', Input.TextArea)
|
||||||
componentMap.set('InputNumber', InputNumber);
|
componentMap.set('InputNumber', InputNumber)
|
||||||
componentMap.set('AutoComplete', AutoComplete);
|
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('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)
|
||||||
componentMap.set('Switch', Switch);
|
componentMap.set('Switch', Switch)
|
||||||
componentMap.set('RadioButtonGroup', RadioButtonGroup);
|
componentMap.set('RadioButtonGroup', RadioButtonGroup)
|
||||||
componentMap.set('RadioGroup', Radio.Group);
|
componentMap.set('RadioGroup', Radio.Group)
|
||||||
componentMap.set('Checkbox', Checkbox);
|
componentMap.set('Checkbox', Checkbox)
|
||||||
componentMap.set('CheckboxGroup', Checkbox.Group);
|
componentMap.set('CheckboxGroup', Checkbox.Group)
|
||||||
componentMap.set('ApiCascader', ApiCascader);
|
componentMap.set('ApiCascader', ApiCascader)
|
||||||
componentMap.set('Cascader', Cascader);
|
componentMap.set('Cascader', Cascader)
|
||||||
componentMap.set('Slider', Slider);
|
componentMap.set('Slider', Slider)
|
||||||
componentMap.set('Rate', Rate);
|
componentMap.set('Rate', Rate)
|
||||||
componentMap.set('ApiTransfer', ApiTransfer);
|
componentMap.set('ApiTransfer', ApiTransfer)
|
||||||
|
|
||||||
componentMap.set('DatePicker', DatePicker);
|
componentMap.set('DatePicker', DatePicker)
|
||||||
componentMap.set('MonthPicker', DatePicker.MonthPicker);
|
componentMap.set('MonthPicker', DatePicker.MonthPicker)
|
||||||
componentMap.set('RangePicker', DatePicker.RangePicker);
|
componentMap.set('RangePicker', DatePicker.RangePicker)
|
||||||
componentMap.set('WeekPicker', DatePicker.WeekPicker);
|
componentMap.set('WeekPicker', DatePicker.WeekPicker)
|
||||||
componentMap.set('TimePicker', TimePicker);
|
componentMap.set('TimePicker', TimePicker)
|
||||||
componentMap.set('StrengthMeter', StrengthMeter);
|
componentMap.set('StrengthMeter', StrengthMeter)
|
||||||
componentMap.set('IconPicker', IconPicker);
|
componentMap.set('IconPicker', IconPicker)
|
||||||
componentMap.set('InputCountDown', CountdownInput);
|
componentMap.set('InputCountDown', CountdownInput)
|
||||||
|
|
||||||
componentMap.set('Upload', BasicUpload);
|
componentMap.set('Upload', BasicUpload)
|
||||||
componentMap.set('Divider', Divider);
|
componentMap.set('Divider', Divider)
|
||||||
|
|
||||||
export function add(compName: ComponentType, component: Component) {
|
export function add(compName: ComponentType, component: Component) {
|
||||||
componentMap.set(compName, component);
|
componentMap.set(compName, component)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function del(compName: ComponentType) {
|
export function del(compName: ComponentType) {
|
||||||
componentMap.delete(compName);
|
componentMap.delete(compName)
|
||||||
}
|
}
|
||||||
|
|
||||||
export { componentMap };
|
export { componentMap }
|
||||||
|
|
|
||||||
|
|
@ -19,20 +19,20 @@
|
||||||
</a-cascader>
|
</a-cascader>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, PropType, ref, unref, watch, watchEffect } from 'vue';
|
import { defineComponent, PropType, ref, unref, watch, watchEffect } from 'vue'
|
||||||
import { Cascader } from 'ant-design-vue';
|
import { Cascader } from 'ant-design-vue'
|
||||||
import { propTypes } from '/@/utils/propTypes';
|
import { propTypes } from '/@/utils/propTypes'
|
||||||
import { isFunction } from '/@/utils/is';
|
import { isFunction } from '/@/utils/is'
|
||||||
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';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
interface Option {
|
interface Option {
|
||||||
value: string;
|
value: string
|
||||||
label: string;
|
label: string
|
||||||
loading?: boolean;
|
loading?: boolean
|
||||||
isLeaf?: boolean;
|
isLeaf?: boolean
|
||||||
children?: Option[];
|
children?: Option[]
|
||||||
}
|
}
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'ApiCascader',
|
name: 'ApiCascader',
|
||||||
|
|
@ -71,117 +71,117 @@
|
||||||
},
|
},
|
||||||
emits: ['change', 'defaultChange'],
|
emits: ['change', 'defaultChange'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const apiData = ref<any[]>([]);
|
const apiData = ref<any[]>([])
|
||||||
const options = ref<Option[]>([]);
|
const options = ref<Option[]>([])
|
||||||
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();
|
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)
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
apiData,
|
apiData,
|
||||||
(data) => {
|
(data) => {
|
||||||
const opts = generatorOptions(data);
|
const opts = generatorOptions(data)
|
||||||
options.value = opts;
|
options.value = opts
|
||||||
},
|
},
|
||||||
{ deep: true },
|
{ deep: true },
|
||||||
);
|
)
|
||||||
|
|
||||||
function generatorOptions(options: any[]): Option[] {
|
function generatorOptions(options: any[]): Option[] {
|
||||||
const { labelField, valueField, numberToString, childrenField, isLeaf } = props;
|
const { labelField, valueField, numberToString, childrenField, isLeaf } = props
|
||||||
return options.reduce((prev, next: Recordable) => {
|
return options.reduce((prev, next: Recordable) => {
|
||||||
if (next) {
|
if (next) {
|
||||||
const value = next[valueField];
|
const value = next[valueField]
|
||||||
const item = {
|
const item = {
|
||||||
...omit(next, [labelField, valueField]),
|
...omit(next, [labelField, valueField]),
|
||||||
label: next[labelField],
|
label: next[labelField],
|
||||||
value: numberToString ? `${value}` : value,
|
value: numberToString ? `${value}` : value,
|
||||||
isLeaf: isLeaf && typeof isLeaf === 'function' ? isLeaf(next) : false,
|
isLeaf: isLeaf && typeof isLeaf === 'function' ? isLeaf(next) : false,
|
||||||
};
|
|
||||||
const children = Reflect.get(next, childrenField);
|
|
||||||
if (children) {
|
|
||||||
Reflect.set(item, childrenField, generatorOptions(children));
|
|
||||||
}
|
}
|
||||||
prev.push(item);
|
const children = Reflect.get(next, childrenField)
|
||||||
|
if (children) {
|
||||||
|
Reflect.set(item, childrenField, generatorOptions(children))
|
||||||
|
}
|
||||||
|
prev.push(item)
|
||||||
}
|
}
|
||||||
return prev;
|
return prev
|
||||||
}, [] as Option[]);
|
}, [] as Option[])
|
||||||
}
|
}
|
||||||
|
|
||||||
async function initialFetch() {
|
async function initialFetch() {
|
||||||
const api = props.api;
|
const api = props.api
|
||||||
if (!api || !isFunction(api)) return;
|
if (!api || !isFunction(api)) return
|
||||||
apiData.value = [];
|
apiData.value = []
|
||||||
loading.value = true;
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const res = await api(props.initFetchParams);
|
const res = await api(props.initFetchParams)
|
||||||
if (Array.isArray(res)) {
|
if (Array.isArray(res)) {
|
||||||
apiData.value = res;
|
apiData.value = res
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if (props.resultField) {
|
if (props.resultField) {
|
||||||
apiData.value = get(res, props.resultField) || [];
|
apiData.value = get(res, props.resultField) || []
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(error);
|
console.warn(error)
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadData(selectedOptions: Option[]) {
|
async function loadData(selectedOptions: Option[]) {
|
||||||
const targetOption = selectedOptions[selectedOptions.length - 1];
|
const targetOption = selectedOptions[selectedOptions.length - 1]
|
||||||
targetOption.loading = true;
|
targetOption.loading = true
|
||||||
|
|
||||||
const api = props.api;
|
const api = props.api
|
||||||
if (!api || !isFunction(api)) return;
|
if (!api || !isFunction(api)) return
|
||||||
try {
|
try {
|
||||||
const res = await api({
|
const res = await api({
|
||||||
[props.asyncFetchParamKey]: Reflect.get(targetOption, 'value'),
|
[props.asyncFetchParamKey]: Reflect.get(targetOption, 'value'),
|
||||||
});
|
})
|
||||||
if (Array.isArray(res)) {
|
if (Array.isArray(res)) {
|
||||||
const children = generatorOptions(res);
|
const children = generatorOptions(res)
|
||||||
targetOption.children = children;
|
targetOption.children = children
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if (props.resultField) {
|
if (props.resultField) {
|
||||||
const children = generatorOptions(get(res, props.resultField) || []);
|
const children = generatorOptions(get(res, props.resultField) || [])
|
||||||
targetOption.children = children;
|
targetOption.children = children
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e)
|
||||||
} finally {
|
} finally {
|
||||||
targetOption.loading = false;
|
targetOption.loading = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
props.immediate && initialFetch();
|
props.immediate && initialFetch()
|
||||||
});
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.initFetchParams,
|
() => props.initFetchParams,
|
||||||
() => {
|
() => {
|
||||||
!unref(isFirstLoad) && initialFetch();
|
!unref(isFirstLoad) && initialFetch()
|
||||||
},
|
},
|
||||||
{ deep: true },
|
{ deep: true },
|
||||||
);
|
)
|
||||||
|
|
||||||
function handleChange(keys, args) {
|
function handleChange(keys, args) {
|
||||||
emitData.value = keys;
|
emitData.value = keys
|
||||||
emit('defaultChange', keys, args);
|
emit('defaultChange', keys, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleRenderDisplay({ labels, selectedOptions }) {
|
function handleRenderDisplay({ labels, selectedOptions }) {
|
||||||
if (unref(emitData).length === selectedOptions.length) {
|
if (unref(emitData).length === selectedOptions.length) {
|
||||||
return labels.join(' / ');
|
return labels.join(' / ')
|
||||||
}
|
}
|
||||||
if (props.displayRenderArray) {
|
if (props.displayRenderArray) {
|
||||||
return props.displayRenderArray.join(' / ');
|
return props.displayRenderArray.join(' / ')
|
||||||
}
|
}
|
||||||
return '';
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -192,7 +192,7 @@
|
||||||
handleChange,
|
handleChange,
|
||||||
loadData,
|
loadData,
|
||||||
handleRenderDisplay,
|
handleRenderDisplay,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -21,17 +21,17 @@
|
||||||
</Select>
|
</Select>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, PropType, ref, watchEffect, computed, unref, watch } from 'vue';
|
import { defineComponent, PropType, ref, watchEffect, computed, unref, watch } from 'vue'
|
||||||
import { Select } from 'ant-design-vue';
|
import { Select } from 'ant-design-vue'
|
||||||
import { isFunction } from '/@/utils/is';
|
import { isFunction } from '/@/utils/is'
|
||||||
import { useRuleFormItem } from '/@/hooks/component/useFormItem';
|
import { useRuleFormItem } from '/@/hooks/component/useFormItem'
|
||||||
import { useAttrs } from '/@/hooks/core/useAttrs';
|
import { useAttrs } from '/@/hooks/core/useAttrs'
|
||||||
import { get, omit } from 'lodash-es';
|
import { get, omit } from 'lodash-es'
|
||||||
import { LoadingOutlined } from '@ant-design/icons-vue';
|
import { LoadingOutlined } from '@ant-design/icons-vue'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
import { propTypes } from '/@/utils/propTypes';
|
import { propTypes } from '/@/utils/propTypes'
|
||||||
|
|
||||||
type OptionsItem = { label: string; value: string; disabled?: boolean };
|
type OptionsItem = { label: string; value: string; disabled?: boolean }
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'ApiSelect',
|
name: 'ApiSelect',
|
||||||
|
|
@ -61,87 +61,87 @@
|
||||||
},
|
},
|
||||||
emits: ['options-change', 'change'],
|
emits: ['options-change', 'change'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const options = ref<OptionsItem[]>([]);
|
const options = ref<OptionsItem[]>([])
|
||||||
const loading = ref(false);
|
const loading = ref(false)
|
||||||
const isFirstLoad = ref(true);
|
const isFirstLoad = ref(true)
|
||||||
const emitData = ref<any[]>([]);
|
const emitData = ref<any[]>([])
|
||||||
const attrs = useAttrs();
|
const attrs = useAttrs()
|
||||||
const { t } = useI18n();
|
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)
|
||||||
|
|
||||||
const getOptions = computed(() => {
|
const getOptions = computed(() => {
|
||||||
const { labelField, valueField, numberToString } = props;
|
const { labelField, valueField, numberToString } = props
|
||||||
|
|
||||||
return unref(options).reduce((prev, next: Recordable) => {
|
return unref(options).reduce((prev, next: Recordable) => {
|
||||||
if (next) {
|
if (next) {
|
||||||
const value = next[valueField];
|
const value = next[valueField]
|
||||||
prev.push({
|
prev.push({
|
||||||
...omit(next, [labelField, valueField]),
|
...omit(next, [labelField, valueField]),
|
||||||
label: next[labelField],
|
label: next[labelField],
|
||||||
value: numberToString ? `${value}` : value,
|
value: numberToString ? `${value}` : value,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
return prev;
|
return prev
|
||||||
}, [] as OptionsItem[]);
|
}, [] as OptionsItem[])
|
||||||
});
|
})
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
props.immediate && !props.alwaysLoad && fetch();
|
props.immediate && !props.alwaysLoad && fetch()
|
||||||
});
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.params,
|
() => props.params,
|
||||||
() => {
|
() => {
|
||||||
!unref(isFirstLoad) && fetch();
|
!unref(isFirstLoad) && fetch()
|
||||||
},
|
},
|
||||||
{ deep: true },
|
{ deep: true },
|
||||||
);
|
)
|
||||||
|
|
||||||
async function fetch() {
|
async function fetch() {
|
||||||
const api = props.api;
|
const api = props.api
|
||||||
if (!api || !isFunction(api)) return;
|
if (!api || !isFunction(api)) return
|
||||||
options.value = [];
|
options.value = []
|
||||||
try {
|
try {
|
||||||
loading.value = true;
|
loading.value = true
|
||||||
const res = await api(props.params);
|
const res = await api(props.params)
|
||||||
if (Array.isArray(res)) {
|
if (Array.isArray(res)) {
|
||||||
options.value = res;
|
options.value = res
|
||||||
emitChange();
|
emitChange()
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if (props.resultField) {
|
if (props.resultField) {
|
||||||
options.value = get(res, props.resultField) || [];
|
options.value = get(res, props.resultField) || []
|
||||||
}
|
}
|
||||||
emitChange();
|
emitChange()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(error);
|
console.warn(error)
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleFetch(visible) {
|
async function handleFetch(visible) {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
if (props.alwaysLoad) {
|
if (props.alwaysLoad) {
|
||||||
await fetch();
|
await fetch()
|
||||||
} else if (!props.immediate && unref(isFirstLoad)) {
|
} else if (!props.immediate && unref(isFirstLoad)) {
|
||||||
await fetch();
|
await fetch()
|
||||||
isFirstLoad.value = false;
|
isFirstLoad.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function emitChange() {
|
function emitChange() {
|
||||||
emit('options-change', unref(getOptions));
|
emit('options-change', unref(getOptions))
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleChange(_, ...args) {
|
function handleChange(_, ...args) {
|
||||||
emitData.value = args;
|
emitData.value = args
|
||||||
}
|
}
|
||||||
|
|
||||||
return { state, attrs, getOptions, loading, t, handleFetch, handleChange };
|
return { state, attrs, getOptions, loading, t, handleFetch, handleChange }
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,13 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineComponent, watch, ref, unref, watchEffect } from 'vue';
|
import { computed, defineComponent, watch, ref, unref, watchEffect } from 'vue'
|
||||||
import { Transfer } from 'ant-design-vue';
|
import { Transfer } from 'ant-design-vue'
|
||||||
import { isFunction } from '/@/utils/is';
|
import { isFunction } from '/@/utils/is'
|
||||||
import { get, omit } from 'lodash-es';
|
import { get, omit } from 'lodash-es'
|
||||||
import { propTypes } from '/@/utils/propTypes';
|
import { propTypes } from '/@/utils/propTypes'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
import { TransferDirection, TransferItem } from 'ant-design-vue/lib/transfer';
|
import { TransferDirection, TransferItem } from 'ant-design-vue/lib/transfer'
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'ApiTransfer',
|
name: 'ApiTransfer',
|
||||||
components: { Transfer },
|
components: { Transfer },
|
||||||
|
|
@ -47,18 +47,18 @@
|
||||||
},
|
},
|
||||||
emits: ['options-change', 'change'],
|
emits: ['options-change', 'change'],
|
||||||
setup(props, { attrs, emit }) {
|
setup(props, { attrs, emit }) {
|
||||||
const _dataSource = ref<TransferItem[]>([]);
|
const _dataSource = ref<TransferItem[]>([])
|
||||||
const _targetKeys = ref<string[]>([]);
|
const _targetKeys = ref<string[]>([])
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
|
|
||||||
const getAttrs = computed(() => {
|
const getAttrs = computed(() => {
|
||||||
return {
|
return {
|
||||||
...(!props.api ? { dataSource: unref(_dataSource) } : {}),
|
...(!props.api ? { dataSource: unref(_dataSource) } : {}),
|
||||||
...attrs,
|
...attrs,
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
const getdataSource = computed(() => {
|
const getdataSource = computed(() => {
|
||||||
const { labelField, valueField } = props;
|
const { labelField, valueField } = props
|
||||||
|
|
||||||
return unref(_dataSource).reduce((prev, next: Recordable) => {
|
return unref(_dataSource).reduce((prev, next: Recordable) => {
|
||||||
if (next) {
|
if (next) {
|
||||||
|
|
@ -66,69 +66,69 @@
|
||||||
...omit(next, [labelField, valueField]),
|
...omit(next, [labelField, valueField]),
|
||||||
title: next[labelField],
|
title: next[labelField],
|
||||||
key: next[valueField],
|
key: next[valueField],
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
return prev;
|
return prev
|
||||||
}, [] as TransferItem[]);
|
}, [] as TransferItem[])
|
||||||
});
|
})
|
||||||
const getTargetKeys = computed<string[]>(() => {
|
const getTargetKeys = computed<string[]>(() => {
|
||||||
if (unref(_targetKeys).length > 0) {
|
if (unref(_targetKeys).length > 0) {
|
||||||
return unref(_targetKeys);
|
return unref(_targetKeys)
|
||||||
}
|
}
|
||||||
if (Array.isArray(props.value)) {
|
if (Array.isArray(props.value)) {
|
||||||
return props.value;
|
return props.value
|
||||||
}
|
}
|
||||||
return [];
|
return []
|
||||||
});
|
})
|
||||||
|
|
||||||
function handleChange(keys: string[], direction: TransferDirection, moveKeys: string[]) {
|
function handleChange(keys: string[], direction: TransferDirection, moveKeys: string[]) {
|
||||||
_targetKeys.value = keys;
|
_targetKeys.value = keys
|
||||||
console.log(direction);
|
console.log(direction)
|
||||||
console.log(moveKeys);
|
console.log(moveKeys)
|
||||||
emit('change', keys);
|
emit('change', keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
props.immediate && !props.alwaysLoad && fetch();
|
props.immediate && !props.alwaysLoad && fetch()
|
||||||
});
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.params,
|
() => props.params,
|
||||||
() => {
|
() => {
|
||||||
fetch();
|
fetch()
|
||||||
},
|
},
|
||||||
{ deep: true },
|
{ deep: true },
|
||||||
);
|
)
|
||||||
|
|
||||||
async function fetch() {
|
async function fetch() {
|
||||||
const api = props.api;
|
const api = props.api
|
||||||
if (!api || !isFunction(api)) {
|
if (!api || !isFunction(api)) {
|
||||||
if (Array.isArray(props.dataSource)) {
|
if (Array.isArray(props.dataSource)) {
|
||||||
_dataSource.value = props.dataSource;
|
_dataSource.value = props.dataSource
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
_dataSource.value = [];
|
_dataSource.value = []
|
||||||
try {
|
try {
|
||||||
const res = await api(props.params);
|
const res = await api(props.params)
|
||||||
if (Array.isArray(res)) {
|
if (Array.isArray(res)) {
|
||||||
_dataSource.value = res;
|
_dataSource.value = res
|
||||||
emitChange();
|
emitChange()
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if (props.resultField) {
|
if (props.resultField) {
|
||||||
_dataSource.value = get(res, props.resultField) || [];
|
_dataSource.value = get(res, props.resultField) || []
|
||||||
}
|
}
|
||||||
emitChange();
|
emitChange()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(error);
|
console.warn(error)
|
||||||
} finally {
|
} finally {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function emitChange() {
|
function emitChange() {
|
||||||
emit('options-change', unref(getdataSource));
|
emit('options-change', unref(getdataSource))
|
||||||
}
|
}
|
||||||
return { getTargetKeys, getdataSource, t, getAttrs, handleChange };
|
return { getTargetKeys, getdataSource, t, getAttrs, handleChange }
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,12 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineComponent, watch, ref, onMounted, unref } from 'vue';
|
import { computed, defineComponent, watch, ref, onMounted, unref } from 'vue'
|
||||||
import { Tree } from 'ant-design-vue';
|
import { Tree } from 'ant-design-vue'
|
||||||
import { isArray, isFunction } from '/@/utils/is';
|
import { isArray, isFunction } from '/@/utils/is'
|
||||||
import { get } from 'lodash-es';
|
import { get } from 'lodash-es'
|
||||||
import { propTypes } from '/@/utils/propTypes';
|
import { propTypes } from '/@/utils/propTypes'
|
||||||
import { LoadingOutlined } from '@ant-design/icons-vue';
|
import { LoadingOutlined } from '@ant-design/icons-vue'
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'ApiTree',
|
name: 'ApiTree',
|
||||||
components: { ATree: Tree, LoadingOutlined },
|
components: { ATree: Tree, LoadingOutlined },
|
||||||
|
|
@ -28,63 +28,63 @@
|
||||||
},
|
},
|
||||||
emits: ['options-change', 'change'],
|
emits: ['options-change', 'change'],
|
||||||
setup(props, { attrs, emit }) {
|
setup(props, { attrs, emit }) {
|
||||||
const treeData = ref<Recordable[]>([]);
|
const treeData = ref<Recordable[]>([])
|
||||||
const isFirstLoaded = ref<Boolean>(false);
|
const isFirstLoaded = ref<Boolean>(false)
|
||||||
const loading = ref(false);
|
const loading = ref(false)
|
||||||
const getAttrs = computed(() => {
|
const getAttrs = computed(() => {
|
||||||
return {
|
return {
|
||||||
...(props.api ? { treeData: unref(treeData) } : {}),
|
...(props.api ? { treeData: unref(treeData) } : {}),
|
||||||
...attrs,
|
...attrs,
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
function handleChange(...args) {
|
function handleChange(...args) {
|
||||||
emit('change', ...args);
|
emit('change', ...args)
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.params,
|
() => props.params,
|
||||||
() => {
|
() => {
|
||||||
!unref(isFirstLoaded) && fetch();
|
!unref(isFirstLoaded) && fetch()
|
||||||
},
|
},
|
||||||
{ deep: true },
|
{ deep: true },
|
||||||
);
|
)
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.immediate,
|
() => props.immediate,
|
||||||
(v) => {
|
(v) => {
|
||||||
v && !isFirstLoaded.value && fetch();
|
v && !isFirstLoaded.value && fetch()
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
props.immediate && fetch();
|
props.immediate && fetch()
|
||||||
});
|
})
|
||||||
|
|
||||||
async function fetch() {
|
async function fetch() {
|
||||||
const { api, afterFetch } = props;
|
const { api, afterFetch } = props
|
||||||
if (!api || !isFunction(api)) return;
|
if (!api || !isFunction(api)) return
|
||||||
loading.value = true;
|
loading.value = true
|
||||||
treeData.value = [];
|
treeData.value = []
|
||||||
let result;
|
let result
|
||||||
try {
|
try {
|
||||||
result = await api(props.params);
|
result = await api(props.params)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e)
|
||||||
}
|
}
|
||||||
if (afterFetch && isFunction(afterFetch)) {
|
if (afterFetch && isFunction(afterFetch)) {
|
||||||
result = afterFetch(result);
|
result = afterFetch(result)
|
||||||
}
|
}
|
||||||
loading.value = false;
|
loading.value = false
|
||||||
if (!result) return;
|
if (!result) return
|
||||||
if (!isArray(result)) {
|
if (!isArray(result)) {
|
||||||
result = get(result, props.resultField);
|
result = get(result, props.resultField)
|
||||||
}
|
}
|
||||||
treeData.value = (result as Recordable[]) || [];
|
treeData.value = (result as Recordable[]) || []
|
||||||
isFirstLoaded.value = true;
|
isFirstLoaded.value = true
|
||||||
emit('options-change', treeData.value);
|
emit('options-change', treeData.value)
|
||||||
}
|
}
|
||||||
return { getAttrs, loading, handleChange };
|
return { getAttrs, loading, handleChange }
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import type { PropType, Ref } from 'vue';
|
import type { PropType, Ref } from 'vue'
|
||||||
import { computed, defineComponent, toRefs, unref } from 'vue';
|
import { computed, defineComponent, toRefs, unref } from 'vue'
|
||||||
import type { FormActionType, FormProps, FormSchema } from '../types/form';
|
import type { FormActionType, FormProps, FormSchema } from '../types/form'
|
||||||
import type { ValidationRule } from 'ant-design-vue/lib/form/Form';
|
import type { ValidationRule } from 'ant-design-vue/lib/form/Form'
|
||||||
import type { TableActionType } from '/@/components/Table';
|
import type { TableActionType } from '/@/components/Table'
|
||||||
import { Col, Divider, Form } from 'ant-design-vue';
|
import { Col, Divider, Form } from 'ant-design-vue'
|
||||||
import { componentMap } from '../componentMap';
|
import { componentMap } from '../componentMap'
|
||||||
import { BasicHelp } from '/@/components/Basic';
|
import { BasicHelp } from '/@/components/Basic'
|
||||||
import { isBoolean, isFunction, isNull } from '/@/utils/is';
|
import { isBoolean, isFunction, isNull } from '/@/utils/is'
|
||||||
import { getSlot } from '/@/utils/helper/tsxHelper';
|
import { getSlot } from '/@/utils/helper/tsxHelper'
|
||||||
import { createPlaceholderMessage, setComponentRuleType } from '../helper';
|
import { createPlaceholderMessage, setComponentRuleType } from '../helper'
|
||||||
import { cloneDeep, upperFirst } from 'lodash-es';
|
import { cloneDeep, upperFirst } from 'lodash-es'
|
||||||
import { useItemLabelWidth } from '../hooks/useLabelWidth';
|
import { useItemLabelWidth } from '../hooks/useLabelWidth'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'BasicFormItem',
|
name: 'BasicFormItem',
|
||||||
|
|
@ -46,18 +46,18 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
setup(props, { slots }) {
|
setup(props, { slots }) {
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
|
|
||||||
const { schema, formProps } = toRefs(props) as {
|
const { schema, formProps } = toRefs(props) as {
|
||||||
schema: Ref<FormSchema>;
|
schema: Ref<FormSchema>
|
||||||
formProps: Ref<FormProps>;
|
formProps: Ref<FormProps>
|
||||||
};
|
}
|
||||||
|
|
||||||
const itemLabelWidthProp = useItemLabelWidth(schema, formProps);
|
const itemLabelWidthProp = useItemLabelWidth(schema, formProps)
|
||||||
|
|
||||||
const getValues = computed(() => {
|
const getValues = computed(() => {
|
||||||
const { allDefaultValues, formModel, schema } = props;
|
const { allDefaultValues, formModel, schema } = props
|
||||||
const { mergeDynamicData } = props.formProps;
|
const { mergeDynamicData } = props.formProps
|
||||||
return {
|
return {
|
||||||
field: schema.field,
|
field: schema.field,
|
||||||
model: formModel,
|
model: formModel,
|
||||||
|
|
@ -67,64 +67,64 @@
|
||||||
...formModel,
|
...formModel,
|
||||||
} as Recordable,
|
} as Recordable,
|
||||||
schema: schema,
|
schema: schema,
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
const getComponentsProps = computed(() => {
|
const getComponentsProps = computed(() => {
|
||||||
const { schema, tableAction, formModel, formActionType } = props;
|
const { schema, tableAction, formModel, formActionType } = props
|
||||||
let { componentProps = {} } = schema;
|
let { componentProps = {} } = schema
|
||||||
if (isFunction(componentProps)) {
|
if (isFunction(componentProps)) {
|
||||||
componentProps = componentProps({ schema, tableAction, formModel, formActionType }) ?? {};
|
componentProps = componentProps({ schema, tableAction, formModel, formActionType }) ?? {}
|
||||||
}
|
}
|
||||||
if (schema.component === 'Divider') {
|
if (schema.component === 'Divider') {
|
||||||
componentProps = Object.assign({ type: 'horizontal' }, componentProps, {
|
componentProps = Object.assign({ type: 'horizontal' }, componentProps, {
|
||||||
orientation: 'left',
|
orientation: 'left',
|
||||||
plain: true,
|
plain: true,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
return componentProps as Recordable;
|
return componentProps as Recordable
|
||||||
});
|
})
|
||||||
|
|
||||||
const getDisable = computed(() => {
|
const getDisable = computed(() => {
|
||||||
const { disabled: globDisabled } = props.formProps;
|
const { disabled: globDisabled } = props.formProps
|
||||||
const { dynamicDisabled } = props.schema;
|
const { dynamicDisabled } = props.schema
|
||||||
const { disabled: itemDisabled = false } = unref(getComponentsProps);
|
const { disabled: itemDisabled = false } = unref(getComponentsProps)
|
||||||
let disabled = !!globDisabled || itemDisabled;
|
let disabled = !!globDisabled || itemDisabled
|
||||||
if (isBoolean(dynamicDisabled)) {
|
if (isBoolean(dynamicDisabled)) {
|
||||||
disabled = dynamicDisabled;
|
disabled = dynamicDisabled
|
||||||
}
|
}
|
||||||
if (isFunction(dynamicDisabled)) {
|
if (isFunction(dynamicDisabled)) {
|
||||||
disabled = dynamicDisabled(unref(getValues));
|
disabled = dynamicDisabled(unref(getValues))
|
||||||
}
|
}
|
||||||
return disabled;
|
return disabled
|
||||||
});
|
})
|
||||||
|
|
||||||
function getShow(): { isShow: boolean; isIfShow: boolean } {
|
function getShow(): { isShow: boolean; isIfShow: boolean } {
|
||||||
const { show, ifShow } = props.schema;
|
const { show, ifShow } = props.schema
|
||||||
const { showAdvancedButton } = props.formProps;
|
const { showAdvancedButton } = props.formProps
|
||||||
const itemIsAdvanced = showAdvancedButton
|
const itemIsAdvanced = showAdvancedButton
|
||||||
? isBoolean(props.schema.isAdvanced)
|
? isBoolean(props.schema.isAdvanced)
|
||||||
? props.schema.isAdvanced
|
? props.schema.isAdvanced
|
||||||
: true
|
: true
|
||||||
: true;
|
: true
|
||||||
|
|
||||||
let isShow = true;
|
let isShow = true
|
||||||
let isIfShow = true;
|
let isIfShow = true
|
||||||
|
|
||||||
if (isBoolean(show)) {
|
if (isBoolean(show)) {
|
||||||
isShow = show;
|
isShow = show
|
||||||
}
|
}
|
||||||
if (isBoolean(ifShow)) {
|
if (isBoolean(ifShow)) {
|
||||||
isIfShow = ifShow;
|
isIfShow = ifShow
|
||||||
}
|
}
|
||||||
if (isFunction(show)) {
|
if (isFunction(show)) {
|
||||||
isShow = show(unref(getValues));
|
isShow = show(unref(getValues))
|
||||||
}
|
}
|
||||||
if (isFunction(ifShow)) {
|
if (isFunction(ifShow)) {
|
||||||
isIfShow = ifShow(unref(getValues));
|
isIfShow = ifShow(unref(getValues))
|
||||||
}
|
}
|
||||||
isShow = isShow && itemIsAdvanced;
|
isShow = isShow && itemIsAdvanced
|
||||||
return { isShow, isIfShow };
|
return { isShow, isIfShow }
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleRules(): ValidationRule[] {
|
function handleRules(): ValidationRule[] {
|
||||||
|
|
@ -135,31 +135,31 @@
|
||||||
label,
|
label,
|
||||||
dynamicRules,
|
dynamicRules,
|
||||||
required,
|
required,
|
||||||
} = props.schema;
|
} = props.schema
|
||||||
|
|
||||||
if (isFunction(dynamicRules)) {
|
if (isFunction(dynamicRules)) {
|
||||||
return dynamicRules(unref(getValues)) as ValidationRule[];
|
return dynamicRules(unref(getValues)) as ValidationRule[]
|
||||||
}
|
}
|
||||||
|
|
||||||
let rules: ValidationRule[] = cloneDeep(defRules) as ValidationRule[];
|
let rules: ValidationRule[] = cloneDeep(defRules) as ValidationRule[]
|
||||||
const { rulesMessageJoinLabel: globalRulesMessageJoinLabel } = props.formProps;
|
const { rulesMessageJoinLabel: globalRulesMessageJoinLabel } = props.formProps
|
||||||
|
|
||||||
const joinLabel = Reflect.has(props.schema, 'rulesMessageJoinLabel')
|
const joinLabel = Reflect.has(props.schema, 'rulesMessageJoinLabel')
|
||||||
? rulesMessageJoinLabel
|
? rulesMessageJoinLabel
|
||||||
: globalRulesMessageJoinLabel;
|
: globalRulesMessageJoinLabel
|
||||||
const defaultMsg = createPlaceholderMessage(component) + `${joinLabel ? label : ''}`;
|
const defaultMsg = createPlaceholderMessage(component) + `${joinLabel ? label : ''}`
|
||||||
|
|
||||||
function validator(rule: any, value: any) {
|
function validator(rule: any, value: any) {
|
||||||
const msg = rule.message || defaultMsg;
|
const msg = rule.message || defaultMsg
|
||||||
if (value === undefined || isNull(value)) {
|
if (value === undefined || isNull(value)) {
|
||||||
// 空值
|
// 空值
|
||||||
return Promise.reject(msg);
|
return Promise.reject(msg)
|
||||||
} else if (Array.isArray(value) && value.length === 0) {
|
} else if (Array.isArray(value) && value.length === 0) {
|
||||||
// 数组类型
|
// 数组类型
|
||||||
return Promise.reject(msg);
|
return Promise.reject(msg)
|
||||||
} else if (typeof value === 'string' && value.trim() === '') {
|
} else if (typeof value === 'string' && value.trim() === '') {
|
||||||
// 空字符串
|
// 空字符串
|
||||||
return Promise.reject(msg);
|
return Promise.reject(msg)
|
||||||
} else if (
|
} else if (
|
||||||
typeof value === 'object' &&
|
typeof value === 'object' &&
|
||||||
Reflect.has(value, 'checked') &&
|
Reflect.has(value, 'checked') &&
|
||||||
|
|
@ -170,12 +170,12 @@
|
||||||
value.halfChecked.length === 0
|
value.halfChecked.length === 0
|
||||||
) {
|
) {
|
||||||
// 非关联选择的tree组件
|
// 非关联选择的tree组件
|
||||||
return Promise.reject(msg);
|
return Promise.reject(msg)
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve()
|
||||||
}
|
}
|
||||||
|
|
||||||
const getRequired = isFunction(required) ? required(unref(getValues)) : required;
|
const getRequired = isFunction(required) ? required(unref(getValues)) : required
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 1、若设置了required属性,又没有其他的rules,就创建一个验证规则;
|
* 1、若设置了required属性,又没有其他的rules,就创建一个验证规则;
|
||||||
|
|
@ -184,49 +184,49 @@
|
||||||
*/
|
*/
|
||||||
if (getRequired) {
|
if (getRequired) {
|
||||||
if (!rules || rules.length === 0) {
|
if (!rules || rules.length === 0) {
|
||||||
rules = [{ required: getRequired, validator }];
|
rules = [{ required: getRequired, validator }]
|
||||||
} else {
|
} else {
|
||||||
const requiredIndex: number = rules.findIndex((rule) => Reflect.has(rule, 'required'));
|
const requiredIndex: number = rules.findIndex((rule) => Reflect.has(rule, 'required'))
|
||||||
|
|
||||||
if (requiredIndex === -1) {
|
if (requiredIndex === -1) {
|
||||||
rules.push({ required: getRequired, validator });
|
rules.push({ required: getRequired, validator })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const requiredRuleIndex: number = rules.findIndex(
|
const requiredRuleIndex: number = rules.findIndex(
|
||||||
(rule) => Reflect.has(rule, 'required') && !Reflect.has(rule, 'validator'),
|
(rule) => Reflect.has(rule, 'required') && !Reflect.has(rule, 'validator'),
|
||||||
);
|
)
|
||||||
|
|
||||||
if (requiredRuleIndex !== -1) {
|
if (requiredRuleIndex !== -1) {
|
||||||
const rule = rules[requiredRuleIndex];
|
const rule = rules[requiredRuleIndex]
|
||||||
const { isShow } = getShow();
|
const { isShow } = getShow()
|
||||||
if (!isShow) {
|
if (!isShow) {
|
||||||
rule.required = false;
|
rule.required = false
|
||||||
}
|
}
|
||||||
if (component) {
|
if (component) {
|
||||||
if (!Reflect.has(rule, 'type')) {
|
if (!Reflect.has(rule, 'type')) {
|
||||||
rule.type = component === 'InputNumber' ? 'number' : 'string';
|
rule.type = component === 'InputNumber' ? 'number' : 'string'
|
||||||
}
|
}
|
||||||
|
|
||||||
rule.message = rule.message || defaultMsg;
|
rule.message = rule.message || defaultMsg
|
||||||
|
|
||||||
if (component.includes('Input') || component.includes('Textarea')) {
|
if (component.includes('Input') || component.includes('Textarea')) {
|
||||||
rule.whitespace = true;
|
rule.whitespace = true
|
||||||
}
|
}
|
||||||
const valueFormat = unref(getComponentsProps)?.valueFormat;
|
const valueFormat = unref(getComponentsProps)?.valueFormat
|
||||||
setComponentRuleType(rule, component, valueFormat);
|
setComponentRuleType(rule, component, valueFormat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maximum input length rule check
|
// Maximum input length rule check
|
||||||
const characterInx = rules.findIndex((val) => val.max);
|
const characterInx = rules.findIndex((val) => val.max)
|
||||||
if (characterInx !== -1 && !rules[characterInx].validator) {
|
if (characterInx !== -1 && !rules[characterInx].validator) {
|
||||||
rules[characterInx].message =
|
rules[characterInx].message =
|
||||||
rules[characterInx].message ||
|
rules[characterInx].message ||
|
||||||
t('component.form.maxTip', [rules[characterInx].max] as Recordable);
|
t('component.form.maxTip', [rules[characterInx].max] as Recordable)
|
||||||
}
|
}
|
||||||
return rules;
|
return rules
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderComponent() {
|
function renderComponent() {
|
||||||
|
|
@ -236,109 +236,107 @@
|
||||||
field,
|
field,
|
||||||
changeEvent = 'change',
|
changeEvent = 'change',
|
||||||
valueField,
|
valueField,
|
||||||
} = props.schema;
|
} = props.schema
|
||||||
|
|
||||||
const isCheck = component && ['Switch', 'Checkbox'].includes(component);
|
const isCheck = component && ['Switch', 'Checkbox'].includes(component)
|
||||||
|
|
||||||
const eventKey = `on${upperFirst(changeEvent)}`;
|
const eventKey = `on${upperFirst(changeEvent)}`
|
||||||
|
|
||||||
const on = {
|
const on = {
|
||||||
[eventKey]: (...args: Nullable<Recordable>[]) => {
|
[eventKey]: (...args: Nullable<Recordable>[]) => {
|
||||||
const [e] = args;
|
const [e] = args
|
||||||
if (propsData[eventKey]) {
|
if (propsData[eventKey]) {
|
||||||
propsData[eventKey](...args);
|
propsData[eventKey](...args)
|
||||||
}
|
}
|
||||||
const target = e ? e.target : null;
|
const target = e ? e.target : null
|
||||||
const value = target ? (isCheck ? target.checked : target.value) : e;
|
const value = target ? (isCheck ? target.checked : target.value) : e
|
||||||
props.setFormModel(field, value);
|
props.setFormModel(field, value)
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
const Comp = componentMap.get(component) as ReturnType<typeof defineComponent>;
|
const Comp = componentMap.get(component) as ReturnType<typeof defineComponent>
|
||||||
|
|
||||||
const { autoSetPlaceHolder, size } = props.formProps;
|
const { autoSetPlaceHolder, size } = props.formProps
|
||||||
const propsData: Recordable = {
|
const propsData: Recordable = {
|
||||||
allowClear: true,
|
allowClear: true,
|
||||||
getPopupContainer: (trigger: Element) => trigger.parentNode,
|
getPopupContainer: (trigger: Element) => trigger.parentNode,
|
||||||
size,
|
size,
|
||||||
...unref(getComponentsProps),
|
...unref(getComponentsProps),
|
||||||
disabled: unref(getDisable),
|
disabled: unref(getDisable),
|
||||||
};
|
}
|
||||||
|
|
||||||
const isCreatePlaceholder = !propsData.disabled && autoSetPlaceHolder;
|
const isCreatePlaceholder = !propsData.disabled && autoSetPlaceHolder
|
||||||
// RangePicker place is an array
|
// RangePicker place is an array
|
||||||
if (isCreatePlaceholder && component !== 'RangePicker' && component) {
|
if (isCreatePlaceholder && component !== 'RangePicker' && component) {
|
||||||
propsData.placeholder =
|
propsData.placeholder =
|
||||||
unref(getComponentsProps)?.placeholder || createPlaceholderMessage(component);
|
unref(getComponentsProps)?.placeholder || createPlaceholderMessage(component)
|
||||||
}
|
}
|
||||||
propsData.codeField = field;
|
propsData.codeField = field
|
||||||
propsData.formValues = unref(getValues);
|
propsData.formValues = unref(getValues)
|
||||||
|
|
||||||
const bindValue: Recordable = {
|
const bindValue: Recordable = {
|
||||||
[valueField || (isCheck ? 'checked' : 'value')]: props.formModel[field],
|
[valueField || (isCheck ? 'checked' : 'value')]: props.formModel[field],
|
||||||
};
|
}
|
||||||
|
|
||||||
const compAttr: Recordable = {
|
const compAttr: Recordable = {
|
||||||
...propsData,
|
...propsData,
|
||||||
...on,
|
...on,
|
||||||
...bindValue,
|
...bindValue,
|
||||||
};
|
}
|
||||||
|
|
||||||
if (!renderComponentContent) {
|
if (!renderComponentContent) {
|
||||||
return <Comp {...compAttr} />;
|
return <Comp {...compAttr} />
|
||||||
}
|
}
|
||||||
const compSlot = isFunction(renderComponentContent)
|
const compSlot = isFunction(renderComponentContent)
|
||||||
? { ...renderComponentContent(unref(getValues)) }
|
? { ...renderComponentContent(unref(getValues)) }
|
||||||
: {
|
: {
|
||||||
default: () => renderComponentContent,
|
default: () => renderComponentContent,
|
||||||
};
|
}
|
||||||
return <Comp {...compAttr}>{compSlot}</Comp>;
|
return <Comp {...compAttr}>{compSlot}</Comp>
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderLabelHelpMessage() {
|
function renderLabelHelpMessage() {
|
||||||
const { label, helpMessage, helpComponentProps, subLabel } = props.schema;
|
const { label, helpMessage, helpComponentProps, subLabel } = props.schema
|
||||||
const renderLabel = subLabel ? (
|
const renderLabel = subLabel ? (
|
||||||
<span>
|
<span>
|
||||||
{label} <span class="text-secondary">{subLabel}</span>
|
{label} <span class="text-secondary">{subLabel}</span>
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
label
|
label
|
||||||
);
|
)
|
||||||
const getHelpMessage = isFunction(helpMessage)
|
const getHelpMessage = isFunction(helpMessage) ? helpMessage(unref(getValues)) : helpMessage
|
||||||
? helpMessage(unref(getValues))
|
|
||||||
: helpMessage;
|
|
||||||
if (!getHelpMessage || (Array.isArray(getHelpMessage) && getHelpMessage.length === 0)) {
|
if (!getHelpMessage || (Array.isArray(getHelpMessage) && getHelpMessage.length === 0)) {
|
||||||
return renderLabel;
|
return renderLabel
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
{renderLabel}
|
{renderLabel}
|
||||||
<BasicHelp placement="top" class="mx-1" text={getHelpMessage} {...helpComponentProps} />
|
<BasicHelp placement="top" class="mx-1" text={getHelpMessage} {...helpComponentProps} />
|
||||||
</span>
|
</span>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderItem() {
|
function renderItem() {
|
||||||
const { itemProps, slot, render, field, suffix, component } = props.schema;
|
const { itemProps, slot, render, field, suffix, component } = props.schema
|
||||||
const { labelCol, wrapperCol } = unref(itemLabelWidthProp);
|
const { labelCol, wrapperCol } = unref(itemLabelWidthProp)
|
||||||
const { colon } = props.formProps;
|
const { colon } = props.formProps
|
||||||
|
|
||||||
if (component === 'Divider') {
|
if (component === 'Divider') {
|
||||||
return (
|
return (
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<Divider {...unref(getComponentsProps)}>{renderLabelHelpMessage()}</Divider>
|
<Divider {...unref(getComponentsProps)}>{renderLabelHelpMessage()}</Divider>
|
||||||
</Col>
|
</Col>
|
||||||
);
|
)
|
||||||
} else {
|
} else {
|
||||||
const getContent = () => {
|
const getContent = () => {
|
||||||
return slot
|
return slot
|
||||||
? getSlot(slots, slot, unref(getValues))
|
? getSlot(slots, slot, unref(getValues))
|
||||||
: render
|
: render
|
||||||
? render(unref(getValues))
|
? render(unref(getValues))
|
||||||
: renderComponent();
|
: renderComponent()
|
||||||
};
|
}
|
||||||
|
|
||||||
const showSuffix = !!suffix;
|
const showSuffix = !!suffix
|
||||||
const getSuffix = isFunction(suffix) ? suffix(unref(getValues)) : suffix;
|
const getSuffix = isFunction(suffix) ? suffix(unref(getValues)) : suffix
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form.Item
|
<Form.Item
|
||||||
|
|
@ -356,28 +354,28 @@
|
||||||
{showSuffix && <span class="suffix">{getSuffix}</span>}
|
{showSuffix && <span class="suffix">{getSuffix}</span>}
|
||||||
</div>
|
</div>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const { colProps = {}, colSlot, renderColContent, component } = props.schema;
|
const { colProps = {}, colSlot, renderColContent, component } = props.schema
|
||||||
if (!componentMap.has(component)) {
|
if (!componentMap.has(component)) {
|
||||||
return null;
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const { baseColProps = {} } = props.formProps;
|
const { baseColProps = {} } = props.formProps
|
||||||
const realColProps = { ...baseColProps, ...colProps };
|
const realColProps = { ...baseColProps, ...colProps }
|
||||||
const { isIfShow, isShow } = getShow();
|
const { isIfShow, isShow } = getShow()
|
||||||
const values = unref(getValues);
|
const values = unref(getValues)
|
||||||
|
|
||||||
const getContent = () => {
|
const getContent = () => {
|
||||||
return colSlot
|
return colSlot
|
||||||
? getSlot(slots, colSlot, values)
|
? getSlot(slots, colSlot, values)
|
||||||
: renderColContent
|
: renderColContent
|
||||||
? renderColContent(values)
|
? renderColContent(values)
|
||||||
: renderItem();
|
: renderItem()
|
||||||
};
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
isIfShow && (
|
isIfShow && (
|
||||||
|
|
@ -385,8 +383,8 @@
|
||||||
{getContent()}
|
{getContent()}
|
||||||
</Col>
|
</Col>
|
||||||
)
|
)
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
import type { ValidationRule } from 'ant-design-vue/lib/form/Form';
|
import type { ValidationRule } from 'ant-design-vue/lib/form/Form'
|
||||||
import type { ComponentType } from './types/index';
|
import type { ComponentType } from './types/index'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
import { dateUtil } from '/@/utils/dateUtil';
|
import { dateUtil } from '/@/utils/dateUtil'
|
||||||
import { isNumber, isObject } from '/@/utils/is';
|
import { isNumber, isObject } from '/@/utils/is'
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description: 生成placeholder
|
* @description: 生成placeholder
|
||||||
*/
|
*/
|
||||||
export function createPlaceholderMessage(component: ComponentType) {
|
export function createPlaceholderMessage(component: ComponentType) {
|
||||||
if (component.includes('Input') || component.includes('Complete')) {
|
if (component.includes('Input') || component.includes('Complete')) {
|
||||||
return t('common.inputText');
|
return t('common.inputText')
|
||||||
}
|
}
|
||||||
if (component.includes('Picker')) {
|
if (component.includes('Picker')) {
|
||||||
return t('common.chooseText');
|
return t('common.chooseText')
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
component.includes('Select') ||
|
component.includes('Select') ||
|
||||||
|
|
@ -24,15 +24,15 @@ export function createPlaceholderMessage(component: ComponentType) {
|
||||||
component.includes('Switch')
|
component.includes('Switch')
|
||||||
) {
|
) {
|
||||||
// return `请选择${label}`;
|
// return `请选择${label}`;
|
||||||
return t('common.chooseText');
|
return t('common.chooseText')
|
||||||
}
|
}
|
||||||
return '';
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
const DATE_TYPE = ['DatePicker', 'MonthPicker', 'WeekPicker', 'TimePicker'];
|
const DATE_TYPE = ['DatePicker', 'MonthPicker', 'WeekPicker', 'TimePicker']
|
||||||
|
|
||||||
function genType() {
|
function genType() {
|
||||||
return [...DATE_TYPE, 'RangePicker'];
|
return [...DATE_TYPE, 'RangePicker']
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setComponentRuleType(
|
export function setComponentRuleType(
|
||||||
|
|
@ -41,34 +41,34 @@ export function setComponentRuleType(
|
||||||
valueFormat: string,
|
valueFormat: string,
|
||||||
) {
|
) {
|
||||||
if (['DatePicker', 'MonthPicker', 'WeekPicker', 'TimePicker'].includes(component)) {
|
if (['DatePicker', 'MonthPicker', 'WeekPicker', 'TimePicker'].includes(component)) {
|
||||||
rule.type = valueFormat ? 'string' : 'object';
|
rule.type = valueFormat ? 'string' : 'object'
|
||||||
} else if (['RangePicker', 'Upload', 'CheckboxGroup', 'TimePicker'].includes(component)) {
|
} else if (['RangePicker', 'Upload', 'CheckboxGroup', 'TimePicker'].includes(component)) {
|
||||||
rule.type = 'array';
|
rule.type = 'array'
|
||||||
} else if (['InputNumber'].includes(component)) {
|
} else if (['InputNumber'].includes(component)) {
|
||||||
rule.type = 'number';
|
rule.type = 'number'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function processDateValue(attr: Recordable, component: string) {
|
export function processDateValue(attr: Recordable, component: string) {
|
||||||
const { valueFormat, value } = attr;
|
const { valueFormat, value } = attr
|
||||||
if (valueFormat) {
|
if (valueFormat) {
|
||||||
attr.value = isObject(value) ? dateUtil(value).format(valueFormat) : value;
|
attr.value = isObject(value) ? dateUtil(value).format(valueFormat) : value
|
||||||
} else if (DATE_TYPE.includes(component) && value) {
|
} else if (DATE_TYPE.includes(component) && value) {
|
||||||
attr.value = dateUtil(attr.value);
|
attr.value = dateUtil(attr.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleInputNumberValue(component?: ComponentType, val?: any) {
|
export function handleInputNumberValue(component?: ComponentType, val?: any) {
|
||||||
if (!component) return val;
|
if (!component) return val
|
||||||
if (['Input', 'InputPassword', 'InputSearch', 'InputTextArea'].includes(component)) {
|
if (['Input', 'InputPassword', 'InputSearch', 'InputTextArea'].includes(component)) {
|
||||||
return val && isNumber(val) ? `${val}` : val;
|
return val && isNumber(val) ? `${val}` : val
|
||||||
}
|
}
|
||||||
return val;
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 时间字段
|
* 时间字段
|
||||||
*/
|
*/
|
||||||
export const dateItemType = genType();
|
export const dateItemType = genType()
|
||||||
|
|
||||||
export const defaultValueComponents = ['Input', 'InputPassword', 'InputSearch', 'InputTextArea'];
|
export const defaultValueComponents = ['Input', 'InputPassword', 'InputSearch', 'InputTextArea']
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,21 @@
|
||||||
import type { ColEx } from '../types';
|
import type { ColEx } from '../types'
|
||||||
import type { AdvanceState } from '../types/hooks';
|
import type { AdvanceState } from '../types/hooks'
|
||||||
import { ComputedRef, getCurrentInstance, Ref } from 'vue';
|
import { ComputedRef, getCurrentInstance, Ref } from 'vue'
|
||||||
import type { FormProps, FormSchema } from '../types/form';
|
import type { FormProps, FormSchema } from '../types/form'
|
||||||
import { computed, unref, watch } from 'vue';
|
import { computed, unref, watch } from 'vue'
|
||||||
import { isBoolean, isFunction, isNumber, isObject } from '/@/utils/is';
|
import { isBoolean, isFunction, isNumber, isObject } from '/@/utils/is'
|
||||||
import { useBreakpoint } from '/@/hooks/event/useBreakpoint';
|
import { useBreakpoint } from '/@/hooks/event/useBreakpoint'
|
||||||
import { useDebounceFn } from '@vueuse/core';
|
import { useDebounceFn } from '@vueuse/core'
|
||||||
|
|
||||||
const BASIC_COL_LEN = 24;
|
const BASIC_COL_LEN = 24
|
||||||
|
|
||||||
interface UseAdvancedContext {
|
interface UseAdvancedContext {
|
||||||
advanceState: AdvanceState;
|
advanceState: AdvanceState
|
||||||
emit: EmitType;
|
emit: EmitType
|
||||||
getProps: ComputedRef<FormProps>;
|
getProps: ComputedRef<FormProps>
|
||||||
getSchema: ComputedRef<FormSchema[]>;
|
getSchema: ComputedRef<FormSchema[]>
|
||||||
formModel: Recordable;
|
formModel: Recordable
|
||||||
defaultValueRef: Ref<Recordable>;
|
defaultValueRef: Ref<Recordable>
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ({
|
export default function ({
|
||||||
|
|
@ -26,104 +26,104 @@ export default function ({
|
||||||
formModel,
|
formModel,
|
||||||
defaultValueRef,
|
defaultValueRef,
|
||||||
}: UseAdvancedContext) {
|
}: UseAdvancedContext) {
|
||||||
const vm = getCurrentInstance();
|
const vm = getCurrentInstance()
|
||||||
|
|
||||||
const { realWidthRef, screenEnum, screenRef } = useBreakpoint();
|
const { realWidthRef, screenEnum, screenRef } = useBreakpoint()
|
||||||
|
|
||||||
const getEmptySpan = computed((): number => {
|
const getEmptySpan = computed((): number => {
|
||||||
if (!advanceState.isAdvanced) {
|
if (!advanceState.isAdvanced) {
|
||||||
return 0;
|
return 0
|
||||||
}
|
}
|
||||||
// For some special cases, you need to manually specify additional blank lines
|
// For some special cases, you need to manually specify additional blank lines
|
||||||
const emptySpan = unref(getProps).emptySpan || 0;
|
const emptySpan = unref(getProps).emptySpan || 0
|
||||||
|
|
||||||
if (isNumber(emptySpan)) {
|
if (isNumber(emptySpan)) {
|
||||||
return emptySpan;
|
return emptySpan
|
||||||
}
|
}
|
||||||
if (isObject(emptySpan)) {
|
if (isObject(emptySpan)) {
|
||||||
const { span = 0 } = emptySpan;
|
const { span = 0 } = emptySpan
|
||||||
const screen = unref(screenRef) as string;
|
const screen = unref(screenRef) as string
|
||||||
|
|
||||||
const screenSpan = (emptySpan as any)[screen.toLowerCase()];
|
const screenSpan = (emptySpan as any)[screen.toLowerCase()]
|
||||||
return screenSpan || span || 0;
|
return screenSpan || span || 0
|
||||||
}
|
}
|
||||||
return 0;
|
return 0
|
||||||
});
|
})
|
||||||
|
|
||||||
const debounceUpdateAdvanced = useDebounceFn(updateAdvanced, 30);
|
const debounceUpdateAdvanced = useDebounceFn(updateAdvanced, 30)
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
[() => unref(getSchema), () => advanceState.isAdvanced, () => unref(realWidthRef)],
|
[() => unref(getSchema), () => advanceState.isAdvanced, () => unref(realWidthRef)],
|
||||||
() => {
|
() => {
|
||||||
const { showAdvancedButton } = unref(getProps);
|
const { showAdvancedButton } = unref(getProps)
|
||||||
if (showAdvancedButton) {
|
if (showAdvancedButton) {
|
||||||
debounceUpdateAdvanced();
|
debounceUpdateAdvanced()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
);
|
)
|
||||||
|
|
||||||
function getAdvanced(itemCol: Partial<ColEx>, itemColSum = 0, isLastAction = false) {
|
function getAdvanced(itemCol: Partial<ColEx>, itemColSum = 0, isLastAction = false) {
|
||||||
const width = unref(realWidthRef);
|
const width = unref(realWidthRef)
|
||||||
|
|
||||||
const mdWidth =
|
const mdWidth =
|
||||||
parseInt(itemCol.md as string) ||
|
parseInt(itemCol.md as string) ||
|
||||||
parseInt(itemCol.xs as string) ||
|
parseInt(itemCol.xs as string) ||
|
||||||
parseInt(itemCol.sm as string) ||
|
parseInt(itemCol.sm as string) ||
|
||||||
(itemCol.span as number) ||
|
(itemCol.span as number) ||
|
||||||
BASIC_COL_LEN;
|
BASIC_COL_LEN
|
||||||
|
|
||||||
const lgWidth = parseInt(itemCol.lg as string) || mdWidth;
|
const lgWidth = parseInt(itemCol.lg as string) || mdWidth
|
||||||
const xlWidth = parseInt(itemCol.xl as string) || lgWidth;
|
const xlWidth = parseInt(itemCol.xl as string) || lgWidth
|
||||||
const xxlWidth = parseInt(itemCol.xxl as string) || xlWidth;
|
const xxlWidth = parseInt(itemCol.xxl as string) || xlWidth
|
||||||
if (width <= screenEnum.LG) {
|
if (width <= screenEnum.LG) {
|
||||||
itemColSum += mdWidth;
|
itemColSum += mdWidth
|
||||||
} else if (width < screenEnum.XL) {
|
} else if (width < screenEnum.XL) {
|
||||||
itemColSum += lgWidth;
|
itemColSum += lgWidth
|
||||||
} else if (width < screenEnum.XXL) {
|
} else if (width < screenEnum.XXL) {
|
||||||
itemColSum += xlWidth;
|
itemColSum += xlWidth
|
||||||
} else {
|
} else {
|
||||||
itemColSum += xxlWidth;
|
itemColSum += xxlWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLastAction) {
|
if (isLastAction) {
|
||||||
advanceState.hideAdvanceBtn = false;
|
advanceState.hideAdvanceBtn = false
|
||||||
if (itemColSum <= BASIC_COL_LEN * 2) {
|
if (itemColSum <= BASIC_COL_LEN * 2) {
|
||||||
// When less than or equal to 2 lines, the collapse and expand buttons are not displayed
|
// When less than or equal to 2 lines, the collapse and expand buttons are not displayed
|
||||||
advanceState.hideAdvanceBtn = true;
|
advanceState.hideAdvanceBtn = true
|
||||||
advanceState.isAdvanced = true;
|
advanceState.isAdvanced = true
|
||||||
} else if (
|
} else if (
|
||||||
itemColSum > BASIC_COL_LEN * 2 &&
|
itemColSum > BASIC_COL_LEN * 2 &&
|
||||||
itemColSum <= BASIC_COL_LEN * (unref(getProps).autoAdvancedLine || 3)
|
itemColSum <= BASIC_COL_LEN * (unref(getProps).autoAdvancedLine || 3)
|
||||||
) {
|
) {
|
||||||
advanceState.hideAdvanceBtn = false;
|
advanceState.hideAdvanceBtn = false
|
||||||
|
|
||||||
// More than 3 lines collapsed by default
|
// More than 3 lines collapsed by default
|
||||||
} else if (!advanceState.isLoad) {
|
} else if (!advanceState.isLoad) {
|
||||||
advanceState.isLoad = true;
|
advanceState.isLoad = true
|
||||||
advanceState.isAdvanced = !advanceState.isAdvanced;
|
advanceState.isAdvanced = !advanceState.isAdvanced
|
||||||
}
|
}
|
||||||
return { isAdvanced: advanceState.isAdvanced, itemColSum };
|
return { isAdvanced: advanceState.isAdvanced, itemColSum }
|
||||||
}
|
}
|
||||||
if (itemColSum > BASIC_COL_LEN * (unref(getProps).alwaysShowLines || 1)) {
|
if (itemColSum > BASIC_COL_LEN * (unref(getProps).alwaysShowLines || 1)) {
|
||||||
return { isAdvanced: advanceState.isAdvanced, itemColSum };
|
return { isAdvanced: advanceState.isAdvanced, itemColSum }
|
||||||
} else {
|
} else {
|
||||||
// The first line is always displayed
|
// The first line is always displayed
|
||||||
return { isAdvanced: true, itemColSum };
|
return { isAdvanced: true, itemColSum }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateAdvanced() {
|
function updateAdvanced() {
|
||||||
let itemColSum = 0;
|
let itemColSum = 0
|
||||||
let realItemColSum = 0;
|
let realItemColSum = 0
|
||||||
const { baseColProps = {} } = unref(getProps);
|
const { baseColProps = {} } = unref(getProps)
|
||||||
|
|
||||||
for (const schema of unref(getSchema)) {
|
for (const schema of unref(getSchema)) {
|
||||||
const { show, colProps } = schema;
|
const { show, colProps } = schema
|
||||||
let isShow = true;
|
let isShow = true
|
||||||
|
|
||||||
if (isBoolean(show)) {
|
if (isBoolean(show)) {
|
||||||
isShow = show;
|
isShow = show
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFunction(show)) {
|
if (isFunction(show)) {
|
||||||
|
|
@ -135,36 +135,36 @@ export default function ({
|
||||||
...unref(defaultValueRef),
|
...unref(defaultValueRef),
|
||||||
...formModel,
|
...formModel,
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isShow && (colProps || baseColProps)) {
|
if (isShow && (colProps || baseColProps)) {
|
||||||
const { itemColSum: sum, isAdvanced } = getAdvanced(
|
const { itemColSum: sum, isAdvanced } = getAdvanced(
|
||||||
{ ...baseColProps, ...colProps },
|
{ ...baseColProps, ...colProps },
|
||||||
itemColSum,
|
itemColSum,
|
||||||
);
|
)
|
||||||
|
|
||||||
itemColSum = sum || 0;
|
itemColSum = sum || 0
|
||||||
if (isAdvanced) {
|
if (isAdvanced) {
|
||||||
realItemColSum = itemColSum;
|
realItemColSum = itemColSum
|
||||||
}
|
}
|
||||||
schema.isAdvanced = isAdvanced;
|
schema.isAdvanced = isAdvanced
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确保页面发送更新
|
// 确保页面发送更新
|
||||||
vm?.proxy?.$forceUpdate();
|
vm?.proxy?.$forceUpdate()
|
||||||
|
|
||||||
advanceState.actionSpan = (realItemColSum % BASIC_COL_LEN) + unref(getEmptySpan);
|
advanceState.actionSpan = (realItemColSum % BASIC_COL_LEN) + unref(getEmptySpan)
|
||||||
|
|
||||||
getAdvanced(unref(getProps).actionColOptions || { span: BASIC_COL_LEN }, itemColSum, true);
|
getAdvanced(unref(getProps).actionColOptions || { span: BASIC_COL_LEN }, itemColSum, true)
|
||||||
|
|
||||||
emit('advanced-change');
|
emit('advanced-change')
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleToggleAdvanced() {
|
function handleToggleAdvanced() {
|
||||||
advanceState.isAdvanced = !advanceState.isAdvanced;
|
advanceState.isAdvanced = !advanceState.isAdvanced
|
||||||
}
|
}
|
||||||
|
|
||||||
return { handleToggleAdvanced };
|
return { handleToggleAdvanced }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,96 +1,96 @@
|
||||||
import type { FormProps, FormActionType, UseFormReturnType, FormSchema } from '../types/form';
|
import type { FormProps, FormActionType, UseFormReturnType, FormSchema } from '../types/form'
|
||||||
import type { NamePath } from 'ant-design-vue/lib/form/interface';
|
import type { NamePath } from 'ant-design-vue/lib/form/interface'
|
||||||
import type { DynamicProps } from '/#/utils';
|
import type { DynamicProps } from '/#/utils'
|
||||||
import { ref, onUnmounted, unref, nextTick, watch } from 'vue';
|
import { ref, onUnmounted, unref, nextTick, watch } from 'vue'
|
||||||
import { isProdMode } from '/@/utils/env';
|
import { isProdMode } from '/@/utils/env'
|
||||||
import { error } from '/@/utils/log';
|
import { error } from '/@/utils/log'
|
||||||
import { getDynamicProps } from '/@/utils';
|
import { getDynamicProps } from '/@/utils'
|
||||||
|
|
||||||
export declare type ValidateFields = (nameList?: NamePath[]) => Promise<Recordable>;
|
export declare type ValidateFields = (nameList?: NamePath[]) => Promise<Recordable>
|
||||||
|
|
||||||
type Props = Partial<DynamicProps<FormProps>>;
|
type Props = Partial<DynamicProps<FormProps>>
|
||||||
|
|
||||||
export function useForm(props?: Props): UseFormReturnType {
|
export function useForm(props?: Props): UseFormReturnType {
|
||||||
const formRef = ref<Nullable<FormActionType>>(null);
|
const formRef = ref<Nullable<FormActionType>>(null)
|
||||||
const loadedRef = ref<Nullable<boolean>>(false);
|
const loadedRef = ref<Nullable<boolean>>(false)
|
||||||
|
|
||||||
async function getForm() {
|
async function getForm() {
|
||||||
const form = unref(formRef);
|
const form = unref(formRef)
|
||||||
if (!form) {
|
if (!form) {
|
||||||
error(
|
error(
|
||||||
'The form instance has not been obtained, please make sure that the form has been rendered when performing the form operation!',
|
'The form instance has not been obtained, please make sure that the form has been rendered when performing the form operation!',
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
await nextTick();
|
await nextTick()
|
||||||
return form as FormActionType;
|
return form as FormActionType
|
||||||
}
|
}
|
||||||
|
|
||||||
function register(instance: FormActionType) {
|
function register(instance: FormActionType) {
|
||||||
isProdMode() &&
|
isProdMode() &&
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
formRef.value = null;
|
formRef.value = null
|
||||||
loadedRef.value = null;
|
loadedRef.value = null
|
||||||
});
|
})
|
||||||
if (unref(loadedRef) && isProdMode() && instance === unref(formRef)) return;
|
if (unref(loadedRef) && isProdMode() && instance === unref(formRef)) return
|
||||||
|
|
||||||
formRef.value = instance;
|
formRef.value = instance
|
||||||
loadedRef.value = true;
|
loadedRef.value = true
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props,
|
() => props,
|
||||||
() => {
|
() => {
|
||||||
props && instance.setProps(getDynamicProps(props));
|
props && instance.setProps(getDynamicProps(props))
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
immediate: true,
|
immediate: true,
|
||||||
deep: true,
|
deep: true,
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const methods: FormActionType = {
|
const methods: FormActionType = {
|
||||||
scrollToField: async (name: NamePath, options?: ScrollOptions | undefined) => {
|
scrollToField: async (name: NamePath, options?: ScrollOptions | undefined) => {
|
||||||
const form = await getForm();
|
const form = await getForm()
|
||||||
form.scrollToField(name, options);
|
form.scrollToField(name, options)
|
||||||
},
|
},
|
||||||
setProps: async (formProps: Partial<FormProps>) => {
|
setProps: async (formProps: Partial<FormProps>) => {
|
||||||
const form = await getForm();
|
const form = await getForm()
|
||||||
form.setProps(formProps);
|
form.setProps(formProps)
|
||||||
},
|
},
|
||||||
|
|
||||||
updateSchema: async (data: Partial<FormSchema> | Partial<FormSchema>[]) => {
|
updateSchema: async (data: Partial<FormSchema> | Partial<FormSchema>[]) => {
|
||||||
const form = await getForm();
|
const form = await getForm()
|
||||||
form.updateSchema(data);
|
form.updateSchema(data)
|
||||||
},
|
},
|
||||||
|
|
||||||
resetSchema: async (data: Partial<FormSchema> | Partial<FormSchema>[]) => {
|
resetSchema: async (data: Partial<FormSchema> | Partial<FormSchema>[]) => {
|
||||||
const form = await getForm();
|
const form = await getForm()
|
||||||
form.resetSchema(data);
|
form.resetSchema(data)
|
||||||
},
|
},
|
||||||
|
|
||||||
clearValidate: async (name?: string | string[]) => {
|
clearValidate: async (name?: string | string[]) => {
|
||||||
const form = await getForm();
|
const form = await getForm()
|
||||||
form.clearValidate(name);
|
form.clearValidate(name)
|
||||||
},
|
},
|
||||||
|
|
||||||
resetFields: async () => {
|
resetFields: async () => {
|
||||||
getForm().then(async (form) => {
|
getForm().then(async (form) => {
|
||||||
await form.resetFields();
|
await form.resetFields()
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
removeSchemaByField: async (field: string | string[]) => {
|
removeSchemaByField: async (field: string | string[]) => {
|
||||||
unref(formRef)?.removeSchemaByField(field);
|
unref(formRef)?.removeSchemaByField(field)
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO promisify
|
// TODO promisify
|
||||||
getFieldsValue: <T>() => {
|
getFieldsValue: <T>() => {
|
||||||
return unref(formRef)?.getFieldsValue() as T;
|
return unref(formRef)?.getFieldsValue() as T
|
||||||
},
|
},
|
||||||
|
|
||||||
setFieldsValue: async <T>(values: T) => {
|
setFieldsValue: async <T>(values: T) => {
|
||||||
const form = await getForm();
|
const form = await getForm()
|
||||||
form.setFieldsValue<T>(values);
|
form.setFieldsValue<T>(values)
|
||||||
},
|
},
|
||||||
|
|
||||||
appendSchemaByField: async (
|
appendSchemaByField: async (
|
||||||
|
|
@ -98,25 +98,25 @@ export function useForm(props?: Props): UseFormReturnType {
|
||||||
prefixField: string | undefined,
|
prefixField: string | undefined,
|
||||||
first: boolean,
|
first: boolean,
|
||||||
) => {
|
) => {
|
||||||
const form = await getForm();
|
const form = await getForm()
|
||||||
form.appendSchemaByField(schema, prefixField, first);
|
form.appendSchemaByField(schema, prefixField, first)
|
||||||
},
|
},
|
||||||
|
|
||||||
submit: async (): Promise<any> => {
|
submit: async (): Promise<any> => {
|
||||||
const form = await getForm();
|
const form = await getForm()
|
||||||
return form.submit();
|
return form.submit()
|
||||||
},
|
},
|
||||||
|
|
||||||
validate: async (nameList?: NamePath[]): Promise<Recordable> => {
|
validate: async (nameList?: NamePath[]): Promise<Recordable> => {
|
||||||
const form = await getForm();
|
const form = await getForm()
|
||||||
return form.validate(nameList);
|
return form.validate(nameList)
|
||||||
},
|
},
|
||||||
|
|
||||||
validateFields: async (nameList?: NamePath[]): Promise<Recordable> => {
|
validateFields: async (nameList?: NamePath[]): Promise<Recordable> => {
|
||||||
const form = await getForm();
|
const form = await getForm()
|
||||||
return form.validateFields(nameList);
|
return form.validateFields(nameList)
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|
||||||
return [register, methods];
|
return [register, methods]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,23 @@
|
||||||
import type { ComputedRef, Ref } from 'vue';
|
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, isDef, isNullOrUnDef } from '/@/utils/is';
|
import { isArray, isFunction, isObject, isString, isDef, isNullOrUnDef } 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'
|
||||||
import { cloneDeep, uniqBy } from 'lodash-es';
|
import { cloneDeep, uniqBy } from 'lodash-es'
|
||||||
import { error } from '/@/utils/log';
|
import { error } from '/@/utils/log'
|
||||||
|
|
||||||
interface UseFormActionContext {
|
interface UseFormActionContext {
|
||||||
emit: EmitType;
|
emit: EmitType
|
||||||
getProps: ComputedRef<FormProps>;
|
getProps: ComputedRef<FormProps>
|
||||||
getSchema: ComputedRef<FormSchema[]>;
|
getSchema: ComputedRef<FormSchema[]>
|
||||||
formModel: Recordable;
|
formModel: Recordable
|
||||||
defaultValueRef: Ref<Recordable>;
|
defaultValueRef: Ref<Recordable>
|
||||||
formElRef: Ref<FormActionType>;
|
formElRef: Ref<FormActionType>
|
||||||
schemaRef: Ref<FormSchema[]>;
|
schemaRef: Ref<FormSchema[]>
|
||||||
handleFormValues: Fn;
|
handleFormValues: Fn
|
||||||
}
|
}
|
||||||
export function useFormEvents({
|
export function useFormEvents({
|
||||||
emit,
|
emit,
|
||||||
|
|
@ -30,22 +30,22 @@ export function useFormEvents({
|
||||||
handleFormValues,
|
handleFormValues,
|
||||||
}: UseFormActionContext) {
|
}: UseFormActionContext) {
|
||||||
async function resetFields(): Promise<void> {
|
async function resetFields(): Promise<void> {
|
||||||
const { resetFunc, submitOnReset } = unref(getProps);
|
const { resetFunc, submitOnReset } = unref(getProps)
|
||||||
resetFunc && isFunction(resetFunc) && (await resetFunc());
|
resetFunc && isFunction(resetFunc) && (await resetFunc())
|
||||||
|
|
||||||
const formEl = unref(formElRef);
|
const formEl = unref(formElRef)
|
||||||
if (!formEl) return;
|
if (!formEl) return
|
||||||
|
|
||||||
Object.keys(formModel).forEach((key) => {
|
Object.keys(formModel).forEach((key) => {
|
||||||
const schema = unref(getSchema).find((item) => item.field === key);
|
const schema = unref(getSchema).find((item) => item.field === key)
|
||||||
const isInput = schema?.component && defaultValueComponents.includes(schema.component);
|
const isInput = schema?.component && defaultValueComponents.includes(schema.component)
|
||||||
const defaultValue = cloneDeep(defaultValueRef.value[key]);
|
const defaultValue = cloneDeep(defaultValueRef.value[key])
|
||||||
formModel[key] = isInput ? defaultValue || '' : defaultValue;
|
formModel[key] = isInput ? defaultValue || '' : defaultValue
|
||||||
});
|
})
|
||||||
nextTick(() => clearValidate());
|
nextTick(() => clearValidate())
|
||||||
|
|
||||||
emit('reset', toRaw(formModel));
|
emit('reset', toRaw(formModel))
|
||||||
submitOnReset && handleSubmit();
|
submitOnReset && handleSubmit()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -54,78 +54,78 @@ export function useFormEvents({
|
||||||
async function setFieldsValue(values: Recordable): Promise<void> {
|
async function setFieldsValue(values: Recordable): Promise<void> {
|
||||||
const fields = unref(getSchema)
|
const fields = unref(getSchema)
|
||||||
.map((item) => item.field)
|
.map((item) => item.field)
|
||||||
.filter(Boolean);
|
.filter(Boolean)
|
||||||
|
|
||||||
// key 支持 a.b.c 的嵌套写法
|
// key 支持 a.b.c 的嵌套写法
|
||||||
const delimiter = '.';
|
const delimiter = '.'
|
||||||
const nestKeyArray = fields.filter((item) => item.indexOf(delimiter) >= 0);
|
const nestKeyArray = fields.filter((item) => item.indexOf(delimiter) >= 0)
|
||||||
|
|
||||||
const validKeys: string[] = [];
|
const validKeys: string[] = []
|
||||||
Object.keys(values).forEach((key) => {
|
Object.keys(values).forEach((key) => {
|
||||||
const schema = unref(getSchema).find((item) => item.field === key);
|
const schema = unref(getSchema).find((item) => item.field === key)
|
||||||
let value = values[key];
|
let value = values[key]
|
||||||
|
|
||||||
const hasKey = Reflect.has(values, key);
|
const hasKey = Reflect.has(values, key)
|
||||||
|
|
||||||
value = handleInputNumberValue(schema?.component, value);
|
value = handleInputNumberValue(schema?.component, value)
|
||||||
// 0| '' is allow
|
// 0| '' is allow
|
||||||
if (hasKey && fields.includes(key)) {
|
if (hasKey && fields.includes(key)) {
|
||||||
// time type
|
// time type
|
||||||
if (itemIsDateType(key)) {
|
if (itemIsDateType(key)) {
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
const arr: any[] = [];
|
const arr: any[] = []
|
||||||
for (const ele of value) {
|
for (const ele of value) {
|
||||||
arr.push(ele ? dateUtil(ele) : null);
|
arr.push(ele ? dateUtil(ele) : null)
|
||||||
}
|
}
|
||||||
formModel[key] = arr;
|
formModel[key] = arr
|
||||||
} else {
|
} else {
|
||||||
const { componentProps } = schema || {};
|
const { componentProps } = schema || {}
|
||||||
let _props = componentProps as any;
|
let _props = componentProps as any
|
||||||
if (typeof componentProps === 'function') {
|
if (typeof componentProps === 'function') {
|
||||||
_props = _props({ formModel });
|
_props = _props({ formModel })
|
||||||
}
|
}
|
||||||
formModel[key] = value ? (_props?.valueFormat ? value : dateUtil(value)) : null;
|
formModel[key] = value ? (_props?.valueFormat ? value : dateUtil(value)) : null
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
formModel[key] = value;
|
formModel[key] = value
|
||||||
}
|
}
|
||||||
validKeys.push(key);
|
validKeys.push(key)
|
||||||
} else {
|
} else {
|
||||||
nestKeyArray.forEach((nestKey: string) => {
|
nestKeyArray.forEach((nestKey: string) => {
|
||||||
try {
|
try {
|
||||||
const value = eval('values' + delimiter + nestKey);
|
const value = eval('values' + delimiter + nestKey)
|
||||||
if (isDef(value)) {
|
if (isDef(value)) {
|
||||||
formModel[nestKey] = value;
|
formModel[nestKey] = value
|
||||||
validKeys.push(nestKey);
|
validKeys.push(nestKey)
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// key not exist
|
// key not exist
|
||||||
if (isDef(defaultValueRef.value[nestKey])) {
|
if (isDef(defaultValueRef.value[nestKey])) {
|
||||||
formModel[nestKey] = cloneDeep(defaultValueRef.value[nestKey]);
|
formModel[nestKey] = cloneDeep(defaultValueRef.value[nestKey])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
validateFields(validKeys).catch((_) => {});
|
validateFields(validKeys).catch((_) => {})
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @description: Delete based on field name
|
* @description: Delete based on field name
|
||||||
*/
|
*/
|
||||||
async function removeSchemaByField(fields: string | string[]): Promise<void> {
|
async function removeSchemaByField(fields: string | string[]): Promise<void> {
|
||||||
const schemaList: FormSchema[] = cloneDeep(unref(getSchema));
|
const schemaList: FormSchema[] = cloneDeep(unref(getSchema))
|
||||||
if (!fields) {
|
if (!fields) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let fieldList: string[] = isString(fields) ? [fields] : fields;
|
let fieldList: string[] = isString(fields) ? [fields] : fields
|
||||||
if (isString(fields)) {
|
if (isString(fields)) {
|
||||||
fieldList = [fields];
|
fieldList = [fields]
|
||||||
}
|
}
|
||||||
for (const field of fieldList) {
|
for (const field of fieldList) {
|
||||||
_removeSchemaByFeild(field, schemaList);
|
_removeSchemaByFeild(field, schemaList)
|
||||||
}
|
}
|
||||||
schemaRef.value = schemaList;
|
schemaRef.value = schemaList
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -133,10 +133,10 @@ export function useFormEvents({
|
||||||
*/
|
*/
|
||||||
function _removeSchemaByFeild(field: string, schemaList: FormSchema[]): void {
|
function _removeSchemaByFeild(field: string, schemaList: FormSchema[]): void {
|
||||||
if (isString(field)) {
|
if (isString(field)) {
|
||||||
const index = schemaList.findIndex((schema) => schema.field === field);
|
const index = schemaList.findIndex((schema) => schema.field === field)
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
delete formModel[field];
|
delete formModel[field]
|
||||||
schemaList.splice(index, 1);
|
schemaList.splice(index, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -145,92 +145,92 @@ export function useFormEvents({
|
||||||
* @description: Insert after a certain field, if not insert the last
|
* @description: Insert after a certain field, if not insert the last
|
||||||
*/
|
*/
|
||||||
async function appendSchemaByField(schema: FormSchema, prefixField?: string, first = false) {
|
async function appendSchemaByField(schema: FormSchema, prefixField?: string, first = false) {
|
||||||
const schemaList: FormSchema[] = cloneDeep(unref(getSchema));
|
const schemaList: FormSchema[] = cloneDeep(unref(getSchema))
|
||||||
|
|
||||||
const index = schemaList.findIndex((schema) => schema.field === prefixField);
|
const index = schemaList.findIndex((schema) => schema.field === prefixField)
|
||||||
|
|
||||||
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);
|
_setDefaultValue(schema)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
schemaList.splice(index + 1, 0, schema);
|
schemaList.splice(index + 1, 0, schema)
|
||||||
}
|
}
|
||||||
_setDefaultValue(schema);
|
_setDefaultValue(schema)
|
||||||
|
|
||||||
schemaRef.value = schemaList;
|
schemaRef.value = schemaList
|
||||||
}
|
}
|
||||||
|
|
||||||
async function resetSchema(data: Partial<FormSchema> | Partial<FormSchema>[]) {
|
async function resetSchema(data: Partial<FormSchema> | Partial<FormSchema>[]) {
|
||||||
let updateData: Partial<FormSchema>[] = [];
|
let updateData: Partial<FormSchema>[] = []
|
||||||
if (isObject(data)) {
|
if (isObject(data)) {
|
||||||
updateData.push(data as FormSchema);
|
updateData.push(data as FormSchema)
|
||||||
}
|
}
|
||||||
if (isArray(data)) {
|
if (isArray(data)) {
|
||||||
updateData = [...data];
|
updateData = [...data]
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasField = updateData.every(
|
const hasField = updateData.every(
|
||||||
(item) => item.component === 'Divider' || (Reflect.has(item, 'field') && item.field),
|
(item) => item.component === 'Divider' || (Reflect.has(item, 'field') && item.field),
|
||||||
);
|
)
|
||||||
|
|
||||||
if (!hasField) {
|
if (!hasField) {
|
||||||
error(
|
error(
|
||||||
'All children of the form Schema array that need to be updated must contain the `field` field',
|
'All children of the form Schema array that need to be updated must contain the `field` field',
|
||||||
);
|
)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
schemaRef.value = updateData as FormSchema[];
|
schemaRef.value = updateData as FormSchema[]
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateSchema(data: Partial<FormSchema> | Partial<FormSchema>[]) {
|
async function updateSchema(data: Partial<FormSchema> | Partial<FormSchema>[]) {
|
||||||
let updateData: Partial<FormSchema>[] = [];
|
let updateData: Partial<FormSchema>[] = []
|
||||||
if (isObject(data)) {
|
if (isObject(data)) {
|
||||||
updateData.push(data as FormSchema);
|
updateData.push(data as FormSchema)
|
||||||
}
|
}
|
||||||
if (isArray(data)) {
|
if (isArray(data)) {
|
||||||
updateData = [...data];
|
updateData = [...data]
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasField = updateData.every(
|
const hasField = updateData.every(
|
||||||
(item) => item.component === 'Divider' || (Reflect.has(item, 'field') && item.field),
|
(item) => item.component === 'Divider' || (Reflect.has(item, 'field') && item.field),
|
||||||
);
|
)
|
||||||
|
|
||||||
if (!hasField) {
|
if (!hasField) {
|
||||||
error(
|
error(
|
||||||
'All children of the form Schema array that need to be updated must contain the `field` field',
|
'All children of the form Schema array that need to be updated must contain the `field` field',
|
||||||
);
|
)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
const schema: FormSchema[] = [];
|
const schema: FormSchema[] = []
|
||||||
updateData.forEach((item) => {
|
updateData.forEach((item) => {
|
||||||
unref(getSchema).forEach((val) => {
|
unref(getSchema).forEach((val) => {
|
||||||
if (val.field === item.field) {
|
if (val.field === item.field) {
|
||||||
const newSchema = deepMerge(val, item);
|
const newSchema = deepMerge(val, item)
|
||||||
schema.push(newSchema as FormSchema);
|
schema.push(newSchema as FormSchema)
|
||||||
} else {
|
} else {
|
||||||
schema.push(val);
|
schema.push(val)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
_setDefaultValue(schema);
|
_setDefaultValue(schema)
|
||||||
|
|
||||||
schemaRef.value = uniqBy(schema, 'field');
|
schemaRef.value = uniqBy(schema, 'field')
|
||||||
}
|
}
|
||||||
|
|
||||||
function _setDefaultValue(data: FormSchema | FormSchema[]) {
|
function _setDefaultValue(data: FormSchema | FormSchema[]) {
|
||||||
let schemas: FormSchema[] = [];
|
let schemas: FormSchema[] = []
|
||||||
if (isObject(data)) {
|
if (isObject(data)) {
|
||||||
schemas.push(data as FormSchema);
|
schemas.push(data as FormSchema)
|
||||||
}
|
}
|
||||||
if (isArray(data)) {
|
if (isArray(data)) {
|
||||||
schemas = [...data];
|
schemas = [...data]
|
||||||
}
|
}
|
||||||
|
|
||||||
const obj: Recordable = {};
|
const obj: Recordable = {}
|
||||||
const currentFieldsValue = getFieldsValue();
|
const currentFieldsValue = getFieldsValue()
|
||||||
schemas.forEach((item) => {
|
schemas.forEach((item) => {
|
||||||
if (
|
if (
|
||||||
item.component != 'Divider' &&
|
item.component != 'Divider' &&
|
||||||
|
|
@ -239,16 +239,16 @@ export function useFormEvents({
|
||||||
!isNullOrUnDef(item.defaultValue) &&
|
!isNullOrUnDef(item.defaultValue) &&
|
||||||
!(item.field in currentFieldsValue)
|
!(item.field in currentFieldsValue)
|
||||||
) {
|
) {
|
||||||
obj[item.field] = item.defaultValue;
|
obj[item.field] = item.defaultValue
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
setFieldsValue(obj);
|
setFieldsValue(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFieldsValue(): Recordable {
|
function getFieldsValue(): Recordable {
|
||||||
const formEl = unref(formElRef);
|
const formEl = unref(formElRef)
|
||||||
if (!formEl) return {};
|
if (!formEl) return {}
|
||||||
return handleFormValues(toRaw(unref(formModel)));
|
return handleFormValues(toRaw(unref(formModel)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -256,44 +256,44 @@ export function useFormEvents({
|
||||||
*/
|
*/
|
||||||
function itemIsDateType(key: string) {
|
function itemIsDateType(key: string) {
|
||||||
return unref(getSchema).some((item) => {
|
return unref(getSchema).some((item) => {
|
||||||
return item.field === key ? dateItemType.includes(item.component) : false;
|
return item.field === key ? dateItemType.includes(item.component) : false
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function validateFields(nameList?: NamePath[] | undefined) {
|
async function validateFields(nameList?: NamePath[] | undefined) {
|
||||||
return unref(formElRef)?.validateFields(nameList);
|
return unref(formElRef)?.validateFields(nameList)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function validate(nameList?: NamePath[] | undefined) {
|
async function validate(nameList?: NamePath[] | undefined) {
|
||||||
return await unref(formElRef)?.validate(nameList);
|
return await unref(formElRef)?.validate(nameList)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function clearValidate(name?: string | string[]) {
|
async function clearValidate(name?: string | string[]) {
|
||||||
await unref(formElRef)?.clearValidate(name);
|
await unref(formElRef)?.clearValidate(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function scrollToField(name: NamePath, options?: ScrollOptions | undefined) {
|
async function scrollToField(name: NamePath, options?: ScrollOptions | undefined) {
|
||||||
await unref(formElRef)?.scrollToField(name, options);
|
await unref(formElRef)?.scrollToField(name, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description: Form submission
|
* @description: Form submission
|
||||||
*/
|
*/
|
||||||
async function handleSubmit(e?: Event): Promise<void> {
|
async function handleSubmit(e?: Event): Promise<void> {
|
||||||
e && e.preventDefault();
|
e && e.preventDefault()
|
||||||
const { submitFunc } = unref(getProps);
|
const { submitFunc } = unref(getProps)
|
||||||
if (submitFunc && isFunction(submitFunc)) {
|
if (submitFunc && isFunction(submitFunc)) {
|
||||||
await submitFunc();
|
await submitFunc()
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
const formEl = unref(formElRef);
|
const formEl = unref(formElRef)
|
||||||
if (!formEl) return;
|
if (!formEl) return
|
||||||
try {
|
try {
|
||||||
const values = await validate();
|
const values = await validate()
|
||||||
const res = handleFormValues(values);
|
const res = handleFormValues(values)
|
||||||
emit('submit', res);
|
emit('submit', res)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
throw new Error(error);
|
throw new Error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -310,5 +310,5 @@ export function useFormEvents({
|
||||||
resetFields,
|
resetFields,
|
||||||
setFieldsValue,
|
setFieldsValue,
|
||||||
scrollToField,
|
scrollToField,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,31 @@
|
||||||
import { isArray, isFunction, isObject, isString, isNullOrUnDef } from '/@/utils/is';
|
import { isArray, isFunction, isObject, isString, isNullOrUnDef } from '/@/utils/is'
|
||||||
import { dateUtil } from '/@/utils/dateUtil';
|
import { dateUtil } from '/@/utils/dateUtil'
|
||||||
import { unref } from 'vue';
|
import { unref } from 'vue'
|
||||||
import type { Ref, ComputedRef } from 'vue';
|
import type { Ref, ComputedRef } from 'vue'
|
||||||
import type { FormProps, FormSchema } from '../types/form';
|
import type { FormProps, FormSchema } from '../types/form'
|
||||||
import { cloneDeep, set } from 'lodash-es';
|
import { cloneDeep, set } from 'lodash-es'
|
||||||
|
|
||||||
interface UseFormValuesContext {
|
interface UseFormValuesContext {
|
||||||
defaultValueRef: Ref<any>;
|
defaultValueRef: Ref<any>
|
||||||
getSchema: ComputedRef<FormSchema[]>;
|
getSchema: ComputedRef<FormSchema[]>
|
||||||
getProps: ComputedRef<FormProps>;
|
getProps: ComputedRef<FormProps>
|
||||||
formModel: Recordable;
|
formModel: Recordable
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @desription deconstruct array-link key. This method will mutate the target.
|
* @desription deconstruct array-link key. This method will mutate the target.
|
||||||
*/
|
*/
|
||||||
function tryDeconstructArray(key: string, value: any, target: Recordable) {
|
function tryDeconstructArray(key: string, value: any, target: Recordable) {
|
||||||
const pattern = /^\[(.+)\]$/;
|
const pattern = /^\[(.+)\]$/
|
||||||
if (pattern.test(key)) {
|
if (pattern.test(key)) {
|
||||||
const match = key.match(pattern);
|
const match = key.match(pattern)
|
||||||
if (match && match[1]) {
|
if (match && match[1]) {
|
||||||
const keys = match[1].split(',');
|
const keys = match[1].split(',')
|
||||||
value = Array.isArray(value) ? value : [value];
|
value = Array.isArray(value) ? value : [value]
|
||||||
keys.forEach((k, index) => {
|
keys.forEach((k, index) => {
|
||||||
set(target, k.trim(), value[index]);
|
set(target, k.trim(), value[index])
|
||||||
});
|
})
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -34,16 +34,16 @@ function tryDeconstructArray(key: string, value: any, target: Recordable) {
|
||||||
* @desription deconstruct object-link key. This method will mutate the target.
|
* @desription deconstruct object-link key. This method will mutate the target.
|
||||||
*/
|
*/
|
||||||
function tryDeconstructObject(key: string, value: any, target: Recordable) {
|
function tryDeconstructObject(key: string, value: any, target: Recordable) {
|
||||||
const pattern = /^\{(.+)\}$/;
|
const pattern = /^\{(.+)\}$/
|
||||||
if (pattern.test(key)) {
|
if (pattern.test(key)) {
|
||||||
const match = key.match(pattern);
|
const match = key.match(pattern)
|
||||||
if (match && match[1]) {
|
if (match && match[1]) {
|
||||||
const keys = match[1].split(',');
|
const keys = match[1].split(',')
|
||||||
value = isObject(value) ? value : {};
|
value = isObject(value) ? value : {}
|
||||||
keys.forEach((k) => {
|
keys.forEach((k) => {
|
||||||
set(target, k.trim(), value[k.trim()]);
|
set(target, k.trim(), value[k.trim()])
|
||||||
});
|
})
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -57,75 +57,75 @@ export function useFormValues({
|
||||||
// Processing form values
|
// Processing form values
|
||||||
function handleFormValues(values: Recordable) {
|
function handleFormValues(values: Recordable) {
|
||||||
if (!isObject(values)) {
|
if (!isObject(values)) {
|
||||||
return {};
|
return {}
|
||||||
}
|
}
|
||||||
const res: Recordable = {};
|
const res: Recordable = {}
|
||||||
for (const item of Object.entries(values)) {
|
for (const item of Object.entries(values)) {
|
||||||
let [, value] = item;
|
let [, value] = item
|
||||||
const [key] = item;
|
const [key] = item
|
||||||
if (!key || (isArray(value) && value.length === 0) || isFunction(value)) {
|
if (!key || (isArray(value) && value.length === 0) || isFunction(value)) {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
const transformDateFunc = unref(getProps).transformDateFunc;
|
const transformDateFunc = unref(getProps).transformDateFunc
|
||||||
if (isObject(value)) {
|
if (isObject(value)) {
|
||||||
value = transformDateFunc?.(value);
|
value = transformDateFunc?.(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isArray(value) && value[0]?.format && value[1]?.format) {
|
if (isArray(value) && value[0]?.format && value[1]?.format) {
|
||||||
value = value.map((item) => transformDateFunc?.(item));
|
value = value.map((item) => transformDateFunc?.(item))
|
||||||
}
|
}
|
||||||
// Remove spaces
|
// Remove spaces
|
||||||
if (isString(value)) {
|
if (isString(value)) {
|
||||||
value = value.trim();
|
value = value.trim()
|
||||||
}
|
}
|
||||||
if (!tryDeconstructArray(key, value, res) && !tryDeconstructObject(key, value, res)) {
|
if (!tryDeconstructArray(key, value, res) && !tryDeconstructObject(key, value, res)) {
|
||||||
// 没有解构成功的,按原样赋值
|
// 没有解构成功的,按原样赋值
|
||||||
set(res, key, value);
|
set(res, key, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return handleRangeTimeValue(res);
|
return handleRangeTimeValue(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description: Processing time interval parameters
|
* @description: Processing time interval parameters
|
||||||
*/
|
*/
|
||||||
function handleRangeTimeValue(values: Recordable) {
|
function handleRangeTimeValue(values: Recordable) {
|
||||||
const fieldMapToTime = unref(getProps).fieldMapToTime;
|
const fieldMapToTime = unref(getProps).fieldMapToTime
|
||||||
|
|
||||||
if (!fieldMapToTime || !Array.isArray(fieldMapToTime)) {
|
if (!fieldMapToTime || !Array.isArray(fieldMapToTime)) {
|
||||||
return values;
|
return values
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [field, [startTimeKey, endTimeKey], format = 'YYYY-MM-DD'] of fieldMapToTime) {
|
for (const [field, [startTimeKey, endTimeKey], format = 'YYYY-MM-DD'] of fieldMapToTime) {
|
||||||
if (!field || !startTimeKey || !endTimeKey || !values[field]) {
|
if (!field || !startTimeKey || !endTimeKey || !values[field]) {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const [startTime, endTime]: string[] = values[field];
|
const [startTime, endTime]: string[] = values[field]
|
||||||
|
|
||||||
values[startTimeKey] = dateUtil(startTime).format(format);
|
values[startTimeKey] = dateUtil(startTime).format(format)
|
||||||
values[endTimeKey] = dateUtil(endTime).format(format);
|
values[endTimeKey] = dateUtil(endTime).format(format)
|
||||||
Reflect.deleteProperty(values, field);
|
Reflect.deleteProperty(values, field)
|
||||||
}
|
}
|
||||||
|
|
||||||
return values;
|
return values
|
||||||
}
|
}
|
||||||
|
|
||||||
function initDefault() {
|
function initDefault() {
|
||||||
const schemas = unref(getSchema);
|
const schemas = unref(getSchema)
|
||||||
const obj: Recordable = {};
|
const obj: Recordable = {}
|
||||||
schemas.forEach((item) => {
|
schemas.forEach((item) => {
|
||||||
const { defaultValue } = item;
|
const { defaultValue } = item
|
||||||
if (!isNullOrUnDef(defaultValue)) {
|
if (!isNullOrUnDef(defaultValue)) {
|
||||||
obj[item.field] = defaultValue;
|
obj[item.field] = defaultValue
|
||||||
|
|
||||||
if (formModel[item.field] === undefined) {
|
if (formModel[item.field] === undefined) {
|
||||||
formModel[item.field] = defaultValue;
|
formModel[item.field] = defaultValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
defaultValueRef.value = cloneDeep(obj);
|
defaultValueRef.value = cloneDeep(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
return { handleFormValues, initDefault };
|
return { handleFormValues, initDefault }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,34 @@
|
||||||
import type { Ref } from 'vue';
|
import type { Ref } from 'vue'
|
||||||
import { computed, unref } from 'vue';
|
import { computed, unref } from 'vue'
|
||||||
import type { FormProps, FormSchema } from '../types/form';
|
import type { FormProps, FormSchema } from '../types/form'
|
||||||
import { isNumber } from '/@/utils/is';
|
import { isNumber } from '/@/utils/is'
|
||||||
|
|
||||||
export function useItemLabelWidth(schemaItemRef: Ref<FormSchema>, propsRef: Ref<FormProps>) {
|
export function useItemLabelWidth(schemaItemRef: Ref<FormSchema>, propsRef: Ref<FormProps>) {
|
||||||
return computed(() => {
|
return computed(() => {
|
||||||
const schemaItem = unref(schemaItemRef);
|
const schemaItem = unref(schemaItemRef)
|
||||||
const { labelCol = {}, wrapperCol = {} } = schemaItem.itemProps || {};
|
const { labelCol = {}, wrapperCol = {} } = schemaItem.itemProps || {}
|
||||||
const { labelWidth, disabledLabelWidth } = schemaItem;
|
const { labelWidth, disabledLabelWidth } = schemaItem
|
||||||
|
|
||||||
const {
|
const {
|
||||||
labelWidth: globalLabelWidth,
|
labelWidth: globalLabelWidth,
|
||||||
labelCol: globalLabelCol,
|
labelCol: globalLabelCol,
|
||||||
wrapperCol: globWrapperCol,
|
wrapperCol: globWrapperCol,
|
||||||
layout,
|
layout,
|
||||||
} = unref(propsRef);
|
} = unref(propsRef)
|
||||||
|
|
||||||
// If labelWidth is set globally, all items setting
|
// If labelWidth is set globally, all items setting
|
||||||
if ((!globalLabelWidth && !labelWidth && !globalLabelCol) || disabledLabelWidth) {
|
if ((!globalLabelWidth && !labelWidth && !globalLabelCol) || disabledLabelWidth) {
|
||||||
labelCol.style = {
|
labelCol.style = {
|
||||||
textAlign: 'left',
|
textAlign: 'left',
|
||||||
};
|
}
|
||||||
return { labelCol, wrapperCol };
|
return { labelCol, wrapperCol }
|
||||||
}
|
}
|
||||||
let width = labelWidth || globalLabelWidth;
|
let width = labelWidth || globalLabelWidth
|
||||||
const col = { ...globalLabelCol, ...labelCol };
|
const col = { ...globalLabelCol, ...labelCol }
|
||||||
const wrapCol = { ...globWrapperCol, ...wrapperCol };
|
const wrapCol = { ...globWrapperCol, ...wrapperCol }
|
||||||
|
|
||||||
if (width) {
|
if (width) {
|
||||||
width = isNumber(width) ? `${width}px` : width;
|
width = isNumber(width) ? `${width}px` : width
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -37,6 +37,6 @@ export function useItemLabelWidth(schemaItemRef: Ref<FormSchema>, propsRef: Ref<
|
||||||
style: { width: layout === 'vertical' ? '100%' : `calc(100% - ${width})` },
|
style: { width: layout === 'vertical' ? '100%' : `calc(100% - ${width})` },
|
||||||
...wrapCol,
|
...wrapCol,
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import type { FieldMapToTime, FormSchema } from './types/form';
|
import type { FieldMapToTime, FormSchema } from './types/form'
|
||||||
import type { CSSProperties, PropType } from 'vue';
|
import type { CSSProperties, PropType } from 'vue'
|
||||||
import type { ColEx } from './types';
|
import type { ColEx } from './types'
|
||||||
import type { TableActionType } from '/@/components/Table';
|
import type { TableActionType } from '/@/components/Table'
|
||||||
import type { ButtonProps } from 'ant-design-vue/es/button/buttonTypes';
|
import type { ButtonProps } from 'ant-design-vue/es/button/buttonTypes'
|
||||||
import type { RowProps } from 'ant-design-vue/lib/grid/Row';
|
import type { RowProps } from 'ant-design-vue/lib/grid/Row'
|
||||||
import { propTypes } from '/@/utils/propTypes';
|
import { propTypes } from '/@/utils/propTypes'
|
||||||
|
|
||||||
export const basicProps = {
|
export const basicProps = {
|
||||||
model: {
|
model: {
|
||||||
|
|
@ -54,7 +54,7 @@ export const basicProps = {
|
||||||
transformDateFunc: {
|
transformDateFunc: {
|
||||||
type: Function as PropType<Fn>,
|
type: Function as PropType<Fn>,
|
||||||
default: (date: any) => {
|
default: (date: any) => {
|
||||||
return date?.format?.('YYYY-MM-DD HH:mm:ss') ?? date;
|
return date?.format?.('YYYY-MM-DD HH:mm:ss') ?? date
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
rulesMessageJoinLabel: propTypes.bool.def(true),
|
rulesMessageJoinLabel: propTypes.bool.def(true),
|
||||||
|
|
@ -100,4 +100,4 @@ export const basicProps = {
|
||||||
labelAlign: propTypes.string,
|
labelAlign: propTypes.string,
|
||||||
|
|
||||||
rowProps: Object as PropType<RowProps>,
|
rowProps: Object as PropType<RowProps>,
|
||||||
};
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,223 +1,223 @@
|
||||||
import type { NamePath, RuleObject } from 'ant-design-vue/lib/form/interface';
|
import type { NamePath, RuleObject } from 'ant-design-vue/lib/form/interface'
|
||||||
import type { VNode } from 'vue';
|
import type { VNode } from 'vue'
|
||||||
import type { ButtonProps as AntdButtonProps } from '/@/components/Button';
|
import type { ButtonProps as AntdButtonProps } from '/@/components/Button'
|
||||||
import type { FormItem } from './formItem';
|
import type { FormItem } from './formItem'
|
||||||
import type { ColEx, ComponentType } from './index';
|
import type { ColEx, ComponentType } from './index'
|
||||||
import type { TableActionType } from '/@/components/Table/src/types/table';
|
import type { TableActionType } from '/@/components/Table/src/types/table'
|
||||||
import type { CSSProperties } from 'vue';
|
import type { CSSProperties } from 'vue'
|
||||||
import type { RowProps } from 'ant-design-vue/lib/grid/Row';
|
import type { RowProps } from 'ant-design-vue/lib/grid/Row'
|
||||||
|
|
||||||
export type FieldMapToTime = [string, [string, string], string?][];
|
export type FieldMapToTime = [string, [string, string], string?][]
|
||||||
|
|
||||||
export type Rule = RuleObject & {
|
export type Rule = RuleObject & {
|
||||||
trigger?: 'blur' | 'change' | ['change', 'blur'];
|
trigger?: 'blur' | 'change' | ['change', 'blur']
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface RenderCallbackParams {
|
export interface RenderCallbackParams {
|
||||||
schema: FormSchema;
|
schema: FormSchema
|
||||||
values: Recordable;
|
values: Recordable
|
||||||
model: Recordable;
|
model: Recordable
|
||||||
field: string;
|
field: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ButtonProps extends AntdButtonProps {
|
export interface ButtonProps extends AntdButtonProps {
|
||||||
text?: string;
|
text?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FormActionType {
|
export interface FormActionType {
|
||||||
submit: () => Promise<void>;
|
submit: () => Promise<void>
|
||||||
setFieldsValue: <T>(values: T) => Promise<void>;
|
setFieldsValue: <T>(values: T) => Promise<void>
|
||||||
resetFields: () => Promise<void>;
|
resetFields: () => Promise<void>
|
||||||
getFieldsValue: () => Recordable;
|
getFieldsValue: () => Recordable
|
||||||
clearValidate: (name?: string | string[]) => Promise<void>;
|
clearValidate: (name?: string | string[]) => Promise<void>
|
||||||
updateSchema: (data: Partial<FormSchema> | Partial<FormSchema>[]) => Promise<void>;
|
updateSchema: (data: Partial<FormSchema> | Partial<FormSchema>[]) => Promise<void>
|
||||||
resetSchema: (data: Partial<FormSchema> | Partial<FormSchema>[]) => Promise<void>;
|
resetSchema: (data: Partial<FormSchema> | Partial<FormSchema>[]) => Promise<void>
|
||||||
setProps: (formProps: Partial<FormProps>) => Promise<void>;
|
setProps: (formProps: Partial<FormProps>) => Promise<void>
|
||||||
removeSchemaByField: (field: string | string[]) => Promise<void>;
|
removeSchemaByField: (field: string | string[]) => Promise<void>
|
||||||
appendSchemaByField: (
|
appendSchemaByField: (
|
||||||
schema: FormSchema,
|
schema: FormSchema,
|
||||||
prefixField: string | undefined,
|
prefixField: string | undefined,
|
||||||
first?: boolean | undefined,
|
first?: boolean | undefined,
|
||||||
) => Promise<void>;
|
) => Promise<void>
|
||||||
validateFields: (nameList?: NamePath[]) => Promise<any>;
|
validateFields: (nameList?: NamePath[]) => Promise<any>
|
||||||
validate: (nameList?: NamePath[]) => Promise<any>;
|
validate: (nameList?: NamePath[]) => Promise<any>
|
||||||
scrollToField: (name: NamePath, options?: ScrollOptions) => Promise<void>;
|
scrollToField: (name: NamePath, options?: ScrollOptions) => Promise<void>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RegisterFn = (formInstance: FormActionType) => void;
|
export type RegisterFn = (formInstance: FormActionType) => void
|
||||||
|
|
||||||
export type UseFormReturnType = [RegisterFn, FormActionType];
|
export type UseFormReturnType = [RegisterFn, FormActionType]
|
||||||
|
|
||||||
export interface FormProps {
|
export interface FormProps {
|
||||||
name?: string;
|
name?: string
|
||||||
layout?: 'vertical' | 'inline' | 'horizontal';
|
layout?: 'vertical' | 'inline' | 'horizontal'
|
||||||
// Form value
|
// Form value
|
||||||
model?: Recordable;
|
model?: Recordable
|
||||||
// The width of all items in the entire form
|
// The width of all items in the entire form
|
||||||
labelWidth?: number | string;
|
labelWidth?: number | string
|
||||||
// alignment
|
// alignment
|
||||||
labelAlign?: 'left' | 'right';
|
labelAlign?: 'left' | 'right'
|
||||||
// Row configuration for the entire form
|
// Row configuration for the entire form
|
||||||
rowProps?: RowProps;
|
rowProps?: RowProps
|
||||||
// Submit form on reset
|
// Submit form on reset
|
||||||
submitOnReset?: boolean;
|
submitOnReset?: boolean
|
||||||
// Submit form on form changing
|
// Submit form on form changing
|
||||||
submitOnChange?: boolean;
|
submitOnChange?: boolean
|
||||||
// Col configuration for the entire form
|
// Col configuration for the entire form
|
||||||
labelCol?: Partial<ColEx>;
|
labelCol?: Partial<ColEx>
|
||||||
// Col configuration for the entire form
|
// Col configuration for the entire form
|
||||||
wrapperCol?: Partial<ColEx>;
|
wrapperCol?: Partial<ColEx>
|
||||||
|
|
||||||
// General row style
|
// General row style
|
||||||
baseRowStyle?: CSSProperties;
|
baseRowStyle?: CSSProperties
|
||||||
|
|
||||||
// General col configuration
|
// General col configuration
|
||||||
baseColProps?: Partial<ColEx>;
|
baseColProps?: Partial<ColEx>
|
||||||
|
|
||||||
// Form configuration rules
|
// Form configuration rules
|
||||||
schemas?: FormSchema[];
|
schemas?: FormSchema[]
|
||||||
// Function values used to merge into dynamic control form items
|
// Function values used to merge into dynamic control form items
|
||||||
mergeDynamicData?: Recordable;
|
mergeDynamicData?: Recordable
|
||||||
// Compact mode for search forms
|
// Compact mode for search forms
|
||||||
compact?: boolean;
|
compact?: boolean
|
||||||
// Blank line span
|
// Blank line span
|
||||||
emptySpan?: number | Partial<ColEx>;
|
emptySpan?: number | Partial<ColEx>
|
||||||
// Internal component size of the form
|
// Internal component size of the form
|
||||||
size?: 'default' | 'small' | 'large';
|
size?: 'default' | 'small' | 'large'
|
||||||
// Whether to disable
|
// Whether to disable
|
||||||
disabled?: boolean;
|
disabled?: boolean
|
||||||
// Time interval fields are mapped into multiple
|
// Time interval fields are mapped into multiple
|
||||||
fieldMapToTime?: FieldMapToTime;
|
fieldMapToTime?: FieldMapToTime
|
||||||
// Placeholder is set automatically
|
// Placeholder is set automatically
|
||||||
autoSetPlaceHolder?: boolean;
|
autoSetPlaceHolder?: boolean
|
||||||
// Auto submit on press enter on input
|
// Auto submit on press enter on input
|
||||||
autoSubmitOnEnter?: boolean;
|
autoSubmitOnEnter?: boolean
|
||||||
// Check whether the information is added to the label
|
// Check whether the information is added to the label
|
||||||
rulesMessageJoinLabel?: boolean;
|
rulesMessageJoinLabel?: boolean
|
||||||
// Whether to show collapse and expand buttons
|
// Whether to show collapse and expand buttons
|
||||||
showAdvancedButton?: boolean;
|
showAdvancedButton?: boolean
|
||||||
// Whether to focus on the first input box, only works when the first form item is input
|
// Whether to focus on the first input box, only works when the first form item is input
|
||||||
autoFocusFirstItem?: boolean;
|
autoFocusFirstItem?: boolean
|
||||||
// Automatically collapse over the specified number of rows
|
// Automatically collapse over the specified number of rows
|
||||||
autoAdvancedLine?: number;
|
autoAdvancedLine?: number
|
||||||
// Always show lines
|
// Always show lines
|
||||||
alwaysShowLines?: number;
|
alwaysShowLines?: number
|
||||||
// Whether to show the operation button
|
// Whether to show the operation button
|
||||||
showActionButtonGroup?: boolean;
|
showActionButtonGroup?: boolean
|
||||||
|
|
||||||
// Reset button configuration
|
// Reset button configuration
|
||||||
resetButtonOptions?: Partial<ButtonProps>;
|
resetButtonOptions?: Partial<ButtonProps>
|
||||||
|
|
||||||
// Confirm button configuration
|
// Confirm button configuration
|
||||||
submitButtonOptions?: Partial<ButtonProps>;
|
submitButtonOptions?: Partial<ButtonProps>
|
||||||
|
|
||||||
// Operation column configuration
|
// Operation column configuration
|
||||||
actionColOptions?: Partial<ColEx>;
|
actionColOptions?: Partial<ColEx>
|
||||||
|
|
||||||
// Show reset button
|
// Show reset button
|
||||||
showResetButton?: boolean;
|
showResetButton?: boolean
|
||||||
// Show confirmation button
|
// Show confirmation button
|
||||||
showSubmitButton?: boolean;
|
showSubmitButton?: boolean
|
||||||
|
|
||||||
resetFunc?: () => Promise<void>;
|
resetFunc?: () => Promise<void>
|
||||||
submitFunc?: () => Promise<void>;
|
submitFunc?: () => Promise<void>
|
||||||
transformDateFunc?: (date: any) => string;
|
transformDateFunc?: (date: any) => string
|
||||||
colon?: boolean;
|
colon?: boolean
|
||||||
}
|
}
|
||||||
export interface FormSchema {
|
export interface FormSchema {
|
||||||
// Field name
|
// Field name
|
||||||
field: string;
|
field: string
|
||||||
// Event name triggered by internal value change, default change
|
// Event name triggered by internal value change, default change
|
||||||
changeEvent?: string;
|
changeEvent?: string
|
||||||
// Variable name bound to v-model Default value
|
// Variable name bound to v-model Default value
|
||||||
valueField?: string;
|
valueField?: string
|
||||||
// Label name
|
// Label name
|
||||||
label: string | VNode;
|
label: string | VNode
|
||||||
// Auxiliary text
|
// Auxiliary text
|
||||||
subLabel?: string;
|
subLabel?: string
|
||||||
// Help text on the right side of the text
|
// Help text on the right side of the text
|
||||||
helpMessage?:
|
helpMessage?:
|
||||||
| string
|
| string
|
||||||
| string[]
|
| string[]
|
||||||
| ((renderCallbackParams: RenderCallbackParams) => string | string[]);
|
| ((renderCallbackParams: RenderCallbackParams) => string | string[])
|
||||||
// BaseHelp component props
|
// BaseHelp component props
|
||||||
helpComponentProps?: Partial<HelpComponentProps>;
|
helpComponentProps?: Partial<HelpComponentProps>
|
||||||
// Label width, if it is passed, the labelCol and WrapperCol configured by itemProps will be invalid
|
// Label width, if it is passed, the labelCol and WrapperCol configured by itemProps will be invalid
|
||||||
labelWidth?: string | number;
|
labelWidth?: string | number
|
||||||
// Disable the adjustment of labelWidth with global settings of formModel, and manually set labelCol and wrapperCol by yourself
|
// Disable the adjustment of labelWidth with global settings of formModel, and manually set labelCol and wrapperCol by yourself
|
||||||
disabledLabelWidth?: boolean;
|
disabledLabelWidth?: boolean
|
||||||
// render component
|
// render component
|
||||||
component: ComponentType;
|
component: ComponentType
|
||||||
// Component parameters
|
// Component parameters
|
||||||
componentProps?:
|
componentProps?:
|
||||||
| ((opt: {
|
| ((opt: {
|
||||||
schema: FormSchema;
|
schema: FormSchema
|
||||||
tableAction: TableActionType;
|
tableAction: TableActionType
|
||||||
formActionType: FormActionType;
|
formActionType: FormActionType
|
||||||
formModel: Recordable;
|
formModel: Recordable
|
||||||
}) => Recordable)
|
}) => Recordable)
|
||||||
| object;
|
| object
|
||||||
// Required
|
// Required
|
||||||
required?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);
|
required?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean)
|
||||||
|
|
||||||
suffix?: string | number | ((values: RenderCallbackParams) => string | number);
|
suffix?: string | number | ((values: RenderCallbackParams) => string | number)
|
||||||
|
|
||||||
// Validation rules
|
// Validation rules
|
||||||
rules?: Rule[];
|
rules?: Rule[]
|
||||||
// Check whether the information is added to the label
|
// Check whether the information is added to the label
|
||||||
rulesMessageJoinLabel?: boolean;
|
rulesMessageJoinLabel?: boolean
|
||||||
|
|
||||||
// Reference formModelItem
|
// Reference formModelItem
|
||||||
itemProps?: Partial<FormItem>;
|
itemProps?: Partial<FormItem>
|
||||||
|
|
||||||
// col configuration outside formModelItem
|
// col configuration outside formModelItem
|
||||||
colProps?: Partial<ColEx>;
|
colProps?: Partial<ColEx>
|
||||||
|
|
||||||
// 默认值
|
// 默认值
|
||||||
defaultValue?: any;
|
defaultValue?: any
|
||||||
isAdvanced?: boolean;
|
isAdvanced?: boolean
|
||||||
|
|
||||||
// Matching details components
|
// Matching details components
|
||||||
span?: number;
|
span?: number
|
||||||
|
|
||||||
ifShow?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);
|
ifShow?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean)
|
||||||
|
|
||||||
show?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);
|
show?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean)
|
||||||
|
|
||||||
// Render the content in the form-item tag
|
// Render the content in the form-item tag
|
||||||
render?: (renderCallbackParams: RenderCallbackParams) => VNode | VNode[] | string;
|
render?: (renderCallbackParams: RenderCallbackParams) => VNode | VNode[] | string
|
||||||
|
|
||||||
// Rendering col content requires outer wrapper form-item
|
// Rendering col content requires outer wrapper form-item
|
||||||
renderColContent?: (renderCallbackParams: RenderCallbackParams) => VNode | VNode[] | string;
|
renderColContent?: (renderCallbackParams: RenderCallbackParams) => VNode | VNode[] | string
|
||||||
|
|
||||||
renderComponentContent?:
|
renderComponentContent?:
|
||||||
| ((renderCallbackParams: RenderCallbackParams) => any)
|
| ((renderCallbackParams: RenderCallbackParams) => any)
|
||||||
| VNode
|
| VNode
|
||||||
| VNode[]
|
| VNode[]
|
||||||
| string;
|
| string
|
||||||
|
|
||||||
// Custom slot, in from-item
|
// Custom slot, in from-item
|
||||||
slot?: string;
|
slot?: string
|
||||||
|
|
||||||
// Custom slot, similar to renderColContent
|
// Custom slot, similar to renderColContent
|
||||||
colSlot?: string;
|
colSlot?: string
|
||||||
|
|
||||||
dynamicDisabled?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);
|
dynamicDisabled?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean)
|
||||||
|
|
||||||
dynamicRules?: (renderCallbackParams: RenderCallbackParams) => Rule[];
|
dynamicRules?: (renderCallbackParams: RenderCallbackParams) => Rule[]
|
||||||
}
|
}
|
||||||
export interface HelpComponentProps {
|
export interface HelpComponentProps {
|
||||||
maxWidth: string;
|
maxWidth: string
|
||||||
// Whether to display the serial number
|
// Whether to display the serial number
|
||||||
showIndex: boolean;
|
showIndex: boolean
|
||||||
// Text list
|
// Text list
|
||||||
text: any;
|
text: any
|
||||||
// colour
|
// colour
|
||||||
color: string;
|
color: string
|
||||||
// font size
|
// font size
|
||||||
fontSize: string;
|
fontSize: string
|
||||||
icon: string;
|
icon: string
|
||||||
absolute: boolean;
|
absolute: boolean
|
||||||
// Positioning
|
// Positioning
|
||||||
position: any;
|
position: any
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,83 +1,83 @@
|
||||||
type ColSpanType = number | string;
|
type ColSpanType = number | string
|
||||||
export interface ColEx {
|
export interface ColEx {
|
||||||
style?: any;
|
style?: any
|
||||||
/**
|
/**
|
||||||
* raster number of cells to occupy, 0 corresponds to display: none
|
* raster number of cells to occupy, 0 corresponds to display: none
|
||||||
* @default none (0)
|
* @default none (0)
|
||||||
* @type ColSpanType
|
* @type ColSpanType
|
||||||
*/
|
*/
|
||||||
span?: ColSpanType;
|
span?: ColSpanType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* raster order, used in flex layout mode
|
* raster order, used in flex layout mode
|
||||||
* @default 0
|
* @default 0
|
||||||
* @type ColSpanType
|
* @type ColSpanType
|
||||||
*/
|
*/
|
||||||
order?: ColSpanType;
|
order?: ColSpanType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the layout fill of flex
|
* the layout fill of flex
|
||||||
* @default none
|
* @default none
|
||||||
* @type ColSpanType
|
* @type ColSpanType
|
||||||
*/
|
*/
|
||||||
flex?: ColSpanType;
|
flex?: ColSpanType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the number of cells to offset Col from the left
|
* the number of cells to offset Col from the left
|
||||||
* @default 0
|
* @default 0
|
||||||
* @type ColSpanType
|
* @type ColSpanType
|
||||||
*/
|
*/
|
||||||
offset?: ColSpanType;
|
offset?: ColSpanType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the number of cells that raster is moved to the right
|
* the number of cells that raster is moved to the right
|
||||||
* @default 0
|
* @default 0
|
||||||
* @type ColSpanType
|
* @type ColSpanType
|
||||||
*/
|
*/
|
||||||
push?: ColSpanType;
|
push?: ColSpanType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the number of cells that raster is moved to the left
|
* the number of cells that raster is moved to the left
|
||||||
* @default 0
|
* @default 0
|
||||||
* @type ColSpanType
|
* @type ColSpanType
|
||||||
*/
|
*/
|
||||||
pull?: ColSpanType;
|
pull?: ColSpanType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <576px and also default setting, could be a span value or an object containing above props
|
* <576px and also default setting, could be a span value or an object containing above props
|
||||||
* @type { span: ColSpanType, offset: ColSpanType } | ColSpanType
|
* @type { span: ColSpanType, offset: ColSpanType } | ColSpanType
|
||||||
*/
|
*/
|
||||||
xs?: { span: ColSpanType; offset: ColSpanType } | ColSpanType;
|
xs?: { span: ColSpanType; offset: ColSpanType } | ColSpanType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ≥576px, could be a span value or an object containing above props
|
* ≥576px, could be a span value or an object containing above props
|
||||||
* @type { span: ColSpanType, offset: ColSpanType } | ColSpanType
|
* @type { span: ColSpanType, offset: ColSpanType } | ColSpanType
|
||||||
*/
|
*/
|
||||||
sm?: { span: ColSpanType; offset: ColSpanType } | ColSpanType;
|
sm?: { span: ColSpanType; offset: ColSpanType } | ColSpanType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ≥768px, could be a span value or an object containing above props
|
* ≥768px, could be a span value or an object containing above props
|
||||||
* @type { span: ColSpanType, offset: ColSpanType } | ColSpanType
|
* @type { span: ColSpanType, offset: ColSpanType } | ColSpanType
|
||||||
*/
|
*/
|
||||||
md?: { span: ColSpanType; offset: ColSpanType } | ColSpanType;
|
md?: { span: ColSpanType; offset: ColSpanType } | ColSpanType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ≥992px, could be a span value or an object containing above props
|
* ≥992px, could be a span value or an object containing above props
|
||||||
* @type { span: ColSpanType, offset: ColSpanType } | ColSpanType
|
* @type { span: ColSpanType, offset: ColSpanType } | ColSpanType
|
||||||
*/
|
*/
|
||||||
lg?: { span: ColSpanType; offset: ColSpanType } | ColSpanType;
|
lg?: { span: ColSpanType; offset: ColSpanType } | ColSpanType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ≥1200px, could be a span value or an object containing above props
|
* ≥1200px, could be a span value or an object containing above props
|
||||||
* @type { span: ColSpanType, offset: ColSpanType } | ColSpanType
|
* @type { span: ColSpanType, offset: ColSpanType } | ColSpanType
|
||||||
*/
|
*/
|
||||||
xl?: { span: ColSpanType; offset: ColSpanType } | ColSpanType;
|
xl?: { span: ColSpanType; offset: ColSpanType } | ColSpanType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ≥1600px, could be a span value or an object containing above props
|
* ≥1600px, could be a span value or an object containing above props
|
||||||
* @type { span: ColSpanType, offset: ColSpanType } | ColSpanType
|
* @type { span: ColSpanType, offset: ColSpanType } | ColSpanType
|
||||||
*/
|
*/
|
||||||
xxl?: { span: ColSpanType; offset: ColSpanType } | ColSpanType;
|
xxl?: { span: ColSpanType; offset: ColSpanType } | ColSpanType
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ComponentType =
|
export type ComponentType =
|
||||||
|
|
@ -114,4 +114,4 @@ export type ComponentType =
|
||||||
| 'Slider'
|
| 'Slider'
|
||||||
| 'Rate'
|
| 'Rate'
|
||||||
| 'Divider'
|
| 'Divider'
|
||||||
| 'ApiTransfer';
|
| 'ApiTransfer'
|
||||||
|
|
|
||||||
|
|
@ -18,21 +18,21 @@
|
||||||
</Menu>
|
</Menu>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { MenuState } from './types';
|
import type { MenuState } from './types'
|
||||||
import { computed, defineComponent, unref, reactive, watch, toRefs, ref } from 'vue';
|
import { computed, defineComponent, unref, reactive, watch, toRefs, ref } from 'vue'
|
||||||
import { Menu } from 'ant-design-vue';
|
import { Menu } from 'ant-design-vue'
|
||||||
import BasicSubMenuItem from './components/BasicSubMenuItem.vue';
|
import BasicSubMenuItem from './components/BasicSubMenuItem.vue'
|
||||||
import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
|
import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum'
|
||||||
import { useOpenKeys } from './useOpenKeys';
|
import { useOpenKeys } from './useOpenKeys'
|
||||||
import { RouteLocationNormalizedLoaded, useRouter } from 'vue-router';
|
import { RouteLocationNormalizedLoaded, useRouter } from 'vue-router'
|
||||||
import { isFunction } from '/@/utils/is';
|
import { isFunction } from '/@/utils/is'
|
||||||
import { basicProps } from './props';
|
import { basicProps } from './props'
|
||||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'
|
||||||
import { REDIRECT_NAME } from '/@/router/constant';
|
import { REDIRECT_NAME } from '/@/router/constant'
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
import { getCurrentParentPath } from '/@/router/menus';
|
import { getCurrentParentPath } from '/@/router/menus'
|
||||||
import { listenerRouteChange } from '/@/logics/mitt/routeChange';
|
import { listenerRouteChange } from '/@/logics/mitt/routeChange'
|
||||||
import { getAllParentPath } from '/@/router/helper/menuHelper';
|
import { getAllParentPath } from '/@/router/helper/menuHelper'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'BasicMenu',
|
name: 'BasicMenu',
|
||||||
|
|
@ -43,41 +43,41 @@
|
||||||
props: basicProps,
|
props: basicProps,
|
||||||
emits: ['menuClick'],
|
emits: ['menuClick'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const isClickGo = ref(false);
|
const isClickGo = ref(false)
|
||||||
const currentActiveMenu = ref('');
|
const currentActiveMenu = ref('')
|
||||||
|
|
||||||
const menuState = reactive<MenuState>({
|
const menuState = reactive<MenuState>({
|
||||||
defaultSelectedKeys: [],
|
defaultSelectedKeys: [],
|
||||||
openKeys: [],
|
openKeys: [],
|
||||||
selectedKeys: [],
|
selectedKeys: [],
|
||||||
collapsedOpenKeys: [],
|
collapsedOpenKeys: [],
|
||||||
});
|
})
|
||||||
|
|
||||||
const { prefixCls } = useDesign('basic-menu');
|
const { prefixCls } = useDesign('basic-menu')
|
||||||
const { items, mode, accordion } = toRefs(props);
|
const { items, mode, accordion } = toRefs(props)
|
||||||
|
|
||||||
const { getCollapsed, getTopMenuAlign, getSplit } = useMenuSetting();
|
const { getCollapsed, getTopMenuAlign, getSplit } = useMenuSetting()
|
||||||
|
|
||||||
const { currentRoute } = useRouter();
|
const { currentRoute } = useRouter()
|
||||||
|
|
||||||
const { handleOpenChange, setOpenKeys, getOpenKeys } = useOpenKeys(
|
const { handleOpenChange, setOpenKeys, getOpenKeys } = useOpenKeys(
|
||||||
menuState,
|
menuState,
|
||||||
items,
|
items,
|
||||||
mode as any,
|
mode as any,
|
||||||
accordion,
|
accordion,
|
||||||
);
|
)
|
||||||
|
|
||||||
const getIsTopMenu = computed(() => {
|
const getIsTopMenu = computed(() => {
|
||||||
const { type, mode } = props;
|
const { type, mode } = props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
(type === MenuTypeEnum.TOP_MENU && mode === MenuModeEnum.HORIZONTAL) ||
|
(type === MenuTypeEnum.TOP_MENU && mode === MenuModeEnum.HORIZONTAL) ||
|
||||||
(props.isHorizontal && unref(getSplit))
|
(props.isHorizontal && unref(getSplit))
|
||||||
);
|
)
|
||||||
});
|
})
|
||||||
|
|
||||||
const getMenuClass = computed(() => {
|
const getMenuClass = computed(() => {
|
||||||
const align = props.isHorizontal && unref(getSplit) ? 'start' : unref(getTopMenuAlign);
|
const align = props.isHorizontal && unref(getSplit) ? 'start' : unref(getTopMenuAlign)
|
||||||
return [
|
return [
|
||||||
prefixCls,
|
prefixCls,
|
||||||
`justify-${align}`,
|
`justify-${align}`,
|
||||||
|
|
@ -85,66 +85,66 @@
|
||||||
[`${prefixCls}__second`]: !props.isHorizontal && unref(getSplit),
|
[`${prefixCls}__second`]: !props.isHorizontal && unref(getSplit),
|
||||||
[`${prefixCls}__sidebar-hor`]: unref(getIsTopMenu),
|
[`${prefixCls}__sidebar-hor`]: unref(getIsTopMenu),
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
});
|
})
|
||||||
|
|
||||||
const getInlineCollapseOptions = computed(() => {
|
const getInlineCollapseOptions = computed(() => {
|
||||||
const isInline = props.mode === MenuModeEnum.INLINE;
|
const isInline = props.mode === MenuModeEnum.INLINE
|
||||||
|
|
||||||
const inlineCollapseOptions: { inlineCollapsed?: boolean } = {};
|
const inlineCollapseOptions: { inlineCollapsed?: boolean } = {}
|
||||||
if (isInline) {
|
if (isInline) {
|
||||||
inlineCollapseOptions.inlineCollapsed = props.mixSider ? false : unref(getCollapsed);
|
inlineCollapseOptions.inlineCollapsed = props.mixSider ? false : unref(getCollapsed)
|
||||||
}
|
}
|
||||||
return inlineCollapseOptions;
|
return inlineCollapseOptions
|
||||||
});
|
})
|
||||||
|
|
||||||
listenerRouteChange((route) => {
|
listenerRouteChange((route) => {
|
||||||
if (route.name === REDIRECT_NAME) return;
|
if (route.name === REDIRECT_NAME) return
|
||||||
handleMenuChange(route);
|
handleMenuChange(route)
|
||||||
currentActiveMenu.value = route.meta?.currentActiveMenu as string;
|
currentActiveMenu.value = route.meta?.currentActiveMenu as string
|
||||||
|
|
||||||
if (unref(currentActiveMenu)) {
|
if (unref(currentActiveMenu)) {
|
||||||
menuState.selectedKeys = [unref(currentActiveMenu)];
|
menuState.selectedKeys = [unref(currentActiveMenu)]
|
||||||
setOpenKeys(unref(currentActiveMenu));
|
setOpenKeys(unref(currentActiveMenu))
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
!props.mixSider &&
|
!props.mixSider &&
|
||||||
watch(
|
watch(
|
||||||
() => props.items,
|
() => props.items,
|
||||||
() => {
|
() => {
|
||||||
handleMenuChange();
|
handleMenuChange()
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
|
|
||||||
async function handleMenuClick({ key }: { key: string; keyPath: string[] }) {
|
async function handleMenuClick({ key }: { key: string; keyPath: string[] }) {
|
||||||
const { beforeClickFn } = props;
|
const { beforeClickFn } = props
|
||||||
if (beforeClickFn && isFunction(beforeClickFn)) {
|
if (beforeClickFn && isFunction(beforeClickFn)) {
|
||||||
const flag = await beforeClickFn(key);
|
const flag = await beforeClickFn(key)
|
||||||
if (!flag) return;
|
if (!flag) return
|
||||||
}
|
}
|
||||||
emit('menuClick', key);
|
emit('menuClick', key)
|
||||||
|
|
||||||
isClickGo.value = true;
|
isClickGo.value = true
|
||||||
menuState.selectedKeys = [key];
|
menuState.selectedKeys = [key]
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleMenuChange(route?: RouteLocationNormalizedLoaded) {
|
async function handleMenuChange(route?: RouteLocationNormalizedLoaded) {
|
||||||
if (unref(isClickGo)) {
|
if (unref(isClickGo)) {
|
||||||
isClickGo.value = false;
|
isClickGo.value = false
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
const path =
|
const path =
|
||||||
(route || unref(currentRoute)).meta?.currentActiveMenu ||
|
(route || unref(currentRoute)).meta?.currentActiveMenu ||
|
||||||
(route || unref(currentRoute)).path;
|
(route || unref(currentRoute)).path
|
||||||
setOpenKeys(path);
|
setOpenKeys(path)
|
||||||
if (unref(currentActiveMenu)) return;
|
if (unref(currentActiveMenu)) return
|
||||||
if (props.isHorizontal && unref(getSplit)) {
|
if (props.isHorizontal && unref(getSplit)) {
|
||||||
const parentPath = await getCurrentParentPath(path);
|
const parentPath = await getCurrentParentPath(path)
|
||||||
menuState.selectedKeys = [parentPath];
|
menuState.selectedKeys = [parentPath]
|
||||||
} else {
|
} else {
|
||||||
const parentPaths = await getAllParentPath(props.items, path);
|
const parentPaths = await getAllParentPath(props.items, path)
|
||||||
menuState.selectedKeys = parentPaths;
|
menuState.selectedKeys = parentPaths
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -155,9 +155,9 @@
|
||||||
handleOpenChange,
|
handleOpenChange,
|
||||||
getOpenKeys,
|
getOpenKeys,
|
||||||
...toRefs(menuState),
|
...toRefs(menuState),
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@import './index.less';
|
@import './index.less';
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { Modal } from 'ant-design-vue';
|
import { Modal } from 'ant-design-vue'
|
||||||
import { defineComponent, toRefs, unref } from 'vue';
|
import { defineComponent, toRefs, unref } from 'vue'
|
||||||
import { basicProps } from '../props';
|
import { basicProps } from '../props'
|
||||||
import { useModalDragMove } from '../hooks/useModalDrag';
|
import { useModalDragMove } from '../hooks/useModalDrag'
|
||||||
import { useAttrs } from '/@/hooks/core/useAttrs';
|
import { useAttrs } from '/@/hooks/core/useAttrs'
|
||||||
import { extendSlots } from '/@/utils/helper/tsxHelper';
|
import { extendSlots } from '/@/utils/helper/tsxHelper'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Modal',
|
name: 'Modal',
|
||||||
|
|
@ -11,21 +11,21 @@ export default defineComponent({
|
||||||
props: basicProps,
|
props: basicProps,
|
||||||
emits: ['cancel'],
|
emits: ['cancel'],
|
||||||
setup(props, { slots, emit }) {
|
setup(props, { slots, emit }) {
|
||||||
const { visible, draggable, destroyOnClose } = toRefs(props);
|
const { visible, draggable, destroyOnClose } = toRefs(props)
|
||||||
const attrs = useAttrs();
|
const attrs = useAttrs()
|
||||||
useModalDragMove({
|
useModalDragMove({
|
||||||
visible,
|
visible,
|
||||||
destroyOnClose,
|
destroyOnClose,
|
||||||
draggable,
|
draggable,
|
||||||
});
|
})
|
||||||
|
|
||||||
const onCancel = (e: Event) => {
|
const onCancel = (e: Event) => {
|
||||||
emit('cancel', e);
|
emit('cancel', e)
|
||||||
};
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const propsData = { ...unref(attrs), ...props, onCancel } as Recordable;
|
const propsData = { ...unref(attrs), ...props, onCancel } as Recordable
|
||||||
return <Modal {...propsData}>{extendSlots(slots)}</Modal>;
|
return <Modal {...propsData}>{extendSlots(slots)}</Modal>
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
|
||||||
|
|
@ -110,16 +110,19 @@
|
||||||
.ant-modal-confirm .ant-modal-body {
|
.ant-modal-confirm .ant-modal-body {
|
||||||
padding: 24px !important;
|
padding: 24px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-height: 600px) {
|
@media screen and (max-height: 600px) {
|
||||||
.ant-modal {
|
.ant-modal {
|
||||||
top: 60px;
|
top: 60px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-height: 540px) {
|
@media screen and (max-height: 540px) {
|
||||||
.ant-modal {
|
.ant-modal {
|
||||||
top: 30px;
|
top: 30px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-height: 480px) {
|
@media screen and (max-height: 480px) {
|
||||||
.ant-modal {
|
.ant-modal {
|
||||||
top: 10px;
|
top: 10px;
|
||||||
|
|
|
||||||
|
|
@ -33,17 +33,17 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { CSSProperties, PropType, provide } from 'vue';
|
import { CSSProperties, PropType, provide } from 'vue'
|
||||||
|
|
||||||
import { defineComponent, computed, watch, ref, unref } from 'vue';
|
import { defineComponent, computed, watch, ref, unref } from 'vue'
|
||||||
import PageFooter from './PageFooter.vue';
|
import PageFooter from './PageFooter.vue'
|
||||||
|
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
import { propTypes } from '/@/utils/propTypes';
|
import { propTypes } from '/@/utils/propTypes'
|
||||||
import { omit } from 'lodash-es';
|
import { omit } from 'lodash-es'
|
||||||
import { PageHeader } from 'ant-design-vue';
|
import { PageHeader } from 'ant-design-vue'
|
||||||
import { useContentHeight } from '/@/hooks/web/useContentHeight';
|
import { useContentHeight } from '/@/hooks/web/useContentHeight'
|
||||||
import { PageWrapperFixedHeightKey } from '..';
|
import { PageWrapperFixedHeightKey } from '..'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'PageWrapper',
|
name: 'PageWrapper',
|
||||||
|
|
@ -64,30 +64,30 @@
|
||||||
upwardSpace: propTypes.oneOfType([propTypes.number, propTypes.string]).def(0),
|
upwardSpace: propTypes.oneOfType([propTypes.number, propTypes.string]).def(0),
|
||||||
},
|
},
|
||||||
setup(props, { slots, attrs }) {
|
setup(props, { slots, attrs }) {
|
||||||
const wrapperRef = ref(null);
|
const wrapperRef = ref(null)
|
||||||
const headerRef = ref(null);
|
const headerRef = ref(null)
|
||||||
const contentRef = ref(null);
|
const contentRef = ref(null)
|
||||||
const footerRef = ref(null);
|
const footerRef = ref(null)
|
||||||
const { prefixCls } = useDesign('page-wrapper');
|
const { prefixCls } = useDesign('page-wrapper')
|
||||||
|
|
||||||
provide(
|
provide(
|
||||||
PageWrapperFixedHeightKey,
|
PageWrapperFixedHeightKey,
|
||||||
computed(() => props.fixedHeight),
|
computed(() => props.fixedHeight),
|
||||||
);
|
)
|
||||||
|
|
||||||
const getIsContentFullHeight = computed(() => {
|
const getIsContentFullHeight = computed(() => {
|
||||||
return props.contentFullHeight;
|
return props.contentFullHeight
|
||||||
});
|
})
|
||||||
|
|
||||||
const getUpwardSpace = computed(() => props.upwardSpace);
|
const getUpwardSpace = computed(() => props.upwardSpace)
|
||||||
const { redoHeight, setCompensation, contentHeight } = useContentHeight(
|
const { redoHeight, setCompensation, contentHeight } = useContentHeight(
|
||||||
getIsContentFullHeight,
|
getIsContentFullHeight,
|
||||||
wrapperRef,
|
wrapperRef,
|
||||||
[headerRef, footerRef],
|
[headerRef, footerRef],
|
||||||
[contentRef],
|
[contentRef],
|
||||||
getUpwardSpace,
|
getUpwardSpace,
|
||||||
);
|
)
|
||||||
setCompensation({ useLayoutFooter: true, elements: [footerRef] });
|
setCompensation({ useLayoutFooter: true, elements: [footerRef] })
|
||||||
|
|
||||||
const getClass = computed(() => {
|
const getClass = computed(() => {
|
||||||
return [
|
return [
|
||||||
|
|
@ -96,54 +96,54 @@
|
||||||
[`${prefixCls}--dense`]: props.dense,
|
[`${prefixCls}--dense`]: props.dense,
|
||||||
},
|
},
|
||||||
attrs.class ?? {},
|
attrs.class ?? {},
|
||||||
];
|
]
|
||||||
});
|
})
|
||||||
|
|
||||||
const getShowHeader = computed(
|
const getShowHeader = computed(
|
||||||
() => props.content || slots?.headerContent || props.title || getHeaderSlots.value.length,
|
() => props.content || slots?.headerContent || props.title || getHeaderSlots.value.length,
|
||||||
);
|
)
|
||||||
|
|
||||||
const getShowFooter = computed(() => slots?.leftFooter || slots?.rightFooter);
|
const getShowFooter = computed(() => slots?.leftFooter || slots?.rightFooter)
|
||||||
|
|
||||||
const getHeaderSlots = computed(() => {
|
const getHeaderSlots = computed(() => {
|
||||||
return Object.keys(omit(slots, 'default', 'leftFooter', 'rightFooter', 'headerContent'));
|
return Object.keys(omit(slots, 'default', 'leftFooter', 'rightFooter', 'headerContent'))
|
||||||
});
|
})
|
||||||
|
|
||||||
const getContentStyle = computed((): CSSProperties => {
|
const getContentStyle = computed((): CSSProperties => {
|
||||||
const { contentFullHeight, contentStyle, fixedHeight } = props;
|
const { contentFullHeight, contentStyle, fixedHeight } = props
|
||||||
if (!contentFullHeight) {
|
if (!contentFullHeight) {
|
||||||
return { ...contentStyle };
|
return { ...contentStyle }
|
||||||
}
|
}
|
||||||
|
|
||||||
const height = `${unref(contentHeight)}px`;
|
const height = `${unref(contentHeight)}px`
|
||||||
return {
|
return {
|
||||||
...contentStyle,
|
...contentStyle,
|
||||||
minHeight: height,
|
minHeight: height,
|
||||||
...(fixedHeight ? { height } : {}),
|
...(fixedHeight ? { height } : {}),
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
const getContentClass = computed(() => {
|
const getContentClass = computed(() => {
|
||||||
const { contentBackground, contentClass } = props;
|
const { contentBackground, contentClass } = props
|
||||||
return [
|
return [
|
||||||
`${prefixCls}-content`,
|
`${prefixCls}-content`,
|
||||||
contentClass,
|
contentClass,
|
||||||
{
|
{
|
||||||
[`${prefixCls}-content-bg`]: contentBackground,
|
[`${prefixCls}-content-bg`]: contentBackground,
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
});
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => [getShowFooter.value],
|
() => [getShowFooter.value],
|
||||||
() => {
|
() => {
|
||||||
redoHeight();
|
redoHeight()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
flush: 'post',
|
flush: 'post',
|
||||||
immediate: true,
|
immediate: true,
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getContentStyle,
|
getContentStyle,
|
||||||
|
|
@ -158,9 +158,9 @@
|
||||||
getShowFooter,
|
getShowFooter,
|
||||||
omit,
|
omit,
|
||||||
getContentClass,
|
getContentClass,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@prefix-cls: ~'@{namespace}-page-wrapper';
|
@prefix-cls: ~'@{namespace}-page-wrapper';
|
||||||
|
|
|
||||||
|
|
@ -43,18 +43,18 @@
|
||||||
</SubMenu>
|
</SubMenu>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { PropType } from 'vue';
|
import type { PropType } from 'vue'
|
||||||
import type { Menu } from '/@/router/types';
|
import type { Menu } from '/@/router/types'
|
||||||
|
|
||||||
import { defineComponent, computed } from 'vue';
|
import { defineComponent, computed } from 'vue'
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
import Icon from '/@/components/Icon/index';
|
import Icon from '/@/components/Icon/index'
|
||||||
|
|
||||||
import MenuItem from './components/MenuItem.vue';
|
import MenuItem from './components/MenuItem.vue'
|
||||||
import SubMenu from './components/SubMenuItem.vue';
|
import SubMenu from './components/SubMenuItem.vue'
|
||||||
import { propTypes } from '/@/utils/propTypes';
|
import { propTypes } from '/@/utils/propTypes'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'SimpleSubMenu',
|
name: 'SimpleSubMenu',
|
||||||
|
|
@ -75,22 +75,22 @@
|
||||||
theme: propTypes.oneOf(['dark', 'light']),
|
theme: propTypes.oneOf(['dark', 'light']),
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
const { prefixCls } = useDesign('simple-menu');
|
const { prefixCls } = useDesign('simple-menu')
|
||||||
|
|
||||||
const getShowMenu = computed(() => !props.item?.meta?.hideMenu);
|
const getShowMenu = computed(() => !props.item?.meta?.hideMenu)
|
||||||
const getIcon = computed(() => props.item?.icon);
|
const getIcon = computed(() => props.item?.icon)
|
||||||
const getI18nName = computed(() => t(props.item?.name));
|
const getI18nName = computed(() => t(props.item?.name))
|
||||||
const getShowSubTitle = computed(() => !props.collapse || !props.parent);
|
const getShowSubTitle = computed(() => !props.collapse || !props.parent)
|
||||||
const getIsCollapseParent = computed(() => !!props.collapse && !!props.parent);
|
const getIsCollapseParent = computed(() => !!props.collapse && !!props.parent)
|
||||||
const getLevelClass = computed(() => {
|
const getLevelClass = computed(() => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
[`${prefixCls}__parent`]: props.parent,
|
[`${prefixCls}__parent`]: props.parent,
|
||||||
[`${prefixCls}__children`]: !props.parent,
|
[`${prefixCls}__children`]: !props.parent,
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
});
|
})
|
||||||
|
|
||||||
function menuHasChildren(menuTreeItem: Menu): boolean {
|
function menuHasChildren(menuTreeItem: Menu): boolean {
|
||||||
return (
|
return (
|
||||||
|
|
@ -98,7 +98,7 @@
|
||||||
Reflect.has(menuTreeItem, 'children') &&
|
Reflect.has(menuTreeItem, 'children') &&
|
||||||
!!menuTreeItem.children &&
|
!!menuTreeItem.children &&
|
||||||
menuTreeItem.children.length > 0
|
menuTreeItem.children.length > 0
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -110,7 +110,7 @@
|
||||||
getShowSubTitle,
|
getShowSubTitle,
|
||||||
getLevelClass,
|
getLevelClass,
|
||||||
getIsCollapseParent,
|
getIsCollapseParent,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,8 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { CSSProperties, PropType } from 'vue';
|
import type { CSSProperties, PropType } from 'vue'
|
||||||
import type { SubMenuProvider } from './types';
|
import type { SubMenuProvider } from './types'
|
||||||
import {
|
import {
|
||||||
defineComponent,
|
defineComponent,
|
||||||
computed,
|
computed,
|
||||||
|
|
@ -68,18 +68,18 @@
|
||||||
provide,
|
provide,
|
||||||
onBeforeMount,
|
onBeforeMount,
|
||||||
inject,
|
inject,
|
||||||
} from 'vue';
|
} from 'vue'
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
import { propTypes } from '/@/utils/propTypes';
|
import { propTypes } from '/@/utils/propTypes'
|
||||||
import { useMenuItem } from './useMenu';
|
import { useMenuItem } from './useMenu'
|
||||||
import { useSimpleRootMenuContext } from './useSimpleMenuContext';
|
import { useSimpleRootMenuContext } from './useSimpleMenuContext'
|
||||||
import { CollapseTransition } from '/@/components/Transition';
|
import { CollapseTransition } from '/@/components/Transition'
|
||||||
import Icon from '/@/components/Icon';
|
import Icon from '/@/components/Icon'
|
||||||
import { Popover } from 'ant-design-vue';
|
import { Popover } from 'ant-design-vue'
|
||||||
import { isBoolean, isObject } from '/@/utils/is';
|
import { isBoolean, isObject } from '/@/utils/is'
|
||||||
import mitt from '/@/utils/mitt';
|
import mitt from '/@/utils/mitt'
|
||||||
|
|
||||||
const DELAY = 200;
|
const DELAY = 200
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'SubMenu',
|
name: 'SubMenu',
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -96,27 +96,26 @@
|
||||||
collapsedShowTitle: propTypes.bool,
|
collapsedShowTitle: propTypes.bool,
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const instance = getCurrentInstance();
|
const instance = getCurrentInstance()
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
active: false,
|
active: false,
|
||||||
opened: false,
|
opened: false,
|
||||||
});
|
})
|
||||||
|
|
||||||
const data = reactive({
|
const data = reactive({
|
||||||
timeout: null as TimeoutHandle | null,
|
timeout: null as TimeoutHandle | null,
|
||||||
mouseInChild: false,
|
mouseInChild: false,
|
||||||
isChild: false,
|
isChild: false,
|
||||||
});
|
})
|
||||||
|
|
||||||
const { getParentSubMenu, getItemStyle, getParentMenu, getParentList } =
|
const { getParentSubMenu, getItemStyle, getParentMenu, getParentList } = useMenuItem(instance)
|
||||||
useMenuItem(instance);
|
|
||||||
|
|
||||||
const { prefixCls } = useDesign('menu');
|
const { prefixCls } = useDesign('menu')
|
||||||
|
|
||||||
const subMenuEmitter = mitt();
|
const subMenuEmitter = mitt()
|
||||||
|
|
||||||
const { rootMenuEmitter } = useSimpleRootMenuContext();
|
const { rootMenuEmitter } = useSimpleRootMenuContext()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
addSubMenu: parentAddSubmenu,
|
addSubMenu: parentAddSubmenu,
|
||||||
|
|
@ -128,7 +127,7 @@
|
||||||
level,
|
level,
|
||||||
props: rootProps,
|
props: rootProps,
|
||||||
handleMouseleave: parentHandleMouseleave,
|
handleMouseleave: parentHandleMouseleave,
|
||||||
} = inject<SubMenuProvider>(`subMenu:${getParentMenu.value?.uid}`)!;
|
} = inject<SubMenuProvider>(`subMenu:${getParentMenu.value?.uid}`)!
|
||||||
|
|
||||||
const getClass = computed(() => {
|
const getClass = computed(() => {
|
||||||
return [
|
return [
|
||||||
|
|
@ -140,29 +139,29 @@
|
||||||
[`${prefixCls}-submenu-has-parent-submenu`]: unref(getParentSubMenu),
|
[`${prefixCls}-submenu-has-parent-submenu`]: unref(getParentSubMenu),
|
||||||
[`${prefixCls}-child-item-active`]: state.active,
|
[`${prefixCls}-child-item-active`]: state.active,
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
});
|
})
|
||||||
|
|
||||||
const getAccordion = computed(() => rootProps.accordion);
|
const getAccordion = computed(() => rootProps.accordion)
|
||||||
const getCollapse = computed(() => rootProps.collapse);
|
const getCollapse = computed(() => rootProps.collapse)
|
||||||
const getTheme = computed(() => rootProps.theme);
|
const getTheme = computed(() => rootProps.theme)
|
||||||
|
|
||||||
const getOverlayStyle = computed((): CSSProperties => {
|
const getOverlayStyle = computed((): CSSProperties => {
|
||||||
return {
|
return {
|
||||||
minWidth: '200px',
|
minWidth: '200px',
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
const getIsOpend = computed(() => {
|
const getIsOpend = computed(() => {
|
||||||
const name = props.name;
|
const name = props.name
|
||||||
if (unref(getCollapse)) {
|
if (unref(getCollapse)) {
|
||||||
return parentGetOpenNames().includes(name);
|
return parentGetOpenNames().includes(name)
|
||||||
}
|
}
|
||||||
return state.opened;
|
return state.opened
|
||||||
});
|
})
|
||||||
|
|
||||||
const getSubClass = computed(() => {
|
const getSubClass = computed(() => {
|
||||||
const isActive = rootProps.activeSubMenuNames.includes(props.name);
|
const isActive = rootProps.activeSubMenuNames.includes(props.name)
|
||||||
return [
|
return [
|
||||||
`${prefixCls}-submenu-title`,
|
`${prefixCls}-submenu-title`,
|
||||||
{
|
{
|
||||||
|
|
@ -170,134 +169,134 @@
|
||||||
[`${prefixCls}-submenu-active-border`]: isActive && level === 0,
|
[`${prefixCls}-submenu-active-border`]: isActive && level === 0,
|
||||||
[`${prefixCls}-submenu-collapse`]: unref(getCollapse) && level === 0,
|
[`${prefixCls}-submenu-collapse`]: unref(getCollapse) && level === 0,
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
});
|
})
|
||||||
|
|
||||||
function getEvents(deep: boolean) {
|
function getEvents(deep: boolean) {
|
||||||
if (!unref(getCollapse)) {
|
if (!unref(getCollapse)) {
|
||||||
return {};
|
return {}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
onMouseenter: handleMouseenter,
|
onMouseenter: handleMouseenter,
|
||||||
onMouseleave: () => handleMouseleave(deep),
|
onMouseleave: () => handleMouseleave(deep),
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleClick() {
|
function handleClick() {
|
||||||
const { disabled } = props;
|
const { disabled } = props
|
||||||
if (disabled || unref(getCollapse)) return;
|
if (disabled || unref(getCollapse)) return
|
||||||
const opened = state.opened;
|
const opened = state.opened
|
||||||
|
|
||||||
if (unref(getAccordion)) {
|
if (unref(getAccordion)) {
|
||||||
const { uidList } = getParentList();
|
const { uidList } = getParentList()
|
||||||
rootMenuEmitter.emit('on-update-opened', {
|
rootMenuEmitter.emit('on-update-opened', {
|
||||||
opend: false,
|
opend: false,
|
||||||
parent: instance?.parent,
|
parent: instance?.parent,
|
||||||
uidList: uidList,
|
uidList: uidList,
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
rootMenuEmitter.emit('open-name-change', {
|
rootMenuEmitter.emit('open-name-change', {
|
||||||
name: props.name,
|
name: props.name,
|
||||||
opened: !opened,
|
opened: !opened,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
state.opened = !opened;
|
state.opened = !opened
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMouseenter() {
|
function handleMouseenter() {
|
||||||
const disabled = props.disabled;
|
const disabled = props.disabled
|
||||||
if (disabled) return;
|
if (disabled) return
|
||||||
|
|
||||||
subMenuEmitter.emit('submenu:mouse-enter-child');
|
subMenuEmitter.emit('submenu:mouse-enter-child')
|
||||||
|
|
||||||
const index = parentGetOpenNames().findIndex((item) => item === props.name);
|
const index = parentGetOpenNames().findIndex((item) => item === props.name)
|
||||||
|
|
||||||
sliceIndex(index);
|
sliceIndex(index)
|
||||||
|
|
||||||
const isRoot = level === 0 && parentGetOpenNames().length === 2;
|
const isRoot = level === 0 && parentGetOpenNames().length === 2
|
||||||
if (isRoot) {
|
if (isRoot) {
|
||||||
parentRemoveAll();
|
parentRemoveAll()
|
||||||
}
|
}
|
||||||
data.isChild = parentGetOpenNames().includes(props.name);
|
data.isChild = parentGetOpenNames().includes(props.name)
|
||||||
clearTimeout(data.timeout!);
|
clearTimeout(data.timeout!)
|
||||||
data.timeout = setTimeout(() => {
|
data.timeout = setTimeout(() => {
|
||||||
parentAddSubmenu(props.name);
|
parentAddSubmenu(props.name)
|
||||||
}, DELAY);
|
}, DELAY)
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMouseleave(deepDispatch = false) {
|
function handleMouseleave(deepDispatch = false) {
|
||||||
const parentName = getParentMenu.value?.props.name;
|
const parentName = getParentMenu.value?.props.name
|
||||||
if (!parentName) {
|
if (!parentName) {
|
||||||
isRemoveAllPopup.value = true;
|
isRemoveAllPopup.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parentGetOpenNames().slice(-1)[0] === props.name) {
|
if (parentGetOpenNames().slice(-1)[0] === props.name) {
|
||||||
data.isChild = false;
|
data.isChild = false
|
||||||
}
|
}
|
||||||
|
|
||||||
subMenuEmitter.emit('submenu:mouse-leave-child');
|
subMenuEmitter.emit('submenu:mouse-leave-child')
|
||||||
if (data.timeout) {
|
if (data.timeout) {
|
||||||
clearTimeout(data.timeout!);
|
clearTimeout(data.timeout!)
|
||||||
data.timeout = setTimeout(() => {
|
data.timeout = setTimeout(() => {
|
||||||
if (isRemoveAllPopup.value) {
|
if (isRemoveAllPopup.value) {
|
||||||
parentRemoveAll();
|
parentRemoveAll()
|
||||||
} else if (!data.mouseInChild) {
|
} else if (!data.mouseInChild) {
|
||||||
parentRemoveSubmenu(props.name);
|
parentRemoveSubmenu(props.name)
|
||||||
}
|
}
|
||||||
}, DELAY);
|
}, DELAY)
|
||||||
}
|
}
|
||||||
if (deepDispatch) {
|
if (deepDispatch) {
|
||||||
if (getParentSubMenu.value) {
|
if (getParentSubMenu.value) {
|
||||||
parentHandleMouseleave?.(true);
|
parentHandleMouseleave?.(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
subMenuEmitter.on('submenu:mouse-enter-child', () => {
|
subMenuEmitter.on('submenu:mouse-enter-child', () => {
|
||||||
data.mouseInChild = true;
|
data.mouseInChild = true
|
||||||
isRemoveAllPopup.value = false;
|
isRemoveAllPopup.value = false
|
||||||
clearTimeout(data.timeout!);
|
clearTimeout(data.timeout!)
|
||||||
});
|
})
|
||||||
subMenuEmitter.on('submenu:mouse-leave-child', () => {
|
subMenuEmitter.on('submenu:mouse-leave-child', () => {
|
||||||
if (data.isChild) return;
|
if (data.isChild) return
|
||||||
data.mouseInChild = false;
|
data.mouseInChild = false
|
||||||
clearTimeout(data.timeout!);
|
clearTimeout(data.timeout!)
|
||||||
});
|
})
|
||||||
|
|
||||||
rootMenuEmitter.on(
|
rootMenuEmitter.on(
|
||||||
'on-update-opened',
|
'on-update-opened',
|
||||||
(data: boolean | (string | number)[] | Recordable) => {
|
(data: boolean | (string | number)[] | Recordable) => {
|
||||||
if (unref(getCollapse)) return;
|
if (unref(getCollapse)) return
|
||||||
if (isBoolean(data)) {
|
if (isBoolean(data)) {
|
||||||
state.opened = data;
|
state.opened = data
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if (isObject(data) && rootProps.accordion) {
|
if (isObject(data) && rootProps.accordion) {
|
||||||
const { opend, parent, uidList } = data as Recordable;
|
const { opend, parent, uidList } = data as Recordable
|
||||||
if (parent === instance?.parent) {
|
if (parent === instance?.parent) {
|
||||||
state.opened = opend;
|
state.opened = opend
|
||||||
} else if (!uidList.includes(instance?.uid)) {
|
} else if (!uidList.includes(instance?.uid)) {
|
||||||
state.opened = false;
|
state.opened = false
|
||||||
}
|
}
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.name && Array.isArray(data)) {
|
if (props.name && Array.isArray(data)) {
|
||||||
state.opened = (data as (string | number)[]).includes(props.name);
|
state.opened = (data as (string | number)[]).includes(props.name)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
|
|
||||||
rootMenuEmitter.on('on-update-active-name:submenu', (data: number[]) => {
|
rootMenuEmitter.on('on-update-active-name:submenu', (data: number[]) => {
|
||||||
if (instance?.uid) {
|
if (instance?.uid) {
|
||||||
state.active = data.includes(instance?.uid);
|
state.active = data.includes(instance?.uid)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
function handleVisibleChange(visible: boolean) {
|
function handleVisibleChange(visible: boolean) {
|
||||||
state.opened = visible;
|
state.opened = visible
|
||||||
}
|
}
|
||||||
|
|
||||||
// provide
|
// provide
|
||||||
|
|
@ -311,7 +310,7 @@
|
||||||
level: level + 1,
|
level: level + 1,
|
||||||
handleMouseleave,
|
handleMouseleave,
|
||||||
props: rootProps,
|
props: rootProps,
|
||||||
});
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getClass,
|
getClass,
|
||||||
|
|
@ -328,7 +327,7 @@
|
||||||
getSubClass,
|
getSubClass,
|
||||||
...toRefs(state),
|
...toRefs(state),
|
||||||
...toRefs(data),
|
...toRefs(data),
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
export { default as BasicTable } from './src/BasicTable.vue';
|
export { default as BasicTable } from './src/BasicTable.vue'
|
||||||
export { default as TableAction } from './src/components/TableAction.vue';
|
export { default as TableAction } from './src/components/TableAction.vue'
|
||||||
export { default as EditTableHeaderIcon } from './src/components/EditTableHeaderIcon.vue';
|
export { default as EditTableHeaderIcon } from './src/components/EditTableHeaderIcon.vue'
|
||||||
export { default as TableImg } from './src/components/TableImg.vue';
|
export { default as TableImg } from './src/components/TableImg.vue'
|
||||||
|
|
||||||
export * from './src/types/table';
|
export * from './src/types/table'
|
||||||
export * from './src/types/pagination';
|
export * from './src/types/pagination'
|
||||||
export * from './src/types/tableAction';
|
export * from './src/types/tableAction'
|
||||||
export { useTable } from './src/hooks/useTable';
|
export { useTable } from './src/hooks/useTable'
|
||||||
export type { FormSchema, FormProps } from '/@/components/Form/src/types/form';
|
export type { FormSchema, FormProps } from '/@/components/Form/src/types/form'
|
||||||
export type { EditRecordRow } from './src/components/editable';
|
export type { EditRecordRow } from './src/components/editable'
|
||||||
|
|
|
||||||
|
|
@ -39,40 +39,35 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type {
|
import type { BasicTableProps, TableActionType, SizeType, ColumnChangeParam } from './types/table'
|
||||||
BasicTableProps,
|
|
||||||
TableActionType,
|
|
||||||
SizeType,
|
|
||||||
ColumnChangeParam,
|
|
||||||
} from './types/table';
|
|
||||||
|
|
||||||
import { defineComponent, ref, computed, unref, toRaw, inject, watchEffect } from 'vue';
|
import { defineComponent, ref, computed, unref, toRaw, inject, watchEffect } from 'vue'
|
||||||
import { Table } from 'ant-design-vue';
|
import { Table } from 'ant-design-vue'
|
||||||
import { BasicForm, useForm } from '/@/components/Form/index';
|
import { BasicForm, useForm } from '/@/components/Form/index'
|
||||||
import { PageWrapperFixedHeightKey } from '/@/components/Page';
|
import { PageWrapperFixedHeightKey } from '/@/components/Page'
|
||||||
import HeaderCell from './components/HeaderCell.vue';
|
import HeaderCell from './components/HeaderCell.vue'
|
||||||
import { InnerHandlers } from './types/table';
|
import { InnerHandlers } from './types/table'
|
||||||
|
|
||||||
import { usePagination } from './hooks/usePagination';
|
import { usePagination } from './hooks/usePagination'
|
||||||
import { useColumns } from './hooks/useColumns';
|
import { useColumns } from './hooks/useColumns'
|
||||||
import { useDataSource } from './hooks/useDataSource';
|
import { useDataSource } from './hooks/useDataSource'
|
||||||
import { useLoading } from './hooks/useLoading';
|
import { useLoading } from './hooks/useLoading'
|
||||||
import { useRowSelection } from './hooks/useRowSelection';
|
import { useRowSelection } from './hooks/useRowSelection'
|
||||||
import { useTableScroll } from './hooks/useTableScroll';
|
import { useTableScroll } from './hooks/useTableScroll'
|
||||||
import { useTableScrollTo } from './hooks/useScrollTo';
|
import { useTableScrollTo } from './hooks/useScrollTo'
|
||||||
import { useCustomRow } from './hooks/useCustomRow';
|
import { useCustomRow } from './hooks/useCustomRow'
|
||||||
import { useTableStyle } from './hooks/useTableStyle';
|
import { useTableStyle } from './hooks/useTableStyle'
|
||||||
import { useTableHeader } from './hooks/useTableHeader';
|
import { useTableHeader } from './hooks/useTableHeader'
|
||||||
import { useTableExpand } from './hooks/useTableExpand';
|
import { useTableExpand } from './hooks/useTableExpand'
|
||||||
import { createTableContext } from './hooks/useTableContext';
|
import { createTableContext } from './hooks/useTableContext'
|
||||||
import { useTableFooter } from './hooks/useTableFooter';
|
import { useTableFooter } from './hooks/useTableFooter'
|
||||||
import { useTableForm } from './hooks/useTableForm';
|
import { useTableForm } from './hooks/useTableForm'
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
|
|
||||||
import { omit } from 'lodash-es';
|
import { omit } from 'lodash-es'
|
||||||
import { basicProps } from './props';
|
import { basicProps } from './props'
|
||||||
import { isFunction } from '/@/utils/is';
|
import { isFunction } from '/@/utils/is'
|
||||||
import { warn } from '/@/utils/log';
|
import { warn } from '/@/utils/log'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -100,37 +95,37 @@
|
||||||
'columns-change',
|
'columns-change',
|
||||||
],
|
],
|
||||||
setup(props, { attrs, emit, slots, expose }) {
|
setup(props, { attrs, emit, slots, expose }) {
|
||||||
const tableElRef = ref(null);
|
const tableElRef = ref(null)
|
||||||
const tableData = ref<Recordable[]>([]);
|
const tableData = ref<Recordable[]>([])
|
||||||
|
|
||||||
const wrapRef = ref(null);
|
const wrapRef = ref(null)
|
||||||
const formRef = ref(null);
|
const formRef = ref(null)
|
||||||
const innerPropsRef = ref<Partial<BasicTableProps>>();
|
const innerPropsRef = ref<Partial<BasicTableProps>>()
|
||||||
|
|
||||||
const { prefixCls } = useDesign('basic-table');
|
const { prefixCls } = useDesign('basic-table')
|
||||||
const [registerForm, formActions] = useForm();
|
const [registerForm, formActions] = useForm()
|
||||||
|
|
||||||
const getProps = computed(() => {
|
const getProps = computed(() => {
|
||||||
return { ...props, ...unref(innerPropsRef) } as BasicTableProps;
|
return { ...props, ...unref(innerPropsRef) } as BasicTableProps
|
||||||
});
|
})
|
||||||
|
|
||||||
const isFixedHeightPage = inject(PageWrapperFixedHeightKey, false);
|
const isFixedHeightPage = inject(PageWrapperFixedHeightKey, false)
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
unref(isFixedHeightPage) &&
|
unref(isFixedHeightPage) &&
|
||||||
props.canResize &&
|
props.canResize &&
|
||||||
warn(
|
warn(
|
||||||
"'canResize' of BasicTable may not work in PageWrapper with 'fixedHeight' (especially in hot updates)",
|
"'canResize' of BasicTable may not work in PageWrapper with 'fixedHeight' (especially in hot updates)",
|
||||||
);
|
)
|
||||||
});
|
})
|
||||||
|
|
||||||
const { getLoading, setLoading } = useLoading(getProps);
|
const { getLoading, setLoading } = useLoading(getProps)
|
||||||
const {
|
const {
|
||||||
getPaginationInfo,
|
getPaginationInfo,
|
||||||
getPagination,
|
getPagination,
|
||||||
setPagination,
|
setPagination,
|
||||||
setShowPagination,
|
setShowPagination,
|
||||||
getShowPagination,
|
getShowPagination,
|
||||||
} = usePagination(getProps);
|
} = usePagination(getProps)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
getRowSelection,
|
getRowSelection,
|
||||||
|
|
@ -140,7 +135,7 @@
|
||||||
getSelectRowKeys,
|
getSelectRowKeys,
|
||||||
deleteSelectRowByKey,
|
deleteSelectRowByKey,
|
||||||
setSelectedRowKeys,
|
setSelectedRowKeys,
|
||||||
} = useRowSelection(getProps, tableData, emit);
|
} = useRowSelection(getProps, tableData, emit)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
handleTableChange: onTableChange,
|
handleTableChange: onTableChange,
|
||||||
|
|
@ -168,14 +163,14 @@
|
||||||
clearSelectedRowKeys,
|
clearSelectedRowKeys,
|
||||||
},
|
},
|
||||||
emit,
|
emit,
|
||||||
);
|
)
|
||||||
|
|
||||||
function handleTableChange(...args) {
|
function handleTableChange(...args) {
|
||||||
onTableChange.call(undefined, ...args);
|
onTableChange.call(undefined, ...args)
|
||||||
emit('change', ...args);
|
emit('change', ...args)
|
||||||
// 解决通过useTable注册onChange时不起作用的问题
|
// 解决通过useTable注册onChange时不起作用的问题
|
||||||
const { onChange } = unref(getProps);
|
const { onChange } = unref(getProps)
|
||||||
onChange && isFunction(onChange) && onChange.call(undefined, ...args);
|
onChange && isFunction(onChange) && onChange.call(undefined, ...args)
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|
@ -185,7 +180,7 @@
|
||||||
setColumns,
|
setColumns,
|
||||||
getColumnsRef,
|
getColumnsRef,
|
||||||
getCacheColumns,
|
getCacheColumns,
|
||||||
} = useColumns(getProps, getPaginationInfo);
|
} = useColumns(getProps, getPaginationInfo)
|
||||||
|
|
||||||
const { getScrollRef, redoHeight } = useTableScroll(
|
const { getScrollRef, redoHeight } = useTableScroll(
|
||||||
getProps,
|
getProps,
|
||||||
|
|
@ -195,9 +190,9 @@
|
||||||
getDataSourceRef,
|
getDataSourceRef,
|
||||||
wrapRef,
|
wrapRef,
|
||||||
formRef,
|
formRef,
|
||||||
);
|
)
|
||||||
|
|
||||||
const { scrollTo } = useTableScrollTo(tableElRef, getDataSourceRef);
|
const { scrollTo } = useTableScrollTo(tableElRef, getDataSourceRef)
|
||||||
|
|
||||||
const { customRow } = useCustomRow(getProps, {
|
const { customRow } = useCustomRow(getProps, {
|
||||||
setSelectedRowKeys,
|
setSelectedRowKeys,
|
||||||
|
|
@ -205,38 +200,38 @@
|
||||||
clearSelectedRowKeys,
|
clearSelectedRowKeys,
|
||||||
getAutoCreateKey,
|
getAutoCreateKey,
|
||||||
emit,
|
emit,
|
||||||
});
|
})
|
||||||
|
|
||||||
const { getRowClassName } = useTableStyle(getProps, prefixCls);
|
const { getRowClassName } = useTableStyle(getProps, prefixCls)
|
||||||
|
|
||||||
const { getExpandOption, expandAll, expandRows, collapseAll } = useTableExpand(
|
const { getExpandOption, expandAll, expandRows, collapseAll } = useTableExpand(
|
||||||
getProps,
|
getProps,
|
||||||
tableData,
|
tableData,
|
||||||
emit,
|
emit,
|
||||||
);
|
)
|
||||||
|
|
||||||
const handlers: InnerHandlers = {
|
const handlers: InnerHandlers = {
|
||||||
onColumnsChange: (data: ColumnChangeParam[]) => {
|
onColumnsChange: (data: ColumnChangeParam[]) => {
|
||||||
emit('columns-change', data);
|
emit('columns-change', data)
|
||||||
// support useTable
|
// support useTable
|
||||||
unref(getProps).onColumnsChange?.(data);
|
unref(getProps).onColumnsChange?.(data)
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|
||||||
const { getHeaderProps } = useTableHeader(getProps, slots, handlers);
|
const { getHeaderProps } = useTableHeader(getProps, slots, handlers)
|
||||||
|
|
||||||
const { getFooterProps } = useTableFooter(
|
const { getFooterProps } = useTableFooter(
|
||||||
getProps,
|
getProps,
|
||||||
getScrollRef,
|
getScrollRef,
|
||||||
tableElRef,
|
tableElRef,
|
||||||
getDataSourceRef,
|
getDataSourceRef,
|
||||||
);
|
)
|
||||||
|
|
||||||
const { getFormProps, replaceFormSlotKey, getFormSlotKeys, handleSearchInfoChange } =
|
const { getFormProps, replaceFormSlotKey, getFormSlotKeys, handleSearchInfoChange } =
|
||||||
useTableForm(getProps, slots, fetch, getLoading);
|
useTableForm(getProps, slots, fetch, getLoading)
|
||||||
|
|
||||||
const getBindValues = computed(() => {
|
const getBindValues = computed(() => {
|
||||||
const dataSource = unref(getDataSourceRef);
|
const dataSource = unref(getDataSourceRef)
|
||||||
let propsData: Recordable = {
|
let propsData: Recordable = {
|
||||||
...attrs,
|
...attrs,
|
||||||
customRow,
|
customRow,
|
||||||
|
|
@ -252,17 +247,17 @@
|
||||||
dataSource,
|
dataSource,
|
||||||
footer: unref(getFooterProps),
|
footer: unref(getFooterProps),
|
||||||
...unref(getExpandOption),
|
...unref(getExpandOption),
|
||||||
};
|
}
|
||||||
// if (slots.expandedRowRender) {
|
// if (slots.expandedRowRender) {
|
||||||
// propsData = omit(propsData, 'scroll');
|
// propsData = omit(propsData, 'scroll');
|
||||||
// }
|
// }
|
||||||
|
|
||||||
propsData = omit(propsData, ['class', 'onChange']);
|
propsData = omit(propsData, ['class', 'onChange'])
|
||||||
return propsData;
|
return propsData
|
||||||
});
|
})
|
||||||
|
|
||||||
const getWrapperClass = computed(() => {
|
const getWrapperClass = computed(() => {
|
||||||
const values = unref(getBindValues);
|
const values = unref(getBindValues)
|
||||||
return [
|
return [
|
||||||
prefixCls,
|
prefixCls,
|
||||||
attrs.class,
|
attrs.class,
|
||||||
|
|
@ -270,19 +265,19 @@
|
||||||
[`${prefixCls}-form-container`]: values.useSearchForm,
|
[`${prefixCls}-form-container`]: values.useSearchForm,
|
||||||
[`${prefixCls}--inset`]: values.inset,
|
[`${prefixCls}--inset`]: values.inset,
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
});
|
})
|
||||||
|
|
||||||
const getEmptyDataIsShowTable = computed(() => {
|
const getEmptyDataIsShowTable = computed(() => {
|
||||||
const { emptyDataIsShowTable, useSearchForm } = unref(getProps);
|
const { emptyDataIsShowTable, useSearchForm } = unref(getProps)
|
||||||
if (emptyDataIsShowTable || !useSearchForm) {
|
if (emptyDataIsShowTable || !useSearchForm) {
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
return !!unref(getDataSourceRef).length;
|
return !!unref(getDataSourceRef).length
|
||||||
});
|
})
|
||||||
|
|
||||||
function setProps(props: Partial<BasicTableProps>) {
|
function setProps(props: Partial<BasicTableProps>) {
|
||||||
innerPropsRef.value = { ...unref(innerPropsRef), ...props };
|
innerPropsRef.value = { ...unref(innerPropsRef), ...props }
|
||||||
}
|
}
|
||||||
|
|
||||||
const tableAction: TableActionType = {
|
const tableAction: TableActionType = {
|
||||||
|
|
@ -318,14 +313,14 @@
|
||||||
collapseAll,
|
collapseAll,
|
||||||
scrollTo,
|
scrollTo,
|
||||||
getSize: () => {
|
getSize: () => {
|
||||||
return unref(getBindValues).size as SizeType;
|
return unref(getBindValues).size as SizeType
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
createTableContext({ ...tableAction, wrapRef, getBindValues });
|
createTableContext({ ...tableAction, wrapRef, getBindValues })
|
||||||
|
|
||||||
expose(tableAction);
|
expose(tableAction)
|
||||||
|
|
||||||
emit('register', tableAction, formActions);
|
emit('register', tableAction, formActions)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
formRef,
|
formRef,
|
||||||
|
|
@ -345,9 +340,9 @@
|
||||||
getFormSlotKeys,
|
getFormSlotKeys,
|
||||||
getWrapperClass,
|
getWrapperClass,
|
||||||
columns: getViewColumns,
|
columns: getViewColumns,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@border-color: #cecece4d;
|
@border-color: #cecece4d;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import type { Component } from 'vue';
|
import type { Component } from 'vue'
|
||||||
import {
|
import {
|
||||||
Input,
|
Input,
|
||||||
Select,
|
Select,
|
||||||
|
|
@ -9,32 +9,32 @@ import {
|
||||||
TimePicker,
|
TimePicker,
|
||||||
AutoComplete,
|
AutoComplete,
|
||||||
Radio,
|
Radio,
|
||||||
} from 'ant-design-vue';
|
} from 'ant-design-vue'
|
||||||
import type { ComponentType } from './types/componentType';
|
import type { ComponentType } from './types/componentType'
|
||||||
import { ApiSelect, ApiTreeSelect, RadioButtonGroup, ApiRadioGroup } from '/@/components/Form';
|
import { ApiSelect, ApiTreeSelect, RadioButtonGroup, ApiRadioGroup } from '/@/components/Form'
|
||||||
|
|
||||||
const componentMap = new Map<ComponentType, Component>();
|
const componentMap = new Map<ComponentType, Component>()
|
||||||
|
|
||||||
componentMap.set('Input', Input);
|
componentMap.set('Input', Input)
|
||||||
componentMap.set('InputNumber', InputNumber);
|
componentMap.set('InputNumber', InputNumber)
|
||||||
componentMap.set('Select', Select);
|
componentMap.set('Select', Select)
|
||||||
componentMap.set('ApiSelect', ApiSelect);
|
componentMap.set('ApiSelect', ApiSelect)
|
||||||
componentMap.set('AutoComplete', AutoComplete);
|
componentMap.set('AutoComplete', AutoComplete)
|
||||||
componentMap.set('ApiTreeSelect', ApiTreeSelect);
|
componentMap.set('ApiTreeSelect', ApiTreeSelect)
|
||||||
componentMap.set('Switch', Switch);
|
componentMap.set('Switch', Switch)
|
||||||
componentMap.set('Checkbox', Checkbox);
|
componentMap.set('Checkbox', Checkbox)
|
||||||
componentMap.set('DatePicker', DatePicker);
|
componentMap.set('DatePicker', DatePicker)
|
||||||
componentMap.set('TimePicker', TimePicker);
|
componentMap.set('TimePicker', TimePicker)
|
||||||
componentMap.set('RadioGroup', Radio.Group);
|
componentMap.set('RadioGroup', Radio.Group)
|
||||||
componentMap.set('RadioButtonGroup', RadioButtonGroup);
|
componentMap.set('RadioButtonGroup', RadioButtonGroup)
|
||||||
componentMap.set('ApiRadioGroup', ApiRadioGroup);
|
componentMap.set('ApiRadioGroup', ApiRadioGroup)
|
||||||
|
|
||||||
export function add(compName: ComponentType, component: Component) {
|
export function add(compName: ComponentType, component: Component) {
|
||||||
componentMap.set(compName, component);
|
componentMap.set(compName, component)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function del(compName: ComponentType) {
|
export function del(compName: ComponentType) {
|
||||||
componentMap.delete(compName);
|
componentMap.delete(compName)
|
||||||
}
|
}
|
||||||
|
|
||||||
export { componentMap };
|
export { componentMap }
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,12 @@
|
||||||
<BasicHelp v-if="getHelpMessage" :text="getHelpMessage" :class="`${prefixCls}__help`" />
|
<BasicHelp v-if="getHelpMessage" :text="getHelpMessage" :class="`${prefixCls}__help`" />
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { PropType } from 'vue';
|
import type { PropType } from 'vue'
|
||||||
import type { BasicColumn } from '../types/table';
|
import type { BasicColumn } from '../types/table'
|
||||||
import { defineComponent, computed } from 'vue';
|
import { defineComponent, computed } from 'vue'
|
||||||
import BasicHelp from '/@/components/Basic/src/BasicHelp.vue';
|
import BasicHelp from '/@/components/Basic/src/BasicHelp.vue'
|
||||||
import EditTableHeaderCell from './EditTableHeaderIcon.vue';
|
import EditTableHeaderCell from './EditTableHeaderIcon.vue'
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'TableHeaderCell',
|
name: 'TableHeaderCell',
|
||||||
|
|
@ -26,15 +26,15 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
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 || props.column?.title);
|
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 }
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@prefix-cls: ~'@{namespace}-basic-table-header-cell';
|
@prefix-cls: ~'@{namespace}-basic-table-header-cell';
|
||||||
|
|
|
||||||
|
|
@ -31,19 +31,19 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, PropType, computed, toRaw, unref } from 'vue';
|
import { defineComponent, PropType, computed, toRaw, unref } from 'vue'
|
||||||
import { MoreOutlined } from '@ant-design/icons-vue';
|
import { MoreOutlined } from '@ant-design/icons-vue'
|
||||||
import { Divider, Tooltip, TooltipProps } from 'ant-design-vue';
|
import { Divider, Tooltip, TooltipProps } from 'ant-design-vue'
|
||||||
import Icon from '/@/components/Icon/index';
|
import Icon from '/@/components/Icon/index'
|
||||||
import { ActionItem, TableActionType } from '/@/components/Table';
|
import { ActionItem, TableActionType } from '/@/components/Table'
|
||||||
import { PopConfirmButton } from '/@/components/Button';
|
import { PopConfirmButton } from '/@/components/Button'
|
||||||
import { Dropdown } from '/@/components/Dropdown';
|
import { Dropdown } from '/@/components/Dropdown'
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
import { useTableContext } from '../hooks/useTableContext';
|
import { useTableContext } from '../hooks/useTableContext'
|
||||||
import { usePermission } from '/@/hooks/web/usePermission';
|
import { usePermission } from '/@/hooks/web/usePermission'
|
||||||
import { isBoolean, isFunction, isString } from '/@/utils/is';
|
import { isBoolean, isFunction, isString } from '/@/utils/is'
|
||||||
import { propTypes } from '/@/utils/propTypes';
|
import { propTypes } from '/@/utils/propTypes'
|
||||||
import { ACTION_COLUMN_FLAG } from '../const';
|
import { ACTION_COLUMN_FLAG } from '../const'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'TableAction',
|
name: 'TableAction',
|
||||||
|
|
@ -62,34 +62,34 @@
|
||||||
stopButtonPropagation: propTypes.bool.def(false),
|
stopButtonPropagation: propTypes.bool.def(false),
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const { prefixCls } = useDesign('basic-table-action');
|
const { prefixCls } = useDesign('basic-table-action')
|
||||||
let table: Partial<TableActionType> = {};
|
let table: Partial<TableActionType> = {}
|
||||||
if (!props.outside) {
|
if (!props.outside) {
|
||||||
table = useTableContext();
|
table = useTableContext()
|
||||||
}
|
}
|
||||||
|
|
||||||
const { hasPermission } = usePermission();
|
const { hasPermission } = usePermission()
|
||||||
function isIfShow(action: ActionItem): boolean {
|
function isIfShow(action: ActionItem): boolean {
|
||||||
const ifShow = action.ifShow;
|
const ifShow = action.ifShow
|
||||||
|
|
||||||
let isIfShow = true;
|
let isIfShow = true
|
||||||
|
|
||||||
if (isBoolean(ifShow)) {
|
if (isBoolean(ifShow)) {
|
||||||
isIfShow = ifShow;
|
isIfShow = ifShow
|
||||||
}
|
}
|
||||||
if (isFunction(ifShow)) {
|
if (isFunction(ifShow)) {
|
||||||
isIfShow = ifShow(action);
|
isIfShow = ifShow(action)
|
||||||
}
|
}
|
||||||
return isIfShow;
|
return isIfShow
|
||||||
}
|
}
|
||||||
|
|
||||||
const getActions = computed(() => {
|
const getActions = computed(() => {
|
||||||
return (toRaw(props.actions) || [])
|
return (toRaw(props.actions) || [])
|
||||||
.filter((action) => {
|
.filter((action) => {
|
||||||
return hasPermission(action.auth) && isIfShow(action);
|
return hasPermission(action.auth) && isIfShow(action)
|
||||||
})
|
})
|
||||||
.map((action) => {
|
.map((action) => {
|
||||||
const { popConfirm } = action;
|
const { popConfirm } = action
|
||||||
return {
|
return {
|
||||||
getPopupContainer: () => unref((table as any)?.wrapRef.value) ?? document.body,
|
getPopupContainer: () => unref((table as any)?.wrapRef.value) ?? document.body,
|
||||||
type: 'link',
|
type: 'link',
|
||||||
|
|
@ -99,16 +99,16 @@
|
||||||
onConfirm: popConfirm?.confirm,
|
onConfirm: popConfirm?.confirm,
|
||||||
onCancel: popConfirm?.cancel,
|
onCancel: popConfirm?.cancel,
|
||||||
enable: !!popConfirm,
|
enable: !!popConfirm,
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
const getDropdownList = computed((): any[] => {
|
const getDropdownList = computed((): any[] => {
|
||||||
const list = (toRaw(props.dropDownActions) || []).filter((action) => {
|
const list = (toRaw(props.dropDownActions) || []).filter((action) => {
|
||||||
return hasPermission(action.auth) && isIfShow(action);
|
return hasPermission(action.auth) && isIfShow(action)
|
||||||
});
|
})
|
||||||
return list.map((action, index) => {
|
return list.map((action, index) => {
|
||||||
const { label, popConfirm } = action;
|
const { label, popConfirm } = action
|
||||||
return {
|
return {
|
||||||
...action,
|
...action,
|
||||||
...popConfirm,
|
...popConfirm,
|
||||||
|
|
@ -116,36 +116,36 @@
|
||||||
onCancel: popConfirm?.cancel,
|
onCancel: popConfirm?.cancel,
|
||||||
text: label,
|
text: label,
|
||||||
divider: index < list.length - 1 ? props.divider : false,
|
divider: index < list.length - 1 ? props.divider : false,
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
const getAlign = computed(() => {
|
const getAlign = computed(() => {
|
||||||
const columns = (table as TableActionType)?.getColumns?.() || [];
|
const columns = (table as TableActionType)?.getColumns?.() || []
|
||||||
const actionColumn = columns.find((item) => item.flag === ACTION_COLUMN_FLAG);
|
const actionColumn = columns.find((item) => item.flag === ACTION_COLUMN_FLAG)
|
||||||
return actionColumn?.align ?? 'left';
|
return actionColumn?.align ?? 'left'
|
||||||
});
|
})
|
||||||
|
|
||||||
function getTooltip(data: string | TooltipProps): TooltipProps {
|
function getTooltip(data: string | TooltipProps): TooltipProps {
|
||||||
return {
|
return {
|
||||||
getPopupContainer: () => unref((table as any)?.wrapRef.value) ?? document.body,
|
getPopupContainer: () => unref((table as any)?.wrapRef.value) ?? document.body,
|
||||||
placement: 'bottom',
|
placement: 'bottom',
|
||||||
...(isString(data) ? { title: data } : data),
|
...(isString(data) ? { title: data } : data),
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCellClick(e: MouseEvent) {
|
function onCellClick(e: MouseEvent) {
|
||||||
if (!props.stopButtonPropagation) return;
|
if (!props.stopButtonPropagation) return
|
||||||
const path = e.composedPath() as HTMLElement[];
|
const path = e.composedPath() as HTMLElement[]
|
||||||
const isInButton = path.find((ele) => {
|
const isInButton = path.find((ele) => {
|
||||||
return ele.tagName?.toUpperCase() === 'BUTTON';
|
return ele.tagName?.toUpperCase() === 'BUTTON'
|
||||||
});
|
})
|
||||||
isInButton && e.stopPropagation();
|
isInButton && e.stopPropagation()
|
||||||
}
|
}
|
||||||
|
|
||||||
return { prefixCls, getActions, getDropdownList, getAlign, onCellClick, getTooltip };
|
return { prefixCls, getActions, getDropdownList, getAlign, onCellClick, getTooltip }
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@prefix-cls: ~'@{namespace}-basic-table-action';
|
@prefix-cls: ~'@{namespace}-basic-table-action';
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
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'
|
||||||
import type { EditRecordRow } from './index';
|
import type { EditRecordRow } from './index'
|
||||||
import { CheckOutlined, CloseOutlined, FormOutlined } from '@ant-design/icons-vue';
|
import { CheckOutlined, CloseOutlined, FormOutlined } from '@ant-design/icons-vue'
|
||||||
import { CellComponent } from './CellComponent';
|
import { CellComponent } from './CellComponent'
|
||||||
|
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
import { useTableContext } from '../../hooks/useTableContext';
|
import { useTableContext } from '../../hooks/useTableContext'
|
||||||
|
|
||||||
import clickOutside from '/@/directives/clickOutside';
|
import clickOutside from '/@/directives/clickOutside'
|
||||||
|
|
||||||
import { propTypes } from '/@/utils/propTypes';
|
import { propTypes } from '/@/utils/propTypes'
|
||||||
import { isArray, isBoolean, isFunction, isNumber, isString } from '/@/utils/is';
|
import { isArray, isBoolean, isFunction, isNumber, isString } from '/@/utils/is'
|
||||||
import { createPlaceholderMessage } from './helper';
|
import { createPlaceholderMessage } from './helper'
|
||||||
import { pick, set } from 'lodash-es';
|
import { pick, set } from 'lodash-es'
|
||||||
import { treeToList } from '/@/utils/helper/treeHelper';
|
import { treeToList } from '/@/utils/helper/treeHelper'
|
||||||
import { Spin } from 'ant-design-vue';
|
import { Spin } from 'ant-design-vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'EditableCell',
|
name: 'EditableCell',
|
||||||
|
|
@ -39,50 +39,50 @@
|
||||||
index: propTypes.number,
|
index: propTypes.number,
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const table = useTableContext();
|
const table = useTableContext()
|
||||||
const isEdit = ref(false);
|
const isEdit = ref(false)
|
||||||
const elRef = ref();
|
const elRef = ref()
|
||||||
const ruleVisible = ref(false);
|
const ruleVisible = ref(false)
|
||||||
const ruleMessage = ref('');
|
const ruleMessage = ref('')
|
||||||
const optionsRef = ref<LabelValueOptions>([]);
|
const optionsRef = ref<LabelValueOptions>([])
|
||||||
const currentValueRef = ref<any>(props.value);
|
const currentValueRef = ref<any>(props.value)
|
||||||
const defaultValueRef = ref<any>(props.value);
|
const defaultValueRef = ref<any>(props.value)
|
||||||
const spinning = ref<boolean>(false);
|
const spinning = ref<boolean>(false)
|
||||||
|
|
||||||
const { prefixCls } = useDesign('editable-cell');
|
const { prefixCls } = useDesign('editable-cell')
|
||||||
|
|
||||||
const getComponent = computed(() => props.column?.editComponent || 'Input');
|
const getComponent = computed(() => props.column?.editComponent || 'Input')
|
||||||
const getRule = computed(() => props.column?.editRule);
|
const getRule = computed(() => props.column?.editRule)
|
||||||
|
|
||||||
const getRuleVisible = computed(() => {
|
const getRuleVisible = computed(() => {
|
||||||
return unref(ruleMessage) && unref(ruleVisible);
|
return unref(ruleMessage) && unref(ruleVisible)
|
||||||
});
|
})
|
||||||
|
|
||||||
const getIsCheckComp = computed(() => {
|
const getIsCheckComp = computed(() => {
|
||||||
const component = unref(getComponent);
|
const component = unref(getComponent)
|
||||||
return ['Checkbox', 'Switch'].includes(component);
|
return ['Checkbox', 'Switch'].includes(component)
|
||||||
});
|
})
|
||||||
|
|
||||||
const getComponentProps = computed(() => {
|
const getComponentProps = computed(() => {
|
||||||
const isCheckValue = unref(getIsCheckComp);
|
const isCheckValue = unref(getIsCheckComp)
|
||||||
|
|
||||||
const valueField = isCheckValue ? 'checked' : 'value';
|
const valueField = isCheckValue ? 'checked' : 'value'
|
||||||
const val = unref(currentValueRef);
|
const val = unref(currentValueRef)
|
||||||
|
|
||||||
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 ?? {};
|
let compProps = props.column?.editComponentProps ?? {}
|
||||||
const { record, column, index } = props;
|
const { record, column, index } = props
|
||||||
|
|
||||||
if (isFunction(compProps)) {
|
if (isFunction(compProps)) {
|
||||||
compProps = compProps({ text: val, record, column, index }) ?? {};
|
compProps = compProps({ text: val, record, column, index }) ?? {}
|
||||||
}
|
}
|
||||||
const component = unref(getComponent);
|
const component = unref(getComponent)
|
||||||
const apiSelectProps: Recordable = {};
|
const apiSelectProps: Recordable = {}
|
||||||
if (component === 'ApiSelect') {
|
if (component === 'ApiSelect') {
|
||||||
apiSelectProps.cache = true;
|
apiSelectProps.cache = true
|
||||||
}
|
}
|
||||||
upEditDynamicDisabled(record, column, value);
|
upEditDynamicDisabled(record, column, value)
|
||||||
return {
|
return {
|
||||||
size: 'small',
|
size: 'small',
|
||||||
getPopupContainer: () => unref(table?.wrapRef.value) ?? document.body,
|
getPopupContainer: () => unref(table?.wrapRef.value) ?? document.body,
|
||||||
|
|
@ -91,241 +91,241 @@
|
||||||
...compProps,
|
...compProps,
|
||||||
[valueField]: value,
|
[valueField]: value,
|
||||||
disabled: unref(getDisable),
|
disabled: unref(getDisable),
|
||||||
} as any;
|
} as any
|
||||||
});
|
})
|
||||||
function upEditDynamicDisabled(record, column, value) {
|
function upEditDynamicDisabled(record, column, value) {
|
||||||
if (!record) return false;
|
if (!record) return false
|
||||||
const { key, dataIndex } = column;
|
const { key, dataIndex } = column
|
||||||
if (!key && !dataIndex) return;
|
if (!key && !dataIndex) return
|
||||||
const dataKey = (dataIndex || key) as string;
|
const dataKey = (dataIndex || key) as string
|
||||||
set(record, dataKey, value);
|
set(record, dataKey, value)
|
||||||
}
|
}
|
||||||
const getDisable = computed(() => {
|
const getDisable = computed(() => {
|
||||||
const { editDynamicDisabled } = props.column;
|
const { editDynamicDisabled } = props.column
|
||||||
let disabled = false;
|
let disabled = false
|
||||||
if (isBoolean(editDynamicDisabled)) {
|
if (isBoolean(editDynamicDisabled)) {
|
||||||
disabled = editDynamicDisabled;
|
disabled = editDynamicDisabled
|
||||||
}
|
}
|
||||||
if (isFunction(editDynamicDisabled)) {
|
if (isFunction(editDynamicDisabled)) {
|
||||||
const { record } = props;
|
const { record } = props
|
||||||
disabled = editDynamicDisabled({ record });
|
disabled = editDynamicDisabled({ record })
|
||||||
}
|
}
|
||||||
return disabled;
|
return disabled
|
||||||
});
|
})
|
||||||
const getValues = computed(() => {
|
const getValues = computed(() => {
|
||||||
const { editValueMap } = props.column;
|
const { editValueMap } = props.column
|
||||||
|
|
||||||
const value = unref(currentValueRef);
|
const value = unref(currentValueRef)
|
||||||
|
|
||||||
if (editValueMap && isFunction(editValueMap)) {
|
if (editValueMap && isFunction(editValueMap)) {
|
||||||
return editValueMap(value);
|
return editValueMap(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const component = unref(getComponent);
|
const component = unref(getComponent)
|
||||||
if (!component.includes('Select') && !component.includes('Radio')) {
|
if (!component.includes('Select') && !component.includes('Radio')) {
|
||||||
return value;
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
const options: LabelValueOptions =
|
const options: LabelValueOptions =
|
||||||
unref(getComponentProps)?.options ?? (unref(optionsRef) || []);
|
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
|
||||||
});
|
})
|
||||||
|
|
||||||
const getWrapperStyle = computed((): CSSProperties => {
|
const getWrapperStyle = computed((): CSSProperties => {
|
||||||
if (unref(getIsCheckComp) || unref(getRowEditable)) {
|
if (unref(getIsCheckComp) || unref(getRowEditable)) {
|
||||||
return {};
|
return {}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
width: 'calc(100% - 48px)',
|
width: 'calc(100% - 48px)',
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
const getWrapperClass = computed(() => {
|
const getWrapperClass = computed(() => {
|
||||||
const { align = 'center' } = props.column;
|
const { align = 'center' } = props.column
|
||||||
return `edit-cell-align-${align}`;
|
return `edit-cell-align-${align}`
|
||||||
});
|
})
|
||||||
|
|
||||||
const getRowEditable = computed(() => {
|
const getRowEditable = computed(() => {
|
||||||
const { editable } = props.record || {};
|
const { editable } = props.record || {}
|
||||||
return !!editable;
|
return !!editable
|
||||||
});
|
})
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
defaultValueRef.value = props.value;
|
defaultValueRef.value = props.value
|
||||||
currentValueRef.value = props.value;
|
currentValueRef.value = props.value
|
||||||
});
|
})
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
const { editable } = props.column;
|
const { editable } = props.column
|
||||||
if (isBoolean(editable) || isBoolean(unref(getRowEditable))) {
|
if (isBoolean(editable) || isBoolean(unref(getRowEditable))) {
|
||||||
isEdit.value = !!editable || unref(getRowEditable);
|
isEdit.value = !!editable || unref(getRowEditable)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
function handleEdit() {
|
function handleEdit() {
|
||||||
if (unref(getRowEditable) || unref(props.column?.editRow)) return;
|
if (unref(getRowEditable) || unref(props.column?.editRow)) return
|
||||||
ruleMessage.value = '';
|
ruleMessage.value = ''
|
||||||
isEdit.value = true;
|
isEdit.value = true
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const el = unref(elRef);
|
const el = unref(elRef)
|
||||||
el?.focus?.();
|
el?.focus?.()
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleChange(e: any) {
|
async function handleChange(e: any) {
|
||||||
const component = unref(getComponent);
|
const component = unref(getComponent)
|
||||||
if (!e) {
|
if (!e) {
|
||||||
currentValueRef.value = e;
|
currentValueRef.value = e
|
||||||
} else if (component === 'Checkbox') {
|
} else if (component === 'Checkbox') {
|
||||||
currentValueRef.value = (e as ChangeEvent).target.checked;
|
currentValueRef.value = (e as ChangeEvent).target.checked
|
||||||
} else if (component === 'Switch') {
|
} else if (component === 'Switch') {
|
||||||
currentValueRef.value = e;
|
currentValueRef.value = e
|
||||||
} else if (e?.target && Reflect.has(e.target, 'value')) {
|
} else if (e?.target && Reflect.has(e.target, 'value')) {
|
||||||
currentValueRef.value = (e as ChangeEvent).target.value;
|
currentValueRef.value = (e as ChangeEvent).target.value
|
||||||
} else if (isString(e) || isBoolean(e) || isNumber(e) || isArray(e)) {
|
} else if (isString(e) || isBoolean(e) || isNumber(e) || isArray(e)) {
|
||||||
currentValueRef.value = e;
|
currentValueRef.value = e
|
||||||
}
|
}
|
||||||
const onChange = unref(getComponentProps)?.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', {
|
||||||
column: props.column,
|
column: props.column,
|
||||||
value: unref(currentValueRef),
|
value: unref(currentValueRef),
|
||||||
record: toRaw(props.record),
|
record: toRaw(props.record),
|
||||||
});
|
})
|
||||||
handleSubmiRule();
|
handleSubmiRule()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleSubmiRule() {
|
async function handleSubmiRule() {
|
||||||
const { column, record } = props;
|
const { column, record } = props
|
||||||
const { editRule } = column;
|
const { editRule } = column
|
||||||
const currentValue = unref(currentValueRef);
|
const currentValue = unref(currentValueRef)
|
||||||
|
|
||||||
if (editRule) {
|
if (editRule) {
|
||||||
if (isBoolean(editRule) && !currentValue && !isNumber(currentValue)) {
|
if (isBoolean(editRule) && !currentValue && !isNumber(currentValue)) {
|
||||||
ruleVisible.value = true;
|
ruleVisible.value = true
|
||||||
const component = unref(getComponent);
|
const component = unref(getComponent)
|
||||||
ruleMessage.value = createPlaceholderMessage(component);
|
ruleMessage.value = createPlaceholderMessage(component)
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
if (isFunction(editRule)) {
|
if (isFunction(editRule)) {
|
||||||
const res = await editRule(currentValue, record as Recordable);
|
const res = await editRule(currentValue, record as Recordable)
|
||||||
if (!!res) {
|
if (!!res) {
|
||||||
ruleMessage.value = res;
|
ruleMessage.value = res
|
||||||
ruleVisible.value = true;
|
ruleVisible.value = true
|
||||||
return false;
|
return false
|
||||||
} else {
|
} else {
|
||||||
ruleMessage.value = '';
|
ruleMessage.value = ''
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ruleMessage.value = '';
|
ruleMessage.value = ''
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleSubmit(needEmit = true, valid = true) {
|
async function handleSubmit(needEmit = true, valid = true) {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
const isPass = await handleSubmiRule();
|
const isPass = await handleSubmiRule()
|
||||||
if (!isPass) return false;
|
if (!isPass) return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const { column, index, record } = props;
|
const { column, index, record } = props
|
||||||
if (!record) return false;
|
if (!record) return false
|
||||||
const { key, dataIndex } = column;
|
const { key, dataIndex } = column
|
||||||
const value = unref(currentValueRef);
|
const value = unref(currentValueRef)
|
||||||
if (!key && !dataIndex) return;
|
if (!key && !dataIndex) return
|
||||||
|
|
||||||
const dataKey = (dataIndex || key) as string;
|
const dataKey = (dataIndex || key) as string
|
||||||
|
|
||||||
if (!record.editable) {
|
if (!record.editable) {
|
||||||
const { getBindValues } = table;
|
const { getBindValues } = table
|
||||||
|
|
||||||
const { beforeEditSubmit, columns } = unref(getBindValues);
|
const { beforeEditSubmit, columns } = unref(getBindValues)
|
||||||
|
|
||||||
if (beforeEditSubmit && isFunction(beforeEditSubmit)) {
|
if (beforeEditSubmit && isFunction(beforeEditSubmit)) {
|
||||||
spinning.value = true;
|
spinning.value = true
|
||||||
const keys: string[] = columns
|
const keys: string[] = columns
|
||||||
.map((_column) => _column.dataIndex)
|
.map((_column) => _column.dataIndex)
|
||||||
.filter((field) => !!field) as string[];
|
.filter((field) => !!field) as string[]
|
||||||
let result: any = true;
|
let result: any = true
|
||||||
try {
|
try {
|
||||||
result = await beforeEditSubmit({
|
result = await beforeEditSubmit({
|
||||||
record: pick(record, keys),
|
record: pick(record, keys),
|
||||||
index,
|
index,
|
||||||
key: dataKey as string,
|
key: dataKey as string,
|
||||||
value,
|
value,
|
||||||
});
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
result = false;
|
result = false
|
||||||
} finally {
|
} finally {
|
||||||
spinning.value = false;
|
spinning.value = false
|
||||||
}
|
}
|
||||||
if (result === false) {
|
if (result === false) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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: dataKey, value });
|
needEmit && table.emit?.('edit-end', { record, index, key: dataKey, value })
|
||||||
isEdit.value = false;
|
isEdit.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleEnter() {
|
async function handleEnter() {
|
||||||
if (props.column?.editRow) {
|
if (props.column?.editRow) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
handleSubmit();
|
handleSubmit()
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSubmitClick() {
|
function handleSubmitClick() {
|
||||||
handleSubmit();
|
handleSubmit()
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleCancel() {
|
function handleCancel() {
|
||||||
isEdit.value = false;
|
isEdit.value = false
|
||||||
currentValueRef.value = defaultValueRef.value;
|
currentValueRef.value = defaultValueRef.value
|
||||||
const { column, index, record } = props;
|
const { column, index, record } = props
|
||||||
const { key, dataIndex } = column;
|
const { key, dataIndex } = column
|
||||||
table.emit?.('edit-cancel', {
|
table.emit?.('edit-cancel', {
|
||||||
record,
|
record,
|
||||||
index,
|
index,
|
||||||
key: dataIndex || key,
|
key: dataIndex || key,
|
||||||
value: unref(currentValueRef),
|
value: unref(currentValueRef),
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function onClickOutside() {
|
function onClickOutside() {
|
||||||
if (props.column?.editable || unref(getRowEditable)) {
|
if (props.column?.editable || unref(getRowEditable)) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
const component = unref(getComponent);
|
const component = unref(getComponent)
|
||||||
|
|
||||||
if (component.includes('Input')) {
|
if (component.includes('Input')) {
|
||||||
handleCancel();
|
handleCancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// only ApiSelect or TreeSelect
|
// only ApiSelect or TreeSelect
|
||||||
function handleOptionsChange(options: LabelValueOptions) {
|
function handleOptionsChange(options: LabelValueOptions) {
|
||||||
const { replaceFields } = unref(getComponentProps);
|
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 || {}
|
||||||
let listOptions: Recordable[] = treeToList(options, { children });
|
let listOptions: Recordable[] = treeToList(options, { children })
|
||||||
listOptions = listOptions.map((item) => {
|
listOptions = listOptions.map((item) => {
|
||||||
return {
|
return {
|
||||||
label: item[title],
|
label: item[title],
|
||||||
value: item[value],
|
value: item[value],
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
optionsRef.value = listOptions as LabelValueOptions;
|
optionsRef.value = listOptions as LabelValueOptions
|
||||||
} else {
|
} else {
|
||||||
optionsRef.value = options;
|
optionsRef.value = options
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
import { ComponentType } from '../../types/componentType';
|
import { ComponentType } from '../../types/componentType'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description: 生成placeholder
|
* @description: 生成placeholder
|
||||||
*/
|
*/
|
||||||
export function createPlaceholderMessage(component: ComponentType) {
|
export function createPlaceholderMessage(component: ComponentType) {
|
||||||
if (component.includes('Input') || component.includes('AutoComplete')) {
|
if (component.includes('Input') || component.includes('AutoComplete')) {
|
||||||
return t('common.inputText');
|
return t('common.inputText')
|
||||||
}
|
}
|
||||||
if (component.includes('Picker')) {
|
if (component.includes('Picker')) {
|
||||||
return t('common.chooseText');
|
return t('common.chooseText')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|
@ -22,7 +22,7 @@ export function createPlaceholderMessage(component: ComponentType) {
|
||||||
component.includes('DatePicker') ||
|
component.includes('DatePicker') ||
|
||||||
component.includes('TimePicker')
|
component.includes('TimePicker')
|
||||||
) {
|
) {
|
||||||
return t('common.chooseText');
|
return t('common.chooseText')
|
||||||
}
|
}
|
||||||
return '';
|
return ''
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { BasicColumn, ColumnChangeParam } from '../../types/table';
|
import type { BasicColumn, ColumnChangeParam } from '../../types/table'
|
||||||
import {
|
import {
|
||||||
defineComponent,
|
defineComponent,
|
||||||
ref,
|
ref,
|
||||||
|
|
@ -109,33 +109,33 @@
|
||||||
nextTick,
|
nextTick,
|
||||||
unref,
|
unref,
|
||||||
computed,
|
computed,
|
||||||
} from 'vue';
|
} from 'vue'
|
||||||
import { Tooltip, Popover, Checkbox, Divider } from 'ant-design-vue';
|
import { Tooltip, Popover, Checkbox, Divider } from 'ant-design-vue'
|
||||||
import type { CheckboxChangeEvent } from 'ant-design-vue/lib/checkbox/interface';
|
import type { CheckboxChangeEvent } from 'ant-design-vue/lib/checkbox/interface'
|
||||||
import { SettingOutlined, DragOutlined } from '@ant-design/icons-vue';
|
import { SettingOutlined, DragOutlined } from '@ant-design/icons-vue'
|
||||||
import { Icon } from '/@/components/Icon';
|
import { Icon } from '/@/components/Icon'
|
||||||
import { ScrollContainer } from '/@/components/Container';
|
import { ScrollContainer } from '/@/components/Container'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
import { useTableContext } from '../../hooks/useTableContext';
|
import { useTableContext } from '../../hooks/useTableContext'
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
// import { useSortable } from '/@/hooks/web/useSortable';
|
// import { useSortable } from '/@/hooks/web/useSortable';
|
||||||
import { isFunction, isNullAndUnDef } from '/@/utils/is';
|
import { isFunction, isNullAndUnDef } from '/@/utils/is'
|
||||||
import { getPopupContainer as getParentContainer } from '/@/utils';
|
import { getPopupContainer as getParentContainer } from '/@/utils'
|
||||||
import { cloneDeep, omit } from 'lodash-es';
|
import { cloneDeep, omit } from 'lodash-es'
|
||||||
import Sortablejs from 'sortablejs';
|
import Sortablejs from 'sortablejs'
|
||||||
import type Sortable from 'sortablejs';
|
import type Sortable from 'sortablejs'
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
checkAll: boolean;
|
checkAll: boolean
|
||||||
isInit?: boolean;
|
isInit?: boolean
|
||||||
checkedList: string[];
|
checkedList: string[]
|
||||||
defaultCheckList: string[];
|
defaultCheckList: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Options {
|
interface Options {
|
||||||
label: string;
|
label: string
|
||||||
value: string;
|
value: string
|
||||||
fixed?: boolean | 'left' | 'right';
|
fixed?: boolean | 'left' | 'right'
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
|
@ -154,145 +154,145 @@
|
||||||
emits: ['columns-change'],
|
emits: ['columns-change'],
|
||||||
|
|
||||||
setup(_, { emit, attrs }) {
|
setup(_, { emit, attrs }) {
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
const table = useTableContext();
|
const table = useTableContext()
|
||||||
|
|
||||||
const defaultRowSelection = omit(table.getRowSelection(), 'selectedRowKeys');
|
const defaultRowSelection = omit(table.getRowSelection(), 'selectedRowKeys')
|
||||||
let inited = false;
|
let inited = false
|
||||||
|
|
||||||
const cachePlainOptions = ref<Options[]>([]);
|
const cachePlainOptions = ref<Options[]>([])
|
||||||
const plainOptions = ref<Options[] | any>([]);
|
const plainOptions = ref<Options[] | any>([])
|
||||||
|
|
||||||
const plainSortOptions = ref<Options[]>([]);
|
const plainSortOptions = ref<Options[]>([])
|
||||||
|
|
||||||
const columnListRef = ref<ComponentRef>(null);
|
const columnListRef = ref<ComponentRef>(null)
|
||||||
|
|
||||||
const state = reactive<State>({
|
const state = reactive<State>({
|
||||||
checkAll: true,
|
checkAll: true,
|
||||||
checkedList: [],
|
checkedList: [],
|
||||||
defaultCheckList: [],
|
defaultCheckList: [],
|
||||||
});
|
})
|
||||||
|
|
||||||
const checkIndex = ref(false);
|
const checkIndex = ref(false)
|
||||||
const checkSelect = ref(false);
|
const checkSelect = ref(false)
|
||||||
|
|
||||||
const { prefixCls } = useDesign('basic-column-setting');
|
const { prefixCls } = useDesign('basic-column-setting')
|
||||||
|
|
||||||
const getValues = computed(() => {
|
const getValues = computed(() => {
|
||||||
return unref(table?.getBindValues) || {};
|
return unref(table?.getBindValues) || {}
|
||||||
});
|
})
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const columns = table.getColumns();
|
const columns = table.getColumns()
|
||||||
if (columns.length && !state.isInit) {
|
if (columns.length && !state.isInit) {
|
||||||
init();
|
init()
|
||||||
}
|
}
|
||||||
}, 0);
|
}, 0)
|
||||||
});
|
})
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
const values = unref(getValues);
|
const values = unref(getValues)
|
||||||
checkIndex.value = !!values.showIndexColumn;
|
checkIndex.value = !!values.showIndexColumn
|
||||||
checkSelect.value = !!values.rowSelection;
|
checkSelect.value = !!values.rowSelection
|
||||||
});
|
})
|
||||||
|
|
||||||
function getColumns() {
|
function getColumns() {
|
||||||
const ret: Options[] = [];
|
const ret: Options[] = []
|
||||||
table.getColumns({ ignoreIndex: true, ignoreAction: true }).forEach((item) => {
|
table.getColumns({ ignoreIndex: true, ignoreAction: true }).forEach((item) => {
|
||||||
ret.push({
|
ret.push({
|
||||||
label: (item.title as string) || (item.customTitle as string),
|
label: (item.title as string) || (item.customTitle as string),
|
||||||
value: (item.dataIndex || item.title) as string,
|
value: (item.dataIndex || item.title) as string,
|
||||||
...item,
|
...item,
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
return ret;
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
const columns = getColumns();
|
const columns = getColumns()
|
||||||
|
|
||||||
const checkList = table
|
const checkList = table
|
||||||
.getColumns({ ignoreAction: true, ignoreIndex: true })
|
.getColumns({ ignoreAction: true, ignoreIndex: true })
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
if (item.defaultHidden) {
|
if (item.defaultHidden) {
|
||||||
return '';
|
return ''
|
||||||
}
|
}
|
||||||
return item.dataIndex || item.title;
|
return item.dataIndex || item.title
|
||||||
})
|
})
|
||||||
.filter(Boolean) as string[];
|
.filter(Boolean) as string[]
|
||||||
|
|
||||||
if (!plainOptions.value.length) {
|
if (!plainOptions.value.length) {
|
||||||
plainOptions.value = columns;
|
plainOptions.value = columns
|
||||||
plainSortOptions.value = columns;
|
plainSortOptions.value = columns
|
||||||
cachePlainOptions.value = columns;
|
cachePlainOptions.value = columns
|
||||||
state.defaultCheckList = checkList;
|
state.defaultCheckList = checkList
|
||||||
} else {
|
} else {
|
||||||
// const fixedColumns = columns.filter((item) =>
|
// const fixedColumns = columns.filter((item) =>
|
||||||
// Reflect.has(item, 'fixed')
|
// Reflect.has(item, 'fixed')
|
||||||
// ) as BasicColumn[];
|
// ) as BasicColumn[];
|
||||||
|
|
||||||
unref(plainOptions).forEach((item: BasicColumn) => {
|
unref(plainOptions).forEach((item: BasicColumn) => {
|
||||||
const findItem = columns.find((col: BasicColumn) => col.dataIndex === item.dataIndex);
|
const findItem = columns.find((col: BasicColumn) => col.dataIndex === item.dataIndex)
|
||||||
if (findItem) {
|
if (findItem) {
|
||||||
item.fixed = findItem.fixed;
|
item.fixed = findItem.fixed
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
state.isInit = true;
|
state.isInit = true
|
||||||
state.checkedList = checkList;
|
state.checkedList = checkList
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkAll change
|
// checkAll change
|
||||||
function onCheckAllChange(e: CheckboxChangeEvent) {
|
function onCheckAllChange(e: CheckboxChangeEvent) {
|
||||||
const checkList = plainOptions.value.map((item) => item.value);
|
const checkList = plainOptions.value.map((item) => item.value)
|
||||||
if (e.target.checked) {
|
if (e.target.checked) {
|
||||||
state.checkedList = checkList;
|
state.checkedList = checkList
|
||||||
setColumns(checkList);
|
setColumns(checkList)
|
||||||
} else {
|
} else {
|
||||||
state.checkedList = [];
|
state.checkedList = []
|
||||||
setColumns([]);
|
setColumns([])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const indeterminate = computed(() => {
|
const indeterminate = computed(() => {
|
||||||
const len = plainOptions.value.length;
|
const len = plainOptions.value.length
|
||||||
let checkedLen = state.checkedList.length;
|
let checkedLen = state.checkedList.length
|
||||||
// unref(checkIndex) && checkedLen--;
|
// unref(checkIndex) && checkedLen--;
|
||||||
return checkedLen > 0 && checkedLen < len;
|
return checkedLen > 0 && checkedLen < len
|
||||||
});
|
})
|
||||||
|
|
||||||
// Trigger when check/uncheck a column
|
// Trigger when check/uncheck a column
|
||||||
function onChange(checkedList: string[]) {
|
function onChange(checkedList: string[]) {
|
||||||
const len = plainSortOptions.value.length;
|
const len = plainSortOptions.value.length
|
||||||
state.checkAll = checkedList.length === len;
|
state.checkAll = checkedList.length === len
|
||||||
const sortList = unref(plainSortOptions).map((item) => item.value);
|
const sortList = unref(plainSortOptions).map((item) => item.value)
|
||||||
checkedList.sort((prev, next) => {
|
checkedList.sort((prev, next) => {
|
||||||
return sortList.indexOf(prev) - sortList.indexOf(next);
|
return sortList.indexOf(prev) - sortList.indexOf(next)
|
||||||
});
|
})
|
||||||
setColumns(checkedList);
|
setColumns(checkedList)
|
||||||
}
|
}
|
||||||
|
|
||||||
let sortable: Sortable;
|
let sortable: Sortable
|
||||||
let sortableOrder: string[] = [];
|
let sortableOrder: string[] = []
|
||||||
// reset columns
|
// reset columns
|
||||||
function reset() {
|
function reset() {
|
||||||
state.checkedList = [...state.defaultCheckList];
|
state.checkedList = [...state.defaultCheckList]
|
||||||
state.checkAll = true;
|
state.checkAll = true
|
||||||
plainOptions.value = unref(cachePlainOptions);
|
plainOptions.value = unref(cachePlainOptions)
|
||||||
plainSortOptions.value = unref(cachePlainOptions);
|
plainSortOptions.value = unref(cachePlainOptions)
|
||||||
setColumns(table.getCacheColumns());
|
setColumns(table.getCacheColumns())
|
||||||
sortable.sort(sortableOrder);
|
sortable.sort(sortableOrder)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open the pop-up window for drag and drop initialization
|
// Open the pop-up window for drag and drop initialization
|
||||||
function handleVisibleChange() {
|
function handleVisibleChange() {
|
||||||
if (inited) return;
|
if (inited) return
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const columnListEl = unref(columnListRef);
|
const columnListEl = unref(columnListRef)
|
||||||
if (!columnListEl) return;
|
if (!columnListEl) return
|
||||||
const el = columnListEl.$el as any;
|
const el = columnListEl.$el as any
|
||||||
if (!el) return;
|
if (!el) return
|
||||||
// Drag and drop sort
|
// Drag and drop sort
|
||||||
sortable = Sortablejs.create(unref(el), {
|
sortable = Sortablejs.create(unref(el), {
|
||||||
animation: 500,
|
animation: 500,
|
||||||
|
|
@ -300,86 +300,86 @@
|
||||||
delayOnTouchOnly: true,
|
delayOnTouchOnly: true,
|
||||||
handle: '.table-column-drag-icon ',
|
handle: '.table-column-drag-icon ',
|
||||||
onEnd: (evt) => {
|
onEnd: (evt) => {
|
||||||
const { oldIndex, newIndex } = evt;
|
const { oldIndex, newIndex } = evt
|
||||||
if (isNullAndUnDef(oldIndex) || isNullAndUnDef(newIndex) || oldIndex === newIndex) {
|
if (isNullAndUnDef(oldIndex) || isNullAndUnDef(newIndex) || oldIndex === newIndex) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
// Sort column
|
// Sort column
|
||||||
const columns = cloneDeep(plainSortOptions.value);
|
const columns = cloneDeep(plainSortOptions.value)
|
||||||
|
|
||||||
if (oldIndex > newIndex) {
|
if (oldIndex > newIndex) {
|
||||||
columns.splice(newIndex, 0, columns[oldIndex]);
|
columns.splice(newIndex, 0, columns[oldIndex])
|
||||||
columns.splice(oldIndex + 1, 1);
|
columns.splice(oldIndex + 1, 1)
|
||||||
} else {
|
} else {
|
||||||
columns.splice(newIndex + 1, 0, columns[oldIndex]);
|
columns.splice(newIndex + 1, 0, columns[oldIndex])
|
||||||
columns.splice(oldIndex, 1);
|
columns.splice(oldIndex, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
plainSortOptions.value = columns;
|
plainSortOptions.value = columns
|
||||||
|
|
||||||
setColumns(
|
setColumns(
|
||||||
columns
|
columns
|
||||||
.map((col: Options) => col.value)
|
.map((col: Options) => col.value)
|
||||||
.filter((value: string) => state.checkedList.includes(value)),
|
.filter((value: string) => state.checkedList.includes(value)),
|
||||||
);
|
)
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
// 记录原始order 序列
|
// 记录原始order 序列
|
||||||
sortableOrder = sortable.toArray();
|
sortableOrder = sortable.toArray()
|
||||||
inited = true;
|
inited = true
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Control whether the serial number column is displayed
|
// Control whether the serial number column is displayed
|
||||||
function handleIndexCheckChange(e: CheckboxChangeEvent) {
|
function handleIndexCheckChange(e: CheckboxChangeEvent) {
|
||||||
table.setProps({
|
table.setProps({
|
||||||
showIndexColumn: e.target.checked,
|
showIndexColumn: e.target.checked,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Control whether the check box is displayed
|
// Control whether the check box is displayed
|
||||||
function handleSelectCheckChange(e: CheckboxChangeEvent) {
|
function handleSelectCheckChange(e: CheckboxChangeEvent) {
|
||||||
table.setProps({
|
table.setProps({
|
||||||
rowSelection: e.target.checked ? defaultRowSelection : undefined,
|
rowSelection: e.target.checked ? defaultRowSelection : undefined,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleColumnFixed(item: BasicColumn, fixed?: 'left' | 'right') {
|
function handleColumnFixed(item: BasicColumn, fixed?: 'left' | 'right') {
|
||||||
if (!state.checkedList.includes(item.dataIndex as string)) return;
|
if (!state.checkedList.includes(item.dataIndex as string)) return
|
||||||
|
|
||||||
const columns = getColumns() as BasicColumn[];
|
const columns = getColumns() as BasicColumn[]
|
||||||
const isFixed = item.fixed === fixed ? false : fixed;
|
const isFixed = item.fixed === fixed ? false : fixed
|
||||||
const index = columns.findIndex((col) => col.dataIndex === item.dataIndex);
|
const index = columns.findIndex((col) => col.dataIndex === item.dataIndex)
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
columns[index].fixed = isFixed;
|
columns[index].fixed = isFixed
|
||||||
}
|
}
|
||||||
item.fixed = isFixed;
|
item.fixed = isFixed
|
||||||
|
|
||||||
if (isFixed && !item.width) {
|
if (isFixed && !item.width) {
|
||||||
item.width = 100;
|
item.width = 100
|
||||||
}
|
}
|
||||||
table.setCacheColumnsByField?.(item.dataIndex as string, { fixed: isFixed });
|
table.setCacheColumnsByField?.(item.dataIndex as string, { fixed: isFixed })
|
||||||
setColumns(columns);
|
setColumns(columns)
|
||||||
}
|
}
|
||||||
|
|
||||||
function setColumns(columns: BasicColumn[] | string[]) {
|
function setColumns(columns: BasicColumn[] | string[]) {
|
||||||
table.setColumns(columns);
|
table.setColumns(columns)
|
||||||
const data: ColumnChangeParam[] = unref(plainSortOptions).map((col) => {
|
const data: ColumnChangeParam[] = unref(plainSortOptions).map((col) => {
|
||||||
const visible =
|
const visible =
|
||||||
columns.findIndex(
|
columns.findIndex(
|
||||||
(c: BasicColumn | string) =>
|
(c: BasicColumn | string) =>
|
||||||
c === col.value || (typeof c !== 'string' && c.dataIndex === col.value),
|
c === col.value || (typeof c !== 'string' && c.dataIndex === col.value),
|
||||||
) !== -1;
|
) !== -1
|
||||||
return { dataIndex: col.value, fixed: col.fixed, visible };
|
return { dataIndex: col.value, fixed: col.fixed, visible }
|
||||||
});
|
})
|
||||||
|
|
||||||
emit('columns-change', data);
|
emit('columns-change', data)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPopupContainer() {
|
function getPopupContainer() {
|
||||||
return isFunction(attrs.getPopupContainer)
|
return isFunction(attrs.getPopupContainer)
|
||||||
? attrs.getPopupContainer()
|
? attrs.getPopupContainer()
|
||||||
: getParentContainer();
|
: getParentContainer()
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -400,9 +400,9 @@
|
||||||
defaultRowSelection,
|
defaultRowSelection,
|
||||||
handleColumnFixed,
|
handleColumnFixed,
|
||||||
getPopupContainer,
|
getPopupContainer,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@prefix-cls: ~'@{namespace}-basic-column-setting';
|
@prefix-cls: ~'@{namespace}-basic-column-setting';
|
||||||
|
|
|
||||||
|
|
@ -23,13 +23,13 @@
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { SizeType } from '../../types/table';
|
import type { SizeType } from '../../types/table'
|
||||||
import { defineComponent, ref } from 'vue';
|
import { defineComponent, ref } from 'vue'
|
||||||
import { Tooltip, Dropdown, Menu } from 'ant-design-vue';
|
import { Tooltip, Dropdown, Menu } from 'ant-design-vue'
|
||||||
import { ColumnHeightOutlined } from '@ant-design/icons-vue';
|
import { ColumnHeightOutlined } from '@ant-design/icons-vue'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
import { useTableContext } from '../../hooks/useTableContext';
|
import { useTableContext } from '../../hooks/useTableContext'
|
||||||
import { getPopupContainer } from '/@/utils';
|
import { getPopupContainer } from '/@/utils'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'SizeSetting',
|
name: 'SizeSetting',
|
||||||
|
|
@ -41,16 +41,16 @@
|
||||||
MenuItem: Menu.Item,
|
MenuItem: Menu.Item,
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const table = useTableContext();
|
const table = useTableContext()
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
|
|
||||||
const selectedKeysRef = ref<SizeType[]>([table.getSize()]);
|
const selectedKeysRef = ref<SizeType[]>([table.getSize()])
|
||||||
|
|
||||||
function handleTitleClick({ key }: { key: SizeType }) {
|
function handleTitleClick({ key }: { key: SizeType }) {
|
||||||
selectedKeysRef.value = [key];
|
selectedKeysRef.value = [key]
|
||||||
table.setProps({
|
table.setProps({
|
||||||
size: key,
|
size: key,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -58,7 +58,7 @@
|
||||||
selectedKeysRef,
|
selectedKeysRef,
|
||||||
getPopupContainer,
|
getPopupContainer,
|
||||||
t,
|
t,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,40 +1,40 @@
|
||||||
import type { BasicColumn, BasicTableProps, CellFormat, GetColumnsParams } from '../types/table';
|
import type { BasicColumn, BasicTableProps, CellFormat, GetColumnsParams } from '../types/table'
|
||||||
import type { PaginationProps } from '../types/pagination';
|
import type { PaginationProps } from '../types/pagination'
|
||||||
import type { ComputedRef } from 'vue';
|
import type { ComputedRef } from 'vue'
|
||||||
import { computed, Ref, ref, reactive, toRaw, unref, watch } from 'vue';
|
import { computed, Ref, ref, reactive, toRaw, unref, watch } from 'vue'
|
||||||
import { renderEditCell } from '../components/editable';
|
import { renderEditCell } from '../components/editable'
|
||||||
import { usePermission } from '/@/hooks/web/usePermission';
|
import { usePermission } from '/@/hooks/web/usePermission'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
import { isArray, isBoolean, isFunction, isMap, isString } from '/@/utils/is';
|
import { isArray, isBoolean, isFunction, isMap, isString } from '/@/utils/is'
|
||||||
import { cloneDeep, isEqual } from 'lodash-es';
|
import { cloneDeep, isEqual } from 'lodash-es'
|
||||||
import { formatToDate } from '/@/utils/dateUtil';
|
import { formatToDate } from '/@/utils/dateUtil'
|
||||||
import { ACTION_COLUMN_FLAG, DEFAULT_ALIGN, INDEX_COLUMN_FLAG, PAGE_SIZE } from '../const';
|
import { ACTION_COLUMN_FLAG, DEFAULT_ALIGN, INDEX_COLUMN_FLAG, PAGE_SIZE } from '../const'
|
||||||
|
|
||||||
function handleItem(item: BasicColumn, ellipsis: boolean) {
|
function handleItem(item: BasicColumn, ellipsis: boolean) {
|
||||||
const { key, dataIndex, children } = item;
|
const { key, dataIndex, children } = item
|
||||||
item.align = item.align || DEFAULT_ALIGN;
|
item.align = item.align || DEFAULT_ALIGN
|
||||||
if (ellipsis) {
|
if (ellipsis) {
|
||||||
if (!key) {
|
if (!key) {
|
||||||
item.key = dataIndex;
|
item.key = dataIndex
|
||||||
}
|
}
|
||||||
if (!isBoolean(item.ellipsis)) {
|
if (!isBoolean(item.ellipsis)) {
|
||||||
Object.assign(item, {
|
Object.assign(item, {
|
||||||
ellipsis,
|
ellipsis,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (children && children.length) {
|
if (children && children.length) {
|
||||||
handleChildren(children, !!ellipsis);
|
handleChildren(children, !!ellipsis)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleChildren(children: BasicColumn[] | undefined, ellipsis: boolean) {
|
function handleChildren(children: BasicColumn[] | undefined, ellipsis: boolean) {
|
||||||
if (!children) return;
|
if (!children) return
|
||||||
children.forEach((item) => {
|
children.forEach((item) => {
|
||||||
const { children } = item;
|
const { children } = item
|
||||||
handleItem(item, ellipsis);
|
handleItem(item, ellipsis)
|
||||||
handleChildren(children, ellipsis);
|
handleChildren(children, ellipsis)
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleIndexColumn(
|
function handleIndexColumn(
|
||||||
|
|
@ -42,26 +42,26 @@ function handleIndexColumn(
|
||||||
getPaginationRef: ComputedRef<boolean | PaginationProps>,
|
getPaginationRef: ComputedRef<boolean | PaginationProps>,
|
||||||
columns: BasicColumn[],
|
columns: BasicColumn[],
|
||||||
) {
|
) {
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
|
|
||||||
const { showIndexColumn, indexColumnProps, isTreeTable } = unref(propsRef);
|
const { showIndexColumn, indexColumnProps, isTreeTable } = unref(propsRef)
|
||||||
|
|
||||||
let pushIndexColumns = false;
|
let pushIndexColumns = false
|
||||||
if (unref(isTreeTable)) {
|
if (unref(isTreeTable)) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
columns.forEach(() => {
|
columns.forEach(() => {
|
||||||
const indIndex = columns.findIndex((column) => column.flag === INDEX_COLUMN_FLAG);
|
const indIndex = columns.findIndex((column) => column.flag === INDEX_COLUMN_FLAG)
|
||||||
if (showIndexColumn) {
|
if (showIndexColumn) {
|
||||||
pushIndexColumns = indIndex === -1;
|
pushIndexColumns = indIndex === -1
|
||||||
} else if (!showIndexColumn && indIndex !== -1) {
|
} else if (!showIndexColumn && indIndex !== -1) {
|
||||||
columns.splice(indIndex, 1);
|
columns.splice(indIndex, 1)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
if (!pushIndexColumns) return;
|
if (!pushIndexColumns) return
|
||||||
|
|
||||||
const isFixedLeft = columns.some((item) => item.fixed === 'left');
|
const isFixedLeft = columns.some((item) => item.fixed === 'left')
|
||||||
|
|
||||||
columns.unshift({
|
columns.unshift({
|
||||||
flag: INDEX_COLUMN_FLAG,
|
flag: INDEX_COLUMN_FLAG,
|
||||||
|
|
@ -69,12 +69,12 @@ function handleIndexColumn(
|
||||||
title: t('component.table.index'),
|
title: t('component.table.index'),
|
||||||
align: 'center',
|
align: 'center',
|
||||||
customRender: ({ index }) => {
|
customRender: ({ index }) => {
|
||||||
const getPagination = unref(getPaginationRef);
|
const getPagination = unref(getPaginationRef)
|
||||||
if (isBoolean(getPagination)) {
|
if (isBoolean(getPagination)) {
|
||||||
return `${index + 1}`;
|
return `${index + 1}`
|
||||||
}
|
}
|
||||||
const { current = 1, pageSize = PAGE_SIZE } = getPagination;
|
const { current = 1, pageSize = PAGE_SIZE } = getPagination
|
||||||
return ((current < 1 ? 1 : current) - 1) * pageSize + index + 1;
|
return ((current < 1 ? 1 : current) - 1) * pageSize + index + 1
|
||||||
},
|
},
|
||||||
...(isFixedLeft
|
...(isFixedLeft
|
||||||
? {
|
? {
|
||||||
|
|
@ -82,21 +82,21 @@ function handleIndexColumn(
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
...indexColumnProps,
|
...indexColumnProps,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleActionColumn(propsRef: ComputedRef<BasicTableProps>, columns: BasicColumn[]) {
|
function handleActionColumn(propsRef: ComputedRef<BasicTableProps>, columns: BasicColumn[]) {
|
||||||
const { actionColumn } = unref(propsRef);
|
const { actionColumn } = unref(propsRef)
|
||||||
if (!actionColumn) return;
|
if (!actionColumn) return
|
||||||
|
|
||||||
const hasIndex = columns.findIndex((column) => column.flag === ACTION_COLUMN_FLAG);
|
const hasIndex = columns.findIndex((column) => column.flag === ACTION_COLUMN_FLAG)
|
||||||
if (hasIndex === -1) {
|
if (hasIndex === -1) {
|
||||||
columns.push({
|
columns.push({
|
||||||
...columns[hasIndex],
|
...columns[hasIndex],
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
...actionColumn,
|
...actionColumn,
|
||||||
flag: ACTION_COLUMN_FLAG,
|
flag: ACTION_COLUMN_FLAG,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,154 +104,154 @@ export function useColumns(
|
||||||
propsRef: ComputedRef<BasicTableProps>,
|
propsRef: ComputedRef<BasicTableProps>,
|
||||||
getPaginationRef: ComputedRef<boolean | PaginationProps>,
|
getPaginationRef: ComputedRef<boolean | PaginationProps>,
|
||||||
) {
|
) {
|
||||||
const columnsRef = ref(unref(propsRef).columns) as unknown as Ref<BasicColumn[]>;
|
const columnsRef = ref(unref(propsRef).columns) as unknown as Ref<BasicColumn[]>
|
||||||
let cacheColumns = unref(propsRef).columns;
|
let cacheColumns = unref(propsRef).columns
|
||||||
|
|
||||||
const getColumnsRef = computed(() => {
|
const getColumnsRef = computed(() => {
|
||||||
const columns = cloneDeep(unref(columnsRef));
|
const columns = cloneDeep(unref(columnsRef))
|
||||||
|
|
||||||
handleIndexColumn(propsRef, getPaginationRef, columns);
|
handleIndexColumn(propsRef, getPaginationRef, columns)
|
||||||
handleActionColumn(propsRef, columns);
|
handleActionColumn(propsRef, columns)
|
||||||
if (!columns) {
|
if (!columns) {
|
||||||
return [];
|
return []
|
||||||
}
|
}
|
||||||
const { ellipsis } = unref(propsRef);
|
const { ellipsis } = unref(propsRef)
|
||||||
|
|
||||||
columns.forEach((item) => {
|
columns.forEach((item) => {
|
||||||
const { customRender, slots } = item;
|
const { customRender, slots } = item
|
||||||
|
|
||||||
handleItem(
|
handleItem(
|
||||||
item,
|
item,
|
||||||
Reflect.has(item, 'ellipsis') ? !!item.ellipsis : !!ellipsis && !customRender && !slots,
|
Reflect.has(item, 'ellipsis') ? !!item.ellipsis : !!ellipsis && !customRender && !slots,
|
||||||
);
|
)
|
||||||
});
|
})
|
||||||
return columns;
|
return columns
|
||||||
});
|
})
|
||||||
|
|
||||||
function isIfShow(column: BasicColumn): boolean {
|
function isIfShow(column: BasicColumn): boolean {
|
||||||
const ifShow = column.ifShow;
|
const ifShow = column.ifShow
|
||||||
|
|
||||||
let isIfShow = true;
|
let isIfShow = true
|
||||||
|
|
||||||
if (isBoolean(ifShow)) {
|
if (isBoolean(ifShow)) {
|
||||||
isIfShow = ifShow;
|
isIfShow = ifShow
|
||||||
}
|
}
|
||||||
if (isFunction(ifShow)) {
|
if (isFunction(ifShow)) {
|
||||||
isIfShow = ifShow(column);
|
isIfShow = ifShow(column)
|
||||||
}
|
}
|
||||||
return isIfShow;
|
return isIfShow
|
||||||
}
|
}
|
||||||
const { hasPermission } = usePermission();
|
const { hasPermission } = usePermission()
|
||||||
|
|
||||||
const getViewColumns = computed(() => {
|
const getViewColumns = computed(() => {
|
||||||
const viewColumns = sortFixedColumn(unref(getColumnsRef));
|
const viewColumns = sortFixedColumn(unref(getColumnsRef))
|
||||||
|
|
||||||
const columns = cloneDeep(viewColumns);
|
const columns = cloneDeep(viewColumns)
|
||||||
return columns
|
return columns
|
||||||
.filter((column) => {
|
.filter((column) => {
|
||||||
return hasPermission(column.auth) && isIfShow(column);
|
return hasPermission(column.auth) && isIfShow(column)
|
||||||
})
|
})
|
||||||
.map((column) => {
|
.map((column) => {
|
||||||
const { slots, 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')
|
||||||
}
|
}
|
||||||
const isDefaultAction = [INDEX_COLUMN_FLAG, ACTION_COLUMN_FLAG].includes(flag!);
|
const isDefaultAction = [INDEX_COLUMN_FLAG, ACTION_COLUMN_FLAG].includes(flag!)
|
||||||
if (!customRender && format && !edit && !isDefaultAction) {
|
if (!customRender && format && !edit && !isDefaultAction) {
|
||||||
column.customRender = ({ text, record, index }) => {
|
column.customRender = ({ text, record, index }) => {
|
||||||
return formatCell(text, format, record, index);
|
return formatCell(text, format, record, index)
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// edit table
|
// edit table
|
||||||
if ((edit || editRow) && !isDefaultAction) {
|
if ((edit || editRow) && !isDefaultAction) {
|
||||||
column.customRender = renderEditCell(column);
|
column.customRender = renderEditCell(column)
|
||||||
}
|
}
|
||||||
return reactive(column);
|
return reactive(column)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => unref(propsRef).columns,
|
() => unref(propsRef).columns,
|
||||||
(columns) => {
|
(columns) => {
|
||||||
columnsRef.value = columns;
|
columnsRef.value = columns
|
||||||
cacheColumns = columns?.filter((item) => !item.flag) ?? [];
|
cacheColumns = columns?.filter((item) => !item.flag) ?? []
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
|
|
||||||
function setCacheColumnsByField(dataIndex: string | undefined, value: Partial<BasicColumn>) {
|
function setCacheColumnsByField(dataIndex: string | undefined, value: Partial<BasicColumn>) {
|
||||||
if (!dataIndex || !value) {
|
if (!dataIndex || !value) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
cacheColumns.forEach((item) => {
|
cacheColumns.forEach((item) => {
|
||||||
if (item.dataIndex === dataIndex) {
|
if (item.dataIndex === dataIndex) {
|
||||||
Object.assign(item, value);
|
Object.assign(item, value)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* set columns
|
* set columns
|
||||||
* @param columnList key|column
|
* @param columnList key|column
|
||||||
*/
|
*/
|
||||||
function setColumns(columnList: Partial<BasicColumn>[] | (string | string[])[]) {
|
function setColumns(columnList: Partial<BasicColumn>[] | (string | string[])[]) {
|
||||||
const columns = cloneDeep(columnList);
|
const columns = cloneDeep(columnList)
|
||||||
if (!isArray(columns)) return;
|
if (!isArray(columns)) return
|
||||||
|
|
||||||
if (columns.length <= 0) {
|
if (columns.length <= 0) {
|
||||||
columnsRef.value = [];
|
columnsRef.value = []
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const firstColumn = columns[0];
|
const firstColumn = columns[0]
|
||||||
|
|
||||||
const cacheKeys = cacheColumns.map((item) => item.dataIndex);
|
const cacheKeys = cacheColumns.map((item) => item.dataIndex)
|
||||||
|
|
||||||
if (!isString(firstColumn) && !isArray(firstColumn)) {
|
if (!isString(firstColumn) && !isArray(firstColumn)) {
|
||||||
columnsRef.value = columns as BasicColumn[];
|
columnsRef.value = columns as BasicColumn[]
|
||||||
} else {
|
} else {
|
||||||
const columnKeys = (columns as (string | string[])[]).map((m) => m.toString());
|
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?.toString() || (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?.toString() as string) -
|
columnKeys.indexOf(prev.dataIndex?.toString() as string) -
|
||||||
columnKeys.indexOf(next.dataIndex?.toString() as string)
|
columnKeys.indexOf(next.dataIndex?.toString() as string)
|
||||||
);
|
)
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
columnsRef.value = newColumns;
|
columnsRef.value = newColumns
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getColumns(opt?: GetColumnsParams) {
|
function getColumns(opt?: GetColumnsParams) {
|
||||||
const { ignoreIndex, ignoreAction, sort } = opt || {};
|
const { ignoreIndex, ignoreAction, sort } = opt || {}
|
||||||
let columns = toRaw(unref(getColumnsRef));
|
let columns = toRaw(unref(getColumnsRef))
|
||||||
if (ignoreIndex) {
|
if (ignoreIndex) {
|
||||||
columns = columns.filter((item) => item.flag !== INDEX_COLUMN_FLAG);
|
columns = columns.filter((item) => item.flag !== INDEX_COLUMN_FLAG)
|
||||||
}
|
}
|
||||||
if (ignoreAction) {
|
if (ignoreAction) {
|
||||||
columns = columns.filter((item) => item.flag !== ACTION_COLUMN_FLAG);
|
columns = columns.filter((item) => item.flag !== ACTION_COLUMN_FLAG)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sort) {
|
if (sort) {
|
||||||
columns = sortFixedColumn(columns);
|
columns = sortFixedColumn(columns)
|
||||||
}
|
}
|
||||||
|
|
||||||
return columns;
|
return columns
|
||||||
}
|
}
|
||||||
function getCacheColumns() {
|
function getCacheColumns() {
|
||||||
return cacheColumns;
|
return cacheColumns
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -261,57 +261,57 @@ export function useColumns(
|
||||||
setColumns,
|
setColumns,
|
||||||
getViewColumns,
|
getViewColumns,
|
||||||
setCacheColumnsByField,
|
setCacheColumnsByField,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function sortFixedColumn(columns: BasicColumn[]) {
|
function sortFixedColumn(columns: BasicColumn[]) {
|
||||||
const fixedLeftColumns: BasicColumn[] = [];
|
const fixedLeftColumns: BasicColumn[] = []
|
||||||
const fixedRightColumns: BasicColumn[] = [];
|
const fixedRightColumns: BasicColumn[] = []
|
||||||
const defColumns: BasicColumn[] = [];
|
const defColumns: BasicColumn[] = []
|
||||||
for (const column of columns) {
|
for (const column of columns) {
|
||||||
if (column.fixed === 'left') {
|
if (column.fixed === 'left') {
|
||||||
fixedLeftColumns.push(column);
|
fixedLeftColumns.push(column)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
if (column.fixed === 'right') {
|
if (column.fixed === 'right') {
|
||||||
fixedRightColumns.push(column);
|
fixedRightColumns.push(column)
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
defColumns.push(column);
|
defColumns.push(column)
|
||||||
}
|
}
|
||||||
return [...fixedLeftColumns, ...defColumns, ...fixedRightColumns].filter(
|
return [...fixedLeftColumns, ...defColumns, ...fixedRightColumns].filter(
|
||||||
(item) => !item.defaultHidden,
|
(item) => !item.defaultHidden,
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// format cell
|
// format cell
|
||||||
export function formatCell(text: string, format: CellFormat, record: Recordable, index: number) {
|
export function formatCell(text: string, format: CellFormat, record: Recordable, index: number) {
|
||||||
if (!format) {
|
if (!format) {
|
||||||
return text;
|
return text
|
||||||
}
|
}
|
||||||
|
|
||||||
// custom function
|
// custom function
|
||||||
if (isFunction(format)) {
|
if (isFunction(format)) {
|
||||||
return format(text, record, index);
|
return format(text, record, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// date type
|
// date type
|
||||||
const DATE_FORMAT_PREFIX = 'date|';
|
const DATE_FORMAT_PREFIX = 'date|'
|
||||||
if (isString(format) && format.startsWith(DATE_FORMAT_PREFIX) && text) {
|
if (isString(format) && format.startsWith(DATE_FORMAT_PREFIX) && text) {
|
||||||
const dateFormat = format.replace(DATE_FORMAT_PREFIX, '');
|
const dateFormat = format.replace(DATE_FORMAT_PREFIX, '')
|
||||||
|
|
||||||
if (!dateFormat) {
|
if (!dateFormat) {
|
||||||
return text;
|
return text
|
||||||
}
|
}
|
||||||
return formatToDate(text, dateFormat);
|
return formatToDate(text, dateFormat)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map
|
// Map
|
||||||
if (isMap(format)) {
|
if (isMap(format)) {
|
||||||
return format.get(text);
|
return format.get(text)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return text;
|
return text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import type { BasicTableProps, FetchParams, SorterResult } from '../types/table';
|
import type { BasicTableProps, FetchParams, SorterResult } from '../types/table'
|
||||||
import type { PaginationProps } from '../types/pagination';
|
import type { PaginationProps } from '../types/pagination'
|
||||||
import {
|
import {
|
||||||
ref,
|
ref,
|
||||||
unref,
|
unref,
|
||||||
|
|
@ -10,25 +10,25 @@ import {
|
||||||
reactive,
|
reactive,
|
||||||
Ref,
|
Ref,
|
||||||
watchEffect,
|
watchEffect,
|
||||||
} from 'vue';
|
} from 'vue'
|
||||||
import { useTimeoutFn } from '/@/hooks/core/useTimeout';
|
import { useTimeoutFn } from '/@/hooks/core/useTimeout'
|
||||||
import { buildUUID } from '/@/utils/uuid';
|
import { buildUUID } from '/@/utils/uuid'
|
||||||
import { isFunction, isBoolean } from '/@/utils/is';
|
import { isFunction, isBoolean } from '/@/utils/is'
|
||||||
import { get, cloneDeep, merge } from 'lodash-es';
|
import { get, cloneDeep, merge } from 'lodash-es'
|
||||||
import { FETCH_SETTING, ROW_KEY, PAGE_SIZE } from '../const';
|
import { FETCH_SETTING, ROW_KEY, PAGE_SIZE } from '../const'
|
||||||
|
|
||||||
interface ActionType {
|
interface ActionType {
|
||||||
getPaginationInfo: ComputedRef<boolean | PaginationProps>;
|
getPaginationInfo: ComputedRef<boolean | PaginationProps>
|
||||||
setPagination: (info: Partial<PaginationProps>) => void;
|
setPagination: (info: Partial<PaginationProps>) => void
|
||||||
setLoading: (loading: boolean) => void;
|
setLoading: (loading: boolean) => void
|
||||||
getFieldsValue: () => Recordable;
|
getFieldsValue: () => Recordable
|
||||||
clearSelectedRowKeys: () => void;
|
clearSelectedRowKeys: () => void
|
||||||
tableData: Ref<Recordable[]>;
|
tableData: Ref<Recordable[]>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SearchState {
|
interface SearchState {
|
||||||
sortInfo: Recordable;
|
sortInfo: Recordable
|
||||||
filterInfo: Record<string, string[]>;
|
filterInfo: Record<string, string[]>
|
||||||
}
|
}
|
||||||
export function useDataSource(
|
export function useDataSource(
|
||||||
propsRef: ComputedRef<BasicTableProps>,
|
propsRef: ComputedRef<BasicTableProps>,
|
||||||
|
|
@ -45,189 +45,188 @@ export function useDataSource(
|
||||||
const searchState = reactive<SearchState>({
|
const searchState = reactive<SearchState>({
|
||||||
sortInfo: {},
|
sortInfo: {},
|
||||||
filterInfo: {},
|
filterInfo: {},
|
||||||
});
|
})
|
||||||
const dataSourceRef = ref<Recordable[]>([]);
|
const dataSourceRef = ref<Recordable[]>([])
|
||||||
const rawDataSourceRef = ref<Recordable>({});
|
const rawDataSourceRef = ref<Recordable>({})
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
tableData.value = unref(dataSourceRef);
|
tableData.value = unref(dataSourceRef)
|
||||||
});
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => unref(propsRef).dataSource,
|
() => unref(propsRef).dataSource,
|
||||||
() => {
|
() => {
|
||||||
const { dataSource, api } = unref(propsRef);
|
const { dataSource, api } = unref(propsRef)
|
||||||
!api && dataSource && (dataSourceRef.value = dataSource);
|
!api && dataSource && (dataSourceRef.value = dataSource)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
immediate: true,
|
immediate: true,
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
|
|
||||||
function handleTableChange(
|
function handleTableChange(
|
||||||
pagination: PaginationProps,
|
pagination: PaginationProps,
|
||||||
filters: Partial<Recordable<string[]>>,
|
filters: Partial<Recordable<string[]>>,
|
||||||
sorter: SorterResult,
|
sorter: SorterResult,
|
||||||
) {
|
) {
|
||||||
const { clearSelectOnPageChange, sortFn, filterFn } = unref(propsRef);
|
const { clearSelectOnPageChange, sortFn, filterFn } = unref(propsRef)
|
||||||
if (clearSelectOnPageChange) {
|
if (clearSelectOnPageChange) {
|
||||||
clearSelectedRowKeys();
|
clearSelectedRowKeys()
|
||||||
}
|
}
|
||||||
setPagination(pagination);
|
setPagination(pagination)
|
||||||
|
|
||||||
const params: Recordable = {};
|
const params: Recordable = {}
|
||||||
if (sorter && isFunction(sortFn)) {
|
if (sorter && isFunction(sortFn)) {
|
||||||
const sortInfo = sortFn(sorter);
|
const sortInfo = sortFn(sorter)
|
||||||
searchState.sortInfo = sortInfo;
|
searchState.sortInfo = sortInfo
|
||||||
params.sortInfo = sortInfo;
|
params.sortInfo = sortInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filters && isFunction(filterFn)) {
|
if (filters && isFunction(filterFn)) {
|
||||||
const filterInfo = filterFn(filters);
|
const filterInfo = filterFn(filters)
|
||||||
searchState.filterInfo = filterInfo;
|
searchState.filterInfo = filterInfo
|
||||||
params.filterInfo = filterInfo;
|
params.filterInfo = filterInfo
|
||||||
}
|
}
|
||||||
fetch(params);
|
fetch(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
function setTableKey(items: any[]) {
|
function setTableKey(items: any[]) {
|
||||||
if (!items || !Array.isArray(items)) return;
|
if (!items || !Array.isArray(items)) return
|
||||||
items.forEach((item) => {
|
items.forEach((item) => {
|
||||||
if (!item[ROW_KEY]) {
|
if (!item[ROW_KEY]) {
|
||||||
item[ROW_KEY] = buildUUID();
|
item[ROW_KEY] = buildUUID()
|
||||||
}
|
}
|
||||||
if (item.children && item.children.length) {
|
if (item.children && item.children.length) {
|
||||||
setTableKey(item.children);
|
setTableKey(item.children)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const getAutoCreateKey = computed(() => {
|
const getAutoCreateKey = computed(() => {
|
||||||
return unref(propsRef).autoCreateKey && !unref(propsRef).rowKey;
|
return unref(propsRef).autoCreateKey && !unref(propsRef).rowKey
|
||||||
});
|
})
|
||||||
|
|
||||||
const getRowKey = computed(() => {
|
const getRowKey = computed(() => {
|
||||||
const { rowKey } = unref(propsRef);
|
const { rowKey } = unref(propsRef)
|
||||||
return unref(getAutoCreateKey) ? ROW_KEY : rowKey;
|
return unref(getAutoCreateKey) ? ROW_KEY : rowKey
|
||||||
});
|
})
|
||||||
|
|
||||||
const getDataSourceRef = computed(() => {
|
const getDataSourceRef = computed(() => {
|
||||||
const dataSource = unref(dataSourceRef);
|
const dataSource = unref(dataSourceRef)
|
||||||
if (!dataSource || dataSource.length === 0) {
|
if (!dataSource || dataSource.length === 0) {
|
||||||
return unref(dataSourceRef);
|
return unref(dataSourceRef)
|
||||||
}
|
}
|
||||||
if (unref(getAutoCreateKey)) {
|
if (unref(getAutoCreateKey)) {
|
||||||
const firstItem = dataSource[0];
|
const firstItem = dataSource[0]
|
||||||
const lastItem = dataSource[dataSource.length - 1];
|
const lastItem = dataSource[dataSource.length - 1]
|
||||||
|
|
||||||
if (firstItem && lastItem) {
|
if (firstItem && lastItem) {
|
||||||
if (!firstItem[ROW_KEY] || !lastItem[ROW_KEY]) {
|
if (!firstItem[ROW_KEY] || !lastItem[ROW_KEY]) {
|
||||||
const data = cloneDeep(unref(dataSourceRef));
|
const data = cloneDeep(unref(dataSourceRef))
|
||||||
data.forEach((item) => {
|
data.forEach((item) => {
|
||||||
if (!item[ROW_KEY]) {
|
if (!item[ROW_KEY]) {
|
||||||
item[ROW_KEY] = buildUUID();
|
item[ROW_KEY] = buildUUID()
|
||||||
}
|
}
|
||||||
if (item.children && item.children.length) {
|
if (item.children && item.children.length) {
|
||||||
setTableKey(item.children);
|
setTableKey(item.children)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
dataSourceRef.value = data;
|
dataSourceRef.value = data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return unref(dataSourceRef);
|
return unref(dataSourceRef)
|
||||||
});
|
})
|
||||||
|
|
||||||
async function updateTableData(index: number, key: string, value: any) {
|
async function updateTableData(index: number, key: string, value: any) {
|
||||||
const record = dataSourceRef.value[index];
|
const record = dataSourceRef.value[index]
|
||||||
if (record) {
|
if (record) {
|
||||||
dataSourceRef.value[index][key] = value;
|
dataSourceRef.value[index][key] = value
|
||||||
}
|
}
|
||||||
return dataSourceRef.value[index];
|
return dataSourceRef.value[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTableDataRecord(
|
function updateTableDataRecord(
|
||||||
rowKey: string | number,
|
rowKey: string | number,
|
||||||
record: Recordable,
|
record: Recordable,
|
||||||
): Recordable | undefined {
|
): Recordable | undefined {
|
||||||
const row = findTableDataRecord(rowKey);
|
const row = findTableDataRecord(rowKey)
|
||||||
|
|
||||||
if (row) {
|
if (row) {
|
||||||
for (const field in row) {
|
for (const field in row) {
|
||||||
if (Reflect.has(record, field)) row[field] = record[field];
|
if (Reflect.has(record, field)) row[field] = record[field]
|
||||||
}
|
}
|
||||||
return row;
|
return row
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteTableDataRecord(rowKey: string | number | string[] | number[]) {
|
function deleteTableDataRecord(rowKey: string | number | string[] | number[]) {
|
||||||
if (!dataSourceRef.value || dataSourceRef.value.length == 0) return;
|
if (!dataSourceRef.value || dataSourceRef.value.length == 0) return
|
||||||
const rowKeyName = unref(getRowKey);
|
const rowKeyName = unref(getRowKey)
|
||||||
if (!rowKeyName) return;
|
if (!rowKeyName) return
|
||||||
const rowKeys = !Array.isArray(rowKey) ? [rowKey] : rowKey;
|
const rowKeys = !Array.isArray(rowKey) ? [rowKey] : rowKey
|
||||||
for (const key of rowKeys) {
|
for (const key of rowKeys) {
|
||||||
let index: number | undefined = dataSourceRef.value.findIndex((row) => {
|
let index: number | undefined = dataSourceRef.value.findIndex((row) => {
|
||||||
let targetKeyName: string;
|
let targetKeyName: string
|
||||||
if (typeof rowKeyName === 'function') {
|
if (typeof rowKeyName === 'function') {
|
||||||
targetKeyName = rowKeyName(row);
|
targetKeyName = rowKeyName(row)
|
||||||
} else {
|
} else {
|
||||||
targetKeyName = rowKeyName as string;
|
targetKeyName = rowKeyName as string
|
||||||
}
|
}
|
||||||
return row[targetKeyName] === key;
|
return row[targetKeyName] === key
|
||||||
});
|
})
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
dataSourceRef.value.splice(index, 1);
|
dataSourceRef.value.splice(index, 1)
|
||||||
}
|
}
|
||||||
index = unref(propsRef).dataSource?.findIndex((row) => {
|
index = unref(propsRef).dataSource?.findIndex((row) => {
|
||||||
let targetKeyName: string;
|
let targetKeyName: string
|
||||||
if (typeof rowKeyName === 'function') {
|
if (typeof rowKeyName === 'function') {
|
||||||
targetKeyName = rowKeyName(row);
|
targetKeyName = rowKeyName(row)
|
||||||
} else {
|
} else {
|
||||||
targetKeyName = rowKeyName as string;
|
targetKeyName = rowKeyName as string
|
||||||
}
|
}
|
||||||
return row[targetKeyName] === key;
|
return row[targetKeyName] === key
|
||||||
});
|
})
|
||||||
if (typeof index !== 'undefined' && index !== -1)
|
if (typeof index !== 'undefined' && index !== -1) unref(propsRef).dataSource?.splice(index, 1)
|
||||||
unref(propsRef).dataSource?.splice(index, 1);
|
|
||||||
}
|
}
|
||||||
setPagination({
|
setPagination({
|
||||||
total: unref(propsRef).dataSource?.length,
|
total: unref(propsRef).dataSource?.length,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function insertTableDataRecord(record: Recordable, index: number): Recordable | undefined {
|
function insertTableDataRecord(record: Recordable, index: number): Recordable | undefined {
|
||||||
// if (!dataSourceRef.value || dataSourceRef.value.length == 0) return;
|
// if (!dataSourceRef.value || dataSourceRef.value.length == 0) return;
|
||||||
index = index ?? dataSourceRef.value?.length;
|
index = index ?? dataSourceRef.value?.length
|
||||||
unref(dataSourceRef).splice(index, 0, record);
|
unref(dataSourceRef).splice(index, 0, record)
|
||||||
return unref(dataSourceRef);
|
return unref(dataSourceRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
function findTableDataRecord(rowKey: string | number) {
|
function findTableDataRecord(rowKey: string | number) {
|
||||||
if (!dataSourceRef.value || dataSourceRef.value.length == 0) return;
|
if (!dataSourceRef.value || dataSourceRef.value.length == 0) return
|
||||||
|
|
||||||
const rowKeyName = unref(getRowKey);
|
const rowKeyName = unref(getRowKey)
|
||||||
if (!rowKeyName) return;
|
if (!rowKeyName) return
|
||||||
|
|
||||||
const { childrenColumnName = 'children' } = unref(propsRef);
|
const { childrenColumnName = 'children' } = unref(propsRef)
|
||||||
|
|
||||||
const findRow = (array: any[]) => {
|
const findRow = (array: any[]) => {
|
||||||
let ret;
|
let ret
|
||||||
array.some(function iter(r) {
|
array.some(function iter(r) {
|
||||||
if (typeof rowKeyName === 'function') {
|
if (typeof rowKeyName === 'function') {
|
||||||
if ((rowKeyName(r) as string) === rowKey) {
|
if ((rowKeyName(r) as string) === rowKey) {
|
||||||
ret = r;
|
ret = r
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Reflect.has(r, rowKeyName) && r[rowKeyName] === rowKey) {
|
if (Reflect.has(r, rowKeyName) && r[rowKeyName] === rowKey) {
|
||||||
ret = r;
|
ret = r
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return r[childrenColumnName] && r[childrenColumnName].some(iter);
|
return r[childrenColumnName] && r[childrenColumnName].some(iter)
|
||||||
});
|
})
|
||||||
return ret;
|
return ret
|
||||||
};
|
}
|
||||||
|
|
||||||
// const row = dataSourceRef.value.find(r => {
|
// const row = dataSourceRef.value.find(r => {
|
||||||
// if (typeof rowKeyName === 'function') {
|
// if (typeof rowKeyName === 'function') {
|
||||||
|
|
@ -236,7 +235,7 @@ export function useDataSource(
|
||||||
// return Reflect.has(r, rowKeyName) && r[rowKeyName] === rowKey
|
// return Reflect.has(r, rowKeyName) && r[rowKeyName] === rowKey
|
||||||
// }
|
// }
|
||||||
// })
|
// })
|
||||||
return findRow(dataSourceRef.value);
|
return findRow(dataSourceRef.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetch(opt?: FetchParams) {
|
async function fetch(opt?: FetchParams) {
|
||||||
|
|
@ -249,27 +248,27 @@ export function useDataSource(
|
||||||
afterFetch,
|
afterFetch,
|
||||||
useSearchForm,
|
useSearchForm,
|
||||||
pagination,
|
pagination,
|
||||||
} = unref(propsRef);
|
} = unref(propsRef)
|
||||||
if (!api || !isFunction(api)) return;
|
if (!api || !isFunction(api)) return
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true)
|
||||||
const { pageField, sizeField, listField, totalField } = Object.assign(
|
const { pageField, sizeField, listField, totalField } = Object.assign(
|
||||||
{},
|
{},
|
||||||
FETCH_SETTING,
|
FETCH_SETTING,
|
||||||
fetchSetting,
|
fetchSetting,
|
||||||
);
|
)
|
||||||
let pageParams: Recordable = {};
|
let pageParams: Recordable = {}
|
||||||
|
|
||||||
const { current = 1, pageSize = PAGE_SIZE } = unref(getPaginationInfo) as PaginationProps;
|
const { current = 1, pageSize = PAGE_SIZE } = unref(getPaginationInfo) as PaginationProps
|
||||||
|
|
||||||
if ((isBoolean(pagination) && !pagination) || isBoolean(getPaginationInfo)) {
|
if ((isBoolean(pagination) && !pagination) || isBoolean(getPaginationInfo)) {
|
||||||
pageParams = {};
|
pageParams = {}
|
||||||
} else {
|
} else {
|
||||||
pageParams[pageField] = (opt && opt.page) || current;
|
pageParams[pageField] = (opt && opt.page) || current
|
||||||
pageParams[sizeField] = pageSize;
|
pageParams[sizeField] = pageSize
|
||||||
}
|
}
|
||||||
|
|
||||||
const { sortInfo = {}, filterInfo } = searchState;
|
const { sortInfo = {}, filterInfo } = searchState
|
||||||
|
|
||||||
let params: Recordable = merge(
|
let params: Recordable = merge(
|
||||||
pageParams,
|
pageParams,
|
||||||
|
|
@ -281,79 +280,79 @@ export function useDataSource(
|
||||||
filterInfo,
|
filterInfo,
|
||||||
opt?.sortInfo ?? {},
|
opt?.sortInfo ?? {},
|
||||||
opt?.filterInfo ?? {},
|
opt?.filterInfo ?? {},
|
||||||
);
|
)
|
||||||
if (beforeFetch && isFunction(beforeFetch)) {
|
if (beforeFetch && isFunction(beforeFetch)) {
|
||||||
params = (await beforeFetch(params)) || params;
|
params = (await beforeFetch(params)) || params
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await api(params);
|
const res = await api(params)
|
||||||
rawDataSourceRef.value = res;
|
rawDataSourceRef.value = res
|
||||||
|
|
||||||
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 ? res.length : get(res, totalField);
|
const resultTotal: number = isArrayResult ? res.length : get(res, totalField)
|
||||||
|
|
||||||
// 假如数据变少,导致总页数变少并小于当前选中页码,通过getPaginationRef获取到的页码是不正确的,需获取正确的页码再次执行
|
// 假如数据变少,导致总页数变少并小于当前选中页码,通过getPaginationRef获取到的页码是不正确的,需获取正确的页码再次执行
|
||||||
if (resultTotal) {
|
if (resultTotal) {
|
||||||
const currentTotalPage = Math.ceil(resultTotal / pageSize);
|
const currentTotalPage = Math.ceil(resultTotal / pageSize)
|
||||||
if (current > currentTotalPage) {
|
if (current > currentTotalPage) {
|
||||||
setPagination({
|
setPagination({
|
||||||
current: currentTotalPage,
|
current: currentTotalPage,
|
||||||
});
|
})
|
||||||
return await fetch(opt);
|
return await fetch(opt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (afterFetch && isFunction(afterFetch)) {
|
if (afterFetch && isFunction(afterFetch)) {
|
||||||
resultItems = (await afterFetch(resultItems)) || resultItems;
|
resultItems = (await afterFetch(resultItems)) || resultItems
|
||||||
}
|
}
|
||||||
dataSourceRef.value = resultItems;
|
dataSourceRef.value = resultItems
|
||||||
setPagination({
|
setPagination({
|
||||||
total: resultTotal || 0,
|
total: resultTotal || 0,
|
||||||
});
|
})
|
||||||
if (opt && opt.page) {
|
if (opt && opt.page) {
|
||||||
setPagination({
|
setPagination({
|
||||||
current: opt.page || 1,
|
current: opt.page || 1,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
emit('fetch-success', {
|
emit('fetch-success', {
|
||||||
items: unref(resultItems),
|
items: unref(resultItems),
|
||||||
total: resultTotal,
|
total: resultTotal,
|
||||||
});
|
})
|
||||||
return resultItems;
|
return resultItems
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
emit('fetch-error', error);
|
emit('fetch-error', error)
|
||||||
dataSourceRef.value = [];
|
dataSourceRef.value = []
|
||||||
setPagination({
|
setPagination({
|
||||||
total: 0,
|
total: 0,
|
||||||
});
|
})
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setTableData<T = Recordable>(values: T[]) {
|
function setTableData<T = Recordable>(values: T[]) {
|
||||||
dataSourceRef.value = values;
|
dataSourceRef.value = values
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDataSource<T = Recordable>() {
|
function getDataSource<T = Recordable>() {
|
||||||
return getDataSourceRef.value as T[];
|
return getDataSourceRef.value as T[]
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRawDataSource<T = Recordable>() {
|
function getRawDataSource<T = Recordable>() {
|
||||||
return rawDataSourceRef.value as T;
|
return rawDataSourceRef.value as T
|
||||||
}
|
}
|
||||||
|
|
||||||
async function reload(opt?: FetchParams) {
|
async function reload(opt?: FetchParams) {
|
||||||
return await fetch(opt);
|
return await fetch(opt)
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
useTimeoutFn(() => {
|
useTimeoutFn(() => {
|
||||||
unref(propsRef).immediate && fetch();
|
unref(propsRef).immediate && fetch()
|
||||||
}, 16);
|
}, 16)
|
||||||
});
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getDataSourceRef,
|
getDataSourceRef,
|
||||||
|
|
@ -370,5 +369,5 @@ export function useDataSource(
|
||||||
insertTableDataRecord,
|
insertTableDataRecord,
|
||||||
findTableDataRecord,
|
findTableDataRecord,
|
||||||
handleTableChange,
|
handleTableChange,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,112 +1,112 @@
|
||||||
import { isFunction } from '/@/utils/is';
|
import { isFunction } from '/@/utils/is'
|
||||||
import type { BasicTableProps, TableRowSelection } from '../types/table';
|
import type { BasicTableProps, TableRowSelection } from '../types/table'
|
||||||
import { computed, ComputedRef, nextTick, Ref, ref, toRaw, unref, watch } from 'vue';
|
import { computed, ComputedRef, nextTick, Ref, ref, toRaw, unref, watch } from 'vue'
|
||||||
import { ROW_KEY } from '../const';
|
import { ROW_KEY } from '../const'
|
||||||
import { omit } from 'lodash-es';
|
import { omit } from 'lodash-es'
|
||||||
import { findNodeAll } from '/@/utils/helper/treeHelper';
|
import { findNodeAll } from '/@/utils/helper/treeHelper'
|
||||||
|
|
||||||
export function useRowSelection(
|
export function useRowSelection(
|
||||||
propsRef: ComputedRef<BasicTableProps>,
|
propsRef: ComputedRef<BasicTableProps>,
|
||||||
tableData: Ref<Recordable[]>,
|
tableData: Ref<Recordable[]>,
|
||||||
emit: EmitType,
|
emit: EmitType,
|
||||||
) {
|
) {
|
||||||
const selectedRowKeysRef = ref<string[]>([]);
|
const selectedRowKeysRef = ref<string[]>([])
|
||||||
const selectedRowRef = ref<Recordable[]>([]);
|
const selectedRowRef = ref<Recordable[]>([])
|
||||||
|
|
||||||
const getRowSelectionRef = computed((): TableRowSelection | null => {
|
const getRowSelectionRef = computed((): TableRowSelection | null => {
|
||||||
const { rowSelection } = unref(propsRef);
|
const { rowSelection } = unref(propsRef)
|
||||||
if (!rowSelection) {
|
if (!rowSelection) {
|
||||||
return null;
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
selectedRowKeys: unref(selectedRowKeysRef),
|
selectedRowKeys: unref(selectedRowKeysRef),
|
||||||
onChange: (selectedRowKeys: string[]) => {
|
onChange: (selectedRowKeys: string[]) => {
|
||||||
setSelectedRowKeys(selectedRowKeys);
|
setSelectedRowKeys(selectedRowKeys)
|
||||||
},
|
},
|
||||||
...omit(rowSelection, ['onChange']),
|
...omit(rowSelection, ['onChange']),
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => unref(propsRef).rowSelection?.selectedRowKeys,
|
() => unref(propsRef).rowSelection?.selectedRowKeys,
|
||||||
(v: string[]) => {
|
(v: string[]) => {
|
||||||
setSelectedRowKeys(v);
|
setSelectedRowKeys(v)
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => unref(selectedRowKeysRef),
|
() => unref(selectedRowKeysRef),
|
||||||
() => {
|
() => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const { rowSelection } = unref(propsRef);
|
const { rowSelection } = unref(propsRef)
|
||||||
if (rowSelection) {
|
if (rowSelection) {
|
||||||
const { onChange } = rowSelection;
|
const { onChange } = rowSelection
|
||||||
if (onChange && isFunction(onChange)) onChange(getSelectRowKeys(), getSelectRows());
|
if (onChange && isFunction(onChange)) onChange(getSelectRowKeys(), getSelectRows())
|
||||||
}
|
}
|
||||||
emit('selection-change', {
|
emit('selection-change', {
|
||||||
keys: getSelectRowKeys(),
|
keys: getSelectRowKeys(),
|
||||||
rows: getSelectRows(),
|
rows: getSelectRows(),
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
{ deep: true },
|
{ deep: true },
|
||||||
);
|
)
|
||||||
|
|
||||||
const getAutoCreateKey = computed(() => {
|
const getAutoCreateKey = computed(() => {
|
||||||
return unref(propsRef).autoCreateKey && !unref(propsRef).rowKey;
|
return unref(propsRef).autoCreateKey && !unref(propsRef).rowKey
|
||||||
});
|
})
|
||||||
|
|
||||||
const getRowKey = computed(() => {
|
const getRowKey = computed(() => {
|
||||||
const { rowKey } = unref(propsRef);
|
const { rowKey } = unref(propsRef)
|
||||||
return unref(getAutoCreateKey) ? ROW_KEY : rowKey;
|
return unref(getAutoCreateKey) ? ROW_KEY : rowKey
|
||||||
});
|
})
|
||||||
|
|
||||||
function setSelectedRowKeys(rowKeys: string[]) {
|
function setSelectedRowKeys(rowKeys: string[]) {
|
||||||
selectedRowKeysRef.value = rowKeys;
|
selectedRowKeysRef.value = rowKeys
|
||||||
const allSelectedRows = findNodeAll(
|
const allSelectedRows = findNodeAll(
|
||||||
toRaw(unref(tableData)).concat(toRaw(unref(selectedRowRef))),
|
toRaw(unref(tableData)).concat(toRaw(unref(selectedRowRef))),
|
||||||
(item) => rowKeys.includes(item[unref(getRowKey) as string]),
|
(item) => rowKeys.includes(item[unref(getRowKey) as string]),
|
||||||
{
|
{
|
||||||
children: propsRef.value.childrenColumnName ?? 'children',
|
children: propsRef.value.childrenColumnName ?? 'children',
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
const trueSelectedRows: any[] = [];
|
const trueSelectedRows: any[] = []
|
||||||
rowKeys.forEach((key: string) => {
|
rowKeys.forEach((key: string) => {
|
||||||
const found = allSelectedRows.find((item) => item[unref(getRowKey) as string] === key);
|
const found = allSelectedRows.find((item) => item[unref(getRowKey) as string] === key)
|
||||||
found && trueSelectedRows.push(found);
|
found && trueSelectedRows.push(found)
|
||||||
});
|
})
|
||||||
selectedRowRef.value = trueSelectedRows;
|
selectedRowRef.value = trueSelectedRows
|
||||||
}
|
}
|
||||||
|
|
||||||
function setSelectedRows(rows: Recordable[]) {
|
function setSelectedRows(rows: Recordable[]) {
|
||||||
selectedRowRef.value = rows;
|
selectedRowRef.value = rows
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearSelectedRowKeys() {
|
function clearSelectedRowKeys() {
|
||||||
selectedRowRef.value = [];
|
selectedRowRef.value = []
|
||||||
selectedRowKeysRef.value = [];
|
selectedRowKeysRef.value = []
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteSelectRowByKey(key: string) {
|
function deleteSelectRowByKey(key: string) {
|
||||||
const selectedRowKeys = unref(selectedRowKeysRef);
|
const selectedRowKeys = unref(selectedRowKeysRef)
|
||||||
const index = selectedRowKeys.findIndex((item) => item === key);
|
const index = selectedRowKeys.findIndex((item) => item === key)
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
unref(selectedRowKeysRef).splice(index, 1);
|
unref(selectedRowKeysRef).splice(index, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSelectRowKeys() {
|
function getSelectRowKeys() {
|
||||||
return unref(selectedRowKeysRef);
|
return unref(selectedRowKeysRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSelectRows<T = Recordable>() {
|
function getSelectRows<T = Recordable>() {
|
||||||
// const ret = toRaw(unref(selectedRowRef)).map((item) => toRaw(item));
|
// const ret = toRaw(unref(selectedRowRef)).map((item) => toRaw(item));
|
||||||
return unref(selectedRowRef) as T[];
|
return unref(selectedRowRef) as T[]
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRowSelection() {
|
function getRowSelection() {
|
||||||
return unref(getRowSelectionRef)!;
|
return unref(getRowSelectionRef)!
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -118,5 +118,5 @@ export function useRowSelection(
|
||||||
clearSelectedRowKeys,
|
clearSelectedRowKeys,
|
||||||
deleteSelectRowByKey,
|
deleteSelectRowByKey,
|
||||||
setSelectedRows,
|
setSelectedRows,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,55 +1,55 @@
|
||||||
import type { ComputedRef, Ref } from 'vue';
|
import type { ComputedRef, Ref } from 'vue'
|
||||||
import { nextTick, unref } from 'vue';
|
import { nextTick, unref } from 'vue'
|
||||||
import { warn } from '/@/utils/log';
|
import { warn } from '/@/utils/log'
|
||||||
|
|
||||||
export function useTableScrollTo(
|
export function useTableScrollTo(
|
||||||
tableElRef: Ref<ComponentRef>,
|
tableElRef: Ref<ComponentRef>,
|
||||||
getDataSourceRef: ComputedRef<Recordable[]>,
|
getDataSourceRef: ComputedRef<Recordable[]>,
|
||||||
) {
|
) {
|
||||||
let bodyEl: HTMLElement | null;
|
let bodyEl: HTMLElement | null
|
||||||
|
|
||||||
async function findTargetRowToScroll(targetRowData: Recordable) {
|
async function findTargetRowToScroll(targetRowData: Recordable) {
|
||||||
const { id } = targetRowData;
|
const { id } = targetRowData
|
||||||
const targetRowEl: HTMLElement | null | undefined = bodyEl?.querySelector(
|
const targetRowEl: HTMLElement | null | undefined = bodyEl?.querySelector(
|
||||||
`[data-row-key="${id}"]`,
|
`[data-row-key="${id}"]`,
|
||||||
);
|
)
|
||||||
//Add a delay to get new dataSource
|
//Add a delay to get new dataSource
|
||||||
await nextTick();
|
await nextTick()
|
||||||
bodyEl?.scrollTo({
|
bodyEl?.scrollTo({
|
||||||
top: targetRowEl?.offsetTop ?? 0,
|
top: targetRowEl?.offsetTop ?? 0,
|
||||||
behavior: 'smooth',
|
behavior: 'smooth',
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrollTo(pos: string): void {
|
function scrollTo(pos: string): void {
|
||||||
const table = unref(tableElRef);
|
const table = unref(tableElRef)
|
||||||
if (!table) return;
|
if (!table) return
|
||||||
|
|
||||||
const tableEl: Element = table.$el;
|
const tableEl: Element = table.$el
|
||||||
if (!tableEl) return;
|
if (!tableEl) return
|
||||||
|
|
||||||
if (!bodyEl) {
|
if (!bodyEl) {
|
||||||
bodyEl = tableEl.querySelector('.ant-table-body');
|
bodyEl = tableEl.querySelector('.ant-table-body')
|
||||||
if (!bodyEl) return;
|
if (!bodyEl) return
|
||||||
}
|
}
|
||||||
|
|
||||||
const dataSource = unref(getDataSourceRef);
|
const dataSource = unref(getDataSourceRef)
|
||||||
if (!dataSource) return;
|
if (!dataSource) return
|
||||||
|
|
||||||
// judge pos type
|
// judge pos type
|
||||||
if (pos === 'top') {
|
if (pos === 'top') {
|
||||||
findTargetRowToScroll(dataSource[0]);
|
findTargetRowToScroll(dataSource[0])
|
||||||
} else if (pos === 'bottom') {
|
} else if (pos === 'bottom') {
|
||||||
findTargetRowToScroll(dataSource[dataSource.length - 1]);
|
findTargetRowToScroll(dataSource[dataSource.length - 1])
|
||||||
} else {
|
} else {
|
||||||
const targetRowData = dataSource.find((data) => data.id === pos);
|
const targetRowData = dataSource.find((data) => data.id === pos)
|
||||||
if (targetRowData) {
|
if (targetRowData) {
|
||||||
findTargetRowToScroll(targetRowData);
|
findTargetRowToScroll(targetRowData)
|
||||||
} else {
|
} else {
|
||||||
warn(`id: ${pos} doesn't exist`);
|
warn(`id: ${pos} doesn't exist`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { scrollTo };
|
return { scrollTo }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,167 +1,167 @@
|
||||||
import type { BasicTableProps, TableActionType, FetchParams, BasicColumn } from '../types/table';
|
import type { BasicTableProps, TableActionType, FetchParams, BasicColumn } from '../types/table'
|
||||||
import type { PaginationProps } from '../types/pagination';
|
import type { PaginationProps } from '../types/pagination'
|
||||||
import type { DynamicProps } from '/#/utils';
|
import type { DynamicProps } from '/#/utils'
|
||||||
import type { FormActionType } from '/@/components/Form';
|
import type { FormActionType } from '/@/components/Form'
|
||||||
import type { WatchStopHandle } from 'vue';
|
import type { WatchStopHandle } from 'vue'
|
||||||
import { getDynamicProps } from '/@/utils';
|
import { getDynamicProps } from '/@/utils'
|
||||||
import { ref, onUnmounted, unref, watch, toRaw } from 'vue';
|
import { ref, onUnmounted, unref, watch, toRaw } from 'vue'
|
||||||
import { isProdMode } from '/@/utils/env';
|
import { isProdMode } from '/@/utils/env'
|
||||||
import { error } from '/@/utils/log';
|
import { error } from '/@/utils/log'
|
||||||
|
|
||||||
type Props = Partial<DynamicProps<BasicTableProps>>;
|
type Props = Partial<DynamicProps<BasicTableProps>>
|
||||||
|
|
||||||
type UseTableMethod = TableActionType & {
|
type UseTableMethod = TableActionType & {
|
||||||
getForm: () => FormActionType;
|
getForm: () => FormActionType
|
||||||
};
|
}
|
||||||
|
|
||||||
export function useTable(tableProps?: Props): [
|
export function useTable(tableProps?: Props): [
|
||||||
(instance: TableActionType, formInstance: UseTableMethod) => void,
|
(instance: TableActionType, formInstance: UseTableMethod) => void,
|
||||||
TableActionType & {
|
TableActionType & {
|
||||||
getForm: () => FormActionType;
|
getForm: () => FormActionType
|
||||||
},
|
},
|
||||||
] {
|
] {
|
||||||
const tableRef = ref<Nullable<TableActionType>>(null);
|
const tableRef = ref<Nullable<TableActionType>>(null)
|
||||||
const loadedRef = ref<Nullable<boolean>>(false);
|
const loadedRef = ref<Nullable<boolean>>(false)
|
||||||
const formRef = ref<Nullable<UseTableMethod>>(null);
|
const formRef = ref<Nullable<UseTableMethod>>(null)
|
||||||
|
|
||||||
let stopWatch: WatchStopHandle;
|
let stopWatch: WatchStopHandle
|
||||||
|
|
||||||
function register(instance: TableActionType, formInstance: UseTableMethod) {
|
function register(instance: TableActionType, formInstance: UseTableMethod) {
|
||||||
isProdMode() &&
|
isProdMode() &&
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
tableRef.value = null;
|
tableRef.value = null
|
||||||
loadedRef.value = null;
|
loadedRef.value = null
|
||||||
});
|
})
|
||||||
|
|
||||||
if (unref(loadedRef) && isProdMode() && instance === unref(tableRef)) return;
|
if (unref(loadedRef) && isProdMode() && instance === unref(tableRef)) return
|
||||||
|
|
||||||
tableRef.value = instance;
|
tableRef.value = instance
|
||||||
formRef.value = formInstance;
|
formRef.value = formInstance
|
||||||
tableProps && instance.setProps(getDynamicProps(tableProps));
|
tableProps && instance.setProps(getDynamicProps(tableProps))
|
||||||
loadedRef.value = true;
|
loadedRef.value = true
|
||||||
|
|
||||||
stopWatch?.();
|
stopWatch?.()
|
||||||
|
|
||||||
stopWatch = watch(
|
stopWatch = watch(
|
||||||
() => tableProps,
|
() => tableProps,
|
||||||
() => {
|
() => {
|
||||||
tableProps && instance.setProps(getDynamicProps(tableProps));
|
tableProps && instance.setProps(getDynamicProps(tableProps))
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
immediate: true,
|
immediate: true,
|
||||||
deep: true,
|
deep: true,
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTableInstance(): TableActionType {
|
function getTableInstance(): TableActionType {
|
||||||
const table = unref(tableRef);
|
const table = unref(tableRef)
|
||||||
if (!table) {
|
if (!table) {
|
||||||
error(
|
error(
|
||||||
'The table instance has not been obtained yet, please make sure the table is presented when performing the table operation!',
|
'The table instance has not been obtained yet, please make sure the table is presented when performing the table operation!',
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
return table as TableActionType;
|
return table as TableActionType
|
||||||
}
|
}
|
||||||
|
|
||||||
const methods: TableActionType & {
|
const methods: TableActionType & {
|
||||||
getForm: () => FormActionType;
|
getForm: () => FormActionType
|
||||||
} = {
|
} = {
|
||||||
reload: async (opt?: FetchParams) => {
|
reload: async (opt?: FetchParams) => {
|
||||||
return await getTableInstance().reload(opt);
|
return await getTableInstance().reload(opt)
|
||||||
},
|
},
|
||||||
setProps: (props: Partial<BasicTableProps>) => {
|
setProps: (props: Partial<BasicTableProps>) => {
|
||||||
getTableInstance().setProps(props);
|
getTableInstance().setProps(props)
|
||||||
},
|
},
|
||||||
redoHeight: () => {
|
redoHeight: () => {
|
||||||
getTableInstance().redoHeight();
|
getTableInstance().redoHeight()
|
||||||
},
|
},
|
||||||
setLoading: (loading: boolean) => {
|
setLoading: (loading: boolean) => {
|
||||||
getTableInstance().setLoading(loading);
|
getTableInstance().setLoading(loading)
|
||||||
},
|
},
|
||||||
getDataSource: () => {
|
getDataSource: () => {
|
||||||
return getTableInstance().getDataSource();
|
return getTableInstance().getDataSource()
|
||||||
},
|
},
|
||||||
getRawDataSource: () => {
|
getRawDataSource: () => {
|
||||||
return getTableInstance().getRawDataSource();
|
return getTableInstance().getRawDataSource()
|
||||||
},
|
},
|
||||||
getColumns: ({ ignoreIndex = false }: { ignoreIndex?: boolean } = {}) => {
|
getColumns: ({ ignoreIndex = false }: { ignoreIndex?: boolean } = {}) => {
|
||||||
const columns = getTableInstance().getColumns({ ignoreIndex }) || [];
|
const columns = getTableInstance().getColumns({ ignoreIndex }) || []
|
||||||
return toRaw(columns);
|
return toRaw(columns)
|
||||||
},
|
},
|
||||||
setColumns: (columns: BasicColumn[]) => {
|
setColumns: (columns: BasicColumn[]) => {
|
||||||
getTableInstance().setColumns(columns);
|
getTableInstance().setColumns(columns)
|
||||||
},
|
},
|
||||||
setTableData: (values: any[]) => {
|
setTableData: (values: any[]) => {
|
||||||
return getTableInstance().setTableData(values);
|
return getTableInstance().setTableData(values)
|
||||||
},
|
},
|
||||||
setPagination: (info: Partial<PaginationProps>) => {
|
setPagination: (info: Partial<PaginationProps>) => {
|
||||||
return getTableInstance().setPagination(info);
|
return getTableInstance().setPagination(info)
|
||||||
},
|
},
|
||||||
deleteSelectRowByKey: (key: string) => {
|
deleteSelectRowByKey: (key: string) => {
|
||||||
getTableInstance().deleteSelectRowByKey(key);
|
getTableInstance().deleteSelectRowByKey(key)
|
||||||
},
|
},
|
||||||
getSelectRowKeys: () => {
|
getSelectRowKeys: () => {
|
||||||
return toRaw(getTableInstance().getSelectRowKeys());
|
return toRaw(getTableInstance().getSelectRowKeys())
|
||||||
},
|
},
|
||||||
getSelectRows: () => {
|
getSelectRows: () => {
|
||||||
return toRaw(getTableInstance().getSelectRows());
|
return toRaw(getTableInstance().getSelectRows())
|
||||||
},
|
},
|
||||||
clearSelectedRowKeys: () => {
|
clearSelectedRowKeys: () => {
|
||||||
getTableInstance().clearSelectedRowKeys();
|
getTableInstance().clearSelectedRowKeys()
|
||||||
},
|
},
|
||||||
setSelectedRowKeys: (keys: string[] | number[]) => {
|
setSelectedRowKeys: (keys: string[] | number[]) => {
|
||||||
getTableInstance().setSelectedRowKeys(keys);
|
getTableInstance().setSelectedRowKeys(keys)
|
||||||
},
|
},
|
||||||
getPaginationRef: () => {
|
getPaginationRef: () => {
|
||||||
return getTableInstance().getPaginationRef();
|
return getTableInstance().getPaginationRef()
|
||||||
},
|
},
|
||||||
getSize: () => {
|
getSize: () => {
|
||||||
return toRaw(getTableInstance().getSize());
|
return toRaw(getTableInstance().getSize())
|
||||||
},
|
},
|
||||||
updateTableData: (index: number, key: string, value: any) => {
|
updateTableData: (index: number, key: string, value: any) => {
|
||||||
return getTableInstance().updateTableData(index, key, value);
|
return getTableInstance().updateTableData(index, key, value)
|
||||||
},
|
},
|
||||||
deleteTableDataRecord: (rowKey: string | number | string[] | number[]) => {
|
deleteTableDataRecord: (rowKey: string | number | string[] | number[]) => {
|
||||||
return getTableInstance().deleteTableDataRecord(rowKey);
|
return getTableInstance().deleteTableDataRecord(rowKey)
|
||||||
},
|
},
|
||||||
insertTableDataRecord: (record: Recordable | Recordable[], index?: number) => {
|
insertTableDataRecord: (record: Recordable | Recordable[], index?: number) => {
|
||||||
return getTableInstance().insertTableDataRecord(record, index);
|
return getTableInstance().insertTableDataRecord(record, index)
|
||||||
},
|
},
|
||||||
updateTableDataRecord: (rowKey: string | number, record: Recordable) => {
|
updateTableDataRecord: (rowKey: string | number, record: Recordable) => {
|
||||||
return getTableInstance().updateTableDataRecord(rowKey, record);
|
return getTableInstance().updateTableDataRecord(rowKey, record)
|
||||||
},
|
},
|
||||||
findTableDataRecord: (rowKey: string | number) => {
|
findTableDataRecord: (rowKey: string | number) => {
|
||||||
return getTableInstance().findTableDataRecord(rowKey);
|
return getTableInstance().findTableDataRecord(rowKey)
|
||||||
},
|
},
|
||||||
getRowSelection: () => {
|
getRowSelection: () => {
|
||||||
return toRaw(getTableInstance().getRowSelection());
|
return toRaw(getTableInstance().getRowSelection())
|
||||||
},
|
},
|
||||||
getCacheColumns: () => {
|
getCacheColumns: () => {
|
||||||
return toRaw(getTableInstance().getCacheColumns());
|
return toRaw(getTableInstance().getCacheColumns())
|
||||||
},
|
},
|
||||||
getForm: () => {
|
getForm: () => {
|
||||||
return unref(formRef) as unknown as FormActionType;
|
return unref(formRef) as unknown as FormActionType
|
||||||
},
|
},
|
||||||
setShowPagination: async (show: boolean) => {
|
setShowPagination: async (show: boolean) => {
|
||||||
getTableInstance().setShowPagination(show);
|
getTableInstance().setShowPagination(show)
|
||||||
},
|
},
|
||||||
getShowPagination: () => {
|
getShowPagination: () => {
|
||||||
return toRaw(getTableInstance().getShowPagination());
|
return toRaw(getTableInstance().getShowPagination())
|
||||||
},
|
},
|
||||||
expandAll: () => {
|
expandAll: () => {
|
||||||
getTableInstance().expandAll();
|
getTableInstance().expandAll()
|
||||||
},
|
},
|
||||||
expandRows: (keys: string[]) => {
|
expandRows: (keys: string[]) => {
|
||||||
getTableInstance().expandRows(keys);
|
getTableInstance().expandRows(keys)
|
||||||
},
|
},
|
||||||
collapseAll: () => {
|
collapseAll: () => {
|
||||||
getTableInstance().collapseAll();
|
getTableInstance().collapseAll()
|
||||||
},
|
},
|
||||||
scrollTo: (pos: string) => {
|
scrollTo: (pos: string) => {
|
||||||
getTableInstance().scrollTo(pos);
|
getTableInstance().scrollTo(pos)
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|
||||||
return [register, methods];
|
return [register, methods]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,65 +1,65 @@
|
||||||
import type { ComputedRef, Ref } from 'vue';
|
import type { ComputedRef, Ref } from 'vue'
|
||||||
import type { BasicTableProps } from '../types/table';
|
import type { BasicTableProps } from '../types/table'
|
||||||
import { computed, unref, ref, toRaw } from 'vue';
|
import { computed, unref, ref, toRaw } from 'vue'
|
||||||
import { ROW_KEY } from '../const';
|
import { ROW_KEY } from '../const'
|
||||||
|
|
||||||
export function useTableExpand(
|
export function useTableExpand(
|
||||||
propsRef: ComputedRef<BasicTableProps>,
|
propsRef: ComputedRef<BasicTableProps>,
|
||||||
tableData: Ref<Recordable[]>,
|
tableData: Ref<Recordable[]>,
|
||||||
emit: EmitType,
|
emit: EmitType,
|
||||||
) {
|
) {
|
||||||
const expandedRowKeys = ref<string[]>([]);
|
const expandedRowKeys = ref<string[]>([])
|
||||||
|
|
||||||
const getAutoCreateKey = computed(() => {
|
const getAutoCreateKey = computed(() => {
|
||||||
return unref(propsRef).autoCreateKey && !unref(propsRef).rowKey;
|
return unref(propsRef).autoCreateKey && !unref(propsRef).rowKey
|
||||||
});
|
})
|
||||||
|
|
||||||
const getRowKey = computed(() => {
|
const getRowKey = computed(() => {
|
||||||
const { rowKey } = unref(propsRef);
|
const { rowKey } = unref(propsRef)
|
||||||
return unref(getAutoCreateKey) ? ROW_KEY : rowKey;
|
return unref(getAutoCreateKey) ? ROW_KEY : rowKey
|
||||||
});
|
})
|
||||||
|
|
||||||
const getExpandOption = computed(() => {
|
const getExpandOption = computed(() => {
|
||||||
const { isTreeTable } = unref(propsRef);
|
const { isTreeTable } = unref(propsRef)
|
||||||
if (!isTreeTable) return {};
|
if (!isTreeTable) return {}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
expandedRowKeys: unref(expandedRowKeys),
|
expandedRowKeys: unref(expandedRowKeys),
|
||||||
onExpandedRowsChange: (keys: string[]) => {
|
onExpandedRowsChange: (keys: string[]) => {
|
||||||
expandedRowKeys.value = keys;
|
expandedRowKeys.value = keys
|
||||||
emit('expanded-rows-change', keys);
|
emit('expanded-rows-change', keys)
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
function expandAll() {
|
function expandAll() {
|
||||||
const keys = getAllKeys();
|
const keys = getAllKeys()
|
||||||
expandedRowKeys.value = keys;
|
expandedRowKeys.value = keys
|
||||||
}
|
}
|
||||||
|
|
||||||
function expandRows(keys: string[]) {
|
function expandRows(keys: string[]) {
|
||||||
// use row ID expands the specified table row
|
// use row ID expands the specified table row
|
||||||
const { isTreeTable } = unref(propsRef);
|
const { isTreeTable } = unref(propsRef)
|
||||||
if (!isTreeTable) return;
|
if (!isTreeTable) return
|
||||||
expandedRowKeys.value = [...expandedRowKeys.value, ...keys];
|
expandedRowKeys.value = [...expandedRowKeys.value, ...keys]
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAllKeys(data?: Recordable[]) {
|
function getAllKeys(data?: Recordable[]) {
|
||||||
const keys: string[] = [];
|
const keys: string[] = []
|
||||||
const { childrenColumnName } = unref(propsRef);
|
const { childrenColumnName } = unref(propsRef)
|
||||||
toRaw(data || unref(tableData)).forEach((item) => {
|
toRaw(data || unref(tableData)).forEach((item) => {
|
||||||
keys.push(item[unref(getRowKey) as string]);
|
keys.push(item[unref(getRowKey) as string])
|
||||||
const children = item[childrenColumnName || 'children'];
|
const children = item[childrenColumnName || 'children']
|
||||||
if (children?.length) {
|
if (children?.length) {
|
||||||
keys.push(...getAllKeys(children));
|
keys.push(...getAllKeys(children))
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
return keys;
|
return keys
|
||||||
}
|
}
|
||||||
|
|
||||||
function collapseAll() {
|
function collapseAll() {
|
||||||
expandedRowKeys.value = [];
|
expandedRowKeys.value = []
|
||||||
}
|
}
|
||||||
|
|
||||||
return { getExpandOption, expandAll, expandRows, collapseAll };
|
return { getExpandOption, expandAll, expandRows, collapseAll }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,56 +1,56 @@
|
||||||
import type { ComputedRef, Ref } from 'vue';
|
import type { ComputedRef, Ref } from 'vue'
|
||||||
import type { BasicTableProps } from '../types/table';
|
import type { BasicTableProps } from '../types/table'
|
||||||
import { unref, computed, h, nextTick, watchEffect } from 'vue';
|
import { unref, computed, h, nextTick, watchEffect } from 'vue'
|
||||||
import TableFooter from '../components/TableFooter.vue';
|
import TableFooter from '../components/TableFooter.vue'
|
||||||
import { useEventListener } from '/@/hooks/event/useEventListener';
|
import { useEventListener } from '/@/hooks/event/useEventListener'
|
||||||
|
|
||||||
export function useTableFooter(
|
export function useTableFooter(
|
||||||
propsRef: ComputedRef<BasicTableProps>,
|
propsRef: ComputedRef<BasicTableProps>,
|
||||||
scrollRef: ComputedRef<{
|
scrollRef: ComputedRef<{
|
||||||
x: string | number | true;
|
x: string | number | true
|
||||||
y: string | number | null;
|
y: string | number | null
|
||||||
scrollToFirstRowOnChange: boolean;
|
scrollToFirstRowOnChange: boolean
|
||||||
}>,
|
}>,
|
||||||
tableElRef: Ref<ComponentRef>,
|
tableElRef: Ref<ComponentRef>,
|
||||||
getDataSourceRef: ComputedRef<Recordable>,
|
getDataSourceRef: ComputedRef<Recordable>,
|
||||||
) {
|
) {
|
||||||
const getIsEmptyData = computed(() => {
|
const getIsEmptyData = computed(() => {
|
||||||
return (unref(getDataSourceRef) || []).length === 0;
|
return (unref(getDataSourceRef) || []).length === 0
|
||||||
});
|
})
|
||||||
|
|
||||||
const getFooterProps = computed((): Recordable | undefined => {
|
const getFooterProps = computed((): Recordable | undefined => {
|
||||||
const { summaryFunc, showSummary, summaryData } = unref(propsRef);
|
const { summaryFunc, showSummary, summaryData } = unref(propsRef)
|
||||||
return showSummary && !unref(getIsEmptyData)
|
return showSummary && !unref(getIsEmptyData)
|
||||||
? () => h(TableFooter, { summaryFunc, summaryData, scroll: unref(scrollRef) })
|
? () => h(TableFooter, { summaryFunc, summaryData, scroll: unref(scrollRef) })
|
||||||
: undefined;
|
: undefined
|
||||||
});
|
})
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
handleSummary();
|
handleSummary()
|
||||||
});
|
})
|
||||||
|
|
||||||
function handleSummary() {
|
function handleSummary() {
|
||||||
const { showSummary } = unref(propsRef);
|
const { showSummary } = unref(propsRef)
|
||||||
if (!showSummary || unref(getIsEmptyData)) return;
|
if (!showSummary || unref(getIsEmptyData)) return
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const tableEl = unref(tableElRef);
|
const tableEl = unref(tableElRef)
|
||||||
if (!tableEl) return;
|
if (!tableEl) return
|
||||||
const bodyDom = tableEl.$el.querySelector('.ant-table-content');
|
const bodyDom = tableEl.$el.querySelector('.ant-table-content')
|
||||||
useEventListener({
|
useEventListener({
|
||||||
el: bodyDom,
|
el: bodyDom,
|
||||||
name: 'scroll',
|
name: 'scroll',
|
||||||
listener: () => {
|
listener: () => {
|
||||||
const footerBodyDom = tableEl.$el.querySelector(
|
const footerBodyDom = tableEl.$el.querySelector(
|
||||||
'.ant-table-footer .ant-table-content',
|
'.ant-table-footer .ant-table-content',
|
||||||
) as HTMLDivElement;
|
) as HTMLDivElement
|
||||||
if (!footerBodyDom || !bodyDom) return;
|
if (!footerBodyDom || !bodyDom) return
|
||||||
footerBodyDom.scrollLeft = bodyDom.scrollLeft;
|
footerBodyDom.scrollLeft = bodyDom.scrollLeft
|
||||||
},
|
},
|
||||||
wait: 0,
|
wait: 0,
|
||||||
options: true,
|
options: true,
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
return { getFooterProps };
|
return { getFooterProps }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import type { BasicTableProps, TableRowSelection, BasicColumn } from '../types/table';
|
import type { BasicTableProps, TableRowSelection, BasicColumn } from '../types/table'
|
||||||
import { Ref, ComputedRef, ref } from 'vue';
|
import { Ref, ComputedRef, ref } from 'vue'
|
||||||
import { computed, unref, nextTick, watch } from 'vue';
|
import { computed, unref, nextTick, watch } from 'vue'
|
||||||
import { getViewportOffset } from '/@/utils/domUtils';
|
import { getViewportOffset } from '/@/utils/domUtils'
|
||||||
import { isBoolean } from '/@/utils/is';
|
import { isBoolean } from '/@/utils/is'
|
||||||
import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
|
import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn'
|
||||||
import { useModalContext } from '/@/components/Modal';
|
import { useModalContext } from '/@/components/Modal'
|
||||||
import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated';
|
import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated'
|
||||||
import { useDebounceFn } from '@vueuse/core';
|
import { useDebounceFn } from '@vueuse/core'
|
||||||
|
|
||||||
export function useTableScroll(
|
export function useTableScroll(
|
||||||
propsRef: ComputedRef<BasicTableProps>,
|
propsRef: ComputedRef<BasicTableProps>,
|
||||||
|
|
@ -17,147 +17,145 @@ export function useTableScroll(
|
||||||
wrapRef: Ref<HTMLElement | null>,
|
wrapRef: Ref<HTMLElement | null>,
|
||||||
formRef: Ref<ComponentRef>,
|
formRef: Ref<ComponentRef>,
|
||||||
) {
|
) {
|
||||||
const tableHeightRef: Ref<Nullable<number | string>> = ref(167);
|
const tableHeightRef: Ref<Nullable<number | string>> = ref(167)
|
||||||
const modalFn = useModalContext();
|
const modalFn = useModalContext()
|
||||||
|
|
||||||
// Greater than animation time 280
|
// Greater than animation time 280
|
||||||
const debounceRedoHeight = useDebounceFn(redoHeight, 100);
|
const debounceRedoHeight = useDebounceFn(redoHeight, 100)
|
||||||
|
|
||||||
const getCanResize = computed(() => {
|
const getCanResize = computed(() => {
|
||||||
const { canResize, scroll } = unref(propsRef);
|
const { canResize, scroll } = unref(propsRef)
|
||||||
return canResize && !(scroll || {}).y;
|
return canResize && !(scroll || {}).y
|
||||||
});
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => [unref(getCanResize), unref(getDataSourceRef)?.length],
|
() => [unref(getCanResize), unref(getDataSourceRef)?.length],
|
||||||
() => {
|
() => {
|
||||||
debounceRedoHeight();
|
debounceRedoHeight()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
flush: 'post',
|
flush: 'post',
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
|
|
||||||
function redoHeight() {
|
function redoHeight() {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
calcTableHeight();
|
calcTableHeight()
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function setHeight(height: number) {
|
function setHeight(height: number) {
|
||||||
tableHeightRef.value = height;
|
tableHeightRef.value = height
|
||||||
// Solve the problem of modal adaptive height calculation when the form is placed in the modal
|
// Solve the problem of modal adaptive height calculation when the form is placed in the modal
|
||||||
modalFn?.redoModalHeight?.();
|
modalFn?.redoModalHeight?.()
|
||||||
}
|
}
|
||||||
|
|
||||||
// No need to repeat queries
|
// No need to repeat queries
|
||||||
let paginationEl: HTMLElement | null;
|
let paginationEl: HTMLElement | null
|
||||||
let footerEl: HTMLElement | null;
|
let footerEl: HTMLElement | null
|
||||||
let bodyEl: HTMLElement | null;
|
let bodyEl: HTMLElement | null
|
||||||
|
|
||||||
async function calcTableHeight() {
|
async function calcTableHeight() {
|
||||||
const { resizeHeightOffset, pagination, maxHeight, isCanResizeParent, useSearchForm } =
|
const { resizeHeightOffset, pagination, maxHeight, isCanResizeParent, useSearchForm } =
|
||||||
unref(propsRef);
|
unref(propsRef)
|
||||||
const tableData = unref(getDataSourceRef);
|
const tableData = unref(getDataSourceRef)
|
||||||
|
|
||||||
const table = unref(tableElRef);
|
const table = unref(tableElRef)
|
||||||
if (!table) return;
|
if (!table) return
|
||||||
|
|
||||||
const tableEl: Element = table.$el;
|
const tableEl: Element = table.$el
|
||||||
if (!tableEl) return;
|
if (!tableEl) return
|
||||||
|
|
||||||
if (!bodyEl) {
|
if (!bodyEl) {
|
||||||
bodyEl = tableEl.querySelector('.ant-table-body');
|
bodyEl = tableEl.querySelector('.ant-table-body')
|
||||||
if (!bodyEl) return;
|
if (!bodyEl) return
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasScrollBarY = bodyEl.scrollHeight > bodyEl.clientHeight;
|
const hasScrollBarY = bodyEl.scrollHeight > bodyEl.clientHeight
|
||||||
const hasScrollBarX = bodyEl.scrollWidth > bodyEl.clientWidth;
|
const hasScrollBarX = bodyEl.scrollWidth > bodyEl.clientWidth
|
||||||
|
|
||||||
if (hasScrollBarY) {
|
if (hasScrollBarY) {
|
||||||
tableEl.classList.contains('hide-scrollbar-y') &&
|
tableEl.classList.contains('hide-scrollbar-y') && tableEl.classList.remove('hide-scrollbar-y')
|
||||||
tableEl.classList.remove('hide-scrollbar-y');
|
|
||||||
} else {
|
} else {
|
||||||
!tableEl.classList.contains('hide-scrollbar-y') && tableEl.classList.add('hide-scrollbar-y');
|
!tableEl.classList.contains('hide-scrollbar-y') && tableEl.classList.add('hide-scrollbar-y')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasScrollBarX) {
|
if (hasScrollBarX) {
|
||||||
tableEl.classList.contains('hide-scrollbar-x') &&
|
tableEl.classList.contains('hide-scrollbar-x') && tableEl.classList.remove('hide-scrollbar-x')
|
||||||
tableEl.classList.remove('hide-scrollbar-x');
|
|
||||||
} else {
|
} else {
|
||||||
!tableEl.classList.contains('hide-scrollbar-x') && tableEl.classList.add('hide-scrollbar-x');
|
!tableEl.classList.contains('hide-scrollbar-x') && tableEl.classList.add('hide-scrollbar-x')
|
||||||
}
|
}
|
||||||
|
|
||||||
bodyEl!.style.height = 'unset';
|
bodyEl!.style.height = 'unset'
|
||||||
|
|
||||||
if (!unref(getCanResize) || !unref(tableData) || tableData.length === 0) return;
|
if (!unref(getCanResize) || !unref(tableData) || tableData.length === 0) return
|
||||||
|
|
||||||
await nextTick();
|
await nextTick()
|
||||||
// Add a delay to get the correct bottomIncludeBody paginationHeight footerHeight headerHeight
|
// Add a delay to get the correct bottomIncludeBody paginationHeight footerHeight headerHeight
|
||||||
|
|
||||||
const headEl = tableEl.querySelector('.ant-table-thead ');
|
const headEl = tableEl.querySelector('.ant-table-thead ')
|
||||||
|
|
||||||
if (!headEl) return;
|
if (!headEl) return
|
||||||
|
|
||||||
// Table height from bottom height-custom offset
|
// Table height from bottom height-custom offset
|
||||||
let paddingHeight = 32;
|
let paddingHeight = 32
|
||||||
// Pager height
|
// Pager height
|
||||||
let paginationHeight = 2;
|
let paginationHeight = 2
|
||||||
if (!isBoolean(pagination)) {
|
if (!isBoolean(pagination)) {
|
||||||
paginationEl = tableEl.querySelector('.ant-pagination') as HTMLElement;
|
paginationEl = tableEl.querySelector('.ant-pagination') as HTMLElement
|
||||||
if (paginationEl) {
|
if (paginationEl) {
|
||||||
const offsetHeight = paginationEl.offsetHeight;
|
const offsetHeight = paginationEl.offsetHeight
|
||||||
paginationHeight += offsetHeight || 0;
|
paginationHeight += offsetHeight || 0
|
||||||
} else {
|
} else {
|
||||||
// TODO First fix 24
|
// TODO First fix 24
|
||||||
paginationHeight += 24;
|
paginationHeight += 24
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
paginationHeight = -8;
|
paginationHeight = -8
|
||||||
}
|
}
|
||||||
|
|
||||||
let footerHeight = 0;
|
let footerHeight = 0
|
||||||
if (!isBoolean(pagination)) {
|
if (!isBoolean(pagination)) {
|
||||||
if (!footerEl) {
|
if (!footerEl) {
|
||||||
footerEl = tableEl.querySelector('.ant-table-footer') as HTMLElement;
|
footerEl = tableEl.querySelector('.ant-table-footer') as HTMLElement
|
||||||
} else {
|
} else {
|
||||||
const offsetHeight = footerEl.offsetHeight;
|
const offsetHeight = footerEl.offsetHeight
|
||||||
footerHeight += offsetHeight || 0;
|
footerHeight += offsetHeight || 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let headerHeight = 0;
|
let headerHeight = 0
|
||||||
if (headEl) {
|
if (headEl) {
|
||||||
headerHeight = (headEl as HTMLElement).offsetHeight;
|
headerHeight = (headEl as HTMLElement).offsetHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
let bottomIncludeBody = 0;
|
let bottomIncludeBody = 0
|
||||||
if (unref(wrapRef) && isCanResizeParent) {
|
if (unref(wrapRef) && isCanResizeParent) {
|
||||||
const tablePadding = 12;
|
const tablePadding = 12
|
||||||
const formMargin = 16;
|
const formMargin = 16
|
||||||
let paginationMargin = 10;
|
let paginationMargin = 10
|
||||||
const wrapHeight = unref(wrapRef)?.offsetHeight ?? 0;
|
const wrapHeight = unref(wrapRef)?.offsetHeight ?? 0
|
||||||
|
|
||||||
let formHeight = unref(formRef)?.$el.offsetHeight ?? 0;
|
let formHeight = unref(formRef)?.$el.offsetHeight ?? 0
|
||||||
if (formHeight) {
|
if (formHeight) {
|
||||||
formHeight += formMargin;
|
formHeight += formMargin
|
||||||
}
|
}
|
||||||
if (isBoolean(pagination) && !pagination) {
|
if (isBoolean(pagination) && !pagination) {
|
||||||
paginationMargin = 0;
|
paginationMargin = 0
|
||||||
}
|
}
|
||||||
if (isBoolean(useSearchForm) && !useSearchForm) {
|
if (isBoolean(useSearchForm) && !useSearchForm) {
|
||||||
paddingHeight = 0;
|
paddingHeight = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
const headerCellHeight =
|
const headerCellHeight =
|
||||||
(tableEl.querySelector('.ant-table-title') as HTMLElement)?.offsetHeight ?? 0;
|
(tableEl.querySelector('.ant-table-title') as HTMLElement)?.offsetHeight ?? 0
|
||||||
|
|
||||||
console.log(wrapHeight - formHeight - headerCellHeight - tablePadding - paginationMargin);
|
console.log(wrapHeight - formHeight - headerCellHeight - tablePadding - paginationMargin)
|
||||||
bottomIncludeBody =
|
bottomIncludeBody =
|
||||||
wrapHeight - formHeight - headerCellHeight - tablePadding - paginationMargin;
|
wrapHeight - formHeight - headerCellHeight - tablePadding - paginationMargin
|
||||||
} else {
|
} else {
|
||||||
// Table height from bottom
|
// Table height from bottom
|
||||||
bottomIncludeBody = getViewportOffset(headEl).bottomIncludeBody;
|
bottomIncludeBody = getViewportOffset(headEl).bottomIncludeBody
|
||||||
}
|
}
|
||||||
|
|
||||||
let height =
|
let height =
|
||||||
|
|
@ -166,55 +164,55 @@ export function useTableScroll(
|
||||||
paddingHeight -
|
paddingHeight -
|
||||||
paginationHeight -
|
paginationHeight -
|
||||||
footerHeight -
|
footerHeight -
|
||||||
headerHeight;
|
headerHeight
|
||||||
height = (height > maxHeight! ? (maxHeight as number) : height) ?? height;
|
height = (height > maxHeight! ? (maxHeight as number) : height) ?? height
|
||||||
setHeight(height);
|
setHeight(height)
|
||||||
|
|
||||||
bodyEl!.style.height = `${height}px`;
|
bodyEl!.style.height = `${height}px`
|
||||||
}
|
}
|
||||||
useWindowSizeFn(calcTableHeight, 280);
|
useWindowSizeFn(calcTableHeight, 280)
|
||||||
onMountedOrActivated(() => {
|
onMountedOrActivated(() => {
|
||||||
calcTableHeight();
|
calcTableHeight()
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
debounceRedoHeight();
|
debounceRedoHeight()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
const getScrollX = computed(() => {
|
const getScrollX = computed(() => {
|
||||||
let width = 0;
|
let width = 0
|
||||||
if (unref(rowSelectionRef)) {
|
if (unref(rowSelectionRef)) {
|
||||||
width += 60;
|
width += 60
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO props ?? 0;
|
// TODO props ?? 0;
|
||||||
const NORMAL_WIDTH = 150;
|
const NORMAL_WIDTH = 150
|
||||||
|
|
||||||
const columns = unref(columnsRef).filter((item) => !item.defaultHidden);
|
const columns = unref(columnsRef).filter((item) => !item.defaultHidden)
|
||||||
columns.forEach((item) => {
|
columns.forEach((item) => {
|
||||||
width += Number.parseFloat(item.width as string) || 0;
|
width += Number.parseFloat(item.width as string) || 0
|
||||||
});
|
})
|
||||||
const unsetWidthColumns = columns.filter((item) => !Reflect.has(item, 'width'));
|
const unsetWidthColumns = columns.filter((item) => !Reflect.has(item, 'width'))
|
||||||
|
|
||||||
const len = unsetWidthColumns.length;
|
const len = unsetWidthColumns.length
|
||||||
if (len !== 0) {
|
if (len !== 0) {
|
||||||
width += len * NORMAL_WIDTH;
|
width += len * NORMAL_WIDTH
|
||||||
}
|
}
|
||||||
|
|
||||||
const table = unref(tableElRef);
|
const table = unref(tableElRef)
|
||||||
const tableWidth = table?.$el?.offsetWidth ?? 0;
|
const tableWidth = table?.$el?.offsetWidth ?? 0
|
||||||
return tableWidth > width ? '100%' : width;
|
return tableWidth > width ? '100%' : width
|
||||||
});
|
})
|
||||||
|
|
||||||
const getScrollRef = computed(() => {
|
const getScrollRef = computed(() => {
|
||||||
const tableHeight = unref(tableHeightRef);
|
const tableHeight = unref(tableHeightRef)
|
||||||
const { canResize, scroll } = unref(propsRef);
|
const { canResize, scroll } = unref(propsRef)
|
||||||
return {
|
return {
|
||||||
x: unref(getScrollX),
|
x: unref(getScrollX),
|
||||||
y: canResize ? tableHeight : null,
|
y: canResize ? tableHeight : null,
|
||||||
scrollToFirstRowOnChange: false,
|
scrollToFirstRowOnChange: false,
|
||||||
...scroll,
|
...scroll,
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
return { getScrollRef, redoHeight };
|
return { getScrollRef, redoHeight }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import type { PropType } from 'vue';
|
import type { PropType } from 'vue'
|
||||||
import type { PaginationProps } from './types/pagination';
|
import type { PaginationProps } from './types/pagination'
|
||||||
import type {
|
import type {
|
||||||
BasicColumn,
|
BasicColumn,
|
||||||
FetchSetting,
|
FetchSetting,
|
||||||
|
|
@ -8,11 +8,11 @@ import type {
|
||||||
TableCustomRecord,
|
TableCustomRecord,
|
||||||
TableRowSelection,
|
TableRowSelection,
|
||||||
SizeType,
|
SizeType,
|
||||||
} from './types/table';
|
} from './types/table'
|
||||||
import type { FormProps } from '/@/components/Form';
|
import type { FormProps } from '/@/components/Form'
|
||||||
|
|
||||||
import { DEFAULT_FILTER_FN, DEFAULT_SORT_FN, FETCH_SETTING, DEFAULT_SIZE } from './const';
|
import { DEFAULT_FILTER_FN, DEFAULT_SORT_FN, FETCH_SETTING, DEFAULT_SIZE } from './const'
|
||||||
import { propTypes } from '/@/utils/propTypes';
|
import { propTypes } from '/@/utils/propTypes'
|
||||||
|
|
||||||
export const basicProps = {
|
export const basicProps = {
|
||||||
clickToRowSelect: { type: Boolean, default: true },
|
clickToRowSelect: { type: Boolean, default: true },
|
||||||
|
|
@ -60,7 +60,7 @@ export const basicProps = {
|
||||||
fetchSetting: {
|
fetchSetting: {
|
||||||
type: Object as PropType<FetchSetting>,
|
type: Object as PropType<FetchSetting>,
|
||||||
default: () => {
|
default: () => {
|
||||||
return FETCH_SETTING;
|
return FETCH_SETTING
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// 立即请求接口
|
// 立即请求接口
|
||||||
|
|
@ -137,10 +137,10 @@ export const basicProps = {
|
||||||
beforeEditSubmit: {
|
beforeEditSubmit: {
|
||||||
type: Function as PropType<
|
type: Function as PropType<
|
||||||
(data: {
|
(data: {
|
||||||
record: Recordable;
|
record: Recordable
|
||||||
index: number;
|
index: number
|
||||||
key: string | number;
|
key: string | number
|
||||||
value: any;
|
value: any
|
||||||
}) => Promise<any>
|
}) => Promise<any>
|
||||||
>,
|
>,
|
||||||
},
|
},
|
||||||
|
|
@ -148,4 +148,4 @@ export const basicProps = {
|
||||||
type: String as PropType<SizeType>,
|
type: String as PropType<SizeType>,
|
||||||
default: DEFAULT_SIZE,
|
default: DEFAULT_SIZE,
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,4 +11,4 @@ export type ComponentType =
|
||||||
| 'TimePicker'
|
| 'TimePicker'
|
||||||
| 'RadioGroup'
|
| 'RadioGroup'
|
||||||
| 'RadioButtonGroup'
|
| 'RadioButtonGroup'
|
||||||
| 'ApiRadioGroup';
|
| 'ApiRadioGroup'
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import Pagination from 'ant-design-vue/lib/pagination';
|
import Pagination from 'ant-design-vue/lib/pagination'
|
||||||
import { VNodeChild } from 'vue';
|
import { VNodeChild } from 'vue'
|
||||||
|
|
||||||
interface PaginationRenderProps {
|
interface PaginationRenderProps {
|
||||||
page: number;
|
page: number
|
||||||
type: 'page' | 'prev' | 'next';
|
type: 'page' | 'prev' | 'next'
|
||||||
originalElement: any;
|
originalElement: any
|
||||||
}
|
}
|
||||||
|
|
||||||
type PaginationPositon =
|
type PaginationPositon =
|
||||||
|
|
@ -13,10 +13,10 @@ type PaginationPositon =
|
||||||
| 'topRight'
|
| 'topRight'
|
||||||
| 'bottomLeft'
|
| 'bottomLeft'
|
||||||
| 'bottomCenter'
|
| 'bottomCenter'
|
||||||
| 'bottomRight';
|
| 'bottomRight'
|
||||||
|
|
||||||
export declare class PaginationConfig extends Pagination {
|
export declare class PaginationConfig extends Pagination {
|
||||||
position?: PaginationPositon[];
|
position?: PaginationPositon[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PaginationProps {
|
export interface PaginationProps {
|
||||||
|
|
@ -25,91 +25,91 @@ export interface PaginationProps {
|
||||||
* @default 0
|
* @default 0
|
||||||
* @type number
|
* @type number
|
||||||
*/
|
*/
|
||||||
total?: number;
|
total?: number
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* default initial page number
|
* default initial page number
|
||||||
* @default 1
|
* @default 1
|
||||||
* @type number
|
* @type number
|
||||||
*/
|
*/
|
||||||
defaultCurrent?: number;
|
defaultCurrent?: number
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* current page number
|
* current page number
|
||||||
* @type number
|
* @type number
|
||||||
*/
|
*/
|
||||||
current?: number;
|
current?: number
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* default number of data items per page
|
* default number of data items per page
|
||||||
* @default 10
|
* @default 10
|
||||||
* @type number
|
* @type number
|
||||||
*/
|
*/
|
||||||
defaultPageSize?: number;
|
defaultPageSize?: number
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* number of data items per page
|
* number of data items per page
|
||||||
* @type number
|
* @type number
|
||||||
*/
|
*/
|
||||||
pageSize?: number;
|
pageSize?: number
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to hide pager on single page
|
* Whether to hide pager on single page
|
||||||
* @default false
|
* @default false
|
||||||
* @type boolean
|
* @type boolean
|
||||||
*/
|
*/
|
||||||
hideOnSinglePage?: boolean;
|
hideOnSinglePage?: boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* determine whether pageSize can be changed
|
* determine whether pageSize can be changed
|
||||||
* @default false
|
* @default false
|
||||||
* @type boolean
|
* @type boolean
|
||||||
*/
|
*/
|
||||||
showSizeChanger?: boolean;
|
showSizeChanger?: boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* specify the sizeChanger options
|
* specify the sizeChanger options
|
||||||
* @default ['10', '20', '30', '40']
|
* @default ['10', '20', '30', '40']
|
||||||
* @type string[]
|
* @type string[]
|
||||||
*/
|
*/
|
||||||
pageSizeOptions?: string[];
|
pageSizeOptions?: string[]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* determine whether you can jump to pages directly
|
* determine whether you can jump to pages directly
|
||||||
* @default false
|
* @default false
|
||||||
* @type boolean
|
* @type boolean
|
||||||
*/
|
*/
|
||||||
showQuickJumper?: boolean | object;
|
showQuickJumper?: boolean | object
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* to display the total number and range
|
* to display the total number and range
|
||||||
* @type Function
|
* @type Function
|
||||||
*/
|
*/
|
||||||
showTotal?: (total: number, range: [number, number]) => any;
|
showTotal?: (total: number, range: [number, number]) => any
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* specify the size of Pagination, can be set to small
|
* specify the size of Pagination, can be set to small
|
||||||
* @default ''
|
* @default ''
|
||||||
* @type string
|
* @type string
|
||||||
*/
|
*/
|
||||||
size?: string;
|
size?: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* whether to setting simple mode
|
* whether to setting simple mode
|
||||||
* @type boolean
|
* @type boolean
|
||||||
*/
|
*/
|
||||||
simple?: boolean;
|
simple?: boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* to customize item innerHTML
|
* to customize item innerHTML
|
||||||
* @type Function
|
* @type Function
|
||||||
*/
|
*/
|
||||||
itemRender?: (props: PaginationRenderProps) => VNodeChild | JSX.Element;
|
itemRender?: (props: PaginationRenderProps) => VNodeChild | JSX.Element
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* specify the position of Pagination
|
* specify the position of Pagination
|
||||||
* @default ['bottomRight']
|
* @default ['bottomRight']
|
||||||
* @type string[]
|
* @type string[]
|
||||||
*/
|
*/
|
||||||
position?: PaginationPositon[];
|
position?: PaginationPositon[]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
import type { VNodeChild } from 'vue';
|
import type { VNodeChild } from 'vue'
|
||||||
import type { PaginationProps } from './pagination';
|
import type { PaginationProps } from './pagination'
|
||||||
import type { FormProps } from '/@/components/Form';
|
import type { FormProps } from '/@/components/Form'
|
||||||
import type { TableRowSelection as ITableRowSelection } from 'ant-design-vue/lib/table/interface';
|
import type { TableRowSelection as ITableRowSelection } from 'ant-design-vue/lib/table/interface'
|
||||||
import type { ColumnProps } from 'ant-design-vue/lib/table';
|
import type { ColumnProps } from 'ant-design-vue/lib/table'
|
||||||
|
|
||||||
import { ComponentType } from './componentType';
|
import { ComponentType } from './componentType'
|
||||||
import { VueNode } from '/@/utils/propTypes';
|
import { VueNode } from '/@/utils/propTypes'
|
||||||
import { RoleEnum } from '/@/enums/roleEnum';
|
import { RoleEnum } from '/@/enums/roleEnum'
|
||||||
|
|
||||||
export declare type SortOrder = 'ascend' | 'descend';
|
export declare type SortOrder = 'ascend' | 'descend'
|
||||||
|
|
||||||
export interface TableCurrentDataSource<T = Recordable> {
|
export interface TableCurrentDataSource<T = Recordable> {
|
||||||
currentDataSource: T[];
|
currentDataSource: T[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TableRowSelection<T = any> extends ITableRowSelection {
|
export interface TableRowSelection<T = any> extends ITableRowSelection {
|
||||||
|
|
@ -19,289 +19,289 @@ export interface TableRowSelection<T = any> extends ITableRowSelection {
|
||||||
* Callback executed when selected rows change
|
* Callback executed when selected rows change
|
||||||
* @type Function
|
* @type Function
|
||||||
*/
|
*/
|
||||||
onChange?: (selectedRowKeys: string[] | number[], selectedRows: T[]) => any;
|
onChange?: (selectedRowKeys: string[] | number[], selectedRows: T[]) => any
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback executed when select/deselect one row
|
* Callback executed when select/deselect one row
|
||||||
* @type Function
|
* @type Function
|
||||||
*/
|
*/
|
||||||
onSelect?: (record: T, selected: boolean, selectedRows: Object[], nativeEvent: Event) => any;
|
onSelect?: (record: T, selected: boolean, selectedRows: Object[], nativeEvent: Event) => any
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback executed when select/deselect all rows
|
* Callback executed when select/deselect all rows
|
||||||
* @type Function
|
* @type Function
|
||||||
*/
|
*/
|
||||||
onSelectAll?: (selected: boolean, selectedRows: T[], changeRows: T[]) => any;
|
onSelectAll?: (selected: boolean, selectedRows: T[], changeRows: T[]) => any
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback executed when row selection is inverted
|
* Callback executed when row selection is inverted
|
||||||
* @type Function
|
* @type Function
|
||||||
*/
|
*/
|
||||||
onSelectInvert?: (selectedRows: string[] | number[]) => any;
|
onSelectInvert?: (selectedRows: string[] | number[]) => any
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TableCustomRecord<T> {
|
export interface TableCustomRecord<T> {
|
||||||
record?: T;
|
record?: T
|
||||||
index?: number;
|
index?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExpandedRowRenderRecord<T> extends TableCustomRecord<T> {
|
export interface ExpandedRowRenderRecord<T> extends TableCustomRecord<T> {
|
||||||
indent?: number;
|
indent?: number
|
||||||
expanded?: boolean;
|
expanded?: boolean
|
||||||
}
|
}
|
||||||
export interface ColumnFilterItem {
|
export interface ColumnFilterItem {
|
||||||
text?: string;
|
text?: string
|
||||||
value?: string;
|
value?: string
|
||||||
children?: any;
|
children?: any
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TableCustomRecord<T = Recordable> {
|
export interface TableCustomRecord<T = Recordable> {
|
||||||
record?: T;
|
record?: T
|
||||||
index?: number;
|
index?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SorterResult {
|
export interface SorterResult {
|
||||||
column: ColumnProps;
|
column: ColumnProps
|
||||||
order: SortOrder;
|
order: SortOrder
|
||||||
field: string;
|
field: string
|
||||||
columnKey: string;
|
columnKey: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FetchParams {
|
export interface FetchParams {
|
||||||
searchInfo?: Recordable;
|
searchInfo?: Recordable
|
||||||
page?: number;
|
page?: number
|
||||||
sortInfo?: Recordable;
|
sortInfo?: Recordable
|
||||||
filterInfo?: Recordable;
|
filterInfo?: Recordable
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GetColumnsParams {
|
export interface GetColumnsParams {
|
||||||
ignoreIndex?: boolean;
|
ignoreIndex?: boolean
|
||||||
ignoreAction?: boolean;
|
ignoreAction?: boolean
|
||||||
sort?: boolean;
|
sort?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SizeType = 'default' | 'middle' | 'small' | 'large';
|
export type SizeType = 'default' | 'middle' | 'small' | 'large'
|
||||||
|
|
||||||
export interface TableActionType {
|
export interface TableActionType {
|
||||||
reload: (opt?: FetchParams) => Promise<void>;
|
reload: (opt?: FetchParams) => Promise<void>
|
||||||
getSelectRows: <T = Recordable>() => T[];
|
getSelectRows: <T = Recordable>() => T[]
|
||||||
clearSelectedRowKeys: () => void;
|
clearSelectedRowKeys: () => void
|
||||||
expandAll: () => void;
|
expandAll: () => void
|
||||||
expandRows: (keys: string[] | number[]) => void;
|
expandRows: (keys: string[] | number[]) => void
|
||||||
collapseAll: () => void;
|
collapseAll: () => void
|
||||||
scrollTo: (pos: string) => void; // pos: id | "top" | "bottom"
|
scrollTo: (pos: string) => void // pos: id | "top" | "bottom"
|
||||||
getSelectRowKeys: () => string[];
|
getSelectRowKeys: () => string[]
|
||||||
deleteSelectRowByKey: (key: string) => void;
|
deleteSelectRowByKey: (key: string) => void
|
||||||
setPagination: (info: Partial<PaginationProps>) => void;
|
setPagination: (info: Partial<PaginationProps>) => void
|
||||||
setTableData: <T = Recordable>(values: T[]) => void;
|
setTableData: <T = Recordable>(values: T[]) => void
|
||||||
updateTableDataRecord: (rowKey: string | number, record: Recordable) => Recordable | void;
|
updateTableDataRecord: (rowKey: string | number, record: Recordable) => Recordable | void
|
||||||
deleteTableDataRecord: (rowKey: string | number | string[] | number[]) => void;
|
deleteTableDataRecord: (rowKey: string | number | string[] | number[]) => void
|
||||||
insertTableDataRecord: (record: Recordable, index?: number) => Recordable | void;
|
insertTableDataRecord: (record: Recordable, index?: number) => Recordable | void
|
||||||
findTableDataRecord: (rowKey: string | number) => Recordable | void;
|
findTableDataRecord: (rowKey: string | number) => Recordable | void
|
||||||
getColumns: (opt?: GetColumnsParams) => BasicColumn[];
|
getColumns: (opt?: GetColumnsParams) => BasicColumn[]
|
||||||
setColumns: (columns: BasicColumn[] | string[]) => void;
|
setColumns: (columns: BasicColumn[] | string[]) => void
|
||||||
getDataSource: <T = Recordable>() => T[];
|
getDataSource: <T = Recordable>() => T[]
|
||||||
getRawDataSource: <T = Recordable>() => T;
|
getRawDataSource: <T = Recordable>() => T
|
||||||
setLoading: (loading: boolean) => void;
|
setLoading: (loading: boolean) => void
|
||||||
setProps: (props: Partial<BasicTableProps>) => void;
|
setProps: (props: Partial<BasicTableProps>) => void
|
||||||
redoHeight: () => void;
|
redoHeight: () => void
|
||||||
setSelectedRowKeys: (rowKeys: string[] | number[]) => void;
|
setSelectedRowKeys: (rowKeys: string[] | number[]) => void
|
||||||
getPaginationRef: () => PaginationProps | boolean;
|
getPaginationRef: () => PaginationProps | boolean
|
||||||
getSize: () => SizeType;
|
getSize: () => SizeType
|
||||||
getRowSelection: () => TableRowSelection<Recordable>;
|
getRowSelection: () => TableRowSelection<Recordable>
|
||||||
getCacheColumns: () => BasicColumn[];
|
getCacheColumns: () => BasicColumn[]
|
||||||
emit?: EmitType;
|
emit?: EmitType
|
||||||
updateTableData: (index: number, key: string, value: any) => Recordable;
|
updateTableData: (index: number, key: string, value: any) => Recordable
|
||||||
setShowPagination: (show: boolean) => Promise<void>;
|
setShowPagination: (show: boolean) => Promise<void>
|
||||||
getShowPagination: () => boolean;
|
getShowPagination: () => boolean
|
||||||
setCacheColumnsByField?: (dataIndex: string | undefined, value: BasicColumn) => void;
|
setCacheColumnsByField?: (dataIndex: string | undefined, value: BasicColumn) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FetchSetting {
|
export interface FetchSetting {
|
||||||
// 请求接口当前页数
|
// 请求接口当前页数
|
||||||
pageField: string;
|
pageField: string
|
||||||
// 每页显示多少条
|
// 每页显示多少条
|
||||||
sizeField: string;
|
sizeField: string
|
||||||
// 请求结果列表字段 支持 a.b.c
|
// 请求结果列表字段 支持 a.b.c
|
||||||
listField: string;
|
listField: string
|
||||||
// 请求结果总数字段 支持 a.b.c
|
// 请求结果总数字段 支持 a.b.c
|
||||||
totalField: string;
|
totalField: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TableSetting {
|
export interface TableSetting {
|
||||||
redo?: boolean;
|
redo?: boolean
|
||||||
size?: boolean;
|
size?: boolean
|
||||||
setting?: boolean;
|
setting?: boolean
|
||||||
fullScreen?: boolean;
|
fullScreen?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BasicTableProps<T = any> {
|
export interface BasicTableProps<T = any> {
|
||||||
// 点击行选中
|
// 点击行选中
|
||||||
clickToRowSelect?: boolean;
|
clickToRowSelect?: boolean
|
||||||
isTreeTable?: boolean;
|
isTreeTable?: boolean
|
||||||
// 自定义排序方法
|
// 自定义排序方法
|
||||||
sortFn?: (sortInfo: SorterResult) => any;
|
sortFn?: (sortInfo: SorterResult) => any
|
||||||
// 排序方法
|
// 排序方法
|
||||||
filterFn?: (data: Partial<Recordable<string[]>>) => any;
|
filterFn?: (data: Partial<Recordable<string[]>>) => any
|
||||||
// 取消表格的默认padding
|
// 取消表格的默认padding
|
||||||
inset?: boolean;
|
inset?: boolean
|
||||||
// 显示表格设置
|
// 显示表格设置
|
||||||
showTableSetting?: boolean;
|
showTableSetting?: boolean
|
||||||
tableSetting?: TableSetting;
|
tableSetting?: TableSetting
|
||||||
// 斑马纹
|
// 斑马纹
|
||||||
striped?: boolean;
|
striped?: boolean
|
||||||
// 是否自动生成key
|
// 是否自动生成key
|
||||||
autoCreateKey?: boolean;
|
autoCreateKey?: boolean
|
||||||
// 计算合计行的方法
|
// 计算合计行的方法
|
||||||
summaryFunc?: (...arg: any) => Recordable[];
|
summaryFunc?: (...arg: any) => Recordable[]
|
||||||
// 自定义合计表格内容
|
// 自定义合计表格内容
|
||||||
summaryData?: Recordable[];
|
summaryData?: Recordable[]
|
||||||
// 是否显示合计行
|
// 是否显示合计行
|
||||||
showSummary?: boolean;
|
showSummary?: boolean
|
||||||
// 是否可拖拽列
|
// 是否可拖拽列
|
||||||
canColDrag?: boolean;
|
canColDrag?: boolean
|
||||||
// 接口请求对象
|
// 接口请求对象
|
||||||
api?: (...arg: any) => Promise<any>;
|
api?: (...arg: any) => Promise<any>
|
||||||
// 请求之前处理参数
|
// 请求之前处理参数
|
||||||
beforeFetch?: Fn;
|
beforeFetch?: Fn
|
||||||
// 自定义处理接口返回参数
|
// 自定义处理接口返回参数
|
||||||
afterFetch?: Fn;
|
afterFetch?: Fn
|
||||||
// 查询条件请求之前处理
|
// 查询条件请求之前处理
|
||||||
handleSearchInfoFn?: Fn;
|
handleSearchInfoFn?: Fn
|
||||||
// 请求接口配置
|
// 请求接口配置
|
||||||
fetchSetting?: Partial<FetchSetting>;
|
fetchSetting?: Partial<FetchSetting>
|
||||||
// 立即请求接口
|
// 立即请求接口
|
||||||
immediate?: boolean;
|
immediate?: boolean
|
||||||
// 在开起搜索表单的时候,如果没有数据是否显示表格
|
// 在开起搜索表单的时候,如果没有数据是否显示表格
|
||||||
emptyDataIsShowTable?: boolean;
|
emptyDataIsShowTable?: boolean
|
||||||
// 额外的请求参数
|
// 额外的请求参数
|
||||||
searchInfo?: Recordable;
|
searchInfo?: Recordable
|
||||||
// 默认的排序参数
|
// 默认的排序参数
|
||||||
defSort?: Recordable;
|
defSort?: Recordable
|
||||||
// 使用搜索表单
|
// 使用搜索表单
|
||||||
useSearchForm?: boolean;
|
useSearchForm?: boolean
|
||||||
// 表单配置
|
// 表单配置
|
||||||
formConfig?: Partial<FormProps>;
|
formConfig?: Partial<FormProps>
|
||||||
// 列配置
|
// 列配置
|
||||||
columns: BasicColumn[];
|
columns: BasicColumn[]
|
||||||
// 是否显示序号列
|
// 是否显示序号列
|
||||||
showIndexColumn?: boolean;
|
showIndexColumn?: boolean
|
||||||
// 序号列配置
|
// 序号列配置
|
||||||
indexColumnProps?: BasicColumn;
|
indexColumnProps?: BasicColumn
|
||||||
actionColumn?: BasicColumn;
|
actionColumn?: BasicColumn
|
||||||
// 文本超过宽度是否显示。。。
|
// 文本超过宽度是否显示。。。
|
||||||
ellipsis?: boolean;
|
ellipsis?: boolean
|
||||||
// 是否继承父级高度(父级高度-表单高度-padding高度)
|
// 是否继承父级高度(父级高度-表单高度-padding高度)
|
||||||
isCanResizeParent?: boolean;
|
isCanResizeParent?: boolean
|
||||||
// 是否可以自适应高度
|
// 是否可以自适应高度
|
||||||
canResize?: boolean;
|
canResize?: boolean
|
||||||
// 自适应高度偏移, 计算结果-偏移量
|
// 自适应高度偏移, 计算结果-偏移量
|
||||||
resizeHeightOffset?: number;
|
resizeHeightOffset?: number
|
||||||
|
|
||||||
// 在分页改变的时候清空选项
|
// 在分页改变的时候清空选项
|
||||||
clearSelectOnPageChange?: boolean;
|
clearSelectOnPageChange?: boolean
|
||||||
//
|
//
|
||||||
rowKey?: string | ((record: Recordable) => string);
|
rowKey?: string | ((record: Recordable) => string)
|
||||||
// 数据
|
// 数据
|
||||||
dataSource?: Recordable[];
|
dataSource?: Recordable[]
|
||||||
// 标题右侧提示
|
// 标题右侧提示
|
||||||
titleHelpMessage?: string | string[];
|
titleHelpMessage?: string | string[]
|
||||||
// 表格滚动最大高度
|
// 表格滚动最大高度
|
||||||
maxHeight?: number;
|
maxHeight?: number
|
||||||
// 是否显示边框
|
// 是否显示边框
|
||||||
bordered?: boolean;
|
bordered?: boolean
|
||||||
// 分页配置
|
// 分页配置
|
||||||
pagination?: PaginationProps | boolean;
|
pagination?: PaginationProps | boolean
|
||||||
// loading加载
|
// loading加载
|
||||||
loading?: boolean;
|
loading?: boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The column contains children to display
|
* The column contains children to display
|
||||||
* @default 'children'
|
* @default 'children'
|
||||||
* @type string | string[]
|
* @type string | string[]
|
||||||
*/
|
*/
|
||||||
childrenColumnName?: string;
|
childrenColumnName?: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override default table elements
|
* Override default table elements
|
||||||
* @type object
|
* @type object
|
||||||
*/
|
*/
|
||||||
components?: object;
|
components?: object
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expand all rows initially
|
* Expand all rows initially
|
||||||
* @default false
|
* @default false
|
||||||
* @type boolean
|
* @type boolean
|
||||||
*/
|
*/
|
||||||
defaultExpandAllRows?: boolean;
|
defaultExpandAllRows?: boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initial expanded row keys
|
* Initial expanded row keys
|
||||||
* @type string[]
|
* @type string[]
|
||||||
*/
|
*/
|
||||||
defaultExpandedRowKeys?: string[];
|
defaultExpandedRowKeys?: string[]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current expanded row keys
|
* Current expanded row keys
|
||||||
* @type string[]
|
* @type string[]
|
||||||
*/
|
*/
|
||||||
expandedRowKeys?: string[];
|
expandedRowKeys?: string[]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expanded container render for each row
|
* Expanded container render for each row
|
||||||
* @type Function
|
* @type Function
|
||||||
*/
|
*/
|
||||||
expandedRowRender?: (record?: ExpandedRowRenderRecord<T>) => VNodeChild | JSX.Element;
|
expandedRowRender?: (record?: ExpandedRowRenderRecord<T>) => VNodeChild | JSX.Element
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Customize row expand Icon.
|
* Customize row expand Icon.
|
||||||
* @type Function | VNodeChild
|
* @type Function | VNodeChild
|
||||||
*/
|
*/
|
||||||
expandIcon?: Function | VNodeChild | JSX.Element;
|
expandIcon?: Function | VNodeChild | JSX.Element
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to expand row by clicking anywhere in the whole row
|
* Whether to expand row by clicking anywhere in the whole row
|
||||||
* @default false
|
* @default false
|
||||||
* @type boolean
|
* @type boolean
|
||||||
*/
|
*/
|
||||||
expandRowByClick?: boolean;
|
expandRowByClick?: boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The index of `expandIcon` which column will be inserted when `expandIconAsCell` is false. default 0
|
* The index of `expandIcon` which column will be inserted when `expandIconAsCell` is false. default 0
|
||||||
*/
|
*/
|
||||||
expandIconColumnIndex?: number;
|
expandIconColumnIndex?: number
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table footer renderer
|
* Table footer renderer
|
||||||
* @type Function | VNodeChild
|
* @type Function | VNodeChild
|
||||||
*/
|
*/
|
||||||
footer?: Function | VNodeChild | JSX.Element;
|
footer?: Function | VNodeChild | JSX.Element
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indent size in pixels of tree data
|
* Indent size in pixels of tree data
|
||||||
* @default 15
|
* @default 15
|
||||||
* @type number
|
* @type number
|
||||||
*/
|
*/
|
||||||
indentSize?: number;
|
indentSize?: number
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* i18n text including filter, sort, empty text, etc
|
* i18n text including filter, sort, empty text, etc
|
||||||
* @default { filterConfirm: 'Ok', filterReset: 'Reset', emptyText: 'No Data' }
|
* @default { filterConfirm: 'Ok', filterReset: 'Reset', emptyText: 'No Data' }
|
||||||
* @type object
|
* @type object
|
||||||
*/
|
*/
|
||||||
locale?: object;
|
locale?: object
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Row's className
|
* Row's className
|
||||||
* @type Function
|
* @type Function
|
||||||
*/
|
*/
|
||||||
rowClassName?: (record: TableCustomRecord<T>, index: number) => string;
|
rowClassName?: (record: TableCustomRecord<T>, index: number) => string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Row selection config
|
* Row selection config
|
||||||
* @type object
|
* @type object
|
||||||
*/
|
*/
|
||||||
rowSelection?: TableRowSelection;
|
rowSelection?: TableRowSelection
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set horizontal or vertical scrolling, can also be used to specify the width and height of the scroll area.
|
* Set horizontal or vertical scrolling, can also be used to specify the width and height of the scroll area.
|
||||||
|
|
@ -309,39 +309,39 @@ export interface BasicTableProps<T = any> {
|
||||||
* you need to add style .ant-table td { white-space: nowrap; }.
|
* you need to add style .ant-table td { white-space: nowrap; }.
|
||||||
* @type object
|
* @type object
|
||||||
*/
|
*/
|
||||||
scroll?: { x?: number | true; y?: number };
|
scroll?: { x?: number | true; y?: number }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to show table header
|
* Whether to show table header
|
||||||
* @default true
|
* @default true
|
||||||
* @type boolean
|
* @type boolean
|
||||||
*/
|
*/
|
||||||
showHeader?: boolean;
|
showHeader?: boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Size of table
|
* Size of table
|
||||||
* @default 'default'
|
* @default 'default'
|
||||||
* @type string
|
* @type string
|
||||||
*/
|
*/
|
||||||
size?: SizeType;
|
size?: SizeType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table title renderer
|
* Table title renderer
|
||||||
* @type Function | ScopedSlot
|
* @type Function | ScopedSlot
|
||||||
*/
|
*/
|
||||||
title?: VNodeChild | JSX.Element | string | ((data: Recordable) => string);
|
title?: VNodeChild | JSX.Element | string | ((data: Recordable) => string)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set props on per header row
|
* Set props on per header row
|
||||||
* @type Function
|
* @type Function
|
||||||
*/
|
*/
|
||||||
customHeaderRow?: (column: ColumnProps, index: number) => object;
|
customHeaderRow?: (column: ColumnProps, index: number) => object
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set props on per row
|
* Set props on per row
|
||||||
* @type Function
|
* @type Function
|
||||||
*/
|
*/
|
||||||
customRow?: (record: T, index: number) => object;
|
customRow?: (record: T, index: number) => object
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `table-layout` attribute of table element
|
* `table-layout` attribute of table element
|
||||||
|
|
@ -350,14 +350,14 @@ export interface BasicTableProps<T = any> {
|
||||||
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/table-layout
|
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/table-layout
|
||||||
* @version 1.5.0
|
* @version 1.5.0
|
||||||
*/
|
*/
|
||||||
tableLayout?: 'auto' | 'fixed' | string;
|
tableLayout?: 'auto' | 'fixed' | string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the render container of dropdowns in table
|
* the render container of dropdowns in table
|
||||||
* @param triggerNode
|
* @param triggerNode
|
||||||
* @version 1.5.0
|
* @version 1.5.0
|
||||||
*/
|
*/
|
||||||
getPopupContainer?: (triggerNode?: HTMLElement) => HTMLElement;
|
getPopupContainer?: (triggerNode?: HTMLElement) => HTMLElement
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data can be changed again before rendering.
|
* Data can be changed again before rendering.
|
||||||
|
|
@ -366,7 +366,7 @@ export interface BasicTableProps<T = any> {
|
||||||
*
|
*
|
||||||
* @version 1.5.4
|
* @version 1.5.4
|
||||||
*/
|
*/
|
||||||
transformCellText?: Function;
|
transformCellText?: Function
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback executed before editable cell submit value, not for row-editor
|
* Callback executed before editable cell submit value, not for row-editor
|
||||||
|
|
@ -374,11 +374,11 @@ export interface BasicTableProps<T = any> {
|
||||||
* The cell will not submit data while callback return false
|
* The cell will not submit data while callback return false
|
||||||
*/
|
*/
|
||||||
beforeEditSubmit?: (data: {
|
beforeEditSubmit?: (data: {
|
||||||
record: Recordable;
|
record: Recordable
|
||||||
index: number;
|
index: number
|
||||||
key: string | number;
|
key: string | number
|
||||||
value: any;
|
value: any
|
||||||
}) => Promise<any>;
|
}) => Promise<any>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback executed when pagination, filters or sorter is changed
|
* Callback executed when pagination, filters or sorter is changed
|
||||||
|
|
@ -387,7 +387,7 @@ export interface BasicTableProps<T = any> {
|
||||||
* @param sorter
|
* @param sorter
|
||||||
* @param currentDataSource
|
* @param currentDataSource
|
||||||
*/
|
*/
|
||||||
onChange?: (pagination: any, filters: any, sorter: any, extra: any) => void;
|
onChange?: (pagination: any, filters: any, sorter: any, extra: any) => void
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback executed when the row expand icon is clicked
|
* Callback executed when the row expand icon is clicked
|
||||||
|
|
@ -395,84 +395,84 @@ export interface BasicTableProps<T = any> {
|
||||||
* @param expanded
|
* @param expanded
|
||||||
* @param record
|
* @param record
|
||||||
*/
|
*/
|
||||||
onExpand?: (expande: boolean, record: T) => void;
|
onExpand?: (expande: boolean, record: T) => void
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback executed when the expanded rows change
|
* Callback executed when the expanded rows change
|
||||||
* @param expandedRows
|
* @param expandedRows
|
||||||
*/
|
*/
|
||||||
onExpandedRowsChange?: (expandedRows: string[] | number[]) => void;
|
onExpandedRowsChange?: (expandedRows: string[] | number[]) => void
|
||||||
|
|
||||||
onColumnsChange?: (data: ColumnChangeParam[]) => void;
|
onColumnsChange?: (data: ColumnChangeParam[]) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CellFormat =
|
export type CellFormat =
|
||||||
| string
|
| string
|
||||||
| ((text: string, record: Recordable, index: number) => string | number)
|
| ((text: string, record: Recordable, index: number) => string | number)
|
||||||
| Map<string | number, any>;
|
| Map<string | number, any>
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
export interface BasicColumn extends ColumnProps<Recordable> {
|
export interface BasicColumn extends ColumnProps<Recordable> {
|
||||||
children?: BasicColumn[];
|
children?: BasicColumn[]
|
||||||
filters?: {
|
filters?: {
|
||||||
text: string;
|
text: string
|
||||||
value: string;
|
value: string
|
||||||
children?:
|
children?:
|
||||||
| unknown[]
|
| unknown[]
|
||||||
| (((props: Record<string, unknown>) => unknown[]) & (() => unknown[]) & (() => unknown[]));
|
| (((props: Record<string, unknown>) => unknown[]) & (() => unknown[]) & (() => unknown[]))
|
||||||
}[];
|
}[]
|
||||||
|
|
||||||
//
|
//
|
||||||
flag?: 'INDEX' | 'DEFAULT' | 'CHECKBOX' | 'RADIO' | 'ACTION';
|
flag?: 'INDEX' | 'DEFAULT' | 'CHECKBOX' | 'RADIO' | 'ACTION'
|
||||||
customTitle?: VueNode;
|
customTitle?: VueNode
|
||||||
|
|
||||||
slots?: Recordable;
|
slots?: Recordable
|
||||||
|
|
||||||
// Whether to hide the column by default, it can be displayed in the column configuration
|
// Whether to hide the column by default, it can be displayed in the column configuration
|
||||||
defaultHidden?: boolean;
|
defaultHidden?: boolean
|
||||||
|
|
||||||
// Help text for table column header
|
// Help text for table column header
|
||||||
helpMessage?: string | string[];
|
helpMessage?: string | string[]
|
||||||
|
|
||||||
format?: CellFormat;
|
format?: CellFormat
|
||||||
|
|
||||||
// Editable
|
// Editable
|
||||||
edit?: boolean;
|
edit?: boolean
|
||||||
editRow?: boolean;
|
editRow?: boolean
|
||||||
editable?: boolean;
|
editable?: boolean
|
||||||
editComponent?: ComponentType;
|
editComponent?: ComponentType
|
||||||
editComponentProps?:
|
editComponentProps?:
|
||||||
| ((opt: {
|
| ((opt: {
|
||||||
text: string | number | boolean | Recordable;
|
text: string | number | boolean | Recordable
|
||||||
record: Recordable;
|
record: Recordable
|
||||||
column: BasicColumn;
|
column: BasicColumn
|
||||||
index: number;
|
index: number
|
||||||
}) => Recordable)
|
}) => Recordable)
|
||||||
| 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
|
||||||
// 权限编码控制是否显示
|
// 权限编码控制是否显示
|
||||||
auth?: RoleEnum | RoleEnum[] | string | string[];
|
auth?: RoleEnum | RoleEnum[] | string | string[]
|
||||||
// 业务控制是否显示
|
// 业务控制是否显示
|
||||||
ifShow?: boolean | ((column: BasicColumn) => boolean);
|
ifShow?: boolean | ((column: BasicColumn) => boolean)
|
||||||
// 自定义修改后显示的内容
|
// 自定义修改后显示的内容
|
||||||
editRender?: (opt: {
|
editRender?: (opt: {
|
||||||
text: string | number | boolean | Recordable;
|
text: string | number | boolean | Recordable
|
||||||
record: Recordable;
|
record: Recordable
|
||||||
column: BasicColumn;
|
column: BasicColumn
|
||||||
index: number;
|
index: number
|
||||||
}) => VNodeChild | JSX.Element;
|
}) => VNodeChild | JSX.Element
|
||||||
// 动态 Disabled
|
// 动态 Disabled
|
||||||
editDynamicDisabled?: boolean | ((record: Recordable) => boolean);
|
editDynamicDisabled?: boolean | ((record: Recordable) => boolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ColumnChangeParam = {
|
export type ColumnChangeParam = {
|
||||||
dataIndex: string;
|
dataIndex: string
|
||||||
fixed: boolean | 'left' | 'right' | undefined;
|
fixed: boolean | 'left' | 'right' | undefined
|
||||||
visible: boolean;
|
visible: boolean
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface InnerHandlers {
|
export interface InnerHandlers {
|
||||||
onColumnsChange: (data: ColumnChangeParam[]) => void;
|
onColumnsChange: (data: ColumnChangeParam[]) => void
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,28 @@
|
||||||
import { ButtonProps } from 'ant-design-vue/es/button/buttonTypes';
|
import { ButtonProps } from 'ant-design-vue/es/button/buttonTypes'
|
||||||
import { TooltipProps } from 'ant-design-vue/es/tooltip/Tooltip';
|
import { TooltipProps } from 'ant-design-vue/es/tooltip/Tooltip'
|
||||||
import { RoleEnum } from '/@/enums/roleEnum';
|
import { RoleEnum } from '/@/enums/roleEnum'
|
||||||
export interface ActionItem extends ButtonProps {
|
export interface ActionItem extends ButtonProps {
|
||||||
onClick?: Fn;
|
onClick?: Fn
|
||||||
label?: string;
|
label?: string
|
||||||
color?: 'success' | 'error' | 'warning';
|
color?: 'success' | 'error' | 'warning'
|
||||||
icon?: string;
|
icon?: string
|
||||||
popConfirm?: PopConfirm;
|
popConfirm?: PopConfirm
|
||||||
disabled?: boolean;
|
disabled?: boolean
|
||||||
divider?: boolean;
|
divider?: boolean
|
||||||
// 权限编码控制是否显示
|
// 权限编码控制是否显示
|
||||||
auth?: RoleEnum | RoleEnum[] | string | string[];
|
auth?: RoleEnum | RoleEnum[] | string | string[]
|
||||||
// 业务控制是否显示
|
// 业务控制是否显示
|
||||||
ifShow?: boolean | ((action: ActionItem) => boolean);
|
ifShow?: boolean | ((action: ActionItem) => boolean)
|
||||||
tooltip?: string | TooltipProps;
|
tooltip?: string | TooltipProps
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PopConfirm {
|
export interface PopConfirm {
|
||||||
title: string;
|
title: string
|
||||||
okText?: string;
|
okText?: string
|
||||||
cancelText?: string;
|
cancelText?: string
|
||||||
confirm: Fn;
|
confirm: Fn
|
||||||
cancel?: Fn;
|
cancel?: Fn
|
||||||
icon?: string;
|
icon?: string
|
||||||
placement?:
|
placement?:
|
||||||
| 'top'
|
| 'top'
|
||||||
| 'left'
|
| 'left'
|
||||||
|
|
@ -35,5 +35,5 @@ export interface PopConfirm {
|
||||||
| 'rightTop'
|
| 'rightTop'
|
||||||
| 'rightBottom'
|
| 'rightBottom'
|
||||||
| 'bottomLeft'
|
| 'bottomLeft'
|
||||||
| 'bottomRight';
|
| 'bottomRight'
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,16 +36,16 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, ref, watch, unref, computed } from 'vue';
|
import { defineComponent, ref, watch, unref, computed } from 'vue'
|
||||||
import { Icon } from '/@/components/Icon';
|
import { Icon } from '/@/components/Icon'
|
||||||
import { Tooltip, Space } from 'ant-design-vue';
|
import { Tooltip, Space } from 'ant-design-vue'
|
||||||
import { useModal } from '/@/components/Modal';
|
import { useModal } from '/@/components/Modal'
|
||||||
import { uploadContainerProps } from './props';
|
import { uploadContainerProps } from './props'
|
||||||
import { omit } from 'lodash-es';
|
import { omit } from 'lodash-es'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
import { isArray } from '/@/utils/is';
|
import { isArray } from '/@/utils/is'
|
||||||
import UploadModal from './UploadModal.vue';
|
import UploadModal from './UploadModal.vue'
|
||||||
import UploadPreviewModal from './UploadPreviewModal.vue';
|
import UploadPreviewModal from './UploadPreviewModal.vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'BasicUpload',
|
name: 'BasicUpload',
|
||||||
|
|
@ -54,54 +54,54 @@
|
||||||
emits: ['change', 'delete', 'preview-delete', 'update:value'],
|
emits: ['change', 'delete', 'preview-delete', 'update:value'],
|
||||||
|
|
||||||
setup(props, { emit, attrs }) {
|
setup(props, { emit, attrs }) {
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
// 上传modal
|
// 上传modal
|
||||||
const [registerUploadModal, { openModal: openUploadModal }] = useModal();
|
const [registerUploadModal, { openModal: openUploadModal }] = useModal()
|
||||||
|
|
||||||
// 预览modal
|
// 预览modal
|
||||||
const [registerPreviewModal, { openModal: openPreviewModal }] = useModal();
|
const [registerPreviewModal, { openModal: openPreviewModal }] = useModal()
|
||||||
|
|
||||||
const fileList = ref<string[]>([]);
|
const fileList = ref<string[]>([])
|
||||||
|
|
||||||
const showPreview = computed(() => {
|
const showPreview = computed(() => {
|
||||||
const { emptyHidePreview } = props;
|
const { emptyHidePreview } = props
|
||||||
if (!emptyHidePreview) return true;
|
if (!emptyHidePreview) return true
|
||||||
return emptyHidePreview ? fileList.value.length > 0 : true;
|
return emptyHidePreview ? fileList.value.length > 0 : true
|
||||||
});
|
})
|
||||||
|
|
||||||
const bindValue = computed(() => {
|
const bindValue = computed(() => {
|
||||||
const value = { ...attrs, ...props };
|
const value = { ...attrs, ...props }
|
||||||
return omit(value, 'onChange');
|
return omit(value, 'onChange')
|
||||||
});
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.value,
|
() => props.value,
|
||||||
(value = []) => {
|
(value = []) => {
|
||||||
fileList.value = isArray(value) ? value : [];
|
fileList.value = isArray(value) ? value : []
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
);
|
)
|
||||||
|
|
||||||
// 上传modal保存操作
|
// 上传modal保存操作
|
||||||
function handleChange(urls: string[]) {
|
function handleChange(urls: string[]) {
|
||||||
fileList.value = [...unref(fileList), ...(urls || [])];
|
fileList.value = [...unref(fileList), ...(urls || [])]
|
||||||
emit('update:value', fileList.value);
|
emit('update:value', fileList.value)
|
||||||
emit('change', fileList.value);
|
emit('change', fileList.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 预览modal保存操作
|
// 预览modal保存操作
|
||||||
function handlePreviewChange(urls: string[]) {
|
function handlePreviewChange(urls: string[]) {
|
||||||
fileList.value = [...(urls || [])];
|
fileList.value = [...(urls || [])]
|
||||||
emit('update:value', fileList.value);
|
emit('update:value', fileList.value)
|
||||||
emit('change', fileList.value);
|
emit('change', fileList.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDelete(record: Recordable) {
|
function handleDelete(record: Recordable) {
|
||||||
emit('delete', record);
|
emit('delete', record)
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePreviewDelete(url: string) {
|
function handlePreviewDelete(url: string) {
|
||||||
emit('preview-delete', url);
|
emit('preview-delete', url)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -117,7 +117,7 @@
|
||||||
handleDelete,
|
handleDelete,
|
||||||
handlePreviewDelete,
|
handlePreviewDelete,
|
||||||
t,
|
t,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -43,24 +43,24 @@
|
||||||
</BasicModal>
|
</BasicModal>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, reactive, ref, toRefs, unref, computed, PropType } from 'vue';
|
import { defineComponent, reactive, ref, toRefs, unref, computed, PropType } from 'vue'
|
||||||
import { Upload, Alert } from 'ant-design-vue';
|
import { Upload, Alert } from 'ant-design-vue'
|
||||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
import { BasicModal, useModalInner } from '/@/components/Modal'
|
||||||
// import { BasicTable, useTable } from '/@/components/Table';
|
// import { BasicTable, useTable } from '/@/components/Table';
|
||||||
// hooks
|
// hooks
|
||||||
import { useUploadType } from './useUpload';
|
import { useUploadType } from './useUpload'
|
||||||
import { useMessage } from '/@/hooks/web/useMessage';
|
import { useMessage } from '/@/hooks/web/useMessage'
|
||||||
// types
|
// types
|
||||||
import { FileItem, UploadResultStatus } from './typing';
|
import { FileItem, UploadResultStatus } from './typing'
|
||||||
import { basicProps } from './props';
|
import { basicProps } from './props'
|
||||||
import { createTableColumns, createActionColumn } from './data';
|
import { createTableColumns, createActionColumn } from './data'
|
||||||
// utils
|
// utils
|
||||||
import { checkImgType, getBase64WithFile } from './helper';
|
import { checkImgType, getBase64WithFile } from './helper'
|
||||||
import { buildUUID } from '/@/utils/uuid';
|
import { buildUUID } from '/@/utils/uuid'
|
||||||
import { isFunction } from '/@/utils/is';
|
import { isFunction } from '/@/utils/is'
|
||||||
import { warn } from '/@/utils/log';
|
import { warn } from '/@/utils/log'
|
||||||
import FileList from './FileList.vue';
|
import FileList from './FileList.vue'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: { BasicModal, Upload, Alert, FileList },
|
components: { BasicModal, Upload, Alert, FileList },
|
||||||
|
|
@ -75,60 +75,58 @@
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const state = reactive<{ fileList: FileItem[] }>({
|
const state = reactive<{ fileList: FileItem[] }>({
|
||||||
fileList: [],
|
fileList: [],
|
||||||
});
|
})
|
||||||
|
|
||||||
// 是否正在上传
|
// 是否正在上传
|
||||||
const isUploadingRef = ref(false);
|
const isUploadingRef = ref(false)
|
||||||
const fileListRef = ref<FileItem[]>([]);
|
const fileListRef = ref<FileItem[]>([])
|
||||||
const { accept, helpText, maxNumber, maxSize } = toRefs(props);
|
const { accept, helpText, maxNumber, maxSize } = toRefs(props)
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
const [register, { closeModal }] = useModalInner();
|
const [register, { closeModal }] = useModalInner()
|
||||||
|
|
||||||
const { getStringAccept, getHelpText } = useUploadType({
|
const { getStringAccept, getHelpText } = useUploadType({
|
||||||
acceptRef: accept,
|
acceptRef: accept,
|
||||||
helpTextRef: helpText,
|
helpTextRef: helpText,
|
||||||
maxNumberRef: maxNumber,
|
maxNumberRef: maxNumber,
|
||||||
maxSizeRef: maxSize,
|
maxSizeRef: maxSize,
|
||||||
});
|
})
|
||||||
|
|
||||||
const { createMessage } = useMessage();
|
const { createMessage } = useMessage()
|
||||||
|
|
||||||
const getIsSelectFile = computed(() => {
|
const getIsSelectFile = computed(() => {
|
||||||
return (
|
return (
|
||||||
fileListRef.value.length > 0 &&
|
fileListRef.value.length > 0 &&
|
||||||
!fileListRef.value.every((item) => item.status === UploadResultStatus.SUCCESS)
|
!fileListRef.value.every((item) => item.status === UploadResultStatus.SUCCESS)
|
||||||
);
|
)
|
||||||
});
|
})
|
||||||
|
|
||||||
const getOkButtonProps = computed(() => {
|
const getOkButtonProps = computed(() => {
|
||||||
const someSuccess = fileListRef.value.some(
|
const someSuccess = fileListRef.value.some(
|
||||||
(item) => item.status === UploadResultStatus.SUCCESS,
|
(item) => item.status === UploadResultStatus.SUCCESS,
|
||||||
);
|
)
|
||||||
return {
|
return {
|
||||||
disabled: isUploadingRef.value || fileListRef.value.length === 0 || !someSuccess,
|
disabled: isUploadingRef.value || fileListRef.value.length === 0 || !someSuccess,
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
const getUploadBtnText = computed(() => {
|
const getUploadBtnText = computed(() => {
|
||||||
const someError = fileListRef.value.some(
|
const someError = fileListRef.value.some((item) => item.status === UploadResultStatus.ERROR)
|
||||||
(item) => item.status === UploadResultStatus.ERROR,
|
|
||||||
);
|
|
||||||
return isUploadingRef.value
|
return isUploadingRef.value
|
||||||
? t('component.upload.uploading')
|
? t('component.upload.uploading')
|
||||||
: someError
|
: someError
|
||||||
? t('component.upload.reUploadFailed')
|
? t('component.upload.reUploadFailed')
|
||||||
: t('component.upload.startUpload');
|
: t('component.upload.startUpload')
|
||||||
});
|
})
|
||||||
|
|
||||||
// 上传前校验
|
// 上传前校验
|
||||||
function beforeUpload(file: File) {
|
function beforeUpload(file: File) {
|
||||||
const { size, name } = file;
|
const { size, name } = file
|
||||||
const { maxSize } = props;
|
const { maxSize } = props
|
||||||
// 设置最大值,则判断
|
// 设置最大值,则判断
|
||||||
if (maxSize && file.size / 1024 / 1024 >= maxSize) {
|
if (maxSize && file.size / 1024 / 1024 >= maxSize) {
|
||||||
createMessage.error(t('component.upload.maxSizeMultiple', [maxSize]));
|
createMessage.error(t('component.upload.maxSizeMultiple', [maxSize]))
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const commonItem = {
|
const commonItem = {
|
||||||
|
|
@ -138,7 +136,7 @@
|
||||||
name,
|
name,
|
||||||
percent: 0,
|
percent: 0,
|
||||||
type: name.split('.').pop(),
|
type: name.split('.').pop(),
|
||||||
};
|
}
|
||||||
// 生成图片缩略图
|
// 生成图片缩略图
|
||||||
if (checkImgType(file)) {
|
if (checkImgType(file)) {
|
||||||
// beforeUpload,如果异步会调用自带上传方法
|
// beforeUpload,如果异步会调用自带上传方法
|
||||||
|
|
@ -150,19 +148,19 @@
|
||||||
thumbUrl,
|
thumbUrl,
|
||||||
...commonItem,
|
...commonItem,
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
fileListRef.value = [...unref(fileListRef), commonItem];
|
fileListRef.value = [...unref(fileListRef), commonItem]
|
||||||
}
|
}
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除
|
// 删除
|
||||||
function handleRemove(record: FileItem) {
|
function handleRemove(record: FileItem) {
|
||||||
const index = fileListRef.value.findIndex((item) => item.uuid === record.uuid);
|
const index = fileListRef.value.findIndex((item) => item.uuid === record.uuid)
|
||||||
index !== -1 && fileListRef.value.splice(index, 1);
|
index !== -1 && fileListRef.value.splice(index, 1)
|
||||||
emit('delete', record);
|
emit('delete', record)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 预览
|
// 预览
|
||||||
|
|
@ -174,12 +172,12 @@
|
||||||
// }
|
// }
|
||||||
|
|
||||||
async function uploadApiByItem(item: FileItem) {
|
async function uploadApiByItem(item: FileItem) {
|
||||||
const { api } = props;
|
const { api } = props
|
||||||
if (!api || !isFunction(api)) {
|
if (!api || !isFunction(api)) {
|
||||||
return warn('upload api must exist and be a function');
|
return warn('upload api must exist and be a function')
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
item.status = UploadResultStatus.UPLOADING;
|
item.status = UploadResultStatus.UPLOADING
|
||||||
const { data } = await props.api?.(
|
const { data } = await props.api?.(
|
||||||
{
|
{
|
||||||
data: {
|
data: {
|
||||||
|
|
@ -190,87 +188,87 @@
|
||||||
filename: props.filename,
|
filename: props.filename,
|
||||||
},
|
},
|
||||||
function onUploadProgress(progressEvent: ProgressEvent) {
|
function onUploadProgress(progressEvent: ProgressEvent) {
|
||||||
const complete = ((progressEvent.loaded / progressEvent.total) * 100) | 0;
|
const complete = ((progressEvent.loaded / progressEvent.total) * 100) | 0
|
||||||
item.percent = complete;
|
item.percent = complete
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
item.status = UploadResultStatus.SUCCESS;
|
item.status = UploadResultStatus.SUCCESS
|
||||||
item.responseData = data;
|
item.responseData = data
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
error: null,
|
error: null,
|
||||||
};
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e)
|
||||||
item.status = UploadResultStatus.ERROR;
|
item.status = UploadResultStatus.ERROR
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
error: e,
|
error: e,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 点击开始上传
|
// 点击开始上传
|
||||||
async function handleStartUpload() {
|
async function handleStartUpload() {
|
||||||
const { maxNumber } = props;
|
const { maxNumber } = props
|
||||||
if ((fileListRef.value.length + props.previewFileList?.length ?? 0) > maxNumber) {
|
if ((fileListRef.value.length + props.previewFileList?.length ?? 0) > maxNumber) {
|
||||||
return createMessage.warning(t('component.upload.maxNumber', [maxNumber]));
|
return createMessage.warning(t('component.upload.maxNumber', [maxNumber]))
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
isUploadingRef.value = true;
|
isUploadingRef.value = true
|
||||||
// 只上传不是成功状态的
|
// 只上传不是成功状态的
|
||||||
const uploadFileList =
|
const uploadFileList =
|
||||||
fileListRef.value.filter((item) => item.status !== UploadResultStatus.SUCCESS) || [];
|
fileListRef.value.filter((item) => item.status !== UploadResultStatus.SUCCESS) || []
|
||||||
const data = await Promise.all(
|
const data = await Promise.all(
|
||||||
uploadFileList.map((item) => {
|
uploadFileList.map((item) => {
|
||||||
return uploadApiByItem(item);
|
return uploadApiByItem(item)
|
||||||
}),
|
}),
|
||||||
);
|
)
|
||||||
isUploadingRef.value = false;
|
isUploadingRef.value = false
|
||||||
// 生产环境:抛出错误
|
// 生产环境:抛出错误
|
||||||
const errorList = data.filter((item: any) => !item.success);
|
const errorList = data.filter((item: any) => !item.success)
|
||||||
if (errorList.length > 0) throw errorList;
|
if (errorList.length > 0) throw errorList
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
isUploadingRef.value = false;
|
isUploadingRef.value = false
|
||||||
throw e;
|
throw e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 点击保存
|
// 点击保存
|
||||||
function handleOk() {
|
function handleOk() {
|
||||||
const { maxNumber } = props;
|
const { maxNumber } = props
|
||||||
|
|
||||||
if (fileListRef.value.length > maxNumber) {
|
if (fileListRef.value.length > maxNumber) {
|
||||||
return createMessage.warning(t('component.upload.maxNumber', [maxNumber]));
|
return createMessage.warning(t('component.upload.maxNumber', [maxNumber]))
|
||||||
}
|
}
|
||||||
if (isUploadingRef.value) {
|
if (isUploadingRef.value) {
|
||||||
return createMessage.warning(t('component.upload.saveWarn'));
|
return createMessage.warning(t('component.upload.saveWarn'))
|
||||||
}
|
}
|
||||||
const fileList: string[] = [];
|
const fileList: string[] = []
|
||||||
|
|
||||||
for (const item of fileListRef.value) {
|
for (const item of fileListRef.value) {
|
||||||
const { status, responseData } = item;
|
const { status, responseData } = item
|
||||||
if (status === UploadResultStatus.SUCCESS && responseData) {
|
if (status === UploadResultStatus.SUCCESS && responseData) {
|
||||||
fileList.push(responseData.url);
|
fileList.push(responseData.url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 存在一个上传成功的即可保存
|
// 存在一个上传成功的即可保存
|
||||||
if (fileList.length <= 0) {
|
if (fileList.length <= 0) {
|
||||||
return createMessage.warning(t('component.upload.saveError'));
|
return createMessage.warning(t('component.upload.saveError'))
|
||||||
}
|
}
|
||||||
fileListRef.value = [];
|
fileListRef.value = []
|
||||||
closeModal();
|
closeModal()
|
||||||
emit('change', fileList);
|
emit('change', fileList)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 点击关闭:则所有操作不保存,包括上传的
|
// 点击关闭:则所有操作不保存,包括上传的
|
||||||
async function handleCloseFunc() {
|
async function handleCloseFunc() {
|
||||||
if (!isUploadingRef.value) {
|
if (!isUploadingRef.value) {
|
||||||
fileListRef.value = [];
|
fileListRef.value = []
|
||||||
return true;
|
return true
|
||||||
} else {
|
} else {
|
||||||
createMessage.warning(t('component.upload.uploadWait'));
|
createMessage.warning(t('component.upload.uploadWait'))
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -293,9 +291,9 @@
|
||||||
getIsSelectFile,
|
getIsSelectFile,
|
||||||
getUploadBtnText,
|
getUploadBtnText,
|
||||||
t,
|
t,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
.upload-modal {
|
.upload-modal {
|
||||||
|
|
|
||||||
|
|
@ -11,30 +11,30 @@
|
||||||
</BasicModal>
|
</BasicModal>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, watch, ref } from 'vue';
|
import { defineComponent, watch, ref } from 'vue'
|
||||||
// import { BasicTable, useTable } from '/@/components/Table';
|
// import { BasicTable, useTable } from '/@/components/Table';
|
||||||
import FileList from './FileList.vue';
|
import FileList from './FileList.vue'
|
||||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
import { BasicModal, useModalInner } from '/@/components/Modal'
|
||||||
import { previewProps } from './props';
|
import { previewProps } from './props'
|
||||||
import { PreviewFileItem } from './typing';
|
import { PreviewFileItem } from './typing'
|
||||||
import { downloadByUrl } from '/@/utils/file/download';
|
import { downloadByUrl } from '/@/utils/file/download'
|
||||||
import { createPreviewColumns, createPreviewActionColumn } from './data';
|
import { createPreviewColumns, createPreviewActionColumn } from './data'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
import { isArray } from '/@/utils/is';
|
import { isArray } from '/@/utils/is'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: { BasicModal, FileList },
|
components: { BasicModal, FileList },
|
||||||
props: previewProps,
|
props: previewProps,
|
||||||
emits: ['list-change', 'register', 'delete'],
|
emits: ['list-change', 'register', 'delete'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const [register, { closeModal }] = useModalInner();
|
const [register, { closeModal }] = useModalInner()
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
|
|
||||||
const fileListRef = ref<PreviewFileItem[]>([]);
|
const fileListRef = ref<PreviewFileItem[]>([])
|
||||||
watch(
|
watch(
|
||||||
() => props.value,
|
() => props.value,
|
||||||
(value) => {
|
(value) => {
|
||||||
if (!isArray(value)) value = [];
|
if (!isArray(value)) value = []
|
||||||
fileListRef.value = value
|
fileListRef.value = value
|
||||||
.filter((item) => !!item)
|
.filter((item) => !!item)
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
|
|
@ -42,22 +42,22 @@
|
||||||
url: item,
|
url: item,
|
||||||
type: item.split('.').pop() || '',
|
type: item.split('.').pop() || '',
|
||||||
name: item.split('/').pop() || '',
|
name: item.split('/').pop() || '',
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
);
|
)
|
||||||
|
|
||||||
// 删除
|
// 删除
|
||||||
function handleRemove(record: PreviewFileItem) {
|
function handleRemove(record: PreviewFileItem) {
|
||||||
const index = fileListRef.value.findIndex((item) => item.url === record.url);
|
const index = fileListRef.value.findIndex((item) => item.url === record.url)
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
const removed = fileListRef.value.splice(index, 1);
|
const removed = fileListRef.value.splice(index, 1)
|
||||||
emit('delete', removed[0].url);
|
emit('delete', removed[0].url)
|
||||||
emit(
|
emit(
|
||||||
'list-change',
|
'list-change',
|
||||||
fileListRef.value.map((item) => item.url),
|
fileListRef.value.map((item) => item.url),
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,8 +71,8 @@
|
||||||
|
|
||||||
// 下载
|
// 下载
|
||||||
function handleDownload(record: PreviewFileItem) {
|
function handleDownload(record: PreviewFileItem) {
|
||||||
const { url = '' } = record;
|
const { url = '' } = record
|
||||||
downloadByUrl({ url });
|
downloadByUrl({ url })
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -82,9 +82,9 @@
|
||||||
fileListRef,
|
fileListRef,
|
||||||
columns: createPreviewColumns() as any[],
|
columns: createPreviewColumns() as any[],
|
||||||
actionColumn: createPreviewActionColumn({ handleRemove, handleDownload }) as any,
|
actionColumn: createPreviewActionColumn({ handleRemove, handleDownload }) as any,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
.upload-preview-modal {
|
.upload-preview-modal {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import type { App } from 'vue';
|
import type { App } from 'vue'
|
||||||
import { Button } from './Button';
|
import { Button } from './Button'
|
||||||
import { Input, Layout } from 'ant-design-vue';
|
import { Input, Layout } from 'ant-design-vue'
|
||||||
|
|
||||||
export function registerGlobComp(app: App) {
|
export function registerGlobComp(app: App) {
|
||||||
app.use(Input).use(Button).use(Layout);
|
app.use(Input).use(Button).use(Layout)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,5 +27,3 @@
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, computed, unref } from 'vue';
|
import { defineComponent, computed, unref } from 'vue'
|
||||||
import { BackTop } from 'ant-design-vue';
|
import { BackTop } from 'ant-design-vue'
|
||||||
|
|
||||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
import { useRootSetting } from '/@/hooks/setting/useRootSetting'
|
||||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting'
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
import { useUserStoreWithOut } from '/@/store/modules/user';
|
import { useUserStoreWithOut } from '/@/store/modules/user'
|
||||||
|
|
||||||
import { SettingButtonPositionEnum } from '/@/enums/appEnum';
|
import { SettingButtonPositionEnum } from '/@/enums/appEnum'
|
||||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'
|
||||||
|
|
||||||
import SessionTimeoutLogin from '/@/views/sys/login/SessionTimeoutLogin.vue';
|
import SessionTimeoutLogin from '/@/views/sys/login/SessionTimeoutLogin.vue'
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'LayoutFeatures',
|
name: 'LayoutFeatures',
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -21,24 +21,24 @@
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const { getUseOpenBackTop, getShowSettingButton, getSettingButtonPosition, getFullContent } =
|
const { getUseOpenBackTop, getShowSettingButton, getSettingButtonPosition, getFullContent } =
|
||||||
useRootSetting();
|
useRootSetting()
|
||||||
const userStore = useUserStoreWithOut();
|
const userStore = useUserStoreWithOut()
|
||||||
const { prefixCls } = useDesign('setting-drawer-feature');
|
const { prefixCls } = useDesign('setting-drawer-feature')
|
||||||
const { getShowHeader } = useHeaderSetting();
|
const { getShowHeader } = useHeaderSetting()
|
||||||
|
|
||||||
const getIsSessionTimeout = computed(() => userStore.getSessionTimeout);
|
const getIsSessionTimeout = computed(() => userStore.getSessionTimeout)
|
||||||
|
|
||||||
const getIsFixedSettingDrawer = computed(() => {
|
const getIsFixedSettingDrawer = computed(() => {
|
||||||
if (!unref(getShowSettingButton)) {
|
if (!unref(getShowSettingButton)) {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
const settingButtonPosition = unref(getSettingButtonPosition);
|
const settingButtonPosition = unref(getSettingButtonPosition)
|
||||||
|
|
||||||
if (settingButtonPosition === SettingButtonPositionEnum.AUTO) {
|
if (settingButtonPosition === SettingButtonPositionEnum.AUTO) {
|
||||||
return !unref(getShowHeader) || unref(getFullContent);
|
return !unref(getShowHeader) || unref(getFullContent)
|
||||||
}
|
}
|
||||||
return settingButtonPosition === SettingButtonPositionEnum.FIXED;
|
return settingButtonPosition === SettingButtonPositionEnum.FIXED
|
||||||
});
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getTarget: () => document.body,
|
getTarget: () => document.body,
|
||||||
|
|
@ -46,9 +46,9 @@
|
||||||
getIsFixedSettingDrawer,
|
getIsFixedSettingDrawer,
|
||||||
prefixCls,
|
prefixCls,
|
||||||
getIsSessionTimeout,
|
getIsSessionTimeout,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
||||||
|
|
@ -14,27 +14,27 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { RouteLocationMatched } from 'vue-router';
|
import type { RouteLocationMatched } from 'vue-router'
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router'
|
||||||
import type { Menu } from '/@/router/types';
|
import type { Menu } from '/@/router/types'
|
||||||
|
|
||||||
import { defineComponent, ref, watchEffect } from 'vue';
|
import { defineComponent, ref, watchEffect } from 'vue'
|
||||||
|
|
||||||
import { Breadcrumb } from 'ant-design-vue';
|
import { Breadcrumb } from 'ant-design-vue'
|
||||||
import Icon from '/@/components/Icon';
|
import Icon from '/@/components/Icon'
|
||||||
|
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
import { useRootSetting } from '/@/hooks/setting/useRootSetting'
|
||||||
import { useGo } from '/@/hooks/web/usePage';
|
import { useGo } from '/@/hooks/web/usePage'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
|
|
||||||
import { propTypes } from '/@/utils/propTypes';
|
import { propTypes } from '/@/utils/propTypes'
|
||||||
import { isString } from '/@/utils/is';
|
import { isString } from '/@/utils/is'
|
||||||
import { filter } from '/@/utils/helper/treeHelper';
|
import { filter } from '/@/utils/helper/treeHelper'
|
||||||
import { getMenus } from '/@/router/menus';
|
import { getMenus } from '/@/router/menus'
|
||||||
|
|
||||||
import { REDIRECT_NAME } from '/@/router/constant';
|
import { REDIRECT_NAME } from '/@/router/constant'
|
||||||
import { getAllParentPath } from '/@/router/helper/menuHelper';
|
import { getAllParentPath } from '/@/router/helper/menuHelper'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'LayoutBreadcrumb',
|
name: 'LayoutBreadcrumb',
|
||||||
|
|
@ -43,111 +43,111 @@
|
||||||
theme: propTypes.oneOf(['dark', 'light']),
|
theme: propTypes.oneOf(['dark', 'light']),
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const routes = ref<RouteLocationMatched[]>([]);
|
const routes = ref<RouteLocationMatched[]>([])
|
||||||
const { currentRoute } = useRouter();
|
const { currentRoute } = useRouter()
|
||||||
const { prefixCls } = useDesign('layout-breadcrumb');
|
const { prefixCls } = useDesign('layout-breadcrumb')
|
||||||
const { getShowBreadCrumbIcon } = useRootSetting();
|
const { getShowBreadCrumbIcon } = useRootSetting()
|
||||||
const go = useGo();
|
const go = useGo()
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
watchEffect(async () => {
|
watchEffect(async () => {
|
||||||
if (currentRoute.value.name === REDIRECT_NAME) return;
|
if (currentRoute.value.name === REDIRECT_NAME) return
|
||||||
const menus = await getMenus();
|
const menus = await getMenus()
|
||||||
|
|
||||||
const routeMatched = currentRoute.value.matched;
|
const routeMatched = currentRoute.value.matched
|
||||||
const cur = routeMatched?.[routeMatched.length - 1];
|
const cur = routeMatched?.[routeMatched.length - 1]
|
||||||
let path = currentRoute.value.path;
|
let path = currentRoute.value.path
|
||||||
|
|
||||||
if (cur && cur?.meta?.currentActiveMenu) {
|
if (cur && cur?.meta?.currentActiveMenu) {
|
||||||
path = cur.meta.currentActiveMenu as string;
|
path = cur.meta.currentActiveMenu as string
|
||||||
}
|
}
|
||||||
|
|
||||||
const parent = getAllParentPath(menus, path);
|
const parent = getAllParentPath(menus, path)
|
||||||
const filterMenus = menus.filter((item) => item.path === parent[0]);
|
const filterMenus = menus.filter((item) => item.path === parent[0])
|
||||||
const matched = getMatched(filterMenus, parent) as any;
|
const matched = getMatched(filterMenus, parent) as any
|
||||||
|
|
||||||
if (!matched || matched.length === 0) return;
|
if (!matched || matched.length === 0) return
|
||||||
|
|
||||||
const breadcrumbList = filterItem(matched);
|
const breadcrumbList = filterItem(matched)
|
||||||
|
|
||||||
if (currentRoute.value.meta?.currentActiveMenu) {
|
if (currentRoute.value.meta?.currentActiveMenu) {
|
||||||
breadcrumbList.push({
|
breadcrumbList.push({
|
||||||
...currentRoute.value,
|
...currentRoute.value,
|
||||||
name: currentRoute.value.meta?.title || currentRoute.value.name,
|
name: currentRoute.value.meta?.title || currentRoute.value.name,
|
||||||
} as unknown as RouteLocationMatched);
|
} as unknown as RouteLocationMatched)
|
||||||
}
|
}
|
||||||
routes.value = breadcrumbList;
|
routes.value = breadcrumbList
|
||||||
});
|
})
|
||||||
|
|
||||||
function getMatched(menus: Menu[], parent: string[]) {
|
function getMatched(menus: Menu[], parent: string[]) {
|
||||||
const metched: Menu[] = [];
|
const metched: Menu[] = []
|
||||||
menus.forEach((item) => {
|
menus.forEach((item) => {
|
||||||
if (parent.includes(item.path)) {
|
if (parent.includes(item.path)) {
|
||||||
metched.push({
|
metched.push({
|
||||||
...item,
|
...item,
|
||||||
name: item.meta?.title || item.name,
|
name: item.meta?.title || item.name,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
if (item.children?.length) {
|
if (item.children?.length) {
|
||||||
metched.push(...getMatched(item.children, parent));
|
metched.push(...getMatched(item.children, parent))
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
return metched;
|
return metched
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterItem(list: RouteLocationMatched[]) {
|
function filterItem(list: RouteLocationMatched[]) {
|
||||||
return filter(list, (item) => {
|
return filter(list, (item) => {
|
||||||
const { meta, name } = item;
|
const { meta, name } = item
|
||||||
if (!meta) {
|
if (!meta) {
|
||||||
return !!name;
|
return !!name
|
||||||
}
|
}
|
||||||
const { title, hideBreadcrumb, hideMenu } = meta;
|
const { title, hideBreadcrumb, hideMenu } = meta
|
||||||
if (!title || hideBreadcrumb || hideMenu) {
|
if (!title || hideBreadcrumb || hideMenu) {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
return true;
|
return true
|
||||||
}).filter((item) => !item.meta?.hideBreadcrumb);
|
}).filter((item) => !item.meta?.hideBreadcrumb)
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleClick(route: RouteLocationMatched, paths: string[], e: Event) {
|
function handleClick(route: RouteLocationMatched, paths: string[], e: Event) {
|
||||||
e?.preventDefault();
|
e?.preventDefault()
|
||||||
const { children, redirect, meta } = route;
|
const { children, redirect, meta } = route
|
||||||
|
|
||||||
if (children?.length && !redirect) {
|
if (children?.length && !redirect) {
|
||||||
e?.stopPropagation();
|
e?.stopPropagation()
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
if (meta?.carryParam) {
|
if (meta?.carryParam) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (redirect && isString(redirect)) {
|
if (redirect && isString(redirect)) {
|
||||||
go(redirect);
|
go(redirect)
|
||||||
} else {
|
} else {
|
||||||
let goPath = '';
|
let goPath = ''
|
||||||
if (paths.length === 1) {
|
if (paths.length === 1) {
|
||||||
goPath = paths[0];
|
goPath = paths[0]
|
||||||
} else {
|
} else {
|
||||||
const ps = paths.slice(1);
|
const ps = paths.slice(1)
|
||||||
const lastPath = ps.pop() || '';
|
const lastPath = ps.pop() || ''
|
||||||
goPath = `${lastPath}`;
|
goPath = `${lastPath}`
|
||||||
}
|
}
|
||||||
goPath = /^\//.test(goPath) ? goPath : `/${goPath}`;
|
goPath = /^\//.test(goPath) ? goPath : `/${goPath}`
|
||||||
go(goPath);
|
go(goPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasRedirect(routes: RouteLocationMatched[], route: RouteLocationMatched) {
|
function hasRedirect(routes: RouteLocationMatched[], route: RouteLocationMatched) {
|
||||||
return routes.indexOf(route) !== routes.length - 1;
|
return routes.indexOf(route) !== routes.length - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
function getIcon(route) {
|
function getIcon(route) {
|
||||||
return route.icon || route.meta?.icon;
|
return route.icon || route.meta?.icon
|
||||||
}
|
}
|
||||||
|
|
||||||
return { routes, t, prefixCls, getIcon, getShowBreadCrumbIcon, handleClick, hasRedirect };
|
return { routes, t, prefixCls, getIcon, getShowBreadCrumbIcon, handleClick, hasRedirect }
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@prefix-cls: ~'@{namespace}-layout-breadcrumb';
|
@prefix-cls: ~'@{namespace}-layout-breadcrumb';
|
||||||
|
|
|
||||||
|
|
@ -25,27 +25,27 @@
|
||||||
</BasicModal>
|
</BasicModal>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, computed } from 'vue';
|
import { defineComponent, computed } from 'vue'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
import { BasicModal, useModalInner } from '/@/components/Modal/index';
|
import { BasicModal, useModalInner } from '/@/components/Modal/index'
|
||||||
import { BasicForm, useForm } from '/@/components/Form/index';
|
import { BasicForm, useForm } from '/@/components/Form/index'
|
||||||
|
|
||||||
import { useUserStore } from '/@/store/modules/user';
|
import { useUserStore } from '/@/store/modules/user'
|
||||||
import { useLockStore } from '/@/store/modules/lock';
|
import { useLockStore } from '/@/store/modules/lock'
|
||||||
import headerImg from '/@/assets/images/header.jpg';
|
import headerImg from '/@/assets/images/header.jpg'
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'LockModal',
|
name: 'LockModal',
|
||||||
components: { BasicModal, BasicForm },
|
components: { BasicModal, BasicForm },
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
const { prefixCls } = useDesign('header-lock-modal');
|
const { prefixCls } = useDesign('header-lock-modal')
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore()
|
||||||
const lockStore = useLockStore();
|
const lockStore = useLockStore()
|
||||||
|
|
||||||
const getRealName = computed(() => userStore.getUserInfo?.realName);
|
const getRealName = computed(() => userStore.getUserInfo?.realName)
|
||||||
const [register, { closeModal }] = useModalInner();
|
const [register, { closeModal }] = useModalInner()
|
||||||
|
|
||||||
const [registerForm, { validateFields, resetFields }] = useForm({
|
const [registerForm, { validateFields, resetFields }] = useForm({
|
||||||
showActionButtonGroup: false,
|
showActionButtonGroup: false,
|
||||||
|
|
@ -60,24 +60,24 @@
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
})
|
||||||
|
|
||||||
async function handleLock() {
|
async function handleLock() {
|
||||||
const values = (await validateFields()) as any;
|
const values = (await validateFields()) as any
|
||||||
const password: string | undefined = values.password;
|
const password: string | undefined = values.password
|
||||||
closeModal();
|
closeModal()
|
||||||
|
|
||||||
lockStore.setLockInfo({
|
lockStore.setLockInfo({
|
||||||
isLock: true,
|
isLock: true,
|
||||||
pwd: password,
|
pwd: password,
|
||||||
});
|
})
|
||||||
await resetFields();
|
await resetFields()
|
||||||
}
|
}
|
||||||
|
|
||||||
const avatar = computed(() => {
|
const avatar = computed(() => {
|
||||||
const { avatar } = userStore.getUserInfo;
|
const { avatar } = userStore.getUserInfo
|
||||||
return avatar || headerImg;
|
return avatar || headerImg
|
||||||
});
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
t,
|
t,
|
||||||
|
|
@ -87,9 +87,9 @@
|
||||||
registerForm,
|
registerForm,
|
||||||
handleLock,
|
handleLock,
|
||||||
avatar,
|
avatar,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@prefix-cls: ~'@{namespace}-header-lock-modal';
|
@prefix-cls: ~'@{namespace}-header-lock-modal';
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,12 @@
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Menu } from 'ant-design-vue';
|
import { Menu } from 'ant-design-vue'
|
||||||
|
|
||||||
import { computed, defineComponent, getCurrentInstance } from 'vue';
|
import { computed, defineComponent, getCurrentInstance } from 'vue'
|
||||||
|
|
||||||
import Icon from '/@/components/Icon/index';
|
import Icon from '/@/components/Icon/index'
|
||||||
import { propTypes } from '/@/utils/propTypes';
|
import { propTypes } from '/@/utils/propTypes'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'DropdownMenuItem',
|
name: 'DropdownMenuItem',
|
||||||
|
|
@ -24,9 +24,9 @@
|
||||||
icon: propTypes.string,
|
icon: propTypes.string,
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const instance = getCurrentInstance();
|
const instance = getCurrentInstance()
|
||||||
const itemKey = computed(() => props.key || instance?.vnode?.props?.key);
|
const itemKey = computed(() => props.key || instance?.vnode?.props?.key)
|
||||||
return { itemKey };
|
return { itemKey }
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -36,26 +36,26 @@
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
// components
|
// components
|
||||||
import { Dropdown, Menu } from 'ant-design-vue';
|
import { Dropdown, Menu } from 'ant-design-vue'
|
||||||
import type { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
|
import type { MenuInfo } from 'ant-design-vue/lib/menu/src/interface'
|
||||||
|
|
||||||
import { defineComponent, computed } from 'vue';
|
import { defineComponent, computed } from 'vue'
|
||||||
|
|
||||||
import { DOC_URL } from '/@/settings/siteSetting';
|
import { DOC_URL } from '/@/settings/siteSetting'
|
||||||
|
|
||||||
import { useUserStore } from '/@/store/modules/user';
|
import { useUserStore } from '/@/store/modules/user'
|
||||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
import { useModal } from '/@/components/Modal';
|
import { useModal } from '/@/components/Modal'
|
||||||
|
|
||||||
import headerImg from '/@/assets/images/header.jpg';
|
import headerImg from '/@/assets/images/header.jpg'
|
||||||
import { propTypes } from '/@/utils/propTypes';
|
import { propTypes } from '/@/utils/propTypes'
|
||||||
import { openWindow } from '/@/utils';
|
import { openWindow } from '/@/utils'
|
||||||
|
|
||||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'
|
||||||
|
|
||||||
type MenuEvent = 'logout' | 'doc' | 'lock';
|
type MenuEvent = 'logout' | 'doc' | 'lock'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'UserDropdown',
|
name: 'UserDropdown',
|
||||||
|
|
@ -70,43 +70,43 @@
|
||||||
theme: propTypes.oneOf(['dark', 'light']),
|
theme: propTypes.oneOf(['dark', 'light']),
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const { prefixCls } = useDesign('header-user-dropdown');
|
const { prefixCls } = useDesign('header-user-dropdown')
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
const { getShowDoc, getUseLockPage } = useHeaderSetting();
|
const { getShowDoc, getUseLockPage } = useHeaderSetting()
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore()
|
||||||
|
|
||||||
const getUserInfo = computed(() => {
|
const getUserInfo = computed(() => {
|
||||||
const { realName = '', avatar, desc } = userStore.getUserInfo || {};
|
const { realName = '', avatar, desc } = userStore.getUserInfo || {}
|
||||||
return { realName, avatar: avatar || headerImg, desc };
|
return { realName, avatar: avatar || headerImg, desc }
|
||||||
});
|
})
|
||||||
|
|
||||||
const [register, { openModal }] = useModal();
|
const [register, { openModal }] = useModal()
|
||||||
|
|
||||||
function handleLock() {
|
function handleLock() {
|
||||||
openModal(true);
|
openModal(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// login out
|
// login out
|
||||||
function handleLoginOut() {
|
function handleLoginOut() {
|
||||||
userStore.confirmLoginOut();
|
userStore.confirmLoginOut()
|
||||||
}
|
}
|
||||||
|
|
||||||
// open doc
|
// open doc
|
||||||
function openDoc() {
|
function openDoc() {
|
||||||
openWindow(DOC_URL);
|
openWindow(DOC_URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMenuClick(e: MenuInfo) {
|
function handleMenuClick(e: MenuInfo) {
|
||||||
switch (e.key as MenuEvent) {
|
switch (e.key as MenuEvent) {
|
||||||
case 'logout':
|
case 'logout':
|
||||||
handleLoginOut();
|
handleLoginOut()
|
||||||
break;
|
break
|
||||||
case 'doc':
|
case 'doc':
|
||||||
openDoc();
|
openDoc()
|
||||||
break;
|
break
|
||||||
case 'lock':
|
case 'lock':
|
||||||
handleLock();
|
handleLock()
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,9 +118,9 @@
|
||||||
getShowDoc,
|
getShowDoc,
|
||||||
register,
|
register,
|
||||||
getUseLockPage,
|
getUseLockPage,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@prefix-cls: ~'@{namespace}-header-user-dropdown';
|
@prefix-cls: ~'@{namespace}-header-user-dropdown';
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { defineComponent, computed, unref } from 'vue';
|
import { defineComponent, computed, unref } from 'vue'
|
||||||
import { BasicDrawer } from '/@/components/Drawer/index';
|
import { BasicDrawer } from '/@/components/Drawer/index'
|
||||||
import { Divider } from 'ant-design-vue';
|
import { Divider } from 'ant-design-vue'
|
||||||
import {
|
import {
|
||||||
TypePicker,
|
TypePicker,
|
||||||
ThemeColorPicker,
|
ThemeColorPicker,
|
||||||
|
|
@ -8,20 +8,20 @@ import {
|
||||||
SwitchItem,
|
SwitchItem,
|
||||||
SelectItem,
|
SelectItem,
|
||||||
InputNumberItem,
|
InputNumberItem,
|
||||||
} from './components';
|
} from './components'
|
||||||
|
|
||||||
import { AppDarkModeToggle } from '/@/components/Application';
|
import { AppDarkModeToggle } from '/@/components/Application'
|
||||||
|
|
||||||
import { MenuTypeEnum, TriggerEnum } from '/@/enums/menuEnum';
|
import { MenuTypeEnum, TriggerEnum } from '/@/enums/menuEnum'
|
||||||
|
|
||||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
import { useRootSetting } from '/@/hooks/setting/useRootSetting'
|
||||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'
|
||||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting'
|
||||||
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting'
|
||||||
import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
|
import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
|
|
||||||
import { baseHandler } from './handler';
|
import { baseHandler } from './handler'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
HandlerEnum,
|
HandlerEnum,
|
||||||
|
|
@ -31,15 +31,15 @@ import {
|
||||||
routerTransitionOptions,
|
routerTransitionOptions,
|
||||||
menuTypeList,
|
menuTypeList,
|
||||||
mixSidebarTriggerOptions,
|
mixSidebarTriggerOptions,
|
||||||
} from './enum';
|
} from './enum'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
HEADER_PRESET_BG_COLOR_LIST,
|
HEADER_PRESET_BG_COLOR_LIST,
|
||||||
SIDE_BAR_BG_COLOR_LIST,
|
SIDE_BAR_BG_COLOR_LIST,
|
||||||
APP_PRESET_COLOR_LIST,
|
APP_PRESET_COLOR_LIST,
|
||||||
} from '/@/settings/designSetting';
|
} from '/@/settings/designSetting'
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'SettingDrawer',
|
name: 'SettingDrawer',
|
||||||
|
|
@ -56,10 +56,10 @@ export default defineComponent({
|
||||||
getLockTime,
|
getLockTime,
|
||||||
getShowDarkModeToggle,
|
getShowDarkModeToggle,
|
||||||
getThemeColor,
|
getThemeColor,
|
||||||
} = useRootSetting();
|
} = useRootSetting()
|
||||||
|
|
||||||
const { getOpenPageLoading, getBasicTransition, getEnableTransition, getOpenNProgress } =
|
const { getOpenPageLoading, getBasicTransition, getEnableTransition, getOpenNProgress } =
|
||||||
useTransitionSetting();
|
useTransitionSetting()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
getIsHorizontal,
|
getIsHorizontal,
|
||||||
|
|
@ -80,20 +80,20 @@ export default defineComponent({
|
||||||
getCloseMixSidebarOnChange,
|
getCloseMixSidebarOnChange,
|
||||||
getMixSideTrigger,
|
getMixSideTrigger,
|
||||||
getMixSideFixed,
|
getMixSideFixed,
|
||||||
} = useMenuSetting();
|
} = useMenuSetting()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
getShowHeader,
|
getShowHeader,
|
||||||
getFixed: getHeaderFixed,
|
getFixed: getHeaderFixed,
|
||||||
getHeaderBgColor,
|
getHeaderBgColor,
|
||||||
getShowSearch,
|
getShowSearch,
|
||||||
} = useHeaderSetting();
|
} = useHeaderSetting()
|
||||||
|
|
||||||
const { getShowMultipleTab, getShowQuick, getShowRedo, getShowFold } = useMultipleTabSetting();
|
const { getShowMultipleTab, getShowQuick, getShowRedo, getShowFold } = useMultipleTabSetting()
|
||||||
|
|
||||||
const getShowMenuRef = computed(() => {
|
const getShowMenuRef = computed(() => {
|
||||||
return unref(getShowMenu) && !unref(getIsHorizontal);
|
return unref(getShowMenu) && !unref(getIsHorizontal)
|
||||||
});
|
})
|
||||||
|
|
||||||
function renderSidebar() {
|
function renderSidebar() {
|
||||||
return (
|
return (
|
||||||
|
|
@ -105,12 +105,12 @@ export default defineComponent({
|
||||||
mode: item.mode,
|
mode: item.mode,
|
||||||
type: item.type,
|
type: item.type,
|
||||||
split: unref(getIsHorizontal) ? false : undefined,
|
split: unref(getIsHorizontal) ? false : undefined,
|
||||||
});
|
})
|
||||||
}}
|
}}
|
||||||
def={unref(getMenuType)}
|
def={unref(getMenuType)}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderHeaderTheme() {
|
function renderHeaderTheme() {
|
||||||
|
|
@ -120,7 +120,7 @@ export default defineComponent({
|
||||||
def={unref(getHeaderBgColor)}
|
def={unref(getHeaderBgColor)}
|
||||||
event={HandlerEnum.HEADER_THEME}
|
event={HandlerEnum.HEADER_THEME}
|
||||||
/>
|
/>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderSiderTheme() {
|
function renderSiderTheme() {
|
||||||
|
|
@ -130,7 +130,7 @@ export default defineComponent({
|
||||||
def={unref(getMenuBgColor)}
|
def={unref(getMenuBgColor)}
|
||||||
event={HandlerEnum.MENU_THEME}
|
event={HandlerEnum.MENU_THEME}
|
||||||
/>
|
/>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderMainTheme() {
|
function renderMainTheme() {
|
||||||
|
|
@ -140,19 +140,19 @@ export default defineComponent({
|
||||||
def={unref(getThemeColor)}
|
def={unref(getThemeColor)}
|
||||||
event={HandlerEnum.CHANGE_THEME_COLOR}
|
event={HandlerEnum.CHANGE_THEME_COLOR}
|
||||||
/>
|
/>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description:
|
* @description:
|
||||||
*/
|
*/
|
||||||
function renderFeatures() {
|
function renderFeatures() {
|
||||||
let triggerDef = unref(getTrigger);
|
let triggerDef = unref(getTrigger)
|
||||||
|
|
||||||
const triggerOptions = getMenuTriggerOptions(unref(getSplit));
|
const triggerOptions = getMenuTriggerOptions(unref(getSplit))
|
||||||
const some = triggerOptions.some((item) => item.value === triggerDef);
|
const some = triggerOptions.some((item) => item.value === triggerDef)
|
||||||
if (!some) {
|
if (!some) {
|
||||||
triggerDef = TriggerEnum.FOOTER;
|
triggerDef = TriggerEnum.FOOTER
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -261,7 +261,7 @@ export default defineComponent({
|
||||||
formatter={(value: string) => {
|
formatter={(value: string) => {
|
||||||
return parseInt(value) === 0
|
return parseInt(value) === 0
|
||||||
? `0(${t('layout.setting.notAutoScreenLock')})`
|
? `0(${t('layout.setting.notAutoScreenLock')})`
|
||||||
: `${value}${t('layout.setting.minute')}`;
|
: `${value}${t('layout.setting.minute')}`
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<InputNumberItem
|
<InputNumberItem
|
||||||
|
|
@ -275,7 +275,7 @@ export default defineComponent({
|
||||||
formatter={(value: string) => `${parseInt(value)}px`}
|
formatter={(value: string) => `${parseInt(value)}px`}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderContent() {
|
function renderContent() {
|
||||||
|
|
@ -362,7 +362,7 @@ export default defineComponent({
|
||||||
def={unref(getColorWeak)}
|
def={unref(getColorWeak)}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderTransition() {
|
function renderTransition() {
|
||||||
|
|
@ -393,7 +393,7 @@ export default defineComponent({
|
||||||
disabled={!unref(getEnableTransition)}
|
disabled={!unref(getEnableTransition)}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
|
|
@ -422,6 +422,6 @@ export default defineComponent({
|
||||||
<Divider />
|
<Divider />
|
||||||
<SettingFooter />
|
<SettingFooter />
|
||||||
</BasicDrawer>
|
</BasicDrawer>
|
||||||
);
|
)
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
|
||||||
|
|
@ -78,26 +78,26 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Menu } from '/@/router/types';
|
import type { Menu } from '/@/router/types'
|
||||||
import type { CSSProperties } from 'vue';
|
import type { CSSProperties } from 'vue'
|
||||||
import { computed, defineComponent, onMounted, ref, unref, watch } from 'vue';
|
import { computed, defineComponent, onMounted, ref, unref, watch } from 'vue'
|
||||||
import type { RouteLocationNormalized } from 'vue-router';
|
import type { RouteLocationNormalized } from 'vue-router'
|
||||||
import { ScrollContainer } from '/@/components/Container';
|
import { ScrollContainer } from '/@/components/Container'
|
||||||
import { SimpleMenu, SimpleMenuTag } from '/@/components/SimpleMenu';
|
import { SimpleMenu, SimpleMenuTag } from '/@/components/SimpleMenu'
|
||||||
import { Icon } from '/@/components/Icon';
|
import { Icon } from '/@/components/Icon'
|
||||||
import { AppLogo } from '/@/components/Application';
|
import { AppLogo } from '/@/components/Application'
|
||||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'
|
||||||
import { usePermissionStore } from '/@/store/modules/permission';
|
import { usePermissionStore } from '/@/store/modules/permission'
|
||||||
import { useDragLine } from './useLayoutSider';
|
import { useDragLine } from './useLayoutSider'
|
||||||
import { useGlobSetting } from '/@/hooks/setting';
|
import { useGlobSetting } from '/@/hooks/setting'
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
import { useGo } from '/@/hooks/web/usePage';
|
import { useGo } from '/@/hooks/web/usePage'
|
||||||
import { SIDE_BAR_MINI_WIDTH, SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '/@/enums/appEnum';
|
import { SIDE_BAR_MINI_WIDTH, SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '/@/enums/appEnum'
|
||||||
import clickOutside from '/@/directives/clickOutside';
|
import clickOutside from '/@/directives/clickOutside'
|
||||||
import { getChildrenMenus, getCurrentParentPath, getShallowMenus } from '/@/router/menus';
|
import { getChildrenMenus, getCurrentParentPath, getShallowMenus } from '/@/router/menus'
|
||||||
import { listenerRouteChange } from '/@/logics/mitt/routeChange';
|
import { listenerRouteChange } from '/@/logics/mitt/routeChange'
|
||||||
import LayoutTrigger from '../trigger/index.vue';
|
import LayoutTrigger from '../trigger/index.vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'LayoutMixSider',
|
name: 'LayoutMixSider',
|
||||||
|
|
@ -113,17 +113,17 @@
|
||||||
clickOutside,
|
clickOutside,
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
let menuModules = ref<Menu[]>([]);
|
let menuModules = ref<Menu[]>([])
|
||||||
const activePath = ref('');
|
const activePath = ref('')
|
||||||
const childrenMenus = ref<Menu[]>([]);
|
const childrenMenus = ref<Menu[]>([])
|
||||||
const openMenu = ref(false);
|
const openMenu = ref(false)
|
||||||
const dragBarRef = ref<ElRef>(null);
|
const dragBarRef = ref<ElRef>(null)
|
||||||
const sideRef = ref<ElRef>(null);
|
const sideRef = ref<ElRef>(null)
|
||||||
const currentRoute = ref<Nullable<RouteLocationNormalized>>(null);
|
const currentRoute = ref<Nullable<RouteLocationNormalized>>(null)
|
||||||
|
|
||||||
const { prefixCls } = useDesign('layout-mix-sider');
|
const { prefixCls } = useDesign('layout-mix-sider')
|
||||||
const go = useGo();
|
const go = useGo()
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
const {
|
const {
|
||||||
getMenuWidth,
|
getMenuWidth,
|
||||||
getCanDrag,
|
getCanDrag,
|
||||||
|
|
@ -136,81 +136,81 @@
|
||||||
setMenuSetting,
|
setMenuSetting,
|
||||||
getIsMixSidebar,
|
getIsMixSidebar,
|
||||||
getCollapsed,
|
getCollapsed,
|
||||||
} = useMenuSetting();
|
} = useMenuSetting()
|
||||||
|
|
||||||
const { title } = useGlobSetting();
|
const { title } = useGlobSetting()
|
||||||
const permissionStore = usePermissionStore();
|
const permissionStore = usePermissionStore()
|
||||||
|
|
||||||
useDragLine(sideRef, dragBarRef, true);
|
useDragLine(sideRef, dragBarRef, true)
|
||||||
|
|
||||||
const getMenuStyle = computed((): CSSProperties => {
|
const getMenuStyle = computed((): CSSProperties => {
|
||||||
return {
|
return {
|
||||||
width: unref(openMenu) ? `${unref(getMenuWidth)}px` : 0,
|
width: unref(openMenu) ? `${unref(getMenuWidth)}px` : 0,
|
||||||
left: `${unref(getMixSideWidth)}px`,
|
left: `${unref(getMixSideWidth)}px`,
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
const getIsFixed = computed(() => {
|
const getIsFixed = computed(() => {
|
||||||
/* eslint-disable-next-line */
|
/* eslint-disable-next-line */
|
||||||
mixSideHasChildren.value = unref(childrenMenus).length > 0;
|
mixSideHasChildren.value = unref(childrenMenus).length > 0;
|
||||||
const isFixed = unref(getMixSideFixed) && unref(mixSideHasChildren);
|
const isFixed = unref(getMixSideFixed) && unref(mixSideHasChildren)
|
||||||
if (isFixed) {
|
if (isFixed) {
|
||||||
/* eslint-disable-next-line */
|
/* eslint-disable-next-line */
|
||||||
openMenu.value = true;
|
openMenu.value = true;
|
||||||
}
|
}
|
||||||
return isFixed;
|
return isFixed
|
||||||
});
|
})
|
||||||
|
|
||||||
const getMixSideWidth = computed(() => {
|
const getMixSideWidth = computed(() => {
|
||||||
return unref(getCollapsed) ? SIDE_BAR_MINI_WIDTH : SIDE_BAR_SHOW_TIT_MINI_WIDTH;
|
return unref(getCollapsed) ? SIDE_BAR_MINI_WIDTH : SIDE_BAR_SHOW_TIT_MINI_WIDTH
|
||||||
});
|
})
|
||||||
|
|
||||||
const getDomStyle = computed((): CSSProperties => {
|
const getDomStyle = computed((): CSSProperties => {
|
||||||
const fixedWidth = unref(getIsFixed) ? unref(getRealWidth) : 0;
|
const fixedWidth = unref(getIsFixed) ? unref(getRealWidth) : 0
|
||||||
const width = `${unref(getMixSideWidth) + fixedWidth}px`;
|
const width = `${unref(getMixSideWidth) + fixedWidth}px`
|
||||||
return getWrapCommonStyle(width);
|
return getWrapCommonStyle(width)
|
||||||
});
|
})
|
||||||
|
|
||||||
const getWrapStyle = computed((): CSSProperties => {
|
const getWrapStyle = computed((): CSSProperties => {
|
||||||
const width = `${unref(getMixSideWidth)}px`;
|
const width = `${unref(getMixSideWidth)}px`
|
||||||
return getWrapCommonStyle(width);
|
return getWrapCommonStyle(width)
|
||||||
});
|
})
|
||||||
|
|
||||||
const getMenuEvents = computed(() => {
|
const getMenuEvents = computed(() => {
|
||||||
return !unref(getMixSideFixed)
|
return !unref(getMixSideFixed)
|
||||||
? {
|
? {
|
||||||
onMouseleave: () => {
|
onMouseleave: () => {
|
||||||
setActive(true);
|
setActive(true)
|
||||||
closeMenu();
|
closeMenu()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
: {};
|
: {}
|
||||||
});
|
})
|
||||||
|
|
||||||
const getShowDragBar = computed(() => unref(getCanDrag));
|
const getShowDragBar = computed(() => unref(getCanDrag))
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
menuModules.value = await getShallowMenus();
|
menuModules.value = await getShallowMenus()
|
||||||
});
|
})
|
||||||
|
|
||||||
// Menu changes
|
// Menu changes
|
||||||
watch(
|
watch(
|
||||||
[() => permissionStore.getLastBuildMenuTime, () => permissionStore.getBackMenuList],
|
[() => permissionStore.getLastBuildMenuTime, () => permissionStore.getBackMenuList],
|
||||||
async () => {
|
async () => {
|
||||||
menuModules.value = await getShallowMenus();
|
menuModules.value = await getShallowMenus()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
immediate: true,
|
immediate: true,
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
|
|
||||||
listenerRouteChange((route) => {
|
listenerRouteChange((route) => {
|
||||||
currentRoute.value = route;
|
currentRoute.value = route
|
||||||
setActive(true);
|
setActive(true)
|
||||||
if (unref(getCloseMixSidebarOnChange)) {
|
if (unref(getCloseMixSidebarOnChange)) {
|
||||||
closeMenu();
|
closeMenu()
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
function getWrapCommonStyle(width: string): CSSProperties {
|
function getWrapCommonStyle(width: string): CSSProperties {
|
||||||
return {
|
return {
|
||||||
|
|
@ -218,73 +218,73 @@
|
||||||
maxWidth: width,
|
maxWidth: width,
|
||||||
minWidth: width,
|
minWidth: width,
|
||||||
flex: `0 0 ${width}`,
|
flex: `0 0 ${width}`,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process module menu click
|
// Process module menu click
|
||||||
async function handleModuleClick(path: string, hover = false) {
|
async function handleModuleClick(path: string, hover = false) {
|
||||||
const children = await getChildrenMenus(path);
|
const children = await getChildrenMenus(path)
|
||||||
if (unref(activePath) === path) {
|
if (unref(activePath) === path) {
|
||||||
if (!hover) {
|
if (!hover) {
|
||||||
if (!unref(openMenu)) {
|
if (!unref(openMenu)) {
|
||||||
openMenu.value = true;
|
openMenu.value = true
|
||||||
} else {
|
} else {
|
||||||
closeMenu();
|
closeMenu()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!unref(openMenu)) {
|
if (!unref(openMenu)) {
|
||||||
openMenu.value = true;
|
openMenu.value = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!unref(openMenu)) {
|
if (!unref(openMenu)) {
|
||||||
setActive();
|
setActive()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
openMenu.value = true;
|
openMenu.value = true
|
||||||
activePath.value = path;
|
activePath.value = path
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!children || children.length === 0) {
|
if (!children || children.length === 0) {
|
||||||
if (!hover) go(path);
|
if (!hover) go(path)
|
||||||
childrenMenus.value = [];
|
childrenMenus.value = []
|
||||||
closeMenu();
|
closeMenu()
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
childrenMenus.value = children;
|
childrenMenus.value = children
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the currently active menu and submenu
|
// Set the currently active menu and submenu
|
||||||
async function setActive(setChildren = false) {
|
async function setActive(setChildren = false) {
|
||||||
const path = currentRoute.value?.path;
|
const path = currentRoute.value?.path
|
||||||
if (!path) return;
|
if (!path) return
|
||||||
activePath.value = await getCurrentParentPath(path);
|
activePath.value = await getCurrentParentPath(path)
|
||||||
// hanldeModuleClick(parentPath);
|
// hanldeModuleClick(parentPath);
|
||||||
if (unref(getIsMixSidebar)) {
|
if (unref(getIsMixSidebar)) {
|
||||||
const activeMenu = unref(menuModules).find((item) => item.path === unref(activePath));
|
const activeMenu = unref(menuModules).find((item) => item.path === unref(activePath))
|
||||||
const p = activeMenu?.path;
|
const p = activeMenu?.path
|
||||||
if (p) {
|
if (p) {
|
||||||
const children = await getChildrenMenus(p);
|
const children = await getChildrenMenus(p)
|
||||||
if (setChildren) {
|
if (setChildren) {
|
||||||
childrenMenus.value = children;
|
childrenMenus.value = children
|
||||||
|
|
||||||
if (unref(getMixSideFixed)) {
|
if (unref(getMixSideFixed)) {
|
||||||
openMenu.value = children.length > 0;
|
openMenu.value = children.length > 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (children.length === 0) {
|
if (children.length === 0) {
|
||||||
childrenMenus.value = [];
|
childrenMenus.value = []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMenuClick(path: string) {
|
function handleMenuClick(path: string) {
|
||||||
go(path);
|
go(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleClickOutside() {
|
function handleClickOutside() {
|
||||||
setActive(true);
|
setActive(true)
|
||||||
closeMenu();
|
closeMenu()
|
||||||
}
|
}
|
||||||
|
|
||||||
function getItemEvents(item: Menu) {
|
function getItemEvents(item: Menu) {
|
||||||
|
|
@ -292,26 +292,26 @@
|
||||||
return {
|
return {
|
||||||
onMouseenter: () => handleModuleClick(item.path, true),
|
onMouseenter: () => handleModuleClick(item.path, true),
|
||||||
onClick: async () => {
|
onClick: async () => {
|
||||||
const children = await getChildrenMenus(item.path);
|
const children = await getChildrenMenus(item.path)
|
||||||
if (item.path && (!children || children.length === 0)) go(item.path);
|
if (item.path && (!children || children.length === 0)) go(item.path)
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
onClick: () => handleModuleClick(item.path),
|
onClick: () => handleModuleClick(item.path),
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleFixedMenu() {
|
function handleFixedMenu() {
|
||||||
setMenuSetting({
|
setMenuSetting({
|
||||||
mixSideFixed: !unref(getIsFixed),
|
mixSideFixed: !unref(getIsFixed),
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close menu
|
// Close menu
|
||||||
function closeMenu() {
|
function closeMenu() {
|
||||||
if (!unref(getIsFixed)) {
|
if (!unref(getIsFixed)) {
|
||||||
openMenu.value = false;
|
openMenu.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -338,9 +338,9 @@
|
||||||
getMixSideFixed,
|
getMixSideFixed,
|
||||||
getWrapStyle,
|
getWrapStyle,
|
||||||
getCollapsed,
|
getCollapsed,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@prefix-cls: ~'@{namespace}-layout-mix-sider';
|
@prefix-cls: ~'@{namespace}-layout-mix-sider';
|
||||||
|
|
|
||||||
|
|
@ -1,61 +1,61 @@
|
||||||
import type { Ref } from 'vue';
|
import type { Ref } from 'vue'
|
||||||
|
|
||||||
import { computed, unref, onMounted, nextTick } from 'vue';
|
import { computed, unref, onMounted, nextTick } from 'vue'
|
||||||
|
|
||||||
import { TriggerEnum } from '/@/enums/menuEnum';
|
import { TriggerEnum } from '/@/enums/menuEnum'
|
||||||
|
|
||||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'
|
||||||
import { useDebounceFn } from '@vueuse/core';
|
import { useDebounceFn } from '@vueuse/core'
|
||||||
import { useAppStore } from '/@/store/modules/app';
|
import { useAppStore } from '/@/store/modules/app'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle related operations of menu events
|
* Handle related operations of menu events
|
||||||
*/
|
*/
|
||||||
export function useSiderEvent() {
|
export function useSiderEvent() {
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore()
|
||||||
const { getMiniWidthNumber } = useMenuSetting();
|
const { getMiniWidthNumber } = useMenuSetting()
|
||||||
|
|
||||||
const getCollapsedWidth = computed(() => {
|
const getCollapsedWidth = computed(() => {
|
||||||
return unref(getMiniWidthNumber);
|
return unref(getMiniWidthNumber)
|
||||||
});
|
})
|
||||||
|
|
||||||
function onBreakpointChange(broken: boolean) {
|
function onBreakpointChange(broken: boolean) {
|
||||||
appStore.setProjectConfig({
|
appStore.setProjectConfig({
|
||||||
menuSetting: {
|
menuSetting: {
|
||||||
siderHidden: broken,
|
siderHidden: broken,
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return { getCollapsedWidth, onBreakpointChange };
|
return { getCollapsedWidth, onBreakpointChange }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle related operations of menu folding
|
* Handle related operations of menu folding
|
||||||
*/
|
*/
|
||||||
export function useTrigger(getIsMobile: Ref<boolean>) {
|
export function useTrigger(getIsMobile: Ref<boolean>) {
|
||||||
const { getTrigger, getSplit } = useMenuSetting();
|
const { getTrigger, getSplit } = useMenuSetting()
|
||||||
|
|
||||||
const getShowTrigger = computed(() => {
|
const getShowTrigger = computed(() => {
|
||||||
const trigger = unref(getTrigger);
|
const trigger = unref(getTrigger)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
trigger !== TriggerEnum.NONE &&
|
trigger !== TriggerEnum.NONE &&
|
||||||
!unref(getIsMobile) &&
|
!unref(getIsMobile) &&
|
||||||
(trigger === TriggerEnum.FOOTER || unref(getSplit))
|
(trigger === TriggerEnum.FOOTER || unref(getSplit))
|
||||||
);
|
)
|
||||||
});
|
})
|
||||||
|
|
||||||
const getTriggerAttr = computed(() => {
|
const getTriggerAttr = computed(() => {
|
||||||
if (unref(getShowTrigger)) {
|
if (unref(getShowTrigger)) {
|
||||||
return {};
|
return {}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
trigger: null,
|
trigger: null,
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
return { getTriggerAttr, getShowTrigger };
|
return { getTriggerAttr, getShowTrigger }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -64,80 +64,80 @@ export function useTrigger(getIsMobile: Ref<boolean>) {
|
||||||
* @param dragBarRef
|
* @param dragBarRef
|
||||||
*/
|
*/
|
||||||
export function useDragLine(siderRef: Ref<any>, dragBarRef: Ref<any>, mix = false) {
|
export function useDragLine(siderRef: Ref<any>, dragBarRef: Ref<any>, mix = false) {
|
||||||
const { getMiniWidthNumber, getCollapsed, setMenuSetting } = useMenuSetting();
|
const { getMiniWidthNumber, getCollapsed, setMenuSetting } = useMenuSetting()
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const exec = useDebounceFn(changeWrapWidth, 80);
|
const exec = useDebounceFn(changeWrapWidth, 80)
|
||||||
exec();
|
exec()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
function getEl(elRef: Ref<ElRef | ComponentRef>): any {
|
function getEl(elRef: Ref<ElRef | ComponentRef>): any {
|
||||||
const el = unref(elRef);
|
const el = unref(elRef)
|
||||||
if (!el) return null;
|
if (!el) return null
|
||||||
if (Reflect.has(el, '$el')) {
|
if (Reflect.has(el, '$el')) {
|
||||||
return (unref(elRef) as ComponentRef)?.$el;
|
return (unref(elRef) as ComponentRef)?.$el
|
||||||
}
|
}
|
||||||
return unref(elRef);
|
return unref(elRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMouseMove(ele: HTMLElement, wrap: HTMLElement, clientX: number) {
|
function handleMouseMove(ele: HTMLElement, wrap: HTMLElement, clientX: number) {
|
||||||
document.onmousemove = function (innerE) {
|
document.onmousemove = function (innerE) {
|
||||||
let iT = (ele as any).left + (innerE.clientX - clientX);
|
let iT = (ele as any).left + (innerE.clientX - clientX)
|
||||||
innerE = innerE || window.event;
|
innerE = innerE || window.event
|
||||||
const maxT = 800;
|
const maxT = 800
|
||||||
const minT = unref(getMiniWidthNumber);
|
const minT = unref(getMiniWidthNumber)
|
||||||
iT < 0 && (iT = 0);
|
iT < 0 && (iT = 0)
|
||||||
iT > maxT && (iT = maxT);
|
iT > maxT && (iT = maxT)
|
||||||
iT < minT && (iT = minT);
|
iT < minT && (iT = minT)
|
||||||
ele.style.left = wrap.style.width = iT + 'px';
|
ele.style.left = wrap.style.width = iT + 'px'
|
||||||
return false;
|
return false
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drag and drop in the menu area-release the mouse
|
// Drag and drop in the menu area-release the mouse
|
||||||
function removeMouseup(ele: any) {
|
function removeMouseup(ele: any) {
|
||||||
const wrap = getEl(siderRef);
|
const wrap = getEl(siderRef)
|
||||||
document.onmouseup = function () {
|
document.onmouseup = function () {
|
||||||
document.onmousemove = null;
|
document.onmousemove = null
|
||||||
document.onmouseup = null;
|
document.onmouseup = null
|
||||||
wrap.style.transition = 'width 0.2s';
|
wrap.style.transition = 'width 0.2s'
|
||||||
const width = parseInt(wrap.style.width);
|
const width = parseInt(wrap.style.width)
|
||||||
|
|
||||||
if (!mix) {
|
if (!mix) {
|
||||||
const miniWidth = unref(getMiniWidthNumber);
|
const miniWidth = unref(getMiniWidthNumber)
|
||||||
if (!unref(getCollapsed)) {
|
if (!unref(getCollapsed)) {
|
||||||
width > miniWidth + 20
|
width > miniWidth + 20
|
||||||
? setMenuSetting({ menuWidth: width })
|
? setMenuSetting({ menuWidth: width })
|
||||||
: setMenuSetting({ collapsed: true });
|
: setMenuSetting({ collapsed: true })
|
||||||
} else {
|
} else {
|
||||||
width > miniWidth && setMenuSetting({ collapsed: false, menuWidth: width });
|
width > miniWidth && setMenuSetting({ collapsed: false, menuWidth: width })
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setMenuSetting({ menuWidth: width });
|
setMenuSetting({ menuWidth: width })
|
||||||
}
|
}
|
||||||
|
|
||||||
ele.releaseCapture?.();
|
ele.releaseCapture?.()
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeWrapWidth() {
|
function changeWrapWidth() {
|
||||||
const ele = getEl(dragBarRef);
|
const ele = getEl(dragBarRef)
|
||||||
if (!ele) return;
|
if (!ele) return
|
||||||
const wrap = getEl(siderRef);
|
const wrap = getEl(siderRef)
|
||||||
if (!wrap) return;
|
if (!wrap) return
|
||||||
|
|
||||||
ele.onmousedown = (e: any) => {
|
ele.onmousedown = (e: any) => {
|
||||||
wrap.style.transition = 'unset';
|
wrap.style.transition = 'unset'
|
||||||
const clientX = e?.clientX;
|
const clientX = e?.clientX
|
||||||
ele.left = ele.offsetLeft;
|
ele.left = ele.offsetLeft
|
||||||
handleMouseMove(ele, wrap, clientX);
|
handleMouseMove(ele, wrap, clientX)
|
||||||
removeMouseup(ele);
|
removeMouseup(ele)
|
||||||
ele.setCapture?.();
|
ele.setCapture?.()
|
||||||
return false;
|
return false
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,18 +15,18 @@
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { PropType } from 'vue';
|
import type { PropType } from 'vue'
|
||||||
import type { RouteLocationNormalized } from 'vue-router';
|
import type { RouteLocationNormalized } from 'vue-router'
|
||||||
|
|
||||||
import { defineComponent, computed, unref } from 'vue';
|
import { defineComponent, computed, unref } from 'vue'
|
||||||
import { Dropdown } from '/@/components/Dropdown/index';
|
import { Dropdown } from '/@/components/Dropdown/index'
|
||||||
import { Icon } from '/@/components/Icon';
|
import { Icon } from '/@/components/Icon'
|
||||||
|
|
||||||
import { TabContentProps } from '../types';
|
import { TabContentProps } from '../types'
|
||||||
|
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
import { useTabDropdown } from '../useTabDropdown';
|
import { useTabDropdown } from '../useTabDropdown'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'TabContent',
|
name: 'TabContent',
|
||||||
|
|
@ -39,27 +39,27 @@
|
||||||
isExtra: Boolean,
|
isExtra: Boolean,
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const { prefixCls } = useDesign('multiple-tabs-content');
|
const { prefixCls } = useDesign('multiple-tabs-content')
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
|
|
||||||
const getTitle = computed(() => {
|
const getTitle = computed(() => {
|
||||||
const { tabItem: { meta } = {} } = props;
|
const { tabItem: { meta } = {} } = props
|
||||||
return meta && t(meta.title as string);
|
return meta && t(meta.title as string)
|
||||||
});
|
})
|
||||||
|
|
||||||
const getIsTabs = computed(() => !props.isExtra);
|
const getIsTabs = computed(() => !props.isExtra)
|
||||||
|
|
||||||
const getTrigger = computed((): ('contextmenu' | 'click' | 'hover')[] =>
|
const getTrigger = computed((): ('contextmenu' | 'click' | 'hover')[] =>
|
||||||
unref(getIsTabs) ? ['contextmenu'] : ['click'],
|
unref(getIsTabs) ? ['contextmenu'] : ['click'],
|
||||||
);
|
)
|
||||||
|
|
||||||
const { getDropMenuList, handleMenuEvent, handleContextMenu } = useTabDropdown(
|
const { getDropMenuList, handleMenuEvent, handleContextMenu } = useTabDropdown(
|
||||||
props as TabContentProps,
|
props as TabContentProps,
|
||||||
getIsTabs,
|
getIsTabs,
|
||||||
);
|
)
|
||||||
|
|
||||||
function handleContext(e) {
|
function handleContext(e) {
|
||||||
props.tabItem && handleContextMenu(props.tabItem)(e);
|
props.tabItem && handleContextMenu(props.tabItem)(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -70,7 +70,7 @@
|
||||||
getTrigger,
|
getTrigger,
|
||||||
getIsTabs,
|
getIsTabs,
|
||||||
getTitle,
|
getTitle,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -27,28 +27,28 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { RouteLocationNormalized, RouteMeta } from 'vue-router';
|
import type { RouteLocationNormalized, RouteMeta } from 'vue-router'
|
||||||
|
|
||||||
import { defineComponent, computed, unref, ref } from 'vue';
|
import { defineComponent, computed, unref, ref } from 'vue'
|
||||||
|
|
||||||
import { Tabs } from 'ant-design-vue';
|
import { Tabs } from 'ant-design-vue'
|
||||||
import TabContent from './components/TabContent.vue';
|
import TabContent from './components/TabContent.vue'
|
||||||
import FoldButton from './components/FoldButton.vue';
|
import FoldButton from './components/FoldButton.vue'
|
||||||
import TabRedo from './components/TabRedo.vue';
|
import TabRedo from './components/TabRedo.vue'
|
||||||
|
|
||||||
import { useGo } from '/@/hooks/web/usePage';
|
import { useGo } from '/@/hooks/web/usePage'
|
||||||
|
|
||||||
import { useMultipleTabStore } from '/@/store/modules/multipleTab';
|
import { useMultipleTabStore } from '/@/store/modules/multipleTab'
|
||||||
import { useUserStore } from '/@/store/modules/user';
|
import { useUserStore } from '/@/store/modules/user'
|
||||||
|
|
||||||
import { initAffixTabs, useTabsDrag } from './useMultipleTabs';
|
import { initAffixTabs, useTabsDrag } from './useMultipleTabs'
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting'
|
||||||
|
|
||||||
import { REDIRECT_NAME } from '/@/router/constant';
|
import { REDIRECT_NAME } from '/@/router/constant'
|
||||||
import { listenerRouteChange } from '/@/logics/mitt/routeChange';
|
import { listenerRouteChange } from '/@/logics/mitt/routeChange'
|
||||||
|
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'MultipleTabs',
|
name: 'MultipleTabs',
|
||||||
|
|
@ -60,23 +60,23 @@
|
||||||
TabContent,
|
TabContent,
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const affixTextList = initAffixTabs();
|
const affixTextList = initAffixTabs()
|
||||||
const activeKeyRef = ref('');
|
const activeKeyRef = ref('')
|
||||||
|
|
||||||
useTabsDrag(affixTextList);
|
useTabsDrag(affixTextList)
|
||||||
const tabStore = useMultipleTabStore();
|
const tabStore = useMultipleTabStore()
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore()
|
||||||
const router = useRouter();
|
const router = useRouter()
|
||||||
|
|
||||||
const { prefixCls } = useDesign('multiple-tabs');
|
const { prefixCls } = useDesign('multiple-tabs')
|
||||||
const go = useGo();
|
const go = useGo()
|
||||||
const { getShowQuick, getShowRedo, getShowFold } = useMultipleTabSetting();
|
const { getShowQuick, getShowRedo, getShowFold } = useMultipleTabSetting()
|
||||||
|
|
||||||
const getTabsState = computed(() => {
|
const getTabsState = computed(() => {
|
||||||
return tabStore.getTabList.filter((item) => !item.meta?.hideTab);
|
return tabStore.getTabList.filter((item) => !item.meta?.hideTab)
|
||||||
});
|
})
|
||||||
|
|
||||||
const unClose = computed(() => unref(getTabsState).length === 1);
|
const unClose = computed(() => unref(getTabsState).length === 1)
|
||||||
|
|
||||||
const getWrapClass = computed(() => {
|
const getWrapClass = computed(() => {
|
||||||
return [
|
return [
|
||||||
|
|
@ -84,47 +84,45 @@
|
||||||
{
|
{
|
||||||
[`${prefixCls}--hide-close`]: unref(unClose),
|
[`${prefixCls}--hide-close`]: unref(unClose),
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
});
|
})
|
||||||
|
|
||||||
listenerRouteChange((route) => {
|
listenerRouteChange((route) => {
|
||||||
const { name } = route;
|
const { name } = route
|
||||||
if (name === REDIRECT_NAME || !route || !userStore.getToken) {
|
if (name === REDIRECT_NAME || !route || !userStore.getToken) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const { path, fullPath, meta = {} } = route;
|
const { path, fullPath, meta = {} } = route
|
||||||
const { currentActiveMenu, hideTab } = meta as RouteMeta;
|
const { currentActiveMenu, hideTab } = meta as RouteMeta
|
||||||
const isHide = !hideTab ? null : currentActiveMenu;
|
const isHide = !hideTab ? null : currentActiveMenu
|
||||||
const p = isHide || fullPath || path;
|
const p = isHide || fullPath || path
|
||||||
if (activeKeyRef.value !== p) {
|
if (activeKeyRef.value !== p) {
|
||||||
activeKeyRef.value = p as string;
|
activeKeyRef.value = p as string
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isHide) {
|
if (isHide) {
|
||||||
const findParentRoute = router
|
const findParentRoute = router.getRoutes().find((item) => item.path === currentActiveMenu)
|
||||||
.getRoutes()
|
|
||||||
.find((item) => item.path === currentActiveMenu);
|
|
||||||
|
|
||||||
findParentRoute && tabStore.addTab(findParentRoute as unknown as RouteLocationNormalized);
|
findParentRoute && tabStore.addTab(findParentRoute as unknown as RouteLocationNormalized)
|
||||||
} else {
|
} else {
|
||||||
tabStore.addTab(unref(route));
|
tabStore.addTab(unref(route))
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
function handleChange(activeKey: any) {
|
function handleChange(activeKey: any) {
|
||||||
activeKeyRef.value = activeKey;
|
activeKeyRef.value = activeKey
|
||||||
go(activeKey, false);
|
go(activeKey, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the current tab
|
// Close the current tab
|
||||||
function handleEdit(targetKey: string) {
|
function handleEdit(targetKey: string) {
|
||||||
// Added operation to hide, currently only use delete operation
|
// Added operation to hide, currently only use delete operation
|
||||||
if (unref(unClose)) {
|
if (unref(unClose)) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tabStore.closeTabByKey(targetKey, router);
|
tabStore.closeTabByKey(targetKey, router)
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
getWrapClass,
|
getWrapClass,
|
||||||
|
|
@ -135,9 +133,9 @@
|
||||||
getShowQuick,
|
getShowQuick,
|
||||||
getShowRedo,
|
getShowRedo,
|
||||||
getShowFold,
|
getShowFold,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@import './index.less';
|
@import './index.less';
|
||||||
|
|
|
||||||
|
|
@ -1,80 +1,80 @@
|
||||||
import { toRaw, ref, nextTick } from 'vue';
|
import { toRaw, ref, nextTick } from 'vue'
|
||||||
import type { RouteLocationNormalized } from 'vue-router';
|
import type { RouteLocationNormalized } from 'vue-router'
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
import { useSortable } from '/@/hooks/web/useSortable';
|
import { useSortable } from '/@/hooks/web/useSortable'
|
||||||
import { useMultipleTabStore } from '/@/store/modules/multipleTab';
|
import { useMultipleTabStore } from '/@/store/modules/multipleTab'
|
||||||
import { isNullAndUnDef } from '/@/utils/is';
|
import { isNullAndUnDef } from '/@/utils/is'
|
||||||
import projectSetting from '/@/settings/projectSetting';
|
import projectSetting from '/@/settings/projectSetting'
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
export function initAffixTabs(): string[] {
|
export function initAffixTabs(): string[] {
|
||||||
const affixList = ref<RouteLocationNormalized[]>([]);
|
const affixList = ref<RouteLocationNormalized[]>([])
|
||||||
|
|
||||||
const tabStore = useMultipleTabStore();
|
const tabStore = useMultipleTabStore()
|
||||||
const router = useRouter();
|
const router = useRouter()
|
||||||
/**
|
/**
|
||||||
* @description: Filter all fixed routes
|
* @description: Filter all fixed routes
|
||||||
*/
|
*/
|
||||||
function filterAffixTabs(routes: RouteLocationNormalized[]) {
|
function filterAffixTabs(routes: RouteLocationNormalized[]) {
|
||||||
const tabs: RouteLocationNormalized[] = [];
|
const tabs: RouteLocationNormalized[] = []
|
||||||
routes &&
|
routes &&
|
||||||
routes.forEach((route) => {
|
routes.forEach((route) => {
|
||||||
if (route.meta && route.meta.affix) {
|
if (route.meta && route.meta.affix) {
|
||||||
tabs.push(toRaw(route));
|
tabs.push(toRaw(route))
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
return tabs;
|
return tabs
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description: Set fixed tabs
|
* @description: Set fixed tabs
|
||||||
*/
|
*/
|
||||||
function addAffixTabs(): void {
|
function addAffixTabs(): void {
|
||||||
const affixTabs = filterAffixTabs(router.getRoutes() as unknown as RouteLocationNormalized[]);
|
const affixTabs = filterAffixTabs(router.getRoutes() as unknown as RouteLocationNormalized[])
|
||||||
affixList.value = affixTabs;
|
affixList.value = affixTabs
|
||||||
for (const tab of affixTabs) {
|
for (const tab of affixTabs) {
|
||||||
tabStore.addTab({
|
tabStore.addTab({
|
||||||
meta: tab.meta,
|
meta: tab.meta,
|
||||||
name: tab.name,
|
name: tab.name,
|
||||||
path: tab.path,
|
path: tab.path,
|
||||||
} as unknown as RouteLocationNormalized);
|
} as unknown as RouteLocationNormalized)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let isAddAffix = false;
|
let isAddAffix = false
|
||||||
|
|
||||||
if (!isAddAffix) {
|
if (!isAddAffix) {
|
||||||
addAffixTabs();
|
addAffixTabs()
|
||||||
isAddAffix = true;
|
isAddAffix = true
|
||||||
}
|
}
|
||||||
return affixList.value.map((item) => item.meta?.title).filter(Boolean) as string[];
|
return affixList.value.map((item) => item.meta?.title).filter(Boolean) as string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useTabsDrag(affixTextList: string[]) {
|
export function useTabsDrag(affixTextList: string[]) {
|
||||||
const tabStore = useMultipleTabStore();
|
const tabStore = useMultipleTabStore()
|
||||||
const { multiTabsSetting } = projectSetting;
|
const { multiTabsSetting } = projectSetting
|
||||||
const { prefixCls } = useDesign('multiple-tabs');
|
const { prefixCls } = useDesign('multiple-tabs')
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
if (!multiTabsSetting.canDrag) return;
|
if (!multiTabsSetting.canDrag) return
|
||||||
const el = document.querySelectorAll(
|
const el = document.querySelectorAll(
|
||||||
`.${prefixCls} .ant-tabs-nav-wrap > div`,
|
`.${prefixCls} .ant-tabs-nav-wrap > div`,
|
||||||
)?.[0] as HTMLElement;
|
)?.[0] as HTMLElement
|
||||||
const { initSortable } = useSortable(el, {
|
const { initSortable } = useSortable(el, {
|
||||||
filter: (e: ChangeEvent) => {
|
filter: (e: ChangeEvent) => {
|
||||||
const text = e?.target?.innerText;
|
const text = e?.target?.innerText
|
||||||
if (!text) return false;
|
if (!text) return false
|
||||||
return affixTextList.includes(text);
|
return affixTextList.includes(text)
|
||||||
},
|
},
|
||||||
onEnd: (evt) => {
|
onEnd: (evt) => {
|
||||||
const { oldIndex, newIndex } = evt;
|
const { oldIndex, newIndex } = evt
|
||||||
|
|
||||||
if (isNullAndUnDef(oldIndex) || isNullAndUnDef(newIndex) || oldIndex === newIndex) {
|
if (isNullAndUnDef(oldIndex) || isNullAndUnDef(newIndex) || oldIndex === newIndex) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tabStore.sortTabs(oldIndex, newIndex);
|
tabStore.sortTabs(oldIndex, newIndex)
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
initSortable();
|
initSortable()
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,37 +27,37 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineComponent, unref } from 'vue';
|
import { computed, defineComponent, unref } from 'vue'
|
||||||
|
|
||||||
import FrameLayout from '/@/layouts/iframe/index.vue';
|
import FrameLayout from '/@/layouts/iframe/index.vue'
|
||||||
|
|
||||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
import { useRootSetting } from '/@/hooks/setting/useRootSetting'
|
||||||
|
|
||||||
import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
|
import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting'
|
||||||
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting'
|
||||||
import { getTransitionName } from './transition';
|
import { getTransitionName } from './transition'
|
||||||
|
|
||||||
import { useMultipleTabStore } from '/@/store/modules/multipleTab';
|
import { useMultipleTabStore } from '/@/store/modules/multipleTab'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'PageLayout',
|
name: 'PageLayout',
|
||||||
components: { FrameLayout },
|
components: { FrameLayout },
|
||||||
setup() {
|
setup() {
|
||||||
const { getShowMultipleTab } = useMultipleTabSetting();
|
const { getShowMultipleTab } = useMultipleTabSetting()
|
||||||
const tabStore = useMultipleTabStore();
|
const tabStore = useMultipleTabStore()
|
||||||
|
|
||||||
const { getOpenKeepAlive, getCanEmbedIFramePage } = useRootSetting();
|
const { getOpenKeepAlive, getCanEmbedIFramePage } = useRootSetting()
|
||||||
|
|
||||||
const { getBasicTransition, getEnableTransition } = useTransitionSetting();
|
const { getBasicTransition, getEnableTransition } = useTransitionSetting()
|
||||||
|
|
||||||
const openCache = computed(() => unref(getOpenKeepAlive) && unref(getShowMultipleTab));
|
const openCache = computed(() => unref(getOpenKeepAlive) && unref(getShowMultipleTab))
|
||||||
|
|
||||||
const getCaches = computed((): string[] => {
|
const getCaches = computed((): string[] => {
|
||||||
if (!unref(getOpenKeepAlive)) {
|
if (!unref(getOpenKeepAlive)) {
|
||||||
return [];
|
return []
|
||||||
}
|
}
|
||||||
return tabStore.getCachedTabList;
|
return tabStore.getCachedTabList
|
||||||
});
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getTransitionName,
|
getTransitionName,
|
||||||
|
|
@ -66,7 +66,7 @@
|
||||||
getBasicTransition,
|
getBasicTransition,
|
||||||
getCaches,
|
getCaches,
|
||||||
getCanEmbedIFramePage,
|
getCanEmbedIFramePage,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,23 @@
|
||||||
import type { Router, RouteRecordRaw } from 'vue-router';
|
import type { Router, RouteRecordRaw } from 'vue-router'
|
||||||
|
|
||||||
import { usePermissionStoreWithOut } from '/@/store/modules/permission';
|
import { usePermissionStoreWithOut } from '/@/store/modules/permission'
|
||||||
|
|
||||||
import { PageEnum } from '/@/enums/pageEnum';
|
import { PageEnum } from '/@/enums/pageEnum'
|
||||||
import { useUserStoreWithOut } from '/@/store/modules/user';
|
import { useUserStoreWithOut } from '/@/store/modules/user'
|
||||||
|
|
||||||
import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic';
|
import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic'
|
||||||
|
|
||||||
import { RootRoute } from '/@/router/routes';
|
import { RootRoute } from '/@/router/routes'
|
||||||
|
|
||||||
const LOGIN_PATH = PageEnum.BASE_LOGIN;
|
const LOGIN_PATH = PageEnum.BASE_LOGIN
|
||||||
|
|
||||||
const ROOT_PATH = RootRoute.path;
|
const ROOT_PATH = RootRoute.path
|
||||||
|
|
||||||
const whitePathList: PageEnum[] = [LOGIN_PATH];
|
const whitePathList: PageEnum[] = [LOGIN_PATH]
|
||||||
|
|
||||||
export function createPermissionGuard(router: Router) {
|
export function createPermissionGuard(router: Router) {
|
||||||
const userStore = useUserStoreWithOut();
|
const userStore = useUserStoreWithOut()
|
||||||
const permissionStore = usePermissionStoreWithOut();
|
const permissionStore = usePermissionStoreWithOut()
|
||||||
router.beforeEach(async (to, from, next) => {
|
router.beforeEach(async (to, from, next) => {
|
||||||
if (
|
if (
|
||||||
from.path === ROOT_PATH &&
|
from.path === ROOT_PATH &&
|
||||||
|
|
@ -25,49 +25,49 @@ export function createPermissionGuard(router: Router) {
|
||||||
userStore.getUserInfo.homePath &&
|
userStore.getUserInfo.homePath &&
|
||||||
userStore.getUserInfo.homePath !== PageEnum.BASE_HOME
|
userStore.getUserInfo.homePath !== PageEnum.BASE_HOME
|
||||||
) {
|
) {
|
||||||
next(userStore.getUserInfo.homePath);
|
next(userStore.getUserInfo.homePath)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const token = userStore.getToken;
|
const token = userStore.getToken
|
||||||
|
|
||||||
// Whitelist can be directly entered
|
// Whitelist can be directly entered
|
||||||
if (whitePathList.includes(to.path as PageEnum)) {
|
if (whitePathList.includes(to.path as PageEnum)) {
|
||||||
if (to.path === LOGIN_PATH && token) {
|
if (to.path === LOGIN_PATH && token) {
|
||||||
const isSessionTimeout = userStore.getSessionTimeout;
|
const isSessionTimeout = userStore.getSessionTimeout
|
||||||
try {
|
try {
|
||||||
await userStore.afterLoginAction();
|
await userStore.afterLoginAction()
|
||||||
if (!isSessionTimeout) {
|
if (!isSessionTimeout) {
|
||||||
next((to.query?.redirect as string) || '/');
|
next((to.query?.redirect as string) || '/')
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
next();
|
next()
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// token does not exist
|
// token does not exist
|
||||||
if (!token) {
|
if (!token) {
|
||||||
// You can access without permission. You need to set the routing meta.ignoreAuth to true
|
// You can access without permission. You need to set the routing meta.ignoreAuth to true
|
||||||
if (to.meta.ignoreAuth) {
|
if (to.meta.ignoreAuth) {
|
||||||
next();
|
next()
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// redirect login page
|
// redirect login page
|
||||||
const redirectData: { path: string; replace: boolean; query?: Recordable<string> } = {
|
const redirectData: { path: string; replace: boolean; query?: Recordable<string> } = {
|
||||||
path: LOGIN_PATH,
|
path: LOGIN_PATH,
|
||||||
replace: true,
|
replace: true,
|
||||||
};
|
}
|
||||||
if (to.path) {
|
if (to.path) {
|
||||||
redirectData.query = {
|
redirectData.query = {
|
||||||
...redirectData.query,
|
...redirectData.query,
|
||||||
redirect: to.path,
|
redirect: to.path,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
next(redirectData);
|
next(redirectData)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jump to the 404 page after processing the login
|
// Jump to the 404 page after processing the login
|
||||||
|
|
@ -76,43 +76,43 @@ export function createPermissionGuard(router: Router) {
|
||||||
to.name === PAGE_NOT_FOUND_ROUTE.name &&
|
to.name === PAGE_NOT_FOUND_ROUTE.name &&
|
||||||
to.fullPath !== (userStore.getUserInfo.homePath || PageEnum.BASE_HOME)
|
to.fullPath !== (userStore.getUserInfo.homePath || PageEnum.BASE_HOME)
|
||||||
) {
|
) {
|
||||||
next(userStore.getUserInfo.homePath || PageEnum.BASE_HOME);
|
next(userStore.getUserInfo.homePath || PageEnum.BASE_HOME)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// get userinfo while last fetch time is empty
|
// get userinfo while last fetch time is empty
|
||||||
if (userStore.getLastUpdateTime === 0) {
|
if (userStore.getLastUpdateTime === 0) {
|
||||||
try {
|
try {
|
||||||
await userStore.getUserInfoAction();
|
await userStore.getUserInfoAction()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
next();
|
next()
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (permissionStore.getIsDynamicAddedRoute) {
|
if (permissionStore.getIsDynamicAddedRoute) {
|
||||||
next();
|
next()
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const routes = await permissionStore.buildRoutesAction();
|
const routes = await permissionStore.buildRoutesAction()
|
||||||
|
|
||||||
routes.forEach((route) => {
|
routes.forEach((route) => {
|
||||||
router.addRoute(route as unknown as RouteRecordRaw);
|
router.addRoute(route as unknown as RouteRecordRaw)
|
||||||
});
|
})
|
||||||
|
|
||||||
router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw);
|
router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw)
|
||||||
|
|
||||||
permissionStore.setDynamicAddedRoute(true);
|
permissionStore.setDynamicAddedRoute(true)
|
||||||
|
|
||||||
if (to.name === PAGE_NOT_FOUND_ROUTE.name) {
|
if (to.name === PAGE_NOT_FOUND_ROUTE.name) {
|
||||||
// 动态添加路由后,此处应当重定向到fullPath,否则会加载404页面内容
|
// 动态添加路由后,此处应当重定向到fullPath,否则会加载404页面内容
|
||||||
next({ path: to.fullPath, replace: true, query: to.query });
|
next({ path: to.fullPath, replace: true, query: to.query })
|
||||||
} else {
|
} else {
|
||||||
const redirectPath = (from.query.redirect || to.path) as string;
|
const redirectPath = (from.query.redirect || to.path) as string
|
||||||
const redirect = decodeURIComponent(redirectPath);
|
const redirect = decodeURIComponent(redirectPath)
|
||||||
const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect };
|
const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect }
|
||||||
next(nextData);
|
next(nextData)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
import { AppRouteModule } from '/@/router/types';
|
import { AppRouteModule } from '/@/router/types'
|
||||||
import type { MenuModule, Menu, AppRouteRecordRaw } from '/@/router/types';
|
import type { MenuModule, Menu, AppRouteRecordRaw } from '/@/router/types'
|
||||||
import { findPath, treeMap } from '/@/utils/helper/treeHelper';
|
import { findPath, treeMap } from '/@/utils/helper/treeHelper'
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es'
|
||||||
import { isUrl } from '/@/utils/is';
|
import { isUrl } from '/@/utils/is'
|
||||||
import { RouteParams } from 'vue-router';
|
import { RouteParams } from 'vue-router'
|
||||||
import { toRaw } from 'vue';
|
import { toRaw } from 'vue'
|
||||||
|
|
||||||
export function getAllParentPath<T = Recordable>(treeData: T[], path: string) {
|
export function getAllParentPath<T = Recordable>(treeData: T[], path: string) {
|
||||||
const menuList = findPath(treeData, (n) => n.path === path) as Menu[];
|
const menuList = findPath(treeData, (n) => n.path === path) as Menu[]
|
||||||
return (menuList || []).map((item) => item.path);
|
return (menuList || []).map((item) => item.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 路径处理
|
// 路径处理
|
||||||
function joinParentPath(menus: Menu[], parentPath = '') {
|
function joinParentPath(menus: Menu[], parentPath = '') {
|
||||||
for (let index = 0; index < menus.length; index++) {
|
for (let index = 0; index < menus.length; index++) {
|
||||||
const menu = menus[index];
|
const menu = menus[index]
|
||||||
// https://next.router.vuejs.org/guide/essentials/nested-routes.html
|
// https://next.router.vuejs.org/guide/essentials/nested-routes.html
|
||||||
// Note that nested paths that start with / will be treated as a root path.
|
// Note that nested paths that start with / will be treated as a root path.
|
||||||
// 请注意,以 / 开头的嵌套路径将被视为根路径。
|
// 请注意,以 / 开头的嵌套路径将被视为根路径。
|
||||||
|
|
@ -23,47 +23,47 @@ function joinParentPath(menus: Menu[], parentPath = '') {
|
||||||
if (!(menu.path.startsWith('/') || isUrl(menu.path))) {
|
if (!(menu.path.startsWith('/') || isUrl(menu.path))) {
|
||||||
// path doesn't start with /, nor is it a url, join parent path
|
// path doesn't start with /, nor is it a url, join parent path
|
||||||
// 路径不以 / 开头,也不是 url,加入父路径
|
// 路径不以 / 开头,也不是 url,加入父路径
|
||||||
menu.path = `${parentPath}/${menu.path}`;
|
menu.path = `${parentPath}/${menu.path}`
|
||||||
}
|
}
|
||||||
if (menu?.children?.length) {
|
if (menu?.children?.length) {
|
||||||
joinParentPath(menu.children, menu.meta?.hidePathForChildren ? parentPath : menu.path);
|
joinParentPath(menu.children, menu.meta?.hidePathForChildren ? parentPath : menu.path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parsing the menu module
|
// Parsing the menu module
|
||||||
export function transformMenuModule(menuModule: MenuModule): Menu {
|
export function transformMenuModule(menuModule: MenuModule): Menu {
|
||||||
const { menu } = menuModule;
|
const { menu } = menuModule
|
||||||
|
|
||||||
const menuList = [menu];
|
const menuList = [menu]
|
||||||
|
|
||||||
joinParentPath(menuList);
|
joinParentPath(menuList)
|
||||||
return menuList[0];
|
return menuList[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将路由转换成菜单
|
// 将路由转换成菜单
|
||||||
export function transformRouteToMenu(routeModList: AppRouteModule[], routerMapping = false) {
|
export function transformRouteToMenu(routeModList: AppRouteModule[], routerMapping = false) {
|
||||||
// 借助 lodash 深拷贝
|
// 借助 lodash 深拷贝
|
||||||
const cloneRouteModList = cloneDeep(routeModList);
|
const cloneRouteModList = cloneDeep(routeModList)
|
||||||
const routeList: AppRouteRecordRaw[] = [];
|
const routeList: AppRouteRecordRaw[] = []
|
||||||
|
|
||||||
// 对路由项进行修改
|
// 对路由项进行修改
|
||||||
cloneRouteModList.forEach((item) => {
|
cloneRouteModList.forEach((item) => {
|
||||||
if (routerMapping && item.meta.hideChildrenInMenu && typeof item.redirect === 'string') {
|
if (routerMapping && item.meta.hideChildrenInMenu && typeof item.redirect === 'string') {
|
||||||
item.path = item.redirect;
|
item.path = item.redirect
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.meta?.single) {
|
if (item.meta?.single) {
|
||||||
const realItem = item?.children?.[0];
|
const realItem = item?.children?.[0]
|
||||||
realItem && routeList.push(realItem);
|
realItem && routeList.push(realItem)
|
||||||
} else {
|
} else {
|
||||||
routeList.push(item);
|
routeList.push(item)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
// 提取树指定结构
|
// 提取树指定结构
|
||||||
const list = treeMap(routeList, {
|
const list = treeMap(routeList, {
|
||||||
conversion: (node: AppRouteRecordRaw) => {
|
conversion: (node: AppRouteRecordRaw) => {
|
||||||
const { meta: { title, hideMenu = false } = {} } = node;
|
const { meta: { title, hideMenu = false } = {} } = node
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...(node.meta || {}),
|
...(node.meta || {}),
|
||||||
|
|
@ -72,35 +72,35 @@ export function transformRouteToMenu(routeModList: AppRouteModule[], routerMappi
|
||||||
hideMenu,
|
hideMenu,
|
||||||
path: node.path,
|
path: node.path,
|
||||||
...(node.redirect ? { redirect: node.redirect } : {}),
|
...(node.redirect ? { redirect: node.redirect } : {}),
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
// 路径处理
|
// 路径处理
|
||||||
joinParentPath(list);
|
joinParentPath(list)
|
||||||
return cloneDeep(list);
|
return cloneDeep(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* config menu with given params
|
* config menu with given params
|
||||||
*/
|
*/
|
||||||
const menuParamRegex = /(?::)([\s\S]+?)((?=\/)|$)/g;
|
const menuParamRegex = /(?::)([\s\S]+?)((?=\/)|$)/g
|
||||||
|
|
||||||
export function configureDynamicParamsMenu(menu: Menu, params: RouteParams) {
|
export function configureDynamicParamsMenu(menu: Menu, params: RouteParams) {
|
||||||
const { path, paramPath } = toRaw(menu);
|
const { path, paramPath } = toRaw(menu)
|
||||||
let realPath = paramPath ? paramPath : path;
|
let realPath = paramPath ? paramPath : path
|
||||||
const matchArr = realPath.match(menuParamRegex);
|
const matchArr = realPath.match(menuParamRegex)
|
||||||
|
|
||||||
matchArr?.forEach((it) => {
|
matchArr?.forEach((it) => {
|
||||||
const realIt = it.substr(1);
|
const realIt = it.substr(1)
|
||||||
if (params[realIt]) {
|
if (params[realIt]) {
|
||||||
realPath = realPath.replace(`:${realIt}`, params[realIt] as string);
|
realPath = realPath.replace(`:${realIt}`, params[realIt] as string)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
// save original param path.
|
// save original param path.
|
||||||
if (!paramPath && matchArr && matchArr.length > 0) {
|
if (!paramPath && matchArr && matchArr.length > 0) {
|
||||||
menu.paramPath = path;
|
menu.paramPath = path
|
||||||
}
|
}
|
||||||
menu.path = realPath;
|
menu.path = realPath
|
||||||
// children
|
// children
|
||||||
menu.children?.forEach((item) => configureDynamicParamsMenu(item, params));
|
menu.children?.forEach((item) => configureDynamicParamsMenu(item, params))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,69 +1,69 @@
|
||||||
import type { AppRouteModule, AppRouteRecordRaw } from '/@/router/types';
|
import type { AppRouteModule, AppRouteRecordRaw } from '/@/router/types'
|
||||||
import type { Router, RouteRecordNormalized } from 'vue-router';
|
import type { Router, RouteRecordNormalized } from 'vue-router'
|
||||||
|
|
||||||
import { getParentLayout, LAYOUT, EXCEPTION_COMPONENT } from '/@/router/constant';
|
import { getParentLayout, LAYOUT, EXCEPTION_COMPONENT } from '/@/router/constant'
|
||||||
import { cloneDeep, omit } from 'lodash-es';
|
import { cloneDeep, omit } from 'lodash-es'
|
||||||
import { warn } from '/@/utils/log';
|
import { warn } from '/@/utils/log'
|
||||||
import { createRouter, createWebHashHistory } from 'vue-router';
|
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||||
|
|
||||||
export type LayoutMapKey = 'LAYOUT';
|
export type LayoutMapKey = 'LAYOUT'
|
||||||
const IFRAME = () => import('/@/views/sys/iframe/FrameBlank.vue');
|
const IFRAME = () => import('/@/views/sys/iframe/FrameBlank.vue')
|
||||||
|
|
||||||
const LayoutMap = new Map<string, () => Promise<typeof import('*.vue')>>();
|
const LayoutMap = new Map<string, () => Promise<typeof import('*.vue')>>()
|
||||||
|
|
||||||
LayoutMap.set('LAYOUT', LAYOUT);
|
LayoutMap.set('LAYOUT', LAYOUT)
|
||||||
LayoutMap.set('IFRAME', IFRAME);
|
LayoutMap.set('IFRAME', IFRAME)
|
||||||
|
|
||||||
let dynamicViewsModules: Record<string, () => Promise<Recordable>>;
|
let dynamicViewsModules: Record<string, () => Promise<Recordable>>
|
||||||
|
|
||||||
// Dynamic introduction
|
// Dynamic introduction
|
||||||
function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) {
|
function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) {
|
||||||
dynamicViewsModules = dynamicViewsModules || import.meta.glob('../../views/**/*.{vue,tsx}');
|
dynamicViewsModules = dynamicViewsModules || import.meta.glob('../../views/**/*.{vue,tsx}')
|
||||||
if (!routes) return;
|
if (!routes) return
|
||||||
routes.forEach((item) => {
|
routes.forEach((item) => {
|
||||||
if (!item.component && item.meta?.frameSrc) {
|
if (!item.component && item.meta?.frameSrc) {
|
||||||
item.component = 'IFRAME';
|
item.component = 'IFRAME'
|
||||||
}
|
}
|
||||||
const { component, name } = item;
|
const { component, name } = item
|
||||||
const { children } = item;
|
const { children } = item
|
||||||
if (component) {
|
if (component) {
|
||||||
const layoutFound = LayoutMap.get(component.toUpperCase());
|
const layoutFound = LayoutMap.get(component.toUpperCase())
|
||||||
if (layoutFound) {
|
if (layoutFound) {
|
||||||
item.component = layoutFound;
|
item.component = layoutFound
|
||||||
} else {
|
} else {
|
||||||
item.component = dynamicImport(dynamicViewsModules, component as string);
|
item.component = dynamicImport(dynamicViewsModules, component as string)
|
||||||
}
|
}
|
||||||
} else if (name) {
|
} else if (name) {
|
||||||
item.component = getParentLayout();
|
item.component = getParentLayout()
|
||||||
}
|
}
|
||||||
children && asyncImportRoute(children);
|
children && asyncImportRoute(children)
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function dynamicImport(
|
function dynamicImport(
|
||||||
dynamicViewsModules: Record<string, () => Promise<Recordable>>,
|
dynamicViewsModules: Record<string, () => Promise<Recordable>>,
|
||||||
component: string,
|
component: string,
|
||||||
) {
|
) {
|
||||||
const keys = Object.keys(dynamicViewsModules);
|
const keys = Object.keys(dynamicViewsModules)
|
||||||
const matchKeys = keys.filter((key) => {
|
const matchKeys = keys.filter((key) => {
|
||||||
const k = key.replace('../../views', '');
|
const k = key.replace('../../views', '')
|
||||||
const startFlag = component.startsWith('/');
|
const startFlag = component.startsWith('/')
|
||||||
const endFlag = component.endsWith('.vue') || component.endsWith('.tsx');
|
const endFlag = component.endsWith('.vue') || component.endsWith('.tsx')
|
||||||
const startIndex = startFlag ? 0 : 1;
|
const startIndex = startFlag ? 0 : 1
|
||||||
const lastIndex = endFlag ? k.length : k.lastIndexOf('.');
|
const lastIndex = endFlag ? k.length : k.lastIndexOf('.')
|
||||||
return k.substring(startIndex, lastIndex) === component;
|
return k.substring(startIndex, lastIndex) === component
|
||||||
});
|
})
|
||||||
if (matchKeys?.length === 1) {
|
if (matchKeys?.length === 1) {
|
||||||
const matchKey = matchKeys[0];
|
const matchKey = matchKeys[0]
|
||||||
return dynamicViewsModules[matchKey];
|
return dynamicViewsModules[matchKey]
|
||||||
} else if (matchKeys?.length > 1) {
|
} else if (matchKeys?.length > 1) {
|
||||||
warn(
|
warn(
|
||||||
'Please do not create `.vue` and `.TSX` files with the same file name in the same hierarchical directory under the views folder. This will cause dynamic introduction failure',
|
'Please do not create `.vue` and `.TSX` files with the same file name in the same hierarchical directory under the views folder. This will cause dynamic introduction failure',
|
||||||
);
|
)
|
||||||
return;
|
return
|
||||||
} else {
|
} else {
|
||||||
warn('在src/views/下找不到`' + component + '.vue` 或 `' + component + '.tsx`, 请自行创建!');
|
warn('在src/views/下找不到`' + component + '.vue` 或 `' + component + '.tsx`, 请自行创建!')
|
||||||
return EXCEPTION_COMPONENT;
|
return EXCEPTION_COMPONENT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,26 +71,26 @@ function dynamicImport(
|
||||||
// 将背景对象变成路由对象
|
// 将背景对象变成路由对象
|
||||||
export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModule[]): T[] {
|
export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModule[]): T[] {
|
||||||
routeList.forEach((route) => {
|
routeList.forEach((route) => {
|
||||||
const component = route.component as string;
|
const component = route.component as string
|
||||||
if (component) {
|
if (component) {
|
||||||
if (component.toUpperCase() === 'LAYOUT') {
|
if (component.toUpperCase() === 'LAYOUT') {
|
||||||
route.component = LayoutMap.get(component.toUpperCase());
|
route.component = LayoutMap.get(component.toUpperCase())
|
||||||
} else {
|
} else {
|
||||||
route.children = [cloneDeep(route)];
|
route.children = [cloneDeep(route)]
|
||||||
route.component = LAYOUT;
|
route.component = LAYOUT
|
||||||
route.name = `${route.name}Parent`;
|
route.name = `${route.name}Parent`
|
||||||
route.path = '';
|
route.path = ''
|
||||||
const meta = route.meta || {};
|
const meta = route.meta || {}
|
||||||
meta.single = true;
|
meta.single = true
|
||||||
meta.affix = false;
|
meta.affix = false
|
||||||
route.meta = meta;
|
route.meta = meta
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
warn('请正确配置路由:' + route?.name + '的component属性');
|
warn('请正确配置路由:' + route?.name + '的component属性')
|
||||||
}
|
}
|
||||||
route.children && asyncImportRoute(route.children);
|
route.children && asyncImportRoute(route.children)
|
||||||
});
|
})
|
||||||
return routeList as unknown as T[];
|
return routeList as unknown as T[]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -98,19 +98,19 @@ export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModul
|
||||||
* 将多级路由转换为 2 级路由
|
* 将多级路由转换为 2 级路由
|
||||||
*/
|
*/
|
||||||
export function flatMultiLevelRoutes(routeModules: AppRouteModule[]) {
|
export function flatMultiLevelRoutes(routeModules: AppRouteModule[]) {
|
||||||
const modules: AppRouteModule[] = cloneDeep(routeModules);
|
const modules: AppRouteModule[] = cloneDeep(routeModules)
|
||||||
|
|
||||||
for (let index = 0; index < modules.length; index++) {
|
for (let index = 0; index < modules.length; index++) {
|
||||||
const routeModule = modules[index];
|
const routeModule = modules[index]
|
||||||
// 判断级别是否 多级 路由
|
// 判断级别是否 多级 路由
|
||||||
if (!isMultipleRoute(routeModule)) {
|
if (!isMultipleRoute(routeModule)) {
|
||||||
// 声明终止当前循环, 即跳过此次循环,进行下一轮
|
// 声明终止当前循环, 即跳过此次循环,进行下一轮
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
// 路由等级提升
|
// 路由等级提升
|
||||||
promoteRouteLevel(routeModule);
|
promoteRouteLevel(routeModule)
|
||||||
}
|
}
|
||||||
return modules;
|
return modules
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routing level upgrade
|
// Routing level upgrade
|
||||||
|
|
@ -122,15 +122,15 @@ function promoteRouteLevel(routeModule: AppRouteModule) {
|
||||||
let router: Router | null = createRouter({
|
let router: Router | null = createRouter({
|
||||||
routes: [routeModule as unknown as RouteRecordNormalized],
|
routes: [routeModule as unknown as RouteRecordNormalized],
|
||||||
history: createWebHashHistory(),
|
history: createWebHashHistory(),
|
||||||
});
|
})
|
||||||
// getRoutes: 获取所有 路由记录的完整列表。
|
// getRoutes: 获取所有 路由记录的完整列表。
|
||||||
const routes = router.getRoutes();
|
const routes = router.getRoutes()
|
||||||
// 将所有子路由添加到二级路由
|
// 将所有子路由添加到二级路由
|
||||||
addToChildren(routes, routeModule.children || [], routeModule);
|
addToChildren(routes, routeModule.children || [], routeModule)
|
||||||
router = null;
|
router = null
|
||||||
|
|
||||||
// omit lodash的函数 对传入的item对象的children进行删除
|
// omit lodash的函数 对传入的item对象的children进行删除
|
||||||
routeModule.children = routeModule.children?.map((item) => omit(item, 'children'));
|
routeModule.children = routeModule.children?.map((item) => omit(item, 'children'))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add all sub-routes to the secondary route
|
// Add all sub-routes to the secondary route
|
||||||
|
|
@ -141,17 +141,17 @@ function addToChildren(
|
||||||
routeModule: AppRouteModule,
|
routeModule: AppRouteModule,
|
||||||
) {
|
) {
|
||||||
for (let index = 0; index < children.length; index++) {
|
for (let index = 0; index < children.length; index++) {
|
||||||
const child = children[index];
|
const child = children[index]
|
||||||
const route = routes.find((item) => item.name === child.name);
|
const route = routes.find((item) => item.name === child.name)
|
||||||
if (!route) {
|
if (!route) {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
routeModule.children = routeModule.children || [];
|
routeModule.children = routeModule.children || []
|
||||||
if (!routeModule.children.find((item) => item.name === route.name)) {
|
if (!routeModule.children.find((item) => item.name === route.name)) {
|
||||||
routeModule.children?.push(route as unknown as AppRouteModule);
|
routeModule.children?.push(route as unknown as AppRouteModule)
|
||||||
}
|
}
|
||||||
if (child.children?.length) {
|
if (child.children?.length) {
|
||||||
addToChildren(routes, child.children, routeModule);
|
addToChildren(routes, child.children, routeModule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -161,18 +161,18 @@ function addToChildren(
|
||||||
function isMultipleRoute(routeModule: AppRouteModule) {
|
function isMultipleRoute(routeModule: AppRouteModule) {
|
||||||
// Reflect.has 与 in 操作符 相同, 用于检查一个对象(包括它原型链上)是否拥有某个属性
|
// Reflect.has 与 in 操作符 相同, 用于检查一个对象(包括它原型链上)是否拥有某个属性
|
||||||
if (!routeModule || !Reflect.has(routeModule, 'children') || !routeModule.children?.length) {
|
if (!routeModule || !Reflect.has(routeModule, 'children') || !routeModule.children?.length) {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const children = routeModule.children;
|
const children = routeModule.children
|
||||||
|
|
||||||
let flag = false;
|
let flag = false
|
||||||
for (let index = 0; index < children.length; index++) {
|
for (let index = 0; index < children.length; index++) {
|
||||||
const child = children[index];
|
const child = children[index]
|
||||||
if (child.children?.length) {
|
if (child.children?.length) {
|
||||||
flag = true;
|
flag = true
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return flag;
|
return flag
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
import type { RouteRecordRaw } from 'vue-router';
|
import type { RouteRecordRaw } from 'vue-router'
|
||||||
import type { App } from 'vue';
|
import type { App } from 'vue'
|
||||||
|
|
||||||
import { createRouter, createWebHashHistory } from 'vue-router';
|
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||||
import { basicRoutes } from './routes';
|
import { basicRoutes } from './routes'
|
||||||
|
|
||||||
// 白名单应该包含基本静态路由
|
// 白名单应该包含基本静态路由
|
||||||
const WHITE_NAME_LIST: string[] = [];
|
const WHITE_NAME_LIST: string[] = []
|
||||||
const getRouteNames = (array: any[]) =>
|
const getRouteNames = (array: any[]) =>
|
||||||
array.forEach((item) => {
|
array.forEach((item) => {
|
||||||
WHITE_NAME_LIST.push(item.name);
|
WHITE_NAME_LIST.push(item.name)
|
||||||
getRouteNames(item.children || []);
|
getRouteNames(item.children || [])
|
||||||
});
|
})
|
||||||
getRouteNames(basicRoutes);
|
getRouteNames(basicRoutes)
|
||||||
|
|
||||||
// app router
|
// app router
|
||||||
// 创建一个可以被 Vue 应用程序使用的路由实例
|
// 创建一个可以被 Vue 应用程序使用的路由实例
|
||||||
|
|
@ -23,20 +23,20 @@ export const router = createRouter({
|
||||||
// 是否应该禁止尾部斜杠。默认为假
|
// 是否应该禁止尾部斜杠。默认为假
|
||||||
strict: true,
|
strict: true,
|
||||||
scrollBehavior: () => ({ left: 0, top: 0 }),
|
scrollBehavior: () => ({ left: 0, top: 0 }),
|
||||||
});
|
})
|
||||||
|
|
||||||
// reset router
|
// reset router
|
||||||
export function resetRouter() {
|
export function resetRouter() {
|
||||||
router.getRoutes().forEach((route) => {
|
router.getRoutes().forEach((route) => {
|
||||||
const { name } = route;
|
const { name } = route
|
||||||
if (name && !WHITE_NAME_LIST.includes(name as string)) {
|
if (name && !WHITE_NAME_LIST.includes(name as string)) {
|
||||||
router.hasRoute(name) && router.removeRoute(name);
|
router.hasRoute(name) && router.removeRoute(name)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// config router
|
// config router
|
||||||
// 配置路由器
|
// 配置路由器
|
||||||
export function setupRouter(app: App<Element>) {
|
export function setupRouter(app: App<Element>) {
|
||||||
app.use(router);
|
app.use(router)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import type { AppRouteModule } from '/@/router/types';
|
import type { AppRouteModule } from '/@/router/types'
|
||||||
|
|
||||||
import { LAYOUT } from '/@/router/constant';
|
import { LAYOUT } from '/@/router/constant'
|
||||||
import { t } from '/@/hooks/web/useI18n';
|
import { t } from '/@/hooks/web/useI18n'
|
||||||
|
|
||||||
const about: AppRouteModule = {
|
const about: AppRouteModule = {
|
||||||
path: '/about',
|
path: '/about',
|
||||||
|
|
@ -26,6 +26,6 @@ const about: AppRouteModule = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
}
|
||||||
|
|
||||||
export default about;
|
export default about
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import type { AppRouteModule } from '/@/router/types';
|
import type { AppRouteModule } from '/@/router/types'
|
||||||
|
|
||||||
import { LAYOUT } from '/@/router/constant';
|
import { LAYOUT } from '/@/router/constant'
|
||||||
import { t } from '/@/hooks/web/useI18n';
|
import { t } from '/@/hooks/web/useI18n'
|
||||||
|
|
||||||
const dashboard: AppRouteModule = {
|
const dashboard: AppRouteModule = {
|
||||||
path: '/dashboard',
|
path: '/dashboard',
|
||||||
|
|
@ -32,6 +32,6 @@ const dashboard: AppRouteModule = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
}
|
||||||
|
|
||||||
export default dashboard;
|
export default dashboard
|
||||||
|
|
|
||||||
|
|
@ -33,23 +33,23 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { ErrorLogInfo } from '/#/store';
|
import type { ErrorLogInfo } from '/#/store'
|
||||||
import { watch, ref, nextTick } from 'vue';
|
import { watch, ref, nextTick } from 'vue'
|
||||||
import DetailModal from './DetailModal.vue';
|
import DetailModal from './DetailModal.vue'
|
||||||
import { BasicTable, useTable, TableAction } from '/@/components/Table/index';
|
import { BasicTable, useTable, TableAction } from '/@/components/Table/index'
|
||||||
import { useModal } from '/@/components/Modal';
|
import { useModal } from '/@/components/Modal'
|
||||||
import { useMessage } from '/@/hooks/web/useMessage';
|
import { useMessage } from '/@/hooks/web/useMessage'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
import { useErrorLogStore } from '/@/store/modules/errorLog';
|
import { useErrorLogStore } from '/@/store/modules/errorLog'
|
||||||
import { fireErrorApi } from '/@/api/demo/error';
|
import { fireErrorApi } from '/@/api/demo/error'
|
||||||
import { getColumns } from './data';
|
import { getColumns } from './data'
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es'
|
||||||
|
|
||||||
const rowInfo = ref<ErrorLogInfo>();
|
const rowInfo = ref<ErrorLogInfo>()
|
||||||
const imgList = ref<string[]>([]);
|
const imgList = ref<string[]>([])
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
const errorLogStore = useErrorLogStore();
|
const errorLogStore = useErrorLogStore()
|
||||||
const [register, { setTableData }] = useTable({
|
const [register, { setTableData }] = useTable({
|
||||||
title: t('sys.errorLog.tableTitle'),
|
title: t('sys.errorLog.tableTitle'),
|
||||||
columns: getColumns(),
|
columns: getColumns(),
|
||||||
|
|
@ -59,39 +59,39 @@
|
||||||
dataIndex: 'action',
|
dataIndex: 'action',
|
||||||
// slots: { customRender: 'action' },
|
// slots: { customRender: 'action' },
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
const [registerModal, { openModal }] = useModal();
|
const [registerModal, { openModal }] = useModal()
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => errorLogStore.getErrorLogInfoList,
|
() => errorLogStore.getErrorLogInfoList,
|
||||||
(list) => {
|
(list) => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
setTableData(cloneDeep(list));
|
setTableData(cloneDeep(list))
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
immediate: true,
|
immediate: true,
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
const { createMessage } = useMessage();
|
const { createMessage } = useMessage()
|
||||||
if (import.meta.env.DEV) {
|
if (import.meta.env.DEV) {
|
||||||
createMessage.info(t('sys.errorLog.enableMessage'));
|
createMessage.info(t('sys.errorLog.enableMessage'))
|
||||||
}
|
}
|
||||||
// 查看详情
|
// 查看详情
|
||||||
function handleDetail(row: ErrorLogInfo) {
|
function handleDetail(row: ErrorLogInfo) {
|
||||||
rowInfo.value = row;
|
rowInfo.value = row
|
||||||
openModal(true);
|
openModal(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
function fireVueError() {
|
function fireVueError() {
|
||||||
throw new Error('fire vue error!');
|
throw new Error('fire vue error!')
|
||||||
}
|
}
|
||||||
|
|
||||||
function fireResourceError() {
|
function fireResourceError() {
|
||||||
imgList.value.push(`${new Date().getTime()}.png`);
|
imgList.value.push(`${new Date().getTime()}.png`)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fireAjaxError() {
|
async function fireAjaxError() {
|
||||||
await fireErrorApi();
|
await fireErrorApi()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { dateUtil } from '/@/utils/dateUtil';
|
import { dateUtil } from '/@/utils/dateUtil'
|
||||||
import { reactive, toRefs } from 'vue';
|
import { reactive, toRefs } from 'vue'
|
||||||
import { tryOnMounted, tryOnUnmounted } from '@vueuse/core';
|
import { tryOnMounted, tryOnUnmounted } from '@vueuse/core'
|
||||||
|
|
||||||
export function useNow(immediate = true) {
|
export function useNow(immediate = true) {
|
||||||
let timer: IntervalHandle;
|
let timer: IntervalHandle
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
year: 0,
|
year: 0,
|
||||||
|
|
@ -14,47 +14,47 @@ export function useNow(immediate = true) {
|
||||||
minute: '',
|
minute: '',
|
||||||
second: 0,
|
second: 0,
|
||||||
meridiem: '',
|
meridiem: '',
|
||||||
});
|
})
|
||||||
|
|
||||||
const update = () => {
|
const update = () => {
|
||||||
const now = dateUtil();
|
const now = dateUtil()
|
||||||
|
|
||||||
const h = now.format('HH');
|
const h = now.format('HH')
|
||||||
const m = now.format('mm');
|
const m = now.format('mm')
|
||||||
const s = now.get('s');
|
const s = now.get('s')
|
||||||
|
|
||||||
state.year = now.get('y');
|
state.year = now.get('y')
|
||||||
state.month = now.get('M') + 1;
|
state.month = now.get('M') + 1
|
||||||
state.week = '星期' + ['日', '一', '二', '三', '四', '五', '六'][now.day()];
|
state.week = '星期' + ['日', '一', '二', '三', '四', '五', '六'][now.day()]
|
||||||
state.day = now.get('date');
|
state.day = now.get('date')
|
||||||
state.hour = h;
|
state.hour = h
|
||||||
state.minute = m;
|
state.minute = m
|
||||||
state.second = s;
|
state.second = s
|
||||||
|
|
||||||
state.meridiem = now.format('A');
|
state.meridiem = now.format('A')
|
||||||
};
|
}
|
||||||
|
|
||||||
function start() {
|
function start() {
|
||||||
update();
|
update()
|
||||||
clearInterval(timer);
|
clearInterval(timer)
|
||||||
timer = setInterval(() => update(), 1000);
|
timer = setInterval(() => update(), 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
function stop() {
|
function stop() {
|
||||||
clearInterval(timer);
|
clearInterval(timer)
|
||||||
}
|
}
|
||||||
|
|
||||||
tryOnMounted(() => {
|
tryOnMounted(() => {
|
||||||
immediate && start();
|
immediate && start()
|
||||||
});
|
})
|
||||||
|
|
||||||
tryOnUnmounted(() => {
|
tryOnUnmounted(() => {
|
||||||
stop();
|
stop()
|
||||||
});
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...toRefs(state),
|
...toRefs(state),
|
||||||
start,
|
start,
|
||||||
stop,
|
stop,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,31 +48,31 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue'
|
||||||
import { AppLogo } from '/@/components/Application';
|
import { AppLogo } from '/@/components/Application'
|
||||||
import { AppLocalePicker, AppDarkModeToggle } from '/@/components/Application';
|
import { AppLocalePicker, AppDarkModeToggle } from '/@/components/Application'
|
||||||
import LoginForm from './LoginForm.vue';
|
import LoginForm from './LoginForm.vue'
|
||||||
import ForgetPasswordForm from './ForgetPasswordForm.vue';
|
import ForgetPasswordForm from './ForgetPasswordForm.vue'
|
||||||
import RegisterForm from './RegisterForm.vue';
|
import RegisterForm from './RegisterForm.vue'
|
||||||
import MobileForm from './MobileForm.vue';
|
import MobileForm from './MobileForm.vue'
|
||||||
import QrCodeForm from './QrCodeForm.vue';
|
import QrCodeForm from './QrCodeForm.vue'
|
||||||
import { useGlobSetting } from '/@/hooks/setting';
|
import { useGlobSetting } from '/@/hooks/setting'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n'
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign'
|
||||||
import { useLocaleStore } from '/@/store/modules/locale';
|
import { useLocaleStore } from '/@/store/modules/locale'
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
sessionTimeout: {
|
sessionTimeout: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
const globSetting = useGlobSetting();
|
const globSetting = useGlobSetting()
|
||||||
const { prefixCls } = useDesign('login');
|
const { prefixCls } = useDesign('login')
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
const localeStore = useLocaleStore();
|
const localeStore = useLocaleStore()
|
||||||
const showLocale = localeStore.getShowPicker;
|
const showLocale = localeStore.getShowPicker
|
||||||
const title = computed(() => globSetting?.title ?? '');
|
const title = computed(() => globSetting?.title ?? '')
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@prefix-cls: ~'@{namespace}-login';
|
@prefix-cls: ~'@{namespace}-login';
|
||||||
|
|
|
||||||
|
|
@ -97,4 +97,4 @@ module.exports = {
|
||||||
extends: ['stylelint-config-standard', 'stylelint-config-recommended-vue'],
|
extends: ['stylelint-config-standard', 'stylelint-config-recommended-vue'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { defineConfig } from 'vite-plugin-windicss';
|
import { defineConfig } from 'vite-plugin-windicss'
|
||||||
import { primaryColor } from './build/config/themeConfig';
|
import { primaryColor } from './build/config/themeConfig'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
darkMode: 'class',
|
darkMode: 'class',
|
||||||
|
|
@ -21,7 +21,7 @@ export default defineConfig({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for animation when the element is displayed.
|
* Used for animation when the element is displayed.
|
||||||
|
|
@ -29,7 +29,7 @@ export default defineConfig({
|
||||||
*/
|
*/
|
||||||
function createEnterPlugin(maxOutput = 6) {
|
function createEnterPlugin(maxOutput = 6) {
|
||||||
const createCss = (index: number, d = 'x') => {
|
const createCss = (index: number, d = 'x') => {
|
||||||
const upd = d.toUpperCase();
|
const upd = d.toUpperCase()
|
||||||
return {
|
return {
|
||||||
[`*> .enter-${d}:nth-child(${index})`]: {
|
[`*> .enter-${d}:nth-child(${index})`]: {
|
||||||
transform: `translate${upd}(50px)`,
|
transform: `translate${upd}(50px)`,
|
||||||
|
|
@ -44,15 +44,15 @@ function createEnterPlugin(maxOutput = 6) {
|
||||||
'animation-fill-mode': 'forwards',
|
'animation-fill-mode': 'forwards',
|
||||||
'animation-delay': `${(index * 1) / 10}s`,
|
'animation-delay': `${(index * 1) / 10}s`,
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
const handler = ({ addBase }) => {
|
const handler = ({ addBase }) => {
|
||||||
const addRawCss = {};
|
const addRawCss = {}
|
||||||
for (let index = 1; index < maxOutput; index++) {
|
for (let index = 1; index < maxOutput; index++) {
|
||||||
Object.assign(addRawCss, {
|
Object.assign(addRawCss, {
|
||||||
...createCss(index, 'x'),
|
...createCss(index, 'x'),
|
||||||
...createCss(index, 'y'),
|
...createCss(index, 'y'),
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
addBase({
|
addBase({
|
||||||
...addRawCss,
|
...addRawCss,
|
||||||
|
|
@ -68,7 +68,7 @@ function createEnterPlugin(maxOutput = 6) {
|
||||||
transform: 'translateY(0)',
|
transform: 'translateY(0)',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
return { handler };
|
return { handler }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue