mirror of
https://github.com/soybeanjs/soybean-admin.git
synced 2025-09-21 19:16:37 +08:00
style(projects): format code
This commit is contained in:
parent
a176dc443e
commit
a748166399
@ -1,9 +1,10 @@
|
|||||||
import type { ProxyOptions } from 'vite';
|
import type { ProxyOptions } from 'vite';
|
||||||
import { createServiceConfig, createProxyPattern } from '../../env.config';
|
import { createProxyPattern, createServiceConfig } from '../../env.config';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set http proxy
|
* Set http proxy
|
||||||
* @param env - the current env
|
*
|
||||||
|
* @param env - The current env
|
||||||
*/
|
*/
|
||||||
export function createViteProxy(env: Env.ImportMeta) {
|
export function createViteProxy(env: Env.ImportMeta) {
|
||||||
const isEnableHttpProxy = env.VITE_HTTP_PROXY === 'Y';
|
const isEnableHttpProxy = env.VITE_HTTP_PROXY === 'Y';
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import process from 'node:process';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import unocss from '@unocss/vite';
|
import unocss from '@unocss/vite';
|
||||||
import presetIcons from '@unocss/preset-icons';
|
import presetIcons from '@unocss/preset-icons';
|
||||||
@ -8,9 +9,7 @@ export function setupUnocss(viteEnv: Env.ImportMeta) {
|
|||||||
|
|
||||||
const localIconPath = path.join(process.cwd(), 'src/assets/svg-icon');
|
const localIconPath = path.join(process.cwd(), 'src/assets/svg-icon');
|
||||||
|
|
||||||
/**
|
/** The name of the local icon collection */
|
||||||
* the name of the local icon collection
|
|
||||||
*/
|
|
||||||
const collectionName = VITE_ICON_LOCAL_PREFIX.replace(`${VITE_ICON_PREFIX}-`, '');
|
const collectionName = VITE_ICON_LOCAL_PREFIX.replace(`${VITE_ICON_PREFIX}-`, '');
|
||||||
|
|
||||||
return unocss({
|
return unocss({
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import process from 'node:process';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import type { PluginOption } from 'vite';
|
import type { PluginOption } from 'vite';
|
||||||
import Icons from 'unplugin-icons/vite';
|
import Icons from 'unplugin-icons/vite';
|
||||||
@ -12,9 +13,7 @@ export function setupUnplugin(viteEnv: Env.ImportMeta) {
|
|||||||
|
|
||||||
const localIconPath = path.join(process.cwd(), 'src/assets/svg-icon');
|
const localIconPath = path.join(process.cwd(), 'src/assets/svg-icon');
|
||||||
|
|
||||||
/**
|
/** The name of the local icon collection */
|
||||||
* the name of the local icon collection
|
|
||||||
*/
|
|
||||||
const collectionName = VITE_ICON_LOCAL_PREFIX.replace(`${VITE_ICON_PREFIX}-`, '');
|
const collectionName = VITE_ICON_LOCAL_PREFIX.replace(`${VITE_ICON_PREFIX}-`, '');
|
||||||
|
|
||||||
const plugins: PluginOption[] = [
|
const plugins: PluginOption[] = [
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* create service config by current env
|
* Create service config by current env
|
||||||
* @param env the current env
|
*
|
||||||
|
* @param env The current env
|
||||||
*/
|
*/
|
||||||
export function createServiceConfig(env: Env.ImportMeta) {
|
export function createServiceConfig(env: Env.ImportMeta) {
|
||||||
const mockURL = 'https://mock.apifox.com/m1/3109515-0-default';
|
const mockURL = 'https://mock.apifox.com/m1/3109515-0-default';
|
||||||
@ -32,8 +33,9 @@ export function createServiceConfig(env: Env.ImportMeta) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get proxy pattern of service url
|
* Get proxy pattern of service url
|
||||||
* @param key if not set, will use the default key
|
*
|
||||||
|
* @param key If not set, will use the default key
|
||||||
*/
|
*/
|
||||||
export function createProxyPattern(key?: App.Service.OtherBaseURLKey) {
|
export function createProxyPattern(key?: App.Service.OtherBaseURLKey) {
|
||||||
if (!key) {
|
if (!key) {
|
||||||
|
61
package.json
61
package.json
@ -1,26 +1,26 @@
|
|||||||
{
|
{
|
||||||
"name": "soybean-admin",
|
"name": "soybean-admin",
|
||||||
|
"type": "module",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
"packageManager": "pnpm@8.10.5",
|
||||||
"description": "A fresh and elegant admin template, based on Vue3、Vite3、TypeScript、NaiveUI and UnoCSS. 一个基于Vue3、Vite3、TypeScript、NaiveUI and UnoCSS的清新优雅的中后台模版。",
|
"description": "A fresh and elegant admin template, based on Vue3、Vite3、TypeScript、NaiveUI and UnoCSS. 一个基于Vue3、Vite3、TypeScript、NaiveUI and UnoCSS的清新优雅的中后台模版。",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Soybean",
|
"name": "Soybean",
|
||||||
"email": "soybeanjs@outlook.com",
|
"email": "soybeanjs@outlook.com",
|
||||||
"url": "https://github.com/soybeanjs"
|
"url": "https://github.com/soybeanjs"
|
||||||
},
|
},
|
||||||
"type": "module",
|
|
||||||
"packageManager": "pnpm@8.10.5",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
|
||||||
"build": "run-s typecheck build-only",
|
"build": "run-s typecheck build-only",
|
||||||
"preview": "vite preview",
|
|
||||||
"build-only": "vite build",
|
"build-only": "vite build",
|
||||||
"typecheck": "vue-tsc --noEmit --skipLibCheck",
|
|
||||||
"lint": "eslint . --fix",
|
|
||||||
"format": "sa prettier-write",
|
|
||||||
"commit": "sa git-commit",
|
|
||||||
"cleanup": "sa cleanup",
|
"cleanup": "sa cleanup",
|
||||||
"update-pkg": "sa update-pkg",
|
"commit": "sa git-commit",
|
||||||
"prepare": "simple-git-hooks"
|
"dev": "vite",
|
||||||
|
"format": "sa prettier-write",
|
||||||
|
"lint": "eslint . --fix",
|
||||||
|
"prepare": "simple-git-hooks",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"typecheck": "vue-tsc --noEmit --skipLibCheck",
|
||||||
|
"update-pkg": "sa update-pkg"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@better-scroll/core": "2.5.1",
|
"@better-scroll/core": "2.5.1",
|
||||||
@ -30,45 +30,48 @@
|
|||||||
"@sa/materials": "workspace:*",
|
"@sa/materials": "workspace:*",
|
||||||
"@sa/request": "workspace:*",
|
"@sa/request": "workspace:*",
|
||||||
"@sa/utils": "workspace:*",
|
"@sa/utils": "workspace:*",
|
||||||
"@vueuse/core": "10.6.1",
|
"@vueuse/core": "10.7.0",
|
||||||
"clipboard": "2.0.11",
|
"clipboard": "2.0.11",
|
||||||
"dayjs": "1.11.10",
|
"dayjs": "1.11.10",
|
||||||
"lodash-es": "4.17.21",
|
"lodash-es": "4.17.21",
|
||||||
"naive-ui": "2.35.0",
|
"naive-ui": "2.35.0",
|
||||||
"nprogress": "0.2.0",
|
"nprogress": "0.2.0",
|
||||||
"pinia": "2.1.7",
|
"pinia": "2.1.7",
|
||||||
"vue": "3.3.8",
|
"vue": "3.3.11",
|
||||||
"vue-i18n": "9.7.0",
|
"vue-i18n": "9.8.0",
|
||||||
"vue-router": "4.2.5"
|
"vue-router": "4.2.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@elegant-router/vue": "0.3.1",
|
"@elegant-router/vue": "0.3.1",
|
||||||
"@iconify/json": "2.2.143",
|
"@iconify/json": "2.2.157",
|
||||||
"@sa/scripts": "workspace:*",
|
"@sa/scripts": "workspace:*",
|
||||||
"@sa/uno-preset": "workspace:*",
|
"@sa/uno-preset": "workspace:*",
|
||||||
"@soybeanjs/eslint-config": "^1.1.2",
|
"@soybeanjs/eslint-config": "1.1.3",
|
||||||
"@types/lodash-es": "4.17.11",
|
"@types/lodash-es": "4.17.12",
|
||||||
"@types/node": "20.9.1",
|
"@types/node": "20.10.4",
|
||||||
"@types/nprogress": "0.2.3",
|
"@types/nprogress": "0.2.3",
|
||||||
"@unocss/preset-icons": "0.57.5",
|
"@unocss/preset-icons": "0.58.0",
|
||||||
"@unocss/preset-uno": "0.57.5",
|
"@unocss/preset-uno": "0.58.0",
|
||||||
"@unocss/transformer-directives": "0.57.5",
|
"@unocss/transformer-directives": "0.58.0",
|
||||||
"@unocss/transformer-variant-group": "0.57.5",
|
"@unocss/transformer-variant-group": "0.58.0",
|
||||||
"@unocss/vite": "0.57.5",
|
"@unocss/vite": "0.58.0",
|
||||||
"@vitejs/plugin-vue": "4.5.0",
|
"@vitejs/plugin-vue": "4.5.2",
|
||||||
"@vitejs/plugin-vue-jsx": "3.1.0",
|
"@vitejs/plugin-vue-jsx": "3.1.0",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
|
"eslint": "8.55.0",
|
||||||
|
"eslint-plugin-vue": "9.19.2",
|
||||||
"npm-run-all": "4.1.5",
|
"npm-run-all": "4.1.5",
|
||||||
"sass": "1.69.5",
|
"sass": "1.69.5",
|
||||||
"simple-git-hooks": "2.9.0",
|
"simple-git-hooks": "2.9.0",
|
||||||
"typescript": "5.2.2",
|
"typescript": "5.3.3",
|
||||||
"unplugin-icons": "0.17.4",
|
"unplugin-icons": "0.18.1",
|
||||||
"unplugin-vue-components": "0.25.2",
|
"unplugin-vue-components": "0.26.0",
|
||||||
"vite": "5.0.0",
|
"vite": "5.0.8",
|
||||||
"vite-plugin-progress": "0.0.7",
|
"vite-plugin-progress": "0.0.7",
|
||||||
"vite-plugin-svg-icons": "2.0.1",
|
"vite-plugin-svg-icons": "2.0.1",
|
||||||
"vite-plugin-vue-devtools": "1.0.0-rc.5",
|
"vite-plugin-vue-devtools": "1.0.0-rc.8",
|
||||||
"vue-tsc": "1.8.22"
|
"vue-eslint-parser": "9.3.2",
|
||||||
|
"vue-tsc": "1.8.25"
|
||||||
},
|
},
|
||||||
"simple-git-hooks": {
|
"simple-git-hooks": {
|
||||||
"commit-msg": "pnpm sa git-commit-verify",
|
"commit-msg": "pnpm sa git-commit-verify",
|
||||||
|
@ -6,9 +6,7 @@
|
|||||||
},
|
},
|
||||||
"typesVersions": {
|
"typesVersions": {
|
||||||
"*": {
|
"*": {
|
||||||
"*": [
|
"*": ["./src/*"]
|
||||||
"./src/*"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { getColorPaletteFamily } from './palette';
|
import { getColorPaletteFamily } from './palette';
|
||||||
import { getColorName } from './name';
|
import { getColorName } from './name';
|
||||||
import type { ColorPalette, ColorPaletteNumber, ColorPaletteItem, ColorPaletteFamily } from './type';
|
import type { ColorPalette, ColorPaletteFamily, ColorPaletteItem, ColorPaletteNumber } from './type';
|
||||||
import defaultPalettes from './json/palette.json';
|
import defaultPalettes from './json/palette.json';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get color palette by provided color and color name
|
* Get color palette by provided color and color name
|
||||||
* @param color the provided color
|
*
|
||||||
* @param colorName color name
|
* @param color The provided color
|
||||||
|
* @param colorName Color name
|
||||||
*/
|
*/
|
||||||
export function getColorPalette(color: string, colorName: string) {
|
export function getColorPalette(color: string, colorName: string) {
|
||||||
const colorPaletteFamily = getColorPaletteFamily(color, colorName);
|
const colorPaletteFamily = getColorPaletteFamily(color, colorName);
|
||||||
@ -31,10 +32,11 @@ export function getColorPalette(color: string, colorName: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get color by color palette number
|
* Get color by color palette number
|
||||||
* @param color color
|
*
|
||||||
* @param num color palette number
|
* @param color Color
|
||||||
* @return color hexcode
|
* @param num Color palette number
|
||||||
|
* @returns Color hexcode
|
||||||
*/
|
*/
|
||||||
export function getColorByColorPaletteNumber(color: string, num: ColorPaletteNumber) {
|
export function getColorByColorPaletteNumber(color: string, num: ColorPaletteNumber) {
|
||||||
const colorPalette = getColorPalette(color, color);
|
const colorPalette = getColorPalette(color, color);
|
||||||
@ -46,9 +48,7 @@ export function getColorByColorPaletteNumber(color: string, num: ColorPaletteNum
|
|||||||
|
|
||||||
export default getColorPalette;
|
export default getColorPalette;
|
||||||
|
|
||||||
/**
|
/** The builtin color palettes */
|
||||||
* the builtin color palettes
|
|
||||||
*/
|
|
||||||
const colorPalettes = defaultPalettes as ColorPaletteFamily[];
|
const colorPalettes = defaultPalettes as ColorPaletteFamily[];
|
||||||
|
|
||||||
export { getColorName, colorPalettes };
|
export { getColorName, colorPalettes };
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { getHex, getRgb, getHsl } from './color';
|
import { getHex, getHsl, getRgb } from './color';
|
||||||
import colorNames from './json/color-name.json';
|
import colorNames from './json/color-name.json';
|
||||||
|
|
||||||
export function getColorName(color: string) {
|
export function getColorName(color: string) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { isValidColor, getHsl, getDeltaE, transformHslToHex } from './color';
|
import { getDeltaE, getHsl, isValidColor, transformHslToHex } from './color';
|
||||||
import { getColorName } from './name';
|
import { getColorName } from './name';
|
||||||
import type { ColorPaletteFamily, ColorPaletteFamilyWithNearestPalette } from './type';
|
import type { ColorPaletteFamily, ColorPaletteFamilyWithNearestPalette } from './type';
|
||||||
import defaultPalettes from './json/palette.json';
|
import defaultPalettes from './json/palette.json';
|
||||||
|
@ -1,35 +1,24 @@
|
|||||||
/**
|
/** The color palette number */
|
||||||
* the color palette number
|
|
||||||
*/
|
|
||||||
export type ColorPaletteNumber = 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950;
|
export type ColorPaletteNumber = 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950;
|
||||||
|
|
||||||
/**
|
/** The color palette item */
|
||||||
* the color palette item
|
|
||||||
*/
|
|
||||||
export type ColorPaletteItem = {
|
export type ColorPaletteItem = {
|
||||||
/**
|
/** The color hexcode */
|
||||||
* the color hexcode
|
|
||||||
*/
|
|
||||||
hexcode: string;
|
hexcode: string;
|
||||||
/**
|
/**
|
||||||
* the color number
|
* The color number
|
||||||
|
*
|
||||||
* @link {@link ColorPaletteNumber}
|
* @link {@link ColorPaletteNumber}
|
||||||
*/
|
*/
|
||||||
number: ColorPaletteNumber;
|
number: ColorPaletteNumber;
|
||||||
/**
|
/** The color name */
|
||||||
* the color name
|
|
||||||
*/
|
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ColorPaletteFamily = {
|
export type ColorPaletteFamily = {
|
||||||
/**
|
/** The color palette family key */
|
||||||
* the color palette family key
|
|
||||||
*/
|
|
||||||
key: string;
|
key: string;
|
||||||
/**
|
/** The color palette family's palettes */
|
||||||
* the color palette family's palettes
|
|
||||||
*/
|
|
||||||
palettes: ColorPaletteItem[];
|
palettes: ColorPaletteItem[];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -47,17 +36,14 @@ export type ColorPaletteFamilyWithNearestPalette = ColorPaletteFamily & {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type ColorPalette = ColorPaletteFamily & {
|
export type ColorPalette = ColorPaletteFamily & {
|
||||||
/**
|
/** The color map of the palette */
|
||||||
* the color map of the palette
|
|
||||||
*/
|
|
||||||
colorMap: Map<ColorPaletteNumber, ColorPaletteItem>;
|
colorMap: Map<ColorPaletteNumber, ColorPaletteItem>;
|
||||||
/**
|
/**
|
||||||
* the main color of the palette
|
* The main color of the palette
|
||||||
* @description which number is 500
|
*
|
||||||
|
* Which number is 500
|
||||||
*/
|
*/
|
||||||
main: ColorPaletteItemWithName;
|
main: ColorPaletteItemWithName;
|
||||||
/**
|
/** The match color of the palette */
|
||||||
* the match color of the palette
|
|
||||||
*/
|
|
||||||
match: ColorPaletteItemWithName;
|
match: ColorPaletteItemWithName;
|
||||||
};
|
};
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import process from 'node:process';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { defineConfig } from 'vitepress';
|
import { defineConfig } from 'vitepress';
|
||||||
|
|
||||||
|
@ -45,11 +45,7 @@
|
|||||||
var(--vp-c-brand-darker)
|
var(--vp-c-brand-darker)
|
||||||
);
|
);
|
||||||
|
|
||||||
--vp-home-hero-image-background-image: linear-gradient(
|
--vp-home-hero-image-background-image: linear-gradient(-45deg, var(--vp-c-brand-lightest) 30%, var(--vp-c-brand) 50%);
|
||||||
-45deg,
|
|
||||||
var(--vp-c-brand-lightest) 30%,
|
|
||||||
var(--vp-c-brand) 50%
|
|
||||||
);
|
|
||||||
--vp-home-hero-image-filter: blur(40px);
|
--vp-home-hero-image-filter: blur(40px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
"name": "@sa/docs",
|
"name": "@sa/docs",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vitepress dev",
|
|
||||||
"build": "vitepress build",
|
"build": "vitepress build",
|
||||||
|
"dev": "vitepress dev",
|
||||||
"serve": "vitepress serve"
|
"serve": "vitepress serve"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"vitepress": "1.0.0-rc.27"
|
"vitepress": "1.0.0-rc.31"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,7 @@
|
|||||||
},
|
},
|
||||||
"typesVersions": {
|
"typesVersions": {
|
||||||
"*": {
|
"*": {
|
||||||
"*": [
|
"*": ["./src/*"]
|
||||||
"./src/*"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* boolean
|
* Boolean
|
||||||
* @param initValue init value
|
*
|
||||||
|
* @param initValue Init value
|
||||||
*/
|
*/
|
||||||
export default function useBoolean(initValue = false) {
|
export default function useBoolean(initValue = false) {
|
||||||
const bool = ref(initValue);
|
const bool = ref(initValue);
|
||||||
|
@ -2,61 +2,60 @@ import { inject, provide } from 'vue';
|
|||||||
import type { InjectionKey } from 'vue';
|
import type { InjectionKey } from 'vue';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* use context
|
* Use context
|
||||||
* @param contextName context name
|
*
|
||||||
* @param fn context function
|
|
||||||
* @example
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
* // there are three vue files: A.vue, B.vue, C.vue, and A.vue is the parent component of B.vue and C.vue
|
* // there are three vue files: A.vue, B.vue, C.vue, and A.vue is the parent component of B.vue and C.vue
|
||||||
*
|
*
|
||||||
* // context.ts
|
* // context.ts
|
||||||
* import { ref } from 'vue';
|
* import { ref } from 'vue';
|
||||||
* import { useContext } from '@sa/hooks';
|
* import { useContext } from '@sa/hooks';
|
||||||
*
|
*
|
||||||
* export const { setupStore, useStore } = useContext('demo', () => {
|
* export const { setupStore, useStore } = useContext('demo', () => {
|
||||||
* const count = ref(0);
|
* const count = ref(0);
|
||||||
*
|
*
|
||||||
* function increment() {
|
* function increment() {
|
||||||
* count.value++;
|
* count.value++;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* function decrement() {
|
* function decrement() {
|
||||||
* count.value--;
|
* count.value--;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* return {
|
* return {
|
||||||
* count,
|
* count,
|
||||||
* increment,
|
* increment,
|
||||||
* decrement
|
* decrement
|
||||||
* };
|
* };
|
||||||
* })
|
* })
|
||||||
* ```
|
* ``` // A.vue
|
||||||
|
* ```vue
|
||||||
|
* <template>
|
||||||
|
* <div>A</div>
|
||||||
|
* </template>
|
||||||
|
* <script setup lang="ts">
|
||||||
|
* import { setupStore } from './context';
|
||||||
*
|
*
|
||||||
* // A.vue
|
* setupStore();
|
||||||
* ```vue
|
* // const { increment } = setupStore(); // also can control the store in the parent component
|
||||||
* <template>
|
* </script>
|
||||||
* <div>A</div>
|
* ``` // B.vue
|
||||||
* </template>
|
* ```vue
|
||||||
* <script setup lang="ts">
|
* <template>
|
||||||
* import { setupStore } from './context';
|
* <div>B</div>
|
||||||
|
* </template>
|
||||||
|
* <script setup lang="ts">
|
||||||
|
* import { useStore } from './context';
|
||||||
*
|
*
|
||||||
* setupStore();
|
* const { count, increment } = useStore();
|
||||||
* // const { increment } = setupStore(); // also can control the store in the parent component
|
* </script>
|
||||||
* </script>
|
* ```;
|
||||||
* ```
|
|
||||||
* // B.vue
|
|
||||||
* ```vue
|
|
||||||
* <template>
|
|
||||||
* <div>B</div>
|
|
||||||
* </template>
|
|
||||||
* <script setup lang="ts">
|
|
||||||
* import { useStore } from './context';
|
|
||||||
*
|
*
|
||||||
* const { count, increment } = useStore();
|
* // C.vue is same as B.vue
|
||||||
* </script>
|
|
||||||
* ```
|
|
||||||
*
|
*
|
||||||
* // C.vue is same as B.vue
|
* @param contextName Context name
|
||||||
|
* @param fn Context function
|
||||||
*/
|
*/
|
||||||
export default function useContext<T extends (...args: any[]) => any>(contextName: string, fn: T) {
|
export default function useContext<T extends (...args: any[]) => any>(contextName: string, fn: T) {
|
||||||
type Context = ReturnType<T>;
|
type Context = ReturnType<T>;
|
||||||
@ -69,20 +68,14 @@ export default function useContext<T extends (...args: any[]) => any>(contextNam
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
/**
|
/** Setup store in the parent component */
|
||||||
* setup store in the parent component
|
|
||||||
*/
|
|
||||||
setupStore,
|
setupStore,
|
||||||
/**
|
/** Use store in the child component */
|
||||||
* use store in the child component
|
|
||||||
*/
|
|
||||||
useStore
|
useStore
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Create context */
|
||||||
* create context
|
|
||||||
*/
|
|
||||||
function createContext<T>(contextName: string) {
|
function createContext<T>(contextName: string) {
|
||||||
const injectKey: InjectionKey<T> = Symbol(contextName);
|
const injectKey: InjectionKey<T> = Symbol(contextName);
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import useBoolean from './use-boolean';
|
import useBoolean from './use-boolean';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* loading
|
* Loading
|
||||||
* @param initValue init value
|
*
|
||||||
|
* @param initValue Init value
|
||||||
*/
|
*/
|
||||||
export default function useLoading(initValue = false) {
|
export default function useLoading(initValue = false) {
|
||||||
const { bool: loading, setTrue: startLoading, setFalse: endLoading } = useBoolean(initValue);
|
const { bool: loading, setTrue: startLoading, setFalse: endLoading } = useBoolean(initValue);
|
||||||
|
@ -2,33 +2,27 @@ import { h } from 'vue';
|
|||||||
import type { Component } from 'vue';
|
import type { Component } from 'vue';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* svg icon render hook
|
* Svg icon render hook
|
||||||
* @param SvgIcon svg icon component
|
*
|
||||||
|
* @param SvgIcon Svg icon component
|
||||||
*/
|
*/
|
||||||
export default function useSvgIconRender(SvgIcon: Component) {
|
export default function useSvgIconRender(SvgIcon: Component) {
|
||||||
interface IconConfig {
|
interface IconConfig {
|
||||||
/**
|
/** Iconify icon name */
|
||||||
* iconify icon name
|
|
||||||
*/
|
|
||||||
icon?: string;
|
icon?: string;
|
||||||
/**
|
/** Local icon name */
|
||||||
* local icon name
|
|
||||||
*/
|
|
||||||
localIcon?: string;
|
localIcon?: string;
|
||||||
/**
|
/** Icon color */
|
||||||
* icon color
|
|
||||||
*/
|
|
||||||
color?: string;
|
color?: string;
|
||||||
/**
|
/** Icon size */
|
||||||
* icon size
|
|
||||||
*/
|
|
||||||
fontSize?: number;
|
fontSize?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
type IconStyle = Partial<Pick<CSSStyleDeclaration, 'color' | 'fontSize'>>;
|
type IconStyle = Partial<Pick<CSSStyleDeclaration, 'color' | 'fontSize'>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* svg icon VNode
|
* Svg icon VNode
|
||||||
|
*
|
||||||
* @param config
|
* @param config
|
||||||
*/
|
*/
|
||||||
const SvgIconVNode = (config: IconConfig) => {
|
const SvgIconVNode = (config: IconConfig) => {
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"jsx": "preserve",
|
||||||
|
"lib": ["DOM", "ESNext"],
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"target": "ESNext",
|
|
||||||
"lib": ["DOM", "ESNext"],
|
|
||||||
"strict": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"allowSyntheticDefaultImports": true,
|
|
||||||
"jsx": "preserve",
|
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"noUnusedLocals": true,
|
"types": ["node"],
|
||||||
|
"strict": true,
|
||||||
"strictNullChecks": true,
|
"strictNullChecks": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"noUnusedLocals": true,
|
||||||
"types": ["node"]
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true
|
||||||
},
|
},
|
||||||
"include": ["src/**/*"],
|
"include": ["src/**/*"],
|
||||||
"exclude": ["node_modules", "dist"]
|
"exclude": ["node_modules", "dist"]
|
||||||
|
@ -6,9 +6,7 @@
|
|||||||
},
|
},
|
||||||
"typesVersions": {
|
"typesVersions": {
|
||||||
"*": {
|
"*": {
|
||||||
"*": [
|
"*": ["./src/*"]
|
||||||
"./src/*"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import AdminLayout, { LAYOUT_SCROLL_EL_ID, LAYOUT_MAX_Z_INDEX } from './libs/admin-layout';
|
import AdminLayout, { LAYOUT_MAX_Z_INDEX, LAYOUT_SCROLL_EL_ID } from './libs/admin-layout';
|
||||||
import PageTab from './libs/page-tab';
|
import PageTab from './libs/page-tab';
|
||||||
import SimpleScrollbar from './libs/simple-scrollbar';
|
import SimpleScrollbar from './libs/simple-scrollbar';
|
||||||
import ColorPicker from './libs/color-picker';
|
import ColorPicker from './libs/color-picker';
|
||||||
|
@ -14,4 +14,5 @@ declare const styles: {
|
|||||||
readonly 'sider-padding-top': string;
|
readonly 'sider-padding-top': string;
|
||||||
readonly 'sider-padding-bottom': string;
|
readonly 'sider-padding-bottom': string;
|
||||||
};
|
};
|
||||||
export = styles;
|
|
||||||
|
export default styles;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import AdminLayout from './index.vue';
|
import AdminLayout from './index.vue';
|
||||||
import { LAYOUT_SCROLL_EL_ID, LAYOUT_MAX_Z_INDEX } from './shared';
|
import { LAYOUT_MAX_Z_INDEX, LAYOUT_SCROLL_EL_ID } from './shared';
|
||||||
|
|
||||||
export default AdminLayout;
|
export default AdminLayout;
|
||||||
export { LAYOUT_SCROLL_EL_ID, LAYOUT_MAX_Z_INDEX };
|
export { LAYOUT_SCROLL_EL_ID, LAYOUT_MAX_Z_INDEX };
|
||||||
|
@ -1,129 +1,7 @@
|
|||||||
<template>
|
|
||||||
<div :class="['relative h-full', commonClass]" :style="cssVars">
|
|
||||||
<div
|
|
||||||
:id="isWrapperScroll ? scrollElId : undefined"
|
|
||||||
:class="['flex flex-col h-full', commonClass, scrollWrapperClass, { 'overflow-y-auto': isWrapperScroll }]"
|
|
||||||
>
|
|
||||||
<!-- Header -->
|
|
||||||
<template v-if="showHeader">
|
|
||||||
<header
|
|
||||||
v-show="!fullContent"
|
|
||||||
:class="[
|
|
||||||
style['layout-header'],
|
|
||||||
'flex-shrink-0',
|
|
||||||
commonClass,
|
|
||||||
headerClass,
|
|
||||||
headerLeftGapClass,
|
|
||||||
{ 'absolute top-0 left-0 w-full': fixedHeaderAndTab }
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<slot name="header"></slot>
|
|
||||||
</header>
|
|
||||||
<div
|
|
||||||
v-show="!fullContent && fixedHeaderAndTab"
|
|
||||||
:class="[style['layout-header-placement'], 'flex-shrink-0 overflow-hidden']"
|
|
||||||
></div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- Tab -->
|
|
||||||
<template v-if="showTab">
|
|
||||||
<div
|
|
||||||
:class="[
|
|
||||||
style['layout-tab'],
|
|
||||||
'flex-shrink-0',
|
|
||||||
commonClass,
|
|
||||||
tabClass,
|
|
||||||
{ 'top-0!': fullContent || !showHeader },
|
|
||||||
leftGapClass,
|
|
||||||
{ 'absolute left-0 w-full': fixedHeaderAndTab }
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<slot name="tab"></slot>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-show="fullContent || fixedHeaderAndTab"
|
|
||||||
:class="[style['layout-tab-placement'], 'flex-shrink-0 overflow-hidden']"
|
|
||||||
></div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- Sider -->
|
|
||||||
<template v-if="showSider">
|
|
||||||
<aside
|
|
||||||
v-show="!fullContent"
|
|
||||||
:class="[
|
|
||||||
'absolute left-0 top-0 h-full',
|
|
||||||
commonClass,
|
|
||||||
siderClass,
|
|
||||||
siderPaddingClass,
|
|
||||||
siderCollapse ? style['layout-sider_collapsed'] : style['layout-sider']
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<slot name="sider"></slot>
|
|
||||||
</aside>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- Mobile Sider -->
|
|
||||||
<template v-if="showMobileSider">
|
|
||||||
<aside
|
|
||||||
:class="[
|
|
||||||
'absolute left-0 top-0 w-0 h-full bg-white',
|
|
||||||
commonClass,
|
|
||||||
mobileSiderClass,
|
|
||||||
style['layout-mobile-sider'],
|
|
||||||
siderCollapse ? 'overflow-hidden' : style['layout-sider']
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<slot name="sider"></slot>
|
|
||||||
</aside>
|
|
||||||
<div
|
|
||||||
v-show="!siderCollapse"
|
|
||||||
:class="['absolute left-0 top-0 w-full h-full bg-[rgba(0,0,0,0.2)]', style['layout-mobile-sider-mask']]"
|
|
||||||
@click="handleClickMask"
|
|
||||||
></div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<main
|
|
||||||
:id="isContentScroll ? scrollElId : undefined"
|
|
||||||
:class="[
|
|
||||||
'flex flex-col flex-grow',
|
|
||||||
commonClass,
|
|
||||||
contentClass,
|
|
||||||
leftGapClass,
|
|
||||||
{ 'overflow-y-auto': isContentScroll }
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<slot></slot>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<template v-if="showFooter">
|
|
||||||
<footer
|
|
||||||
v-show="!fullContent"
|
|
||||||
:class="[
|
|
||||||
style['layout-footer'],
|
|
||||||
'flex-shrink-0',
|
|
||||||
commonClass,
|
|
||||||
footerClass,
|
|
||||||
footerLeftGapClass,
|
|
||||||
{ 'absolute left-0 bottom-0 w-full': fixedFooter }
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<slot name="footer"></slot>
|
|
||||||
</footer>
|
|
||||||
<div
|
|
||||||
v-show="!fullContent && fixedFooter"
|
|
||||||
:class="[style['layout-footer-placement'], 'flex-shrink-0 overflow-hidden']"
|
|
||||||
></div>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import type { AdminLayoutProps } from '../../types';
|
import type { AdminLayoutProps } from '../../types';
|
||||||
import { LAYOUT_SCROLL_EL_ID, LAYOUT_MAX_Z_INDEX, createLayoutCssVars } from './shared';
|
import { LAYOUT_MAX_Z_INDEX, LAYOUT_SCROLL_EL_ID, createLayoutCssVars } from './shared';
|
||||||
import style from './index.module.css';
|
import style from './index.module.css';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -150,31 +28,29 @@ const props = withDefaults(defineProps<AdminLayoutProps>(), {
|
|||||||
rightFooter: false
|
rightFooter: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
|
const slots = defineSlots<Slots>();
|
||||||
|
|
||||||
interface Emits {
|
interface Emits {
|
||||||
/**
|
/** Update siderCollapse */
|
||||||
* update siderCollapse
|
|
||||||
*/
|
|
||||||
(e: 'update:siderCollapse', collapse: boolean): void;
|
(e: 'update:siderCollapse', collapse: boolean): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>();
|
|
||||||
|
|
||||||
type SlotFn = (props?: Record<string, unknown>) => any;
|
type SlotFn = (props?: Record<string, unknown>) => any;
|
||||||
|
|
||||||
type Slots = {
|
type Slots = {
|
||||||
/** main */
|
/** Main */
|
||||||
default?: SlotFn;
|
default?: SlotFn;
|
||||||
/** header */
|
/** Header */
|
||||||
header?: SlotFn;
|
header?: SlotFn;
|
||||||
/** tab */
|
/** Tab */
|
||||||
tab?: SlotFn;
|
tab?: SlotFn;
|
||||||
/** sider */
|
/** Sider */
|
||||||
sider?: SlotFn;
|
sider?: SlotFn;
|
||||||
/** footer */
|
/** Footer */
|
||||||
footer?: SlotFn;
|
footer?: SlotFn;
|
||||||
};
|
};
|
||||||
const slots = defineSlots<Slots>();
|
|
||||||
|
|
||||||
const cssVars = computed(() => createLayoutCssVars(props));
|
const cssVars = computed(() => createLayoutCssVars(props));
|
||||||
|
|
||||||
// config visible
|
// config visible
|
||||||
@ -235,4 +111,126 @@ function handleClickMask() {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="relative h-full" :class="[commonClass]" :style="cssVars">
|
||||||
|
<div
|
||||||
|
:id="isWrapperScroll ? scrollElId : undefined"
|
||||||
|
class="flex flex-col h-full"
|
||||||
|
:class="[commonClass, scrollWrapperClass, { 'overflow-y-auto': isWrapperScroll }]"
|
||||||
|
>
|
||||||
|
<!-- Header -->
|
||||||
|
<template v-if="showHeader">
|
||||||
|
<header
|
||||||
|
v-show="!fullContent"
|
||||||
|
class="flex-shrink-0"
|
||||||
|
:class="[
|
||||||
|
style['layout-header'],
|
||||||
|
commonClass,
|
||||||
|
headerClass,
|
||||||
|
headerLeftGapClass,
|
||||||
|
{ 'absolute top-0 left-0 w-full': fixedHeaderAndTab }
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<slot name="header"></slot>
|
||||||
|
</header>
|
||||||
|
<div
|
||||||
|
v-show="!fullContent && fixedHeaderAndTab"
|
||||||
|
class="flex-shrink-0 overflow-hidden"
|
||||||
|
:class="[style['layout-header-placement']]"
|
||||||
|
></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- Tab -->
|
||||||
|
<template v-if="showTab">
|
||||||
|
<div
|
||||||
|
class="flex-shrink-0"
|
||||||
|
:class="[
|
||||||
|
style['layout-tab'],
|
||||||
|
commonClass,
|
||||||
|
tabClass,
|
||||||
|
{ 'top-0!': fullContent || !showHeader },
|
||||||
|
leftGapClass,
|
||||||
|
{ 'absolute left-0 w-full': fixedHeaderAndTab }
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<slot name="tab"></slot>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-show="fullContent || fixedHeaderAndTab"
|
||||||
|
class="flex-shrink-0 overflow-hidden"
|
||||||
|
:class="[style['layout-tab-placement']]"
|
||||||
|
></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- Sider -->
|
||||||
|
<template v-if="showSider">
|
||||||
|
<aside
|
||||||
|
v-show="!fullContent"
|
||||||
|
class="absolute left-0 top-0 h-full"
|
||||||
|
:class="[
|
||||||
|
commonClass,
|
||||||
|
siderClass,
|
||||||
|
siderPaddingClass,
|
||||||
|
siderCollapse ? style['layout-sider_collapsed'] : style['layout-sider']
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<slot name="sider"></slot>
|
||||||
|
</aside>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- Mobile Sider -->
|
||||||
|
<template v-if="showMobileSider">
|
||||||
|
<aside
|
||||||
|
class="absolute left-0 top-0 w-0 h-full bg-white"
|
||||||
|
:class="[
|
||||||
|
commonClass,
|
||||||
|
mobileSiderClass,
|
||||||
|
style['layout-mobile-sider'],
|
||||||
|
siderCollapse ? 'overflow-hidden' : style['layout-sider']
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<slot name="sider"></slot>
|
||||||
|
</aside>
|
||||||
|
<div
|
||||||
|
v-show="!siderCollapse"
|
||||||
|
class="absolute left-0 top-0 w-full h-full bg-[rgba(0,0,0,0.2)]"
|
||||||
|
:class="[style['layout-mobile-sider-mask']]"
|
||||||
|
@click="handleClickMask"
|
||||||
|
></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- Main Content -->
|
||||||
|
<main
|
||||||
|
:id="isContentScroll ? scrollElId : undefined"
|
||||||
|
class="flex flex-col flex-grow"
|
||||||
|
:class="[commonClass, contentClass, leftGapClass, { 'overflow-y-auto': isContentScroll }]"
|
||||||
|
>
|
||||||
|
<slot></slot>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<template v-if="showFooter">
|
||||||
|
<footer
|
||||||
|
v-show="!fullContent"
|
||||||
|
class="flex-shrink-0"
|
||||||
|
:class="[
|
||||||
|
style['layout-footer'],
|
||||||
|
commonClass,
|
||||||
|
footerClass,
|
||||||
|
footerLeftGapClass,
|
||||||
|
{ 'absolute left-0 bottom-0 w-full': fixedFooter }
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<slot name="footer"></slot>
|
||||||
|
</footer>
|
||||||
|
<div
|
||||||
|
v-show="!fullContent && fixedFooter"
|
||||||
|
class="flex-shrink-0 overflow-hidden"
|
||||||
|
:class="[style['layout-footer-placement']]"
|
||||||
|
></div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@ -1,18 +1,15 @@
|
|||||||
import type { AdminLayoutProps, LayoutCssVarsProps, LayoutCssVars } from '../../types';
|
import type { AdminLayoutProps, LayoutCssVars, LayoutCssVarsProps } from '../../types';
|
||||||
|
|
||||||
/**
|
/** The id of the scroll element of the layout */
|
||||||
* the id of the scroll element of the layout
|
|
||||||
*/
|
|
||||||
export const LAYOUT_SCROLL_EL_ID = '__SCROLL_EL_ID__';
|
export const LAYOUT_SCROLL_EL_ID = '__SCROLL_EL_ID__';
|
||||||
|
|
||||||
/**
|
/** The max z-index of the layout */
|
||||||
* the max z-index of the layout
|
|
||||||
*/
|
|
||||||
export const LAYOUT_MAX_Z_INDEX = 100;
|
export const LAYOUT_MAX_Z_INDEX = 100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* create layout css vars by css vars props
|
* Create layout css vars by css vars props
|
||||||
* @param props css vars props
|
*
|
||||||
|
* @param props Css vars props
|
||||||
*/
|
*/
|
||||||
function createLayoutCssVarsByCssVarsProps(props: LayoutCssVarsProps) {
|
function createLayoutCssVarsByCssVarsProps(props: LayoutCssVarsProps) {
|
||||||
const cssVars: LayoutCssVars = {
|
const cssVars: LayoutCssVars = {
|
||||||
@ -32,7 +29,8 @@ function createLayoutCssVarsByCssVarsProps(props: LayoutCssVarsProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* create layout css vars
|
* Create layout css vars
|
||||||
|
*
|
||||||
* @param props
|
* @param props
|
||||||
*/
|
*/
|
||||||
export function createLayoutCssVars(props: AdminLayoutProps) {
|
export function createLayoutCssVars(props: AdminLayoutProps) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, watch, onMounted } from 'vue';
|
import { onMounted, ref, watch } from 'vue';
|
||||||
import ColorPicker from '@simonwep/pickr';
|
import ColorPicker from '@simonwep/pickr';
|
||||||
import '@simonwep/pickr/dist/themes/nano.min.css';
|
import '@simonwep/pickr/dist/themes/nano.min.css';
|
||||||
|
|
||||||
@ -7,12 +7,6 @@ defineOptions({
|
|||||||
name: 'ColorPicker'
|
name: 'ColorPicker'
|
||||||
});
|
});
|
||||||
|
|
||||||
interface Props {
|
|
||||||
color: string;
|
|
||||||
palettes?: string[];
|
|
||||||
disabled?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
palettes: () => [
|
palettes: () => [
|
||||||
'#3b82f6',
|
'#3b82f6',
|
||||||
@ -35,12 +29,18 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
color: string;
|
||||||
|
palettes?: string[];
|
||||||
|
disabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
interface Emits {
|
interface Emits {
|
||||||
(e: 'update:color', value: string): void;
|
(e: 'update:color', value: string): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>();
|
|
||||||
|
|
||||||
const domRef = ref<HTMLElement | null>(null);
|
const domRef = ref<HTMLElement | null>(null);
|
||||||
const instance = ref<ColorPicker | null>(null);
|
const instance = ref<ColorPicker | null>(null);
|
||||||
|
|
||||||
|
@ -1,7 +1,43 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { PageTabProps } from '../../types';
|
||||||
|
import style from './index.module.css';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'ButtonTab'
|
||||||
|
});
|
||||||
|
|
||||||
|
defineProps<PageTabProps>();
|
||||||
|
|
||||||
|
defineSlots<Slots>();
|
||||||
|
|
||||||
|
type SlotFn = (props?: Record<string, unknown>) => any;
|
||||||
|
|
||||||
|
type Slots = {
|
||||||
|
/**
|
||||||
|
* Slot
|
||||||
|
*
|
||||||
|
* The center content of the tab
|
||||||
|
*/
|
||||||
|
default?: SlotFn;
|
||||||
|
/**
|
||||||
|
* Slot
|
||||||
|
*
|
||||||
|
* The left content of the tab
|
||||||
|
*/
|
||||||
|
prefix?: SlotFn;
|
||||||
|
/**
|
||||||
|
* Slot
|
||||||
|
*
|
||||||
|
* The right content of the tab
|
||||||
|
*/
|
||||||
|
suffix?: SlotFn;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
|
class=":soy: relative inline-flex justify-center items-center gap-12px px-12px py-4px border-1px border-solid rounded-4px cursor-pointer whitespace-nowrap"
|
||||||
:class="[
|
:class="[
|
||||||
':soy: relative inline-flex justify-center items-center gap-12px px-12px py-4px border-1px border-solid rounded-4px cursor-pointer whitespace-nowrap',
|
|
||||||
style['button-tab'],
|
style['button-tab'],
|
||||||
{ [style['button-tab_dark']]: darkMode },
|
{ [style['button-tab_dark']]: darkMode },
|
||||||
{ [style['button-tab_active']]: active },
|
{ [style['button-tab_active']]: active },
|
||||||
@ -14,36 +50,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import style from './index.module.css';
|
|
||||||
import type { PageTabProps } from '../../types';
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: 'ButtonTab'
|
|
||||||
});
|
|
||||||
|
|
||||||
defineProps<PageTabProps>();
|
|
||||||
|
|
||||||
type SlotFn = (props?: Record<string, unknown>) => any;
|
|
||||||
|
|
||||||
type Slots = {
|
|
||||||
/**
|
|
||||||
* slot
|
|
||||||
* @description the center content of the tab
|
|
||||||
*/
|
|
||||||
default?: SlotFn;
|
|
||||||
/**
|
|
||||||
* slot
|
|
||||||
* @description the left content of the tab
|
|
||||||
*/
|
|
||||||
prefix?: SlotFn;
|
|
||||||
/**
|
|
||||||
* slot
|
|
||||||
* @description the right content of the tab
|
|
||||||
*/
|
|
||||||
suffix?: SlotFn;
|
|
||||||
};
|
|
||||||
defineSlots<Slots>();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
defineOptions({
|
||||||
|
name: 'ChromeTabBg'
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<svg style="width: 100%; height: 100%">
|
<svg class="wh-full">
|
||||||
<defs>
|
<defs>
|
||||||
<symbol id="geometry-left" viewBox="0 0 214 36">
|
<symbol id="geometry-left" viewBox="0 0 214 36">
|
||||||
<path d="M17 0h197v36H0v-2c4.5 0 9-3.5 9-8V8c0-4.5 3.5-8 8-8z"></path>
|
<path d="M17 0h197v36H0v-2c4.5 0 9-3.5 9-8V8c0-4.5 3.5-8 8-8z"></path>
|
||||||
@ -22,10 +28,4 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
defineOptions({
|
|
||||||
name: 'ChromeTabBg'
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@ -1,27 +1,7 @@
|
|||||||
<template>
|
|
||||||
<div
|
|
||||||
:class="[
|
|
||||||
':soy: relative inline-flex justify-center items-center gap-16px -mr-18px px-24px py-6px cursor-pointer whitespace-nowrap',
|
|
||||||
style['chrome-tab'],
|
|
||||||
{ [style['chrome-tab_dark']]: darkMode },
|
|
||||||
{ [style['chrome-tab_active']]: active },
|
|
||||||
{ [style['chrome-tab_active_dark']]: active && darkMode }
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<div :class="[':soy: absolute left-0 top-0 -z-1 w-full h-full pointer-events-none', style['chrome-tab__bg']]">
|
|
||||||
<ChromeTabBg />
|
|
||||||
</div>
|
|
||||||
<slot name="prefix"></slot>
|
|
||||||
<slot></slot>
|
|
||||||
<slot name="suffix"></slot>
|
|
||||||
<div :class="[':soy: absolute right-7px w-1px h-16px bg-#1f2225', style['chrome-tab-divider']]"></div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import type { PageTabProps } from '../../types';
|
||||||
import ChromeTabBg from './chrome-tab-bg.vue';
|
import ChromeTabBg from './chrome-tab-bg.vue';
|
||||||
import style from './index.module.css';
|
import style from './index.module.css';
|
||||||
import type { PageTabProps } from '../../types';
|
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'ChromeTab'
|
name: 'ChromeTab'
|
||||||
@ -29,27 +9,50 @@ defineOptions({
|
|||||||
|
|
||||||
defineProps<PageTabProps>();
|
defineProps<PageTabProps>();
|
||||||
|
|
||||||
|
defineSlots<Slots>();
|
||||||
|
|
||||||
type SlotFn = (props?: Record<string, unknown>) => any;
|
type SlotFn = (props?: Record<string, unknown>) => any;
|
||||||
|
|
||||||
type Slots = {
|
type Slots = {
|
||||||
/**
|
/**
|
||||||
* slot
|
* Slot
|
||||||
* @description the center content of the tab
|
*
|
||||||
|
* The center content of the tab
|
||||||
*/
|
*/
|
||||||
default?: SlotFn;
|
default?: SlotFn;
|
||||||
/**
|
/**
|
||||||
* slot
|
* Slot
|
||||||
* @description the left content of the tab
|
*
|
||||||
|
* The left content of the tab
|
||||||
*/
|
*/
|
||||||
prefix?: SlotFn;
|
prefix?: SlotFn;
|
||||||
/**
|
/**
|
||||||
* slot
|
* Slot
|
||||||
* @description the right content of the tab
|
*
|
||||||
|
* The right content of the tab
|
||||||
*/
|
*/
|
||||||
suffix?: SlotFn;
|
suffix?: SlotFn;
|
||||||
};
|
};
|
||||||
|
|
||||||
defineSlots<Slots>();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class=":soy: relative inline-flex justify-center items-center gap-16px -mr-18px px-24px py-6px cursor-pointer whitespace-nowrap"
|
||||||
|
:class="[
|
||||||
|
style['chrome-tab'],
|
||||||
|
{ [style['chrome-tab_dark']]: darkMode },
|
||||||
|
{ [style['chrome-tab_active']]: active },
|
||||||
|
{ [style['chrome-tab_active_dark']]: active && darkMode }
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<div class=":soy: absolute left-0 top-0 -z-1 w-full h-full pointer-events-none" :class="[style['chrome-tab__bg']]">
|
||||||
|
<ChromeTabBg />
|
||||||
|
</div>
|
||||||
|
<slot name="prefix"></slot>
|
||||||
|
<slot></slot>
|
||||||
|
<slot name="suffix"></slot>
|
||||||
|
<div class=":soy: absolute right-7px w-1px h-16px bg-#1f2225" :class="[style['chrome-tab-divider']]"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@ -1,3 +1,19 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
defineOptions({
|
||||||
|
name: 'IconClose'
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
|
interface Emits {
|
||||||
|
(e: 'click'): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleClick() {
|
||||||
|
emit('click');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class=":soy: relative inline-flex justify-center items-center w-16px h-16px text-14px rd-50%"
|
class=":soy: relative inline-flex justify-center items-center w-16px h-16px text-14px rd-50%"
|
||||||
@ -12,20 +28,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
defineOptions({
|
|
||||||
name: 'IconClose'
|
|
||||||
});
|
|
||||||
|
|
||||||
interface Emits {
|
|
||||||
(e: 'click'): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const emit = defineEmits<Emits>();
|
|
||||||
|
|
||||||
function handleClick() {
|
|
||||||
emit('click');
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@ -11,4 +11,5 @@ declare const styles: {
|
|||||||
readonly 'chrome-tab_dark': string;
|
readonly 'chrome-tab_dark': string;
|
||||||
readonly 'chrome-tab-divider': string;
|
readonly 'chrome-tab-divider': string;
|
||||||
};
|
};
|
||||||
export = styles;
|
|
||||||
|
export default styles;
|
||||||
|
@ -1,26 +1,12 @@
|
|||||||
<template>
|
|
||||||
<component :is="activeTabComponent.component" :class="activeTabComponent.class" :style="cssVars" v-bind="bindProps">
|
|
||||||
<template #prefix>
|
|
||||||
<slot name="prefix"></slot>
|
|
||||||
</template>
|
|
||||||
<slot></slot>
|
|
||||||
<template #suffix>
|
|
||||||
<slot name="suffix">
|
|
||||||
<SvgIconClose v-if="closable" :class="[style['icon_close']]" @click="handleClose" />
|
|
||||||
</slot>
|
|
||||||
</template>
|
|
||||||
</component>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import type { Component } from 'vue';
|
import type { Component } from 'vue';
|
||||||
import { createTabCssVars, ACTIVE_COLOR } from './shared';
|
import type { PageTabMode, PageTabProps } from '../../types';
|
||||||
|
import { ACTIVE_COLOR, createTabCssVars } from './shared';
|
||||||
import ChromeTab from './chrome-tab.vue';
|
import ChromeTab from './chrome-tab.vue';
|
||||||
import ButtonTab from './button-tab.vue';
|
import ButtonTab from './button-tab.vue';
|
||||||
import SvgIconClose from './icon-close.vue';
|
import SvgIconClose from './icon-close.vue';
|
||||||
import style from './index.module.css';
|
import style from './index.module.css';
|
||||||
import type { PageTabProps, PageTabMode } from '../../types';
|
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'PageTab'
|
name: 'PageTab'
|
||||||
@ -33,34 +19,37 @@ const props = withDefaults(defineProps<PageTabProps>(), {
|
|||||||
closable: true
|
closable: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
|
defineSlots<Slots>();
|
||||||
|
|
||||||
interface Emits {
|
interface Emits {
|
||||||
(e: 'close'): void;
|
(e: 'close'): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>();
|
|
||||||
|
|
||||||
type SlotFn = (props?: Record<string, unknown>) => any;
|
type SlotFn = (props?: Record<string, unknown>) => any;
|
||||||
|
|
||||||
type Slots = {
|
type Slots = {
|
||||||
/**
|
/**
|
||||||
* slot
|
* Slot
|
||||||
* @description the center content of the tab
|
*
|
||||||
|
* The center content of the tab
|
||||||
*/
|
*/
|
||||||
default?: SlotFn;
|
default?: SlotFn;
|
||||||
/**
|
/**
|
||||||
* slot
|
* Slot
|
||||||
* @description the left content of the tab
|
*
|
||||||
|
* The left content of the tab
|
||||||
*/
|
*/
|
||||||
prefix?: SlotFn;
|
prefix?: SlotFn;
|
||||||
/**
|
/**
|
||||||
* slot
|
* Slot
|
||||||
* @description the right content of the tab
|
*
|
||||||
|
* The right content of the tab
|
||||||
*/
|
*/
|
||||||
suffix?: SlotFn;
|
suffix?: SlotFn;
|
||||||
};
|
};
|
||||||
|
|
||||||
defineSlots<Slots>();
|
|
||||||
|
|
||||||
const activeTabComponent = computed(() => {
|
const activeTabComponent = computed(() => {
|
||||||
const { mode, chromeClass, buttonClass } = props;
|
const { mode, chromeClass, buttonClass } = props;
|
||||||
|
|
||||||
@ -91,4 +80,18 @@ function handleClose() {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<component :is="activeTabComponent.component" :class="activeTabComponent.class" :style="cssVars" v-bind="bindProps">
|
||||||
|
<template #prefix>
|
||||||
|
<slot name="prefix"></slot>
|
||||||
|
</template>
|
||||||
|
<slot></slot>
|
||||||
|
<template #suffix>
|
||||||
|
<slot name="suffix">
|
||||||
|
<SvgIconClose v-if="closable" :class="[style['icon_close']]" @click="handleClose" />
|
||||||
|
</slot>
|
||||||
|
</template>
|
||||||
|
</component>
|
||||||
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import { addColorAlpha, transformColorWithOpacity } from '@sa/utils';
|
import { addColorAlpha, transformColorWithOpacity } from '@sa/utils';
|
||||||
import type { PageTabCssVarsProps, PageTabCssVars } from '../../types';
|
import type { PageTabCssVars, PageTabCssVarsProps } from '../../types';
|
||||||
|
|
||||||
/**
|
/** The active color of the tab */
|
||||||
* the active color of the tab
|
|
||||||
*/
|
|
||||||
export const ACTIVE_COLOR = '#1890ff';
|
export const ACTIVE_COLOR = '#1890ff';
|
||||||
|
|
||||||
function createCssVars(props: PageTabCssVarsProps) {
|
function createCssVars(props: PageTabCssVarsProps) {
|
||||||
|
@ -1,146 +1,156 @@
|
|||||||
/**
|
/** Header config */
|
||||||
* header config
|
|
||||||
*/
|
|
||||||
interface AdminLayoutHeaderConfig {
|
interface AdminLayoutHeaderConfig {
|
||||||
/**
|
/**
|
||||||
* whether header is visible
|
* Whether header is visible
|
||||||
|
*
|
||||||
* @default true
|
* @default true
|
||||||
*/
|
*/
|
||||||
headerVisible?: boolean;
|
headerVisible?: boolean;
|
||||||
/**
|
/**
|
||||||
* header class
|
* Header class
|
||||||
|
*
|
||||||
* @default ''
|
* @default ''
|
||||||
*/
|
*/
|
||||||
headerClass?: string;
|
headerClass?: string;
|
||||||
/**
|
/**
|
||||||
* header height
|
* Header height
|
||||||
|
*
|
||||||
* @default 56px
|
* @default 56px
|
||||||
*/
|
*/
|
||||||
headerHeight?: number;
|
headerHeight?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Tab config */
|
||||||
* tab config
|
|
||||||
*/
|
|
||||||
interface AdminLayoutTabConfig {
|
interface AdminLayoutTabConfig {
|
||||||
/**
|
/**
|
||||||
* whether tab is visible
|
* Whether tab is visible
|
||||||
|
*
|
||||||
* @default true
|
* @default true
|
||||||
*/
|
*/
|
||||||
tabVisible?: boolean;
|
tabVisible?: boolean;
|
||||||
/**
|
/**
|
||||||
* tab class
|
* Tab class
|
||||||
|
*
|
||||||
* @default ''
|
* @default ''
|
||||||
*/
|
*/
|
||||||
tabClass?: string;
|
tabClass?: string;
|
||||||
/**
|
/**
|
||||||
* tab height
|
* Tab height
|
||||||
|
*
|
||||||
* @default 48px
|
* @default 48px
|
||||||
*/
|
*/
|
||||||
tabHeight?: number;
|
tabHeight?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Sider config */
|
||||||
* sider config
|
|
||||||
*/
|
|
||||||
interface AdminLayoutSiderConfig {
|
interface AdminLayoutSiderConfig {
|
||||||
/**
|
/**
|
||||||
* whether sider is visible
|
* Whether sider is visible
|
||||||
|
*
|
||||||
* @default true
|
* @default true
|
||||||
*/
|
*/
|
||||||
siderVisible?: boolean;
|
siderVisible?: boolean;
|
||||||
/**
|
/**
|
||||||
* sider class
|
* Sider class
|
||||||
|
*
|
||||||
* @default ''
|
* @default ''
|
||||||
*/
|
*/
|
||||||
siderClass?: string;
|
siderClass?: string;
|
||||||
/**
|
/**
|
||||||
* mobile sider class
|
* Mobile sider class
|
||||||
|
*
|
||||||
* @default ''
|
* @default ''
|
||||||
*/
|
*/
|
||||||
mobileSiderClass?: string;
|
mobileSiderClass?: string;
|
||||||
/**
|
/**
|
||||||
* sider collapse status
|
* Sider collapse status
|
||||||
|
*
|
||||||
* @default false
|
* @default false
|
||||||
*/
|
*/
|
||||||
siderCollapse?: boolean;
|
siderCollapse?: boolean;
|
||||||
/**
|
/**
|
||||||
* sider width when collapse is false
|
* Sider width when collapse is false
|
||||||
|
*
|
||||||
* @default '220px'
|
* @default '220px'
|
||||||
*/
|
*/
|
||||||
siderWidth?: number;
|
siderWidth?: number;
|
||||||
/**
|
/**
|
||||||
* sider width when collapse is true
|
* Sider width when collapse is true
|
||||||
|
*
|
||||||
* @default '64px'
|
* @default '64px'
|
||||||
*/
|
*/
|
||||||
siderCollapsedWidth?: number;
|
siderCollapsedWidth?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Content config */
|
||||||
* content config
|
|
||||||
*/
|
|
||||||
export interface AdminLayoutContentConfig {
|
export interface AdminLayoutContentConfig {
|
||||||
/**
|
/**
|
||||||
* content class
|
* Content class
|
||||||
|
*
|
||||||
* @default ''
|
* @default ''
|
||||||
*/
|
*/
|
||||||
contentClass?: string;
|
contentClass?: string;
|
||||||
/**
|
/**
|
||||||
* whether content is full the page
|
* Whether content is full the page
|
||||||
* @description if true, other elements will be hidden by `display: none`
|
*
|
||||||
|
* If true, other elements will be hidden by `display: none`
|
||||||
*/
|
*/
|
||||||
fullContent?: boolean;
|
fullContent?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Footer config */
|
||||||
* footer config
|
|
||||||
*/
|
|
||||||
export interface AdminLayoutFooterConfig {
|
export interface AdminLayoutFooterConfig {
|
||||||
/**
|
/**
|
||||||
* whether footer is visible
|
* Whether footer is visible
|
||||||
|
*
|
||||||
* @default true
|
* @default true
|
||||||
*/
|
*/
|
||||||
footerVisible?: boolean;
|
footerVisible?: boolean;
|
||||||
/**
|
/**
|
||||||
* whether footer is fixed
|
* Whether footer is fixed
|
||||||
|
*
|
||||||
* @default true
|
* @default true
|
||||||
*/
|
*/
|
||||||
fixedFooter?: boolean;
|
fixedFooter?: boolean;
|
||||||
/**
|
/**
|
||||||
* footer class
|
* Footer class
|
||||||
|
*
|
||||||
* @default ''
|
* @default ''
|
||||||
*/
|
*/
|
||||||
footerClass?: string;
|
footerClass?: string;
|
||||||
/**
|
/**
|
||||||
* footer height
|
* Footer height
|
||||||
|
*
|
||||||
* @default 48px
|
* @default 48px
|
||||||
*/
|
*/
|
||||||
footerHeight?: number;
|
footerHeight?: number;
|
||||||
/**
|
/**
|
||||||
* whether footer is on the right side
|
* Whether footer is on the right side
|
||||||
* @description when the layout is vertical, the footer is on the right side
|
*
|
||||||
|
* When the layout is vertical, the footer is on the right side
|
||||||
*/
|
*/
|
||||||
rightFooter?: boolean;
|
rightFooter?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* layout mode
|
* Layout mode
|
||||||
* - horizontal
|
*
|
||||||
* - vertical
|
* - Horizontal
|
||||||
|
* - Vertical
|
||||||
*/
|
*/
|
||||||
export type LayoutMode = 'horizontal' | 'vertical';
|
export type LayoutMode = 'horizontal' | 'vertical';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the scroll mode when content overflow
|
* The scroll mode when content overflow
|
||||||
* - wrapper: the layout component's wrapper element has a scrollbar
|
*
|
||||||
* - content: the layout component's content element has a scrollbar
|
* - Wrapper: the layout component's wrapper element has a scrollbar
|
||||||
|
* - Content: the layout component's content element has a scrollbar
|
||||||
|
*
|
||||||
* @default 'wrapper'
|
* @default 'wrapper'
|
||||||
*/
|
*/
|
||||||
export type LayoutScrollMode = 'wrapper' | 'content';
|
export type LayoutScrollMode = 'wrapper' | 'content';
|
||||||
|
|
||||||
/**
|
/** Admin layout props */
|
||||||
* admin layout props
|
|
||||||
*/
|
|
||||||
export interface AdminLayoutProps
|
export interface AdminLayoutProps
|
||||||
extends AdminLayoutHeaderConfig,
|
extends AdminLayoutHeaderConfig,
|
||||||
AdminLayoutTabConfig,
|
AdminLayoutTabConfig,
|
||||||
@ -148,52 +158,58 @@ export interface AdminLayoutProps
|
|||||||
AdminLayoutContentConfig,
|
AdminLayoutContentConfig,
|
||||||
AdminLayoutFooterConfig {
|
AdminLayoutFooterConfig {
|
||||||
/**
|
/**
|
||||||
* layout mode
|
* Layout mode
|
||||||
|
*
|
||||||
* - {@link LayoutMode}
|
* - {@link LayoutMode}
|
||||||
*/
|
*/
|
||||||
mode?: LayoutMode;
|
mode?: LayoutMode;
|
||||||
/** is mobile layout */
|
/** Is mobile layout */
|
||||||
isMobile?: boolean;
|
isMobile?: boolean;
|
||||||
/**
|
/**
|
||||||
* scroll mode
|
* Scroll mode
|
||||||
|
*
|
||||||
* - {@link ScrollMode}
|
* - {@link ScrollMode}
|
||||||
*/
|
*/
|
||||||
scrollMode?: LayoutScrollMode;
|
scrollMode?: LayoutScrollMode;
|
||||||
/**
|
/**
|
||||||
* the id of the scroll element of the layout
|
* The id of the scroll element of the layout
|
||||||
* @description it can be used to get the corresponding Dom and scroll it
|
*
|
||||||
|
* It can be used to get the corresponding Dom and scroll it
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* use the default id by import
|
||||||
|
* ```ts
|
||||||
|
* import { adminLayoutScrollElId } from '@sa/vue-materials';
|
||||||
|
* ```
|
||||||
|
*
|
||||||
* @default
|
* @default
|
||||||
* ```ts
|
* ```ts
|
||||||
* const adminLayoutScrollElId = '__ADMIN_LAYOUT_SCROLL_EL_ID__'
|
* const adminLayoutScrollElId = '__ADMIN_LAYOUT_SCROLL_EL_ID__'
|
||||||
* ```
|
* ```
|
||||||
* @example use the default id by import
|
|
||||||
* ```ts
|
|
||||||
* import { adminLayoutScrollElId } from '@sa/vue-materials';
|
|
||||||
* ```
|
|
||||||
*/
|
*/
|
||||||
scrollElId?: string;
|
scrollElId?: string;
|
||||||
/**
|
/** The class of the scroll element */
|
||||||
* the class of the scroll element
|
|
||||||
*/
|
|
||||||
scrollElClass?: string;
|
scrollElClass?: string;
|
||||||
/**
|
/** The class of the scroll wrapper element */
|
||||||
* the class of the scroll wrapper element
|
|
||||||
*/
|
|
||||||
scrollWrapperClass?: string;
|
scrollWrapperClass?: string;
|
||||||
/**
|
/**
|
||||||
* the common class of the layout
|
* The common class of the layout
|
||||||
* @description is can be used to configure the transition animation
|
*
|
||||||
|
* Is can be used to configure the transition animation
|
||||||
|
*
|
||||||
* @default 'transition-all-300'
|
* @default 'transition-all-300'
|
||||||
*/
|
*/
|
||||||
commonClass?: string;
|
commonClass?: string;
|
||||||
/**
|
/**
|
||||||
* whether fix the header and tab
|
* Whether fix the header and tab
|
||||||
|
*
|
||||||
* @default true
|
* @default true
|
||||||
*/
|
*/
|
||||||
fixedTop?: boolean;
|
fixedTop?: boolean;
|
||||||
/**
|
/**
|
||||||
* the max z-index of the layout
|
* The max z-index of the layout
|
||||||
* @description the z-index of Header,Tab,Sider and Footer will not exceed this value
|
*
|
||||||
|
* The z-index of Header,Tab,Sider and Footer will not exceed this value
|
||||||
*/
|
*/
|
||||||
maxZIndex?: number;
|
maxZIndex?: number;
|
||||||
}
|
}
|
||||||
@ -222,48 +238,44 @@ export type LayoutCssVars = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the mode of the tab
|
* The mode of the tab
|
||||||
* - button: button style
|
*
|
||||||
* - chrome: chrome style
|
* - Button: button style
|
||||||
|
* - Chrome: chrome style
|
||||||
|
*
|
||||||
* @default chrome
|
* @default chrome
|
||||||
*/
|
*/
|
||||||
export type PageTabMode = 'button' | 'chrome';
|
export type PageTabMode = 'button' | 'chrome';
|
||||||
|
|
||||||
export interface PageTabProps {
|
export interface PageTabProps {
|
||||||
/**
|
/** Whether is dark mode */
|
||||||
* whether is dark mode
|
|
||||||
*/
|
|
||||||
darkMode?: boolean;
|
darkMode?: boolean;
|
||||||
/**
|
/**
|
||||||
* the mode of the tab
|
* The mode of the tab
|
||||||
|
*
|
||||||
* - {@link TabMode}
|
* - {@link TabMode}
|
||||||
*/
|
*/
|
||||||
mode?: PageTabMode;
|
mode?: PageTabMode;
|
||||||
/**
|
/**
|
||||||
* the common class of the layout
|
* The common class of the layout
|
||||||
* @description is can be used to configure the transition animation
|
*
|
||||||
|
* Is can be used to configure the transition animation
|
||||||
|
*
|
||||||
* @default 'transition-all-300'
|
* @default 'transition-all-300'
|
||||||
*/
|
*/
|
||||||
commonClass?: string;
|
commonClass?: string;
|
||||||
/**
|
/** The class of the button tab */
|
||||||
* the class of the button tab
|
|
||||||
*/
|
|
||||||
buttonClass?: string;
|
buttonClass?: string;
|
||||||
/**
|
/** The class of the chrome tab */
|
||||||
* the class of the chrome tab
|
|
||||||
*/
|
|
||||||
chromeClass?: string;
|
chromeClass?: string;
|
||||||
/**
|
/** Whether the tab is active */
|
||||||
* whether the tab is active
|
|
||||||
*/
|
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
/**
|
/** The color of the active tab */
|
||||||
* the color of the active tab
|
|
||||||
*/
|
|
||||||
activeColor?: string;
|
activeColor?: string;
|
||||||
/**
|
/**
|
||||||
* whether the tab is closable
|
* Whether the tab is closable
|
||||||
* @description show the close icon when true
|
*
|
||||||
|
* Show the close icon when true
|
||||||
*/
|
*/
|
||||||
closable?: boolean;
|
closable?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"jsx": "preserve",
|
||||||
|
"lib": ["DOM", "ESNext"],
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"target": "ESNext",
|
|
||||||
"lib": ["DOM", "ESNext"],
|
|
||||||
"strict": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"allowSyntheticDefaultImports": true,
|
|
||||||
"jsx": "preserve",
|
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"noUnusedLocals": true,
|
"types": ["node"],
|
||||||
|
"strict": true,
|
||||||
"strictNullChecks": true,
|
"strictNullChecks": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"noUnusedLocals": true,
|
||||||
"types": ["node"]
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true
|
||||||
},
|
},
|
||||||
"include": ["src/**/*"],
|
"include": ["src/**/*"],
|
||||||
"exclude": ["node_modules", "dist"]
|
"exclude": ["node_modules", "dist"]
|
||||||
|
@ -6,9 +6,7 @@
|
|||||||
},
|
},
|
||||||
"typesVersions": {
|
"typesVersions": {
|
||||||
"*": {
|
"*": {
|
||||||
"*": [
|
"*": ["./src/*"]
|
||||||
"./src/*"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"jsx": "preserve",
|
||||||
|
"lib": ["DOM", "ESNext"],
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"target": "ESNext",
|
|
||||||
"lib": ["DOM", "ESNext"],
|
|
||||||
"strict": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"allowSyntheticDefaultImports": true,
|
|
||||||
"jsx": "preserve",
|
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"noUnusedLocals": true,
|
"types": ["node"],
|
||||||
|
"strict": true,
|
||||||
"strictNullChecks": true,
|
"strictNullChecks": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"noUnusedLocals": true,
|
||||||
"types": ["node"]
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true
|
||||||
},
|
},
|
||||||
"include": ["src/**/*"],
|
"include": ["src/**/*"],
|
||||||
"exclude": ["node_modules", "dist"]
|
"exclude": ["node_modules", "dist"]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
const path = require('path');
|
const path = require('node:path');
|
||||||
const jiti = require('jiti')(__filename);
|
const jiti = require('jiti')(__filename);
|
||||||
|
|
||||||
jiti(path.resolve(__dirname, './src/index.ts'));
|
jiti(path.resolve(__dirname, './src/index.ts'));
|
||||||
|
@ -1,19 +1,17 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/scripts",
|
"name": "@sa/scripts",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
"bin": {
|
||||||
|
"sa": "./bin.cjs"
|
||||||
|
},
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
"typesVersions": {
|
"typesVersions": {
|
||||||
"*": {
|
"*": {
|
||||||
"*": [
|
"*": ["./src/*"]
|
||||||
"./src/*"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bin": {
|
|
||||||
"sa": "./bin.cjs"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"c12": "1.5.1",
|
"c12": "1.5.1",
|
||||||
"cac": "6.7.14",
|
"cac": "6.7.14",
|
||||||
@ -21,8 +19,8 @@
|
|||||||
"enquirer": "2.4.1",
|
"enquirer": "2.4.1",
|
||||||
"execa": "8.0.1",
|
"execa": "8.0.1",
|
||||||
"jiti": "1.21.0",
|
"jiti": "1.21.0",
|
||||||
"lint-staged": "15.1.0",
|
"lint-staged": "15.2.0",
|
||||||
"npm-check-updates": "16.14.6",
|
"npm-check-updates": "16.14.12",
|
||||||
"rimraf": "5.0.5"
|
"rimraf": "5.0.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { readFileSync } from 'node:fs';
|
import { readFileSync } from 'node:fs';
|
||||||
import enquirer from 'enquirer';
|
import enquirer from 'enquirer';
|
||||||
import { bgRed, red, green } from 'kolorist';
|
import { bgRed, green, red } from 'kolorist';
|
||||||
import { execCommand } from '../shared';
|
import { execCommand } from '../shared';
|
||||||
import type { CliOption } from '../types';
|
import type { CliOption } from '../types';
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import process from 'node:process';
|
||||||
import { loadConfig } from 'c12';
|
import { loadConfig } from 'c12';
|
||||||
import type { CliOption } from '../types';
|
import type { CliOption } from '../types';
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import cac from 'cac';
|
import cac from 'cac';
|
||||||
import { blue, lightGreen } from 'kolorist';
|
import { blue, lightGreen } from 'kolorist';
|
||||||
import { version } from '../package.json';
|
import { version } from '../package.json';
|
||||||
import { cleanup, updatePkg, gitCommit, gitCommitVerify, prettierWrite, execLintStaged } from './commands';
|
import { cleanup, execLintStaged, gitCommit, gitCommitVerify, prettierWrite, updatePkg } from './commands';
|
||||||
import { loadCliOptions } from './config';
|
import { loadCliOptions } from './config';
|
||||||
|
|
||||||
type Command = 'cleanup' | 'update-pkg' | 'git-commit' | 'git-commit-verify' | 'prettier-write' | 'lint-staged';
|
type Command = 'cleanup' | 'update-pkg' | 'git-commit' | 'git-commit-verify' | 'prettier-write' | 'lint-staged';
|
||||||
|
@ -1,37 +1,33 @@
|
|||||||
export interface CliOption {
|
export interface CliOption {
|
||||||
/**
|
/** The project root directory */
|
||||||
* the project root directory
|
|
||||||
*/
|
|
||||||
cwd: string;
|
cwd: string;
|
||||||
/**
|
/**
|
||||||
* cleanup dirs
|
* Cleanup dirs
|
||||||
|
*
|
||||||
|
* Glob pattern syntax {@link https://github.com/isaacs/minimatch}
|
||||||
|
*
|
||||||
* @default
|
* @default
|
||||||
* ```json
|
* ```json
|
||||||
* ["** /dist", "** /pnpm-lock.yaml", "** /node_modules", "!node_modules/**"]
|
* ["** /dist", "** /pnpm-lock.yaml", "** /node_modules", "!node_modules/**"]
|
||||||
* ```
|
* ```
|
||||||
* @description glob pattern syntax {@link https://github.com/isaacs/minimatch}
|
|
||||||
*/
|
*/
|
||||||
cleanupDirs: string[];
|
cleanupDirs: string[];
|
||||||
/**
|
/** Git commit types */
|
||||||
* git commit types
|
|
||||||
*/
|
|
||||||
gitCommitTypes: [string, string][];
|
gitCommitTypes: [string, string][];
|
||||||
/**
|
/** Git commit scopes */
|
||||||
* git commit scopes
|
|
||||||
*/
|
|
||||||
gitCommitScopes: [string, string][];
|
gitCommitScopes: [string, string][];
|
||||||
/**
|
/**
|
||||||
* npm-check-updates command args
|
* Npm-check-updates command args
|
||||||
* @default ["--deep","-u"]
|
*
|
||||||
|
* @default ['--deep', '-u']
|
||||||
*/
|
*/
|
||||||
ncuCommandArgs: string[];
|
ncuCommandArgs: string[];
|
||||||
/**
|
/**
|
||||||
* prettier write glob
|
* Prettier write glob
|
||||||
* @description glob pattern syntax {@link https://github.com/micromatch/micromatch}
|
*
|
||||||
|
* Glob pattern syntax {@link https://github.com/micromatch/micromatch}
|
||||||
*/
|
*/
|
||||||
prettierWriteGlob: string[];
|
prettierWriteGlob: string[];
|
||||||
/**
|
/** Lint-staged config */
|
||||||
* lint-staged config
|
|
||||||
*/
|
|
||||||
lintStagedConfig: Record<string, string | string[]>;
|
lintStagedConfig: Record<string, string | string[]>;
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"jsx": "preserve",
|
||||||
|
"lib": ["DOM", "ESNext"],
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"target": "ESNext",
|
|
||||||
"lib": ["DOM", "ESNext"],
|
|
||||||
"strict": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"allowSyntheticDefaultImports": true,
|
|
||||||
"jsx": "preserve",
|
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"noUnusedLocals": true,
|
"types": ["node"],
|
||||||
|
"strict": true,
|
||||||
"strictNullChecks": true,
|
"strictNullChecks": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"noUnusedLocals": true,
|
||||||
"types": ["node"]
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true
|
||||||
},
|
},
|
||||||
"include": ["src/**/*", "typings/**/*"],
|
"include": ["src/**/*", "typings/**/*"],
|
||||||
"exclude": ["node_modules", "dist"]
|
"exclude": ["node_modules", "dist"]
|
||||||
|
@ -6,9 +6,7 @@
|
|||||||
},
|
},
|
||||||
"typesVersions": {
|
"typesVersions": {
|
||||||
"*": {
|
"*": {
|
||||||
"*": [
|
"*": ["./src/*"]
|
||||||
"./src/*"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"jsx": "preserve",
|
||||||
|
"lib": ["DOM", "ESNext"],
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"target": "ESNext",
|
|
||||||
"lib": ["DOM", "ESNext"],
|
|
||||||
"strict": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"allowSyntheticDefaultImports": true,
|
|
||||||
"jsx": "preserve",
|
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"noUnusedLocals": true,
|
"types": ["node"],
|
||||||
|
"strict": true,
|
||||||
"strictNullChecks": true,
|
"strictNullChecks": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"noUnusedLocals": true,
|
||||||
"types": ["node"]
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true
|
||||||
},
|
},
|
||||||
"include": ["src/**/*"],
|
"include": ["src/**/*"],
|
||||||
"exclude": ["node_modules", "dist"]
|
"exclude": ["node_modules", "dist"]
|
||||||
|
@ -6,9 +6,7 @@
|
|||||||
},
|
},
|
||||||
"typesVersions": {
|
"typesVersions": {
|
||||||
"*": {
|
"*": {
|
||||||
"*": [
|
"*": ["./src/*"]
|
||||||
"./src/*"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -6,29 +6,32 @@ import type { AnyColor, HsvColor, RgbColor } from 'colord';
|
|||||||
extend([namesPlugin, mixPlugin]);
|
extend([namesPlugin, mixPlugin]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add color alpha
|
* Add color alpha
|
||||||
* @param color - color
|
*
|
||||||
* @param alpha - alpha (0 - 1)
|
* @param color - Color
|
||||||
|
* @param alpha - Alpha (0 - 1)
|
||||||
*/
|
*/
|
||||||
export function addColorAlpha(color: string, alpha: number) {
|
export function addColorAlpha(color: string, alpha: number) {
|
||||||
return colord(color).alpha(alpha).toHex();
|
return colord(color).alpha(alpha).toHex();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mix color
|
* Mix color
|
||||||
* @param firstColor - first color
|
*
|
||||||
* @param secondColor - second color
|
* @param firstColor - First color
|
||||||
* @param ratio - the ratio of the second color (0 - 1)
|
* @param secondColor - Second color
|
||||||
|
* @param ratio - The ratio of the second color (0 - 1)
|
||||||
*/
|
*/
|
||||||
export function mixColor(firstColor: string, secondColor: string, ratio: number) {
|
export function mixColor(firstColor: string, secondColor: string, ratio: number) {
|
||||||
return colord(firstColor).mix(secondColor, ratio).toHex();
|
return colord(firstColor).mix(secondColor, ratio).toHex();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* transform color with opacity to similar color without opacity
|
* Transform color with opacity to similar color without opacity
|
||||||
* @param color - color
|
*
|
||||||
* @param alpha - alpha (0 - 1)
|
* @param color - Color
|
||||||
* @param bgColor background color (usually white or black)
|
* @param alpha - Alpha (0 - 1)
|
||||||
|
* @param bgColor Background color (usually white or black)
|
||||||
*/
|
*/
|
||||||
export function transformColorWithOpacity(color: string, alpha: number, bgColor = '#ffffff') {
|
export function transformColorWithOpacity(color: string, alpha: number, bgColor = '#ffffff') {
|
||||||
const originColor = addColorAlpha(color, alpha);
|
const originColor = addColorAlpha(color, alpha);
|
||||||
@ -50,67 +53,57 @@ export function transformColorWithOpacity(color: string, alpha: number, bgColor
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* is white color
|
* Is white color
|
||||||
* @param color - color
|
*
|
||||||
|
* @param color - Color
|
||||||
*/
|
*/
|
||||||
export function isWhiteColor(color: string) {
|
export function isWhiteColor(color: string) {
|
||||||
return colord(color).isEqual('#ffffff');
|
return colord(color).isEqual('#ffffff');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get rgb of color
|
* Get rgb of color
|
||||||
* @param color color
|
*
|
||||||
|
* @param color Color
|
||||||
*/
|
*/
|
||||||
export function getRgbOfColor(color: string) {
|
export function getRgbOfColor(color: string) {
|
||||||
return colord(color).toRgb();
|
return colord(color).toRgb();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Hue step */
|
||||||
* hue step
|
|
||||||
*/
|
|
||||||
const hueStep = 2;
|
const hueStep = 2;
|
||||||
/**
|
/** Saturation step, light color part */
|
||||||
* saturation step, light color part
|
|
||||||
*/
|
|
||||||
const saturationStep = 16;
|
const saturationStep = 16;
|
||||||
/**
|
/** Saturation step, dark color part */
|
||||||
* saturation step, dark color part
|
|
||||||
*/
|
|
||||||
const saturationStep2 = 5;
|
const saturationStep2 = 5;
|
||||||
/**
|
/** Brightness step, light color part */
|
||||||
* brightness step, light color part
|
|
||||||
*/
|
|
||||||
const brightnessStep1 = 5;
|
const brightnessStep1 = 5;
|
||||||
/**
|
/** Brightness step, dark color part */
|
||||||
* brightness step, dark color part
|
|
||||||
*/
|
|
||||||
const brightnessStep2 = 15;
|
const brightnessStep2 = 15;
|
||||||
/**
|
/** Light color count, main color up */
|
||||||
* light color count, main color up
|
|
||||||
*/
|
|
||||||
const lightColorCount = 5;
|
const lightColorCount = 5;
|
||||||
/**
|
/** Dark color count, main color down */
|
||||||
* dark color count, main color down
|
|
||||||
*/
|
|
||||||
const darkColorCount = 4;
|
const darkColorCount = 4;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the color index of color palette
|
* The color index of color palette
|
||||||
* @description from left to right, the color is from light to dark, 6 is main color
|
*
|
||||||
|
* From left to right, the color is from light to dark, 6 is main color
|
||||||
*/
|
*/
|
||||||
type ColorIndex = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
|
type ColorIndex = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get color palette (from left to right, the color is from light to dark, 6 is main color)
|
* Get color palette (from left to right, the color is from light to dark, 6 is main color)
|
||||||
* @param color - color
|
*
|
||||||
* @param index - the color index of color palette (the main color index is 6)
|
* @param color - Color
|
||||||
* @returns hex color
|
* @param index - The color index of color palette (the main color index is 6)
|
||||||
|
* @returns Hex color
|
||||||
*/
|
*/
|
||||||
export function getColorPalette(color: AnyColor, index: ColorIndex): string {
|
export function getColorPalette(color: AnyColor, index: ColorIndex): string {
|
||||||
const transformColor = colord(color);
|
const transformColor = colord(color);
|
||||||
|
|
||||||
if (!transformColor.isValid()) {
|
if (!transformColor.isValid()) {
|
||||||
throw Error('invalid input color value');
|
throw new Error('invalid input color value');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index === 6) {
|
if (index === 6) {
|
||||||
@ -130,9 +123,7 @@ export function getColorPalette(color: AnyColor, index: ColorIndex): string {
|
|||||||
return colord(newHsv).toHex();
|
return colord(newHsv).toHex();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Map of dark color index and opacity */
|
||||||
* map of dark color index and opacity
|
|
||||||
*/
|
|
||||||
const darkColorMap = [
|
const darkColorMap = [
|
||||||
{ index: 7, opacity: 0.15 },
|
{ index: 7, opacity: 0.15 },
|
||||||
{ index: 6, opacity: 0.25 },
|
{ index: 6, opacity: 0.25 },
|
||||||
@ -147,10 +138,11 @@ const darkColorMap = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get color palettes
|
* Get color palettes
|
||||||
* @param color - color
|
*
|
||||||
* @param darkTheme - dark theme
|
* @param color - Color
|
||||||
* @param darkThemeMixColor - dark theme mix color (default: #141414)
|
* @param darkTheme - Dark theme
|
||||||
|
* @param darkThemeMixColor - Dark theme mix color (default: #141414)
|
||||||
*/
|
*/
|
||||||
export function getColorPalettes(color: AnyColor, darkTheme = false, darkThemeMixColor = '#141414'): string[] {
|
export function getColorPalettes(color: AnyColor, darkTheme = false, darkThemeMixColor = '#141414'): string[] {
|
||||||
const indexes: ColorIndex[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
const indexes: ColorIndex[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||||
@ -171,10 +163,11 @@ export function getColorPalettes(color: AnyColor, darkTheme = false, darkThemeMi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get hue
|
* Get hue
|
||||||
* @param hsv - hsv format color
|
*
|
||||||
* @param i - the relative distance from 6
|
* @param hsv - Hsv format color
|
||||||
* @param isLight - is light color
|
* @param i - The relative distance from 6
|
||||||
|
* @param isLight - Is light color
|
||||||
*/
|
*/
|
||||||
function getHue(hsv: HsvColor, i: number, isLight: boolean) {
|
function getHue(hsv: HsvColor, i: number, isLight: boolean) {
|
||||||
let hue: number;
|
let hue: number;
|
||||||
@ -199,10 +192,11 @@ function getHue(hsv: HsvColor, i: number, isLight: boolean) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get saturation
|
* Get saturation
|
||||||
* @param hsv - hsv format color
|
*
|
||||||
* @param i - the relative distance from 6
|
* @param hsv - Hsv format color
|
||||||
* @param isLight - is light color
|
* @param i - The relative distance from 6
|
||||||
|
* @param isLight - Is light color
|
||||||
*/
|
*/
|
||||||
function getSaturation(hsv: HsvColor, i: number, isLight: boolean) {
|
function getSaturation(hsv: HsvColor, i: number, isLight: boolean) {
|
||||||
if (hsv.h === 0 && hsv.s === 0) {
|
if (hsv.h === 0 && hsv.s === 0) {
|
||||||
@ -235,10 +229,11 @@ function getSaturation(hsv: HsvColor, i: number, isLight: boolean) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get value of hsv
|
* Get value of hsv
|
||||||
* @param hsv - hsv format color
|
*
|
||||||
* @param i - the relative distance from 6
|
* @param hsv - Hsv format color
|
||||||
* @param isLight - is light color
|
* @param i - The relative distance from 6
|
||||||
|
* @param isLight - Is light color
|
||||||
*/
|
*/
|
||||||
function getValue(hsv: HsvColor, i: number, isLight: boolean) {
|
function getValue(hsv: HsvColor, i: number, isLight: boolean) {
|
||||||
let value: number;
|
let value: number;
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import CryptoJS from 'crypto-js';
|
import CryptoJS from 'crypto-js';
|
||||||
|
|
||||||
export class Crypto<T extends object> {
|
export class Crypto<T extends object> {
|
||||||
/**
|
/** Secret */
|
||||||
* secret
|
|
||||||
*/
|
|
||||||
secret: string;
|
secret: string;
|
||||||
|
|
||||||
constructor(secret: string) {
|
constructor(secret: string) {
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import localforage from 'localforage';
|
import localforage from 'localforage';
|
||||||
|
|
||||||
/**
|
/** The storage type */
|
||||||
* the storage type
|
|
||||||
*/
|
|
||||||
export type StorageType = 'local' | 'session';
|
export type StorageType = 'local' | 'session';
|
||||||
|
|
||||||
export function createStorage<T extends object>(type: StorageType) {
|
export function createStorage<T extends object>(type: StorageType) {
|
||||||
@ -10,9 +8,10 @@ export function createStorage<T extends object>(type: StorageType) {
|
|||||||
|
|
||||||
const storage = {
|
const storage = {
|
||||||
/**
|
/**
|
||||||
* set session
|
* Set session
|
||||||
* @param key session key
|
*
|
||||||
* @param value session value
|
* @param key Session key
|
||||||
|
* @param value Session value
|
||||||
*/
|
*/
|
||||||
set<K extends keyof T>(key: K, value: T[K]) {
|
set<K extends keyof T>(key: K, value: T[K]) {
|
||||||
const json = JSON.stringify(value);
|
const json = JSON.stringify(value);
|
||||||
@ -20,8 +19,9 @@ export function createStorage<T extends object>(type: StorageType) {
|
|||||||
stg.setItem(key as string, json);
|
stg.setItem(key as string, json);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* get session
|
* Get session
|
||||||
* @param key session key
|
*
|
||||||
|
* @param key Session key
|
||||||
*/
|
*/
|
||||||
get<K extends keyof T>(key: K): T[K] | null {
|
get<K extends keyof T>(key: K): T[K] | null {
|
||||||
const json = stg.getItem(key as string);
|
const json = stg.getItem(key as string);
|
||||||
|
2444
pnpm-lock.yaml
2444
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@ import { computed } from 'vue';
|
|||||||
import { NConfigProvider, darkTheme } from 'naive-ui';
|
import { NConfigProvider, darkTheme } from 'naive-ui';
|
||||||
import { useAppStore } from './store/modules/app';
|
import { useAppStore } from './store/modules/app';
|
||||||
import { useThemeStore } from './store/modules/theme';
|
import { useThemeStore } from './store/modules/theme';
|
||||||
import { naiveLocales, naiveDateLocales } from './locales/naive';
|
import { naiveDateLocales, naiveLocales } from './locales/naive';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'App'
|
name: 'App'
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineComponent, createTextVNode } from 'vue';
|
import { createTextVNode, defineComponent } from 'vue';
|
||||||
import { useDialog, useLoadingBar, useMessage, useNotification } from 'naive-ui';
|
import { useDialog, useLoadingBar, useMessage, useNotification } from 'naive-ui';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -17,9 +17,8 @@ const ContextHolder = defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
register();
|
register();
|
||||||
},
|
|
||||||
render() {
|
return () => createTextVNode();
|
||||||
return createTextVNode();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
defineOptions({ name: 'DarkModeContainer' });
|
defineOptions({ name: 'DarkModeContainer' });
|
||||||
|
|
||||||
|
defineProps<Props>();
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
inverted?: boolean;
|
inverted?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
defineProps<Props>();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -4,11 +4,14 @@ import { $t } from '@/locales';
|
|||||||
|
|
||||||
defineOptions({ name: 'ExceptionBase' });
|
defineOptions({ name: 'ExceptionBase' });
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
type ExceptionType = '403' | '404' | '500';
|
type ExceptionType = '403' | '404' | '500';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
/**
|
/**
|
||||||
* exception type
|
* Exception type
|
||||||
|
*
|
||||||
* - 403: no permission
|
* - 403: no permission
|
||||||
* - 404: not found
|
* - 404: not found
|
||||||
* - 500: service error
|
* - 500: service error
|
||||||
@ -16,8 +19,6 @@ interface Props {
|
|||||||
type: ExceptionType;
|
type: ExceptionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>();
|
|
||||||
|
|
||||||
const iconMap: Record<ExceptionType, string> = {
|
const iconMap: Record<ExceptionType, string> = {
|
||||||
'403': 'no-permission',
|
'403': 'no-permission',
|
||||||
'404': 'not-found',
|
'404': 'not-found',
|
||||||
|
@ -5,17 +5,17 @@ defineOptions({
|
|||||||
name: 'FullScreen'
|
name: 'FullScreen'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
defineProps<Props>();
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
full?: boolean;
|
full?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
defineProps<Props>();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ButtonIcon :key="String(full)" :tooltip-content="full ? $t('icon.fullscreenExit') : $t('icon.fullscreen')">
|
<ButtonIcon :key="String(full)" :tooltip-content="full ? $t('icon.fullscreenExit') : $t('icon.fullscreen')">
|
||||||
<icon-gridicons-fullscreen-exit v-if="full" />
|
<IconGridiconsFullscreenExit v-if="full" />
|
||||||
<icon-gridicons-fullscreen v-else />
|
<IconGridiconsFullscreen v-else />
|
||||||
</ButtonIcon>
|
</ButtonIcon>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -6,31 +6,25 @@ defineOptions({
|
|||||||
name: 'LangSwitch'
|
name: 'LangSwitch'
|
||||||
});
|
});
|
||||||
|
|
||||||
interface Props {
|
|
||||||
/**
|
|
||||||
* current language
|
|
||||||
*/
|
|
||||||
lang: App.I18n.LangType;
|
|
||||||
/**
|
|
||||||
* language options
|
|
||||||
*/
|
|
||||||
langOptions: App.I18n.LangOption[];
|
|
||||||
/**
|
|
||||||
* show tooltip
|
|
||||||
*/
|
|
||||||
showTooltip?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
showTooltip: true
|
showTooltip: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
/** Current language */
|
||||||
|
lang: App.I18n.LangType;
|
||||||
|
/** Language options */
|
||||||
|
langOptions: App.I18n.LangOption[];
|
||||||
|
/** Show tooltip */
|
||||||
|
showTooltip?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
type Emits = {
|
type Emits = {
|
||||||
(e: 'changeLang', lang: App.I18n.LangType): void;
|
(e: 'changeLang', lang: App.I18n.LangType): void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const emits = defineEmits<Emits>();
|
|
||||||
|
|
||||||
const tooltipContent = computed(() => {
|
const tooltipContent = computed(() => {
|
||||||
if (!props.showTooltip) return '';
|
if (!props.showTooltip) return '';
|
||||||
|
|
||||||
@ -38,7 +32,7 @@ const tooltipContent = computed(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function changeLang(lang: App.I18n.LangType) {
|
function changeLang(lang: App.I18n.LangType) {
|
||||||
emits('changeLang', lang);
|
emit('changeLang', lang);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -1,22 +1,18 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { $t } from '@/locales';
|
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
import { $t } from '@/locales';
|
||||||
|
|
||||||
defineOptions({ name: 'MenuToggler' });
|
defineOptions({ name: 'MenuToggler' });
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
/**
|
/** Show collapsed icon */
|
||||||
* show collapsed icon
|
|
||||||
*/
|
|
||||||
collapsed?: boolean;
|
collapsed?: boolean;
|
||||||
/**
|
/** Arrow style icon */
|
||||||
* arrow style icon
|
|
||||||
*/
|
|
||||||
arrowIcon?: boolean;
|
arrowIcon?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>();
|
|
||||||
|
|
||||||
type NumberBool = 0 | 1;
|
type NumberBool = 0 | 1;
|
||||||
|
|
||||||
const icon = computed(() => {
|
const icon = computed(() => {
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { $t } from '@/locales';
|
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
import { $t } from '@/locales';
|
||||||
|
|
||||||
defineOptions({ name: 'PinToggler' });
|
defineOptions({ name: 'PinToggler' });
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
pin?: boolean;
|
pin?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>();
|
|
||||||
|
|
||||||
const icon = computed(() => (props.pin ? 'mdi-pin-off' : 'mdi-pin'));
|
const icon = computed(() => (props.pin ? 'mdi-pin-off' : 'mdi-pin'));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -5,16 +5,16 @@ defineOptions({
|
|||||||
name: 'ReloadButton'
|
name: 'ReloadButton'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
defineProps<Props>();
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
defineProps<Props>();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ButtonIcon :tooltip-content="$t('icon.reload')">
|
<ButtonIcon :tooltip-content="$t('icon.reload')">
|
||||||
<icon-ant-design-reload-outlined :class="{ 'animate-spin animate-duration-750': loading }" />
|
<IconAntDesignReloadOutlined :class="{ 'animate-spin animate-duration-750': loading }" />
|
||||||
</ButtonIcon>
|
</ButtonIcon>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ defineOptions({ name: 'SystemLogo' });
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<icon-local-logo />
|
<IconLocalLogo />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@ -5,32 +5,26 @@ import { $t } from '@/locales';
|
|||||||
|
|
||||||
defineOptions({ name: 'ThemeSchemaSwitch' });
|
defineOptions({ name: 'ThemeSchemaSwitch' });
|
||||||
|
|
||||||
interface Props {
|
|
||||||
/**
|
|
||||||
* theme schema
|
|
||||||
*/
|
|
||||||
themeSchema: UnionKey.ThemeScheme;
|
|
||||||
/**
|
|
||||||
* show tooltip
|
|
||||||
*/
|
|
||||||
showTooltip?: boolean;
|
|
||||||
/**
|
|
||||||
* tooltip placement
|
|
||||||
*/
|
|
||||||
tooltipPlacement?: PopoverPlacement;
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
tooltipPlacement: 'bottom'
|
tooltipPlacement: 'bottom'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
/** Theme schema */
|
||||||
|
themeSchema: UnionKey.ThemeScheme;
|
||||||
|
/** Show tooltip */
|
||||||
|
showTooltip?: boolean;
|
||||||
|
/** Tooltip placement */
|
||||||
|
tooltipPlacement?: PopoverPlacement;
|
||||||
|
}
|
||||||
|
|
||||||
interface Emits {
|
interface Emits {
|
||||||
(e: 'switch'): void;
|
(e: 'switch'): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>();
|
|
||||||
|
|
||||||
function handleSwitch() {
|
function handleSwitch() {
|
||||||
emit('switch');
|
emit('switch');
|
||||||
}
|
}
|
||||||
|
@ -6,16 +6,17 @@ import type { Options } from '@better-scroll/core';
|
|||||||
|
|
||||||
defineOptions({ name: 'BetterScroll' });
|
defineOptions({ name: 'BetterScroll' });
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
/**
|
/**
|
||||||
* BetterScroll options
|
* BetterScroll options
|
||||||
|
*
|
||||||
* @link https://better-scroll.github.io/docs/zh-CN/guide/base-scroll-options.html
|
* @link https://better-scroll.github.io/docs/zh-CN/guide/base-scroll-options.html
|
||||||
*/
|
*/
|
||||||
options: Options;
|
options: Options;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>();
|
|
||||||
|
|
||||||
const bsWrap = ref<HTMLElement>();
|
const bsWrap = ref<HTMLElement>();
|
||||||
const bsContent = ref<HTMLElement>();
|
const bsContent = ref<HTMLElement>();
|
||||||
const { width: wrapWidth } = useElementSize(bsWrap);
|
const { width: wrapWidth } = useElementSize(bsWrap);
|
||||||
|
@ -8,25 +8,6 @@ defineOptions({
|
|||||||
inheritAttrs: false
|
inheritAttrs: false
|
||||||
});
|
});
|
||||||
|
|
||||||
interface Props {
|
|
||||||
/**
|
|
||||||
* button class
|
|
||||||
*/
|
|
||||||
class?: string;
|
|
||||||
/**
|
|
||||||
* iconify icon name
|
|
||||||
*/
|
|
||||||
icon?: string;
|
|
||||||
/**
|
|
||||||
* tooltip content
|
|
||||||
*/
|
|
||||||
tooltipContent?: string;
|
|
||||||
/**
|
|
||||||
* tooltip placement
|
|
||||||
*/
|
|
||||||
tooltipPlacement?: PopoverPlacement;
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
class: 'h-36px text-icon',
|
class: 'h-36px text-icon',
|
||||||
icon: '',
|
icon: '',
|
||||||
@ -34,6 +15,17 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
tooltipPlacement: 'bottom'
|
tooltipPlacement: 'bottom'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
/** Button class */
|
||||||
|
class?: string;
|
||||||
|
/** Iconify icon name */
|
||||||
|
icon?: string;
|
||||||
|
/** Tooltip content */
|
||||||
|
tooltipContent?: string;
|
||||||
|
/** Tooltip placement */
|
||||||
|
tooltipPlacement?: PopoverPlacement;
|
||||||
|
}
|
||||||
|
|
||||||
interface ButtonProps {
|
interface ButtonProps {
|
||||||
className: string;
|
className: string;
|
||||||
}
|
}
|
||||||
|
@ -4,24 +4,21 @@ import { Icon } from '@iconify/vue';
|
|||||||
|
|
||||||
defineOptions({ name: 'SvgIcon' });
|
defineOptions({ name: 'SvgIcon' });
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* props
|
* Props
|
||||||
* - support iconify and local svg icon
|
*
|
||||||
* - if icon and localIcon are passed at the same time, localIcon will be rendered first
|
* - Support iconify and local svg icon
|
||||||
|
* - If icon and localIcon are passed at the same time, localIcon will be rendered first
|
||||||
*/
|
*/
|
||||||
interface Props {
|
interface Props {
|
||||||
/**
|
/** Iconify icon name */
|
||||||
* iconify icon name
|
|
||||||
*/
|
|
||||||
icon?: string;
|
icon?: string;
|
||||||
/**
|
/** Local svg icon name */
|
||||||
* local svg icon name
|
|
||||||
*/
|
|
||||||
localIcon?: string;
|
localIcon?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>();
|
|
||||||
|
|
||||||
const attrs = useAttrs();
|
const attrs = useAttrs();
|
||||||
|
|
||||||
const bindAttrs = computed<{ class: string; style: string }>(() => ({
|
const bindAttrs = computed<{ class: string; style: string }>(() => ({
|
||||||
@ -39,9 +36,7 @@ const symbolId = computed(() => {
|
|||||||
return `#${prefix}-${icon}`;
|
return `#${prefix}-${icon}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/** If localIcon is passed, render localIcon first */
|
||||||
* if localIcon is passed, render localIcon first
|
|
||||||
*/
|
|
||||||
const renderLocalIcon = computed(() => props.localIcon || !props.icon);
|
const renderLocalIcon = computed(() => props.localIcon || !props.icon);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -3,9 +3,7 @@ import { computed } from 'vue';
|
|||||||
import { getColorPalette } from '@sa/utils';
|
import { getColorPalette } from '@sa/utils';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
/**
|
/** Theme color */
|
||||||
* theme color
|
|
||||||
*/
|
|
||||||
themeColor: string;
|
themeColor: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,34 +1,25 @@
|
|||||||
export const REG_USER_NAME = /^[\u4e00-\u9fa5a-zA-Z0-9_-]{4,16}$/;
|
export const REG_USER_NAME = /^[\u4E00-\u9FA5a-zA-Z0-9_-]{4,16}$/;
|
||||||
|
|
||||||
/**
|
/** Phone reg */
|
||||||
* phone reg
|
|
||||||
*/
|
|
||||||
export const REG_PHONE =
|
export const REG_PHONE =
|
||||||
/^[1](([3][0-9])|([4][01456789])|([5][012356789])|([6][2567])|([7][0-8])|([8][0-9])|([9][012356789]))[0-9]{8}$/;
|
/^[1](([3][0-9])|([4][01456789])|([5][012356789])|([6][2567])|([7][0-8])|([8][0-9])|([9][012356789]))[0-9]{8}$/;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* password reg
|
* Password reg
|
||||||
* @description 6-18 characters, including letters, numbers, and underscores
|
*
|
||||||
|
* 6-18 characters, including letters, numbers, and underscores
|
||||||
*/
|
*/
|
||||||
export const REG_PWD = /^\w{6,18}$/;
|
export const REG_PWD = /^\w{6,18}$/;
|
||||||
|
|
||||||
/**
|
/** Email reg */
|
||||||
* email reg
|
|
||||||
*/
|
|
||||||
export const REG_EMAIL = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
|
export const REG_EMAIL = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
|
||||||
|
|
||||||
/**
|
/** Six digit code reg */
|
||||||
* six digit code reg
|
|
||||||
*/
|
|
||||||
export const REG_CODE_SIX = /^\d{6}$/;
|
export const REG_CODE_SIX = /^\d{6}$/;
|
||||||
|
|
||||||
/**
|
/** Four digit code reg */
|
||||||
* four digit code reg
|
|
||||||
*/
|
|
||||||
export const REG_CODE_FOUR = /^\d{4}$/;
|
export const REG_CODE_FOUR = /^\d{4}$/;
|
||||||
|
|
||||||
/**
|
/** Url reg */
|
||||||
* url reg
|
|
||||||
*/
|
|
||||||
export const REG_URL =
|
export const REG_URL =
|
||||||
/(((^https?:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)$/;
|
/(((^https?:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)$/;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import type { FormInst } from 'naive-ui';
|
import type { FormInst } from 'naive-ui';
|
||||||
import { REG_USER_NAME, REG_PHONE, REG_PWD, REG_CODE_SIX, REG_EMAIL } from '@/constants/reg';
|
import { REG_CODE_SIX, REG_EMAIL, REG_PHONE, REG_PWD, REG_USER_NAME } from '@/constants/reg';
|
||||||
import { $t } from '@/locales';
|
import { $t } from '@/locales';
|
||||||
|
|
||||||
export function useFormRules() {
|
export function useFormRules() {
|
||||||
|
@ -4,9 +4,11 @@ import type { RouteKey } from '@elegant-router/types';
|
|||||||
import { router as globalRouter } from '@/router';
|
import { router as globalRouter } from '@/router';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* router push
|
* Router push
|
||||||
* @description jump to the specified route, it can replace function router.push
|
*
|
||||||
* @param inSetup whether is in vue script setup
|
* Jump to the specified route, it can replace function router.push
|
||||||
|
*
|
||||||
|
* @param inSetup Whether is in vue script setup
|
||||||
*/
|
*/
|
||||||
export function useRouterPush(inSetup = true) {
|
export function useRouterPush(inSetup = true) {
|
||||||
const router = inSetup ? useRouter() : globalRouter;
|
const router = inSetup ? useRouter() : globalRouter;
|
||||||
@ -44,9 +46,10 @@ export function useRouterPush(inSetup = true) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* navigate to login page
|
* Navigate to login page
|
||||||
* @param loginModule the login module
|
*
|
||||||
* @param redirectUrl the redirect url, if not specified, it will be the current route fullPath
|
* @param loginModule The login module
|
||||||
|
* @param redirectUrl The redirect url, if not specified, it will be the current route fullPath
|
||||||
*/
|
*/
|
||||||
async function toLogin(loginModule?: UnionKey.LoginModule, redirectUrl?: string) {
|
async function toLogin(loginModule?: UnionKey.LoginModule, redirectUrl?: string) {
|
||||||
const module = loginModule || 'pwd-login';
|
const module = loginModule || 'pwd-login';
|
||||||
@ -67,7 +70,8 @@ export function useRouterPush(inSetup = true) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* toggle login module
|
* Toggle login module
|
||||||
|
*
|
||||||
* @param module
|
* @param module
|
||||||
*/
|
*/
|
||||||
async function toggleLoginModule(module: UnionKey.LoginModule) {
|
async function toggleLoginModule(module: UnionKey.LoginModule) {
|
||||||
@ -76,9 +80,7 @@ export function useRouterPush(inSetup = true) {
|
|||||||
return routerPushByKey('login', { query, params: { module } });
|
return routerPushByKey('login', { query, params: { module } });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Redirect from login */
|
||||||
* redirect from login
|
|
||||||
*/
|
|
||||||
async function redirectFromLogin() {
|
async function redirectFromLogin() {
|
||||||
const redirect = route.value.query?.redirect as string;
|
const redirect = route.value.query?.redirect as string;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ref, computed, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useContext } from '@sa/hooks';
|
import { useContext } from '@sa/hooks';
|
||||||
import { useRouteStore } from '@/store/modules/route';
|
import { useRouteStore } from '@/store/modules/route';
|
||||||
|
@ -7,17 +7,15 @@ defineOptions({
|
|||||||
name: 'GlobalContent'
|
name: 'GlobalContent'
|
||||||
});
|
});
|
||||||
|
|
||||||
interface Props {
|
|
||||||
/**
|
|
||||||
* show padding for content
|
|
||||||
*/
|
|
||||||
showPadding?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
withDefaults(defineProps<Props>(), {
|
withDefaults(defineProps<Props>(), {
|
||||||
showPadding: true
|
showPadding: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
/** Show padding for content */
|
||||||
|
showPadding?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const themeStore = useThemeStore();
|
const themeStore = useThemeStore();
|
||||||
const routeStore = useRouteStore();
|
const routeStore = useRouteStore();
|
||||||
|
@ -7,37 +7,29 @@ import { useRouteStore } from '@/store/modules/route';
|
|||||||
import HorizontalMenu from '../global-menu/base-menu.vue';
|
import HorizontalMenu from '../global-menu/base-menu.vue';
|
||||||
import GlobalLogo from '../global-logo/index.vue';
|
import GlobalLogo from '../global-logo/index.vue';
|
||||||
import GlobalBreadcrumb from '../global-breadcrumb/index.vue';
|
import GlobalBreadcrumb from '../global-breadcrumb/index.vue';
|
||||||
|
import { useMixMenuContext } from '../../hooks/use-mix-menu';
|
||||||
import ThemeButton from './components/theme-button.vue';
|
import ThemeButton from './components/theme-button.vue';
|
||||||
import UserAvatar from './components/user-avatar.vue';
|
import UserAvatar from './components/user-avatar.vue';
|
||||||
import { useMixMenuContext } from '../../hooks/use-mix-menu';
|
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'GlobalHeader'
|
||||||
|
});
|
||||||
|
defineProps<Props>();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const themeStore = useThemeStore();
|
const themeStore = useThemeStore();
|
||||||
const routeStore = useRouteStore();
|
const routeStore = useRouteStore();
|
||||||
const { isFullscreen, toggle } = useFullscreen();
|
const { isFullscreen, toggle } = useFullscreen();
|
||||||
const { menus } = useMixMenuContext();
|
const { menus } = useMixMenuContext();
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: 'GlobalHeader'
|
|
||||||
});
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
/**
|
/** Whether to show the logo */
|
||||||
* whether to show the logo
|
|
||||||
*/
|
|
||||||
showLogo?: App.Global.HeaderProps['showLogo'];
|
showLogo?: App.Global.HeaderProps['showLogo'];
|
||||||
/**
|
/** Whether to show the menu toggler */
|
||||||
* whether to show the menu toggler
|
|
||||||
*/
|
|
||||||
showMenuToggler?: App.Global.HeaderProps['showMenuToggler'];
|
showMenuToggler?: App.Global.HeaderProps['showMenuToggler'];
|
||||||
/**
|
/** Whether to show the menu */
|
||||||
* whether to show the menu
|
|
||||||
*/
|
|
||||||
showMenu?: App.Global.HeaderProps['showMenu'];
|
showMenu?: App.Global.HeaderProps['showMenu'];
|
||||||
}
|
}
|
||||||
|
|
||||||
defineProps<Props>();
|
|
||||||
|
|
||||||
const headerMenus = computed(() => {
|
const headerMenus = computed(() => {
|
||||||
if (themeStore.layout.mode === 'horizontal') {
|
if (themeStore.layout.mode === 'horizontal') {
|
||||||
return routeStore.menus;
|
return routeStore.menus;
|
||||||
|
@ -5,16 +5,14 @@ defineOptions({
|
|||||||
name: 'GlobalLogo'
|
name: 'GlobalLogo'
|
||||||
});
|
});
|
||||||
|
|
||||||
interface Props {
|
|
||||||
/**
|
|
||||||
* whether to show the title
|
|
||||||
*/
|
|
||||||
showTitle?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
withDefaults(defineProps<Props>(), {
|
withDefaults(defineProps<Props>(), {
|
||||||
showTitle: true
|
showTitle: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
/** Whether to show the title */
|
||||||
|
showTitle?: boolean;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import type { MenuProps, MentionOption } from 'naive-ui';
|
import type { MentionOption, MenuProps } from 'naive-ui';
|
||||||
import { SimpleScrollbar } from '@sa/materials';
|
import { SimpleScrollbar } from '@sa/materials';
|
||||||
import type { RouteKey } from '@elegant-router/types';
|
import type { RouteKey } from '@elegant-router/types';
|
||||||
import { useAppStore } from '@/store/modules/app';
|
import { useAppStore } from '@/store/modules/app';
|
||||||
@ -13,16 +13,16 @@ defineOptions({
|
|||||||
name: 'BaseMenu'
|
name: 'BaseMenu'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
mode: 'vertical'
|
||||||
|
});
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
darkTheme?: boolean;
|
darkTheme?: boolean;
|
||||||
mode?: MenuProps['mode'];
|
mode?: MenuProps['mode'];
|
||||||
menus: App.Global.Menu[];
|
menus: App.Global.Menu[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
|
||||||
mode: 'vertical'
|
|
||||||
});
|
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const themeStore = useThemeStore();
|
const themeStore = useThemeStore();
|
||||||
|
@ -11,39 +11,31 @@ defineOptions({
|
|||||||
name: 'FirstLevelMenu'
|
name: 'FirstLevelMenu'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
defineProps<Props>();
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
activeMenuKey?: string;
|
activeMenuKey?: string;
|
||||||
inverted?: boolean;
|
inverted?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
defineProps<Props>();
|
|
||||||
|
|
||||||
interface Emits {
|
interface Emits {
|
||||||
(e: 'select', menu: App.Global.Menu): boolean;
|
(e: 'select', menu: App.Global.Menu): boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>();
|
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const themeStore = useThemeStore();
|
const themeStore = useThemeStore();
|
||||||
const routeStore = useRouteStore();
|
const routeStore = useRouteStore();
|
||||||
|
|
||||||
interface MixMenuItemProps {
|
interface MixMenuItemProps {
|
||||||
/**
|
/** Menu item label */
|
||||||
* menu item label
|
|
||||||
*/
|
|
||||||
label: App.Global.Menu['label'];
|
label: App.Global.Menu['label'];
|
||||||
/**
|
/** Menu item icon */
|
||||||
* menu item icon
|
|
||||||
*/
|
|
||||||
icon: App.Global.Menu['icon'];
|
icon: App.Global.Menu['icon'];
|
||||||
/**
|
/** Active menu item */
|
||||||
* active menu item
|
|
||||||
*/
|
|
||||||
active: boolean;
|
active: boolean;
|
||||||
/**
|
/** Mini size */
|
||||||
* mini size
|
|
||||||
*/
|
|
||||||
isMini: boolean;
|
isMini: boolean;
|
||||||
}
|
}
|
||||||
const [DefineMixMenuItem, MixMenuItem] = createReusableTemplate<MixMenuItemProps>();
|
const [DefineMixMenuItem, MixMenuItem] = createReusableTemplate<MixMenuItemProps>();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import FirstLevelMenu from './first-level-menu.vue';
|
|
||||||
import { useMixMenuContext } from '../../hooks/use-mix-menu';
|
|
||||||
import { useRouterPush } from '@/hooks/common/router';
|
import { useRouterPush } from '@/hooks/common/router';
|
||||||
|
import { useMixMenuContext } from '../../hooks/use-mix-menu';
|
||||||
|
import FirstLevelMenu from './first-level-menu.vue';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'HorizontalMixMenu'
|
name: 'HorizontalMixMenu'
|
||||||
|
@ -5,9 +5,9 @@ import { useAppStore } from '@/store/modules/app';
|
|||||||
import { useRouteStore } from '@/store/modules/route';
|
import { useRouteStore } from '@/store/modules/route';
|
||||||
import { useThemeStore } from '@/store/modules/theme';
|
import { useThemeStore } from '@/store/modules/theme';
|
||||||
import { useRouterPush } from '@/hooks/common/router';
|
import { useRouterPush } from '@/hooks/common/router';
|
||||||
|
import { useMixMenu } from '../../hooks/use-mix-menu';
|
||||||
import FirstLevelMenu from './first-level-menu.vue';
|
import FirstLevelMenu from './first-level-menu.vue';
|
||||||
import BaseMenu from './base-menu.vue';
|
import BaseMenu from './base-menu.vue';
|
||||||
import { useMixMenu } from '../../hooks/use-mix-menu';
|
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'VerticalMixMenu'
|
name: 'VerticalMixMenu'
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import type { VNode } from 'vue';
|
import type { VNode } from 'vue';
|
||||||
import { $t } from '@/locales';
|
|
||||||
import { useSvgIconRender } from '@sa/hooks';
|
import { useSvgIconRender } from '@sa/hooks';
|
||||||
|
import { $t } from '@/locales';
|
||||||
import { useTabStore } from '@/store/modules/tab';
|
import { useTabStore } from '@/store/modules/tab';
|
||||||
import SvgIcon from '@/components/custom/svg-icon.vue';
|
import SvgIcon from '@/components/custom/svg-icon.vue';
|
||||||
|
|
||||||
@ -10,25 +10,21 @@ defineOptions({
|
|||||||
name: 'ContextMenu'
|
name: 'ContextMenu'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
excludeKeys: () => [],
|
||||||
|
disabledKeys: () => []
|
||||||
|
});
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
/**
|
/** ClientX */
|
||||||
* clientX
|
|
||||||
*/
|
|
||||||
x: number;
|
x: number;
|
||||||
/**
|
/** ClientY */
|
||||||
* clientY
|
|
||||||
*/
|
|
||||||
y: number;
|
y: number;
|
||||||
tabId: string;
|
tabId: string;
|
||||||
excludeKeys?: App.Global.DropdownKey[];
|
excludeKeys?: App.Global.DropdownKey[];
|
||||||
disabledKeys?: App.Global.DropdownKey[];
|
disabledKeys?: App.Global.DropdownKey[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
|
||||||
excludeKeys: () => [],
|
|
||||||
disabledKeys: () => []
|
|
||||||
});
|
|
||||||
|
|
||||||
const visible = defineModel<boolean>('visible');
|
const visible = defineModel<boolean>('visible');
|
||||||
|
|
||||||
const { removeTab, clearTabs, clearLeftTabs, clearRightTabs } = useTabStore();
|
const { removeTab, clearTabs, clearLeftTabs, clearRightTabs } = useTabStore();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive, watch, nextTick } from 'vue';
|
import { nextTick, reactive, ref, watch } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useElementBounding } from '@vueuse/core';
|
import { useElementBounding } from '@vueuse/core';
|
||||||
import { PageTab } from '@sa/materials';
|
import { PageTab } from '@sa/materials';
|
||||||
|
@ -7,28 +7,22 @@ defineOptions({
|
|||||||
name: 'LayoutModeCard'
|
name: 'LayoutModeCard'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
/**
|
/** Layout mode */
|
||||||
* layout mode
|
|
||||||
*/
|
|
||||||
mode: UnionKey.ThemeLayoutMode;
|
mode: UnionKey.ThemeLayoutMode;
|
||||||
/**
|
/** Disabled */
|
||||||
* disabled
|
|
||||||
*/
|
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>();
|
|
||||||
|
|
||||||
interface Emits {
|
interface Emits {
|
||||||
/**
|
/** Layout mode change */
|
||||||
* layout mode change
|
|
||||||
*/
|
|
||||||
(e: 'update:mode', mode: UnionKey.ThemeLayoutMode): void;
|
(e: 'update:mode', mode: UnionKey.ThemeLayoutMode): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<Emits>();
|
|
||||||
|
|
||||||
type LayoutConfig = Record<
|
type LayoutConfig = Record<
|
||||||
UnionKey.ThemeLayoutMode,
|
UnionKey.ThemeLayoutMode,
|
||||||
{
|
{
|
||||||
|
@ -3,14 +3,12 @@ defineOptions({
|
|||||||
name: 'SettingItem'
|
name: 'SettingItem'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
defineProps<Props>();
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
/**
|
/** Label */
|
||||||
* label
|
|
||||||
*/
|
|
||||||
label: string;
|
label: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
defineProps<Props>();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import Clipboard from 'clipboard';
|
import Clipboard from 'clipboard';
|
||||||
import { $t } from '@/locales';
|
import { $t } from '@/locales';
|
||||||
import { useThemeStore } from '@/store/modules/theme';
|
import { useThemeStore } from '@/store/modules/theme';
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { $t } from '@/locales';
|
import { $t } from '@/locales';
|
||||||
import { useThemeStore } from '@/store/modules/theme';
|
import { useThemeStore } from '@/store/modules/theme';
|
||||||
import { themeScrollModeOptions, themePageAnimationModeOptions, themeTabModeOptions } from '@/constants/app';
|
import { themePageAnimationModeOptions, themeScrollModeOptions, themeTabModeOptions } from '@/constants/app';
|
||||||
import SettingItem from '../components/setting-item.vue';
|
import SettingItem from '../components/setting-item.vue';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
|
@ -4,7 +4,8 @@ import 'dayjs/locale/en';
|
|||||||
import { localStg } from '@/utils/storage';
|
import { localStg } from '@/utils/storage';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set dayjs locale
|
* Set dayjs locale
|
||||||
|
*
|
||||||
* @param lang
|
* @param lang
|
||||||
*/
|
*/
|
||||||
export function setDayjsLocale(lang: App.I18n.LangType = 'zh-CN') {
|
export function setDayjsLocale(lang: App.I18n.LangType = 'zh-CN') {
|
||||||
|
@ -11,7 +11,8 @@ const i18n = createI18n({
|
|||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* setup plugin i18n
|
* Setup plugin i18n
|
||||||
|
*
|
||||||
* @param app
|
* @param app
|
||||||
*/
|
*/
|
||||||
export function setupI18n(app: App) {
|
export function setupI18n(app: App) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { zhCN, enUS, dateZhCN, dateEnUS } from 'naive-ui';
|
import { dateEnUS, dateZhCN, enUS, zhCN } from 'naive-ui';
|
||||||
import type { NLocale, NDateLocale } from 'naive-ui';
|
import type { NDateLocale, NLocale } from 'naive-ui';
|
||||||
|
|
||||||
export const naiveLocales: Record<App.I18n.LangType, NLocale> = {
|
export const naiveLocales: Record<App.I18n.LangType, NLocale> = {
|
||||||
'zh-CN': zhCN,
|
'zh-CN': zhCN,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { createApp } from 'vue';
|
import { createApp } from 'vue';
|
||||||
import './plugins/assets';
|
import './plugins/assets';
|
||||||
import { setupNProgress, setupIconifyOffline, setupDayjs } from './plugins';
|
import { setupDayjs, setupIconifyOffline, setupNProgress } from './plugins';
|
||||||
import { setupStore } from './store';
|
import { setupStore } from './store';
|
||||||
import { setupRouter } from './router';
|
import { setupRouter } from './router';
|
||||||
import { setupI18n } from './locales';
|
import { setupI18n } from './locales';
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import { addAPIProvider, disableCache } from '@iconify/vue';
|
import { addAPIProvider, disableCache } from '@iconify/vue';
|
||||||
|
|
||||||
/**
|
/** Setup the iconify offline */
|
||||||
* setup the iconify offline
|
|
||||||
*/
|
|
||||||
export function setupIconifyOffline() {
|
export function setupIconifyOffline() {
|
||||||
const { VITE_ICONIFY_URL } = import.meta.env;
|
const { VITE_ICONIFY_URL } = import.meta.env;
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import NProgress from 'nprogress';
|
import NProgress from 'nprogress';
|
||||||
|
|
||||||
/**
|
/** Setup plugin NProgress */
|
||||||
* setup plugin NProgress
|
|
||||||
*/
|
|
||||||
export function setupNProgress() {
|
export function setupNProgress() {
|
||||||
NProgress.configure({ easing: 'ease', speed: 500 });
|
NProgress.configure({ easing: 'ease', speed: 500 });
|
||||||
|
|
||||||
|
@ -4,8 +4,9 @@ import { createDocumentTitleGuard } from './title';
|
|||||||
import { createPermissionGuard } from './permission';
|
import { createPermissionGuard } from './permission';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* router guard
|
* Router guard
|
||||||
* @param router - router instance
|
*
|
||||||
|
* @param router - Router instance
|
||||||
*/
|
*/
|
||||||
export function createRouterGuard(router: Router) {
|
export function createRouterGuard(router: Router) {
|
||||||
createProgressGuard(router);
|
createProgressGuard(router);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { Router, NavigationGuardNext, RouteLocationNormalized } from 'vue-router';
|
import type { NavigationGuardNext, RouteLocationNormalized, Router } from 'vue-router';
|
||||||
import type { RouteKey, RoutePath } from '@elegant-router/types';
|
import type { RouteKey, RoutePath } from '@elegant-router/types';
|
||||||
import { useAuthStore } from '@/store/modules/auth';
|
import { useAuthStore } from '@/store/modules/auth';
|
||||||
import { useRouteStore } from '@/store/modules/route';
|
import { useRouteStore } from '@/store/modules/route';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { $t } from '@/locales';
|
|
||||||
import { useTitle } from '@vueuse/core';
|
import { useTitle } from '@vueuse/core';
|
||||||
import type { Router } from 'vue-router';
|
import type { Router } from 'vue-router';
|
||||||
|
import { $t } from '@/locales';
|
||||||
|
|
||||||
export function createDocumentTitleGuard(router: Router) {
|
export function createDocumentTitleGuard(router: Router) {
|
||||||
router.afterEach(to => {
|
router.afterEach(to => {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import type { App } from 'vue';
|
import type { App } from 'vue';
|
||||||
import {
|
import {
|
||||||
createRouter,
|
type RouterHistory,
|
||||||
createWebHistory,
|
|
||||||
createWebHashHistory,
|
|
||||||
createMemoryHistory,
|
createMemoryHistory,
|
||||||
type RouterHistory
|
createRouter,
|
||||||
|
createWebHashHistory,
|
||||||
|
createWebHistory
|
||||||
} from 'vue-router';
|
} from 'vue-router';
|
||||||
import { createRoutes } from './routes';
|
import { createRoutes } from './routes';
|
||||||
import { createRouterGuard } from './guard';
|
import { createRouterGuard } from './guard';
|
||||||
@ -24,9 +24,7 @@ export const router = createRouter({
|
|||||||
routes: constantVueRoutes
|
routes: constantVueRoutes
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/** Setup Vue Router */
|
||||||
* setup Vue Router
|
|
||||||
*/
|
|
||||||
export async function setupRouter(app: App) {
|
export async function setupRouter(app: App) {
|
||||||
app.use(router);
|
app.use(router);
|
||||||
createRouterGuard(router);
|
createRouterGuard(router);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { ElegantConstRoute, ElegantRoute, CustomRoute } from '@elegant-router/types';
|
import type { CustomRoute, ElegantConstRoute, ElegantRoute } from '@elegant-router/types';
|
||||||
import { generatedRoutes } from '../elegant/routes';
|
import { generatedRoutes } from '../elegant/routes';
|
||||||
import { layouts, views } from '../elegant/imports';
|
import { layouts, views } from '../elegant/imports';
|
||||||
import { transformElegantRoutesToVueRoutes } from '../elegant/transform';
|
import { transformElegantRoutesToVueRoutes } from '../elegant/transform';
|
||||||
@ -26,9 +26,7 @@ const customRoutes: CustomRoute[] = [
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/** Create routes */
|
||||||
* create routes
|
|
||||||
*/
|
|
||||||
export function createRoutes() {
|
export function createRoutes() {
|
||||||
const constantRoutes: ElegantRoute[] = [];
|
const constantRoutes: ElegantRoute[] = [];
|
||||||
|
|
||||||
@ -51,8 +49,9 @@ export function createRoutes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get auth vue routes
|
* Get auth vue routes
|
||||||
* @param routes elegant routes
|
*
|
||||||
|
* @param routes Elegant routes
|
||||||
*/
|
*/
|
||||||
export function getAuthVueRoutes(routes: ElegantConstRoute[]) {
|
export function getAuthVueRoutes(routes: ElegantConstRoute[]) {
|
||||||
return transformElegantRoutesToVueRoutes(routes, layouts, views);
|
return transformElegantRoutesToVueRoutes(routes, layouts, views);
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { request } from '../request';
|
import { request } from '../request';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* login
|
* Login
|
||||||
* @param userName user name
|
*
|
||||||
* @param password password
|
* @param userName User name
|
||||||
|
* @param password Password
|
||||||
*/
|
*/
|
||||||
export function fetchLogin(userName: string, password: string) {
|
export function fetchLogin(userName: string, password: string) {
|
||||||
return request<App.Service.Response<Api.Auth.LoginToken>>('/auth/login', {
|
return request<App.Service.Response<Api.Auth.LoginToken>>('/auth/login', {
|
||||||
@ -15,16 +16,15 @@ export function fetchLogin(userName: string, password: string) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Get user info */
|
||||||
* get user info
|
|
||||||
*/
|
|
||||||
export function fetchGetUserInfo() {
|
export function fetchGetUserInfo() {
|
||||||
return request<App.Service.Response<Api.Auth.UserInfo>>('/auth/getUserInfo');
|
return request<App.Service.Response<Api.Auth.UserInfo>>('/auth/getUserInfo');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* refresh token
|
* Refresh token
|
||||||
* @param refreshToken refresh token
|
*
|
||||||
|
* @param refreshToken Refresh token
|
||||||
*/
|
*/
|
||||||
export function fetchRefreshToken(refreshToken: string) {
|
export function fetchRefreshToken(refreshToken: string) {
|
||||||
return request<App.Service.Response<Api.Auth.LoginToken>>('/auth/refreshToken', {
|
return request<App.Service.Response<Api.Auth.LoginToken>>('/auth/refreshToken', {
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
import { request } from '../request';
|
import { request } from '../request';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get user routes
|
* Get user routes
|
||||||
* @param example whether to use example data, default: 0
|
*
|
||||||
|
* @param example Whether to use example data, default: 0
|
||||||
*/
|
*/
|
||||||
export function fetchGetUserRoutes(example: '0' | '1' = '0') {
|
export function fetchGetUserRoutes(example: '0' | '1' = '0') {
|
||||||
return request<App.Service.Response<Api.Route.UserRoute>>('/route/getUserRoutes', { params: { example } });
|
return request<App.Service.Response<Api.Route.UserRoute>>('/route/getUserRoutes', { params: { example } });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* whether the route is exist
|
* Whether the route is exist
|
||||||
* @param routeName route name
|
*
|
||||||
* @param example whether to use example data, default: 0
|
* @param routeName Route name
|
||||||
|
* @param example Whether to use example data, default: 0
|
||||||
*/
|
*/
|
||||||
export function fetchIsRouteExist(routeName: string, example: '0' | '1' = '0') {
|
export function fetchIsRouteExist(routeName: string, example: '0' | '1' = '0') {
|
||||||
return request<App.Service.Response<boolean>>('/route/isRouteExist', { params: { routeName, example } });
|
return request<App.Service.Response<boolean>>('/route/isRouteExist', { params: { routeName, example } });
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { localStg } from '@/utils/storage';
|
|
||||||
import { createOfetch as createRequest } from '@sa/request';
|
import { createOfetch as createRequest } from '@sa/request';
|
||||||
import { createServiceConfig, createProxyPattern } from '~/env.config';
|
import { localStg } from '@/utils/storage';
|
||||||
|
import { createProxyPattern, createServiceConfig } from '~/env.config';
|
||||||
|
|
||||||
const { baseURL, otherBaseURL } = createServiceConfig(import.meta.env);
|
const { baseURL, otherBaseURL } = createServiceConfig(import.meta.env);
|
||||||
|
|
||||||
|
@ -2,9 +2,7 @@ import type { App } from 'vue';
|
|||||||
import { createPinia } from 'pinia';
|
import { createPinia } from 'pinia';
|
||||||
import { resetSetupStore } from './plugins';
|
import { resetSetupStore } from './plugins';
|
||||||
|
|
||||||
/**
|
/** Setup Vue store plugin pinia */
|
||||||
* setup Vue store plugin pinia
|
|
||||||
*/
|
|
||||||
export function setupStore(app: App) {
|
export function setupStore(app: App) {
|
||||||
const store = createPinia();
|
const store = createPinia();
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ref, watch, effectScope, onScopeDispose } from 'vue';
|
import { effectScope, onScopeDispose, ref, watch } from 'vue';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { breakpointsTailwind, useBreakpoints, useTitle } from '@vueuse/core';
|
import { breakpointsTailwind, useBreakpoints, useTitle } from '@vueuse/core';
|
||||||
import { useBoolean } from '@sa/hooks';
|
import { useBoolean } from '@sa/hooks';
|
||||||
@ -24,14 +24,13 @@ export const useAppStore = defineStore(SetupStoreId.App, () => {
|
|||||||
const { bool: siderCollapse, setBool: setSiderCollapse, toggle: toggleSiderCollapse } = useBoolean();
|
const { bool: siderCollapse, setBool: setSiderCollapse, toggle: toggleSiderCollapse } = useBoolean();
|
||||||
const { bool: mixSiderFixed, setBool: setMixSiderFixed, toggle: toggleMixSiderFixed } = useBoolean();
|
const { bool: mixSiderFixed, setBool: setMixSiderFixed, toggle: toggleMixSiderFixed } = useBoolean();
|
||||||
|
|
||||||
/**
|
/** Is mobile layout */
|
||||||
* is mobile layout
|
|
||||||
*/
|
|
||||||
const isMobile = breakpoints.smaller('sm');
|
const isMobile = breakpoints.smaller('sm');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* reload page
|
* Reload page
|
||||||
* @param duration duration time
|
*
|
||||||
|
* @param duration Duration time
|
||||||
*/
|
*/
|
||||||
async function reloadPage(duration = 0) {
|
async function reloadPage(duration = 0) {
|
||||||
setReloadFlag(false);
|
setReloadFlag(false);
|
||||||
@ -64,9 +63,7 @@ export const useAppStore = defineStore(SetupStoreId.App, () => {
|
|||||||
localStg.set('lang', lang);
|
localStg.set('lang', lang);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Update document title by locale */
|
||||||
* update document title by locale
|
|
||||||
*/
|
|
||||||
function updateDocumentTitleByLocale() {
|
function updateDocumentTitleByLocale() {
|
||||||
const { i18nKey, title } = router.currentRoute.value.meta;
|
const { i18nKey, title } = router.currentRoute.value.meta;
|
||||||
|
|
||||||
@ -110,9 +107,7 @@ export const useAppStore = defineStore(SetupStoreId.App, () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/** On scope dispose */
|
||||||
* on scope dispose
|
|
||||||
*/
|
|
||||||
onScopeDispose(() => {
|
onScopeDispose(() => {
|
||||||
scope.stop();
|
scope.stop();
|
||||||
});
|
});
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { ref, reactive, computed } from 'vue';
|
import { computed, reactive, ref } from 'vue';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { useLoading } from '@sa/hooks';
|
import { useLoading } from '@sa/hooks';
|
||||||
import { SetupStoreId } from '@/enum';
|
import { SetupStoreId } from '@/enum';
|
||||||
import { useRouterPush } from '@/hooks/common/router';
|
import { useRouterPush } from '@/hooks/common/router';
|
||||||
import { fetchLogin, fetchGetUserInfo } from '@/service/api';
|
import { fetchGetUserInfo, fetchLogin } from '@/service/api';
|
||||||
import { localStg } from '@/utils/storage';
|
import { localStg } from '@/utils/storage';
|
||||||
import { useRouteStore } from '../route';
|
|
||||||
import { getToken, getUserInfo, clearAuthStorage } from './shared';
|
|
||||||
import { $t } from '@/locales';
|
import { $t } from '@/locales';
|
||||||
|
import { useRouteStore } from '../route';
|
||||||
|
import { clearAuthStorage, getToken, getUserInfo } from './shared';
|
||||||
|
|
||||||
export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
||||||
const routeStore = useRouteStore();
|
const routeStore = useRouteStore();
|
||||||
@ -18,14 +18,10 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
|||||||
|
|
||||||
const userInfo: Api.Auth.UserInfo = reactive(getUserInfo());
|
const userInfo: Api.Auth.UserInfo = reactive(getUserInfo());
|
||||||
|
|
||||||
/**
|
/** Is login */
|
||||||
* is login
|
|
||||||
*/
|
|
||||||
const isLogin = computed(() => Boolean(token.value));
|
const isLogin = computed(() => Boolean(token.value));
|
||||||
|
|
||||||
/**
|
/** Reset auth store */
|
||||||
* reset auth store
|
|
||||||
*/
|
|
||||||
async function resetStore() {
|
async function resetStore() {
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
|
|
||||||
@ -41,9 +37,10 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* login
|
* Login
|
||||||
* @param userName user name
|
*
|
||||||
* @param password password
|
* @param userName User name
|
||||||
|
* @param password Password
|
||||||
*/
|
*/
|
||||||
async function login(userName: string, password: string) {
|
async function login(userName: string, password: string) {
|
||||||
startLoading();
|
startLoading();
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user