feat: 合并1.0.7
This commit is contained in:
parent
d84ebef239
commit
2f714da4a2
2
.npmrc
2
.npmrc
@ -1,4 +1,4 @@
|
|||||||
registry=https://registry.npmmirror.com/
|
registry=https://registry.npmmirror.com/
|
||||||
shamefully-hoist=true
|
shamefully-hoist=true
|
||||||
ignore-workspace-root-check=true
|
ignore-workspace-root-check=true
|
||||||
engine-strict=true
|
link-workspace-packages=true
|
||||||
|
@ -9,7 +9,18 @@ export function setupElegantRouter() {
|
|||||||
blank: 'src/layouts/blank-layout/index.vue'
|
blank: 'src/layouts/blank-layout/index.vue'
|
||||||
},
|
},
|
||||||
customRoutes: {
|
customRoutes: {
|
||||||
names: ['exception_403', 'exception_404', 'exception_500']
|
names: [
|
||||||
|
'exception_403',
|
||||||
|
'exception_404',
|
||||||
|
'exception_500',
|
||||||
|
'document_project',
|
||||||
|
'document_project-link',
|
||||||
|
'document_vue',
|
||||||
|
'document_vite',
|
||||||
|
'document_unocss',
|
||||||
|
'document_naive',
|
||||||
|
'document_antd'
|
||||||
|
]
|
||||||
},
|
},
|
||||||
routePathTransformer(routeName, routePath) {
|
routePathTransformer(routeName, routePath) {
|
||||||
const key = routeName as RouteKey;
|
const key = routeName as RouteKey;
|
||||||
|
@ -7,7 +7,7 @@ export default defineConfig(
|
|||||||
'vue/multi-word-component-names': [
|
'vue/multi-word-component-names': [
|
||||||
'warn',
|
'warn',
|
||||||
{
|
{
|
||||||
ignores: ['index', 'App', '[id]']
|
ignores: ['index', 'App', '[id]', '[url]']
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'vue/component-name-in-template-casing': [
|
'vue/component-name-in-template-casing': [
|
||||||
|
19
package.json
19
package.json
@ -1,10 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "snail-job",
|
"name": "snail-job",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "1.0.5",
|
"version": "1.0.8",
|
||||||
"packageManager": "pnpm@9.0.5",
|
|
||||||
"description": "A flexible, reliable, and fast platform for distributed task retry and distributed task scheduling.",
|
"description": "A flexible, reliable, and fast platform for distributed task retry and distributed task scheduling.",
|
||||||
"license": "Apache",
|
"license": "Apache-2.0",
|
||||||
"homepage": "https://gitee.com/aizuda/snail-job",
|
"homepage": "https://gitee.com/aizuda/snail-job",
|
||||||
"repository": {
|
"repository": {
|
||||||
"url": "https://gitee.com/aizuda/snail-job.git"
|
"url": "https://gitee.com/aizuda/snail-job.git"
|
||||||
@ -25,8 +24,8 @@
|
|||||||
"UnoCSS"
|
"UnoCSS"
|
||||||
],
|
],
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 18.19.0",
|
"node": ">=18.12.0",
|
||||||
"pnpm": ">= 8.15.0"
|
"pnpm": ">=8.7.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vite build --mode prod",
|
"build": "vite build --mode prod",
|
||||||
@ -61,17 +60,17 @@
|
|||||||
"nprogress": "0.2.0",
|
"nprogress": "0.2.0",
|
||||||
"pinia": "2.1.7",
|
"pinia": "2.1.7",
|
||||||
"ts-md5": "1.3.1",
|
"ts-md5": "1.3.1",
|
||||||
"vue": "3.4.23",
|
"vue": "3.4.25",
|
||||||
"vue-draggable-plus": "0.4.0",
|
"vue-draggable-plus": "0.4.0",
|
||||||
"vue-i18n": "9.13.1",
|
"vue-i18n": "9.13.1",
|
||||||
"vue-router": "4.3.2"
|
"vue-router": "4.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@elegant-router/vue": "0.3.6",
|
"@elegant-router/vue": "0.3.6",
|
||||||
"@iconify/json": "2.2.203",
|
"@iconify/json": "2.2.204",
|
||||||
"@sa/scripts": "workspace:*",
|
"@sa/scripts": "workspace:*",
|
||||||
"@sa/uno-preset": "workspace:*",
|
"@sa/uno-preset": "workspace:*",
|
||||||
"@soybeanjs/eslint-config": "1.3.2",
|
"@soybeanjs/eslint-config": "1.3.3",
|
||||||
"@types/lodash-es": "4.17.12",
|
"@types/lodash-es": "4.17.12",
|
||||||
"@types/node": "20.12.7",
|
"@types/node": "20.12.7",
|
||||||
"@types/nprogress": "0.2.3",
|
"@types/nprogress": "0.2.3",
|
||||||
@ -88,14 +87,14 @@
|
|||||||
"lint-staged": "15.2.2",
|
"lint-staged": "15.2.2",
|
||||||
"sass": "1.75.0",
|
"sass": "1.75.0",
|
||||||
"simple-git-hooks": "2.11.1",
|
"simple-git-hooks": "2.11.1",
|
||||||
"tsx": "4.7.2",
|
"tsx": "4.7.3",
|
||||||
"typescript": "5.4.5",
|
"typescript": "5.4.5",
|
||||||
"unplugin-icons": "0.18.5",
|
"unplugin-icons": "0.18.5",
|
||||||
"unplugin-vue-components": "0.26.0",
|
"unplugin-vue-components": "0.26.0",
|
||||||
"vite": "5.2.10",
|
"vite": "5.2.10",
|
||||||
"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": "7.1.2",
|
"vite-plugin-vue-devtools": "7.1.3",
|
||||||
"vue-eslint-parser": "9.4.2",
|
"vue-eslint-parser": "9.4.2",
|
||||||
"vue-tsc": "2.0.14"
|
"vue-tsc": "2.0.14"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/axios",
|
"name": "@sa/axios",
|
||||||
"version": "1.0.5",
|
"version": "1.0.8",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/color-palette",
|
"name": "@sa/color-palette",
|
||||||
"version": "1.0.5",
|
"version": "1.0.8",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
20
packages/color-palette/tsconfig.json
Normal file
20
packages/color-palette/tsconfig.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"jsx": "preserve",
|
||||||
|
"lib": ["DOM", "ESNext"],
|
||||||
|
"baseUrl": ".",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"types": ["node"],
|
||||||
|
"strict": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true
|
||||||
|
},
|
||||||
|
"include": ["src/**/*"],
|
||||||
|
"exclude": ["node_modules", "dist"]
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/hooks",
|
"name": "@sa/hooks",
|
||||||
"version": "1.0.5",
|
"version": "1.0.8",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
@ -7,5 +7,5 @@ import useHookTable from './use-table';
|
|||||||
|
|
||||||
export { useBoolean, useLoading, useCountDown, useContext, useSvgIconRender, useHookTable };
|
export { useBoolean, useLoading, useCountDown, useContext, useSvgIconRender, useHookTable };
|
||||||
|
|
||||||
export * from './use-state';
|
export * from './use-signal';
|
||||||
export * from './use-table';
|
export * from './use-table';
|
||||||
|
144
packages/hooks/src/use-signal.ts
Normal file
144
packages/hooks/src/use-signal.ts
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
import { computed, ref, shallowRef, triggerRef } from 'vue';
|
||||||
|
import type {
|
||||||
|
ComputedGetter,
|
||||||
|
DebuggerOptions,
|
||||||
|
Ref,
|
||||||
|
ShallowRef,
|
||||||
|
WritableComputedOptions,
|
||||||
|
WritableComputedRef
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
|
type Updater<T> = (value: T) => T;
|
||||||
|
type Mutator<T> = (value: T) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signal is a reactive value that can be set, updated or mutated
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* const count = useSignal(0);
|
||||||
|
*
|
||||||
|
* // `watchEffect`
|
||||||
|
* watchEffect(() => {
|
||||||
|
* console.log(count());
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* // watch
|
||||||
|
* watch(count, value => {
|
||||||
|
* console.log(value);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* // useComputed
|
||||||
|
* const double = useComputed(() => count() * 2);
|
||||||
|
* const writeableDouble = useComputed({
|
||||||
|
* get: () => count() * 2,
|
||||||
|
* set: value => count.set(value / 2)
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export interface Signal<T> {
|
||||||
|
(): Readonly<T>;
|
||||||
|
/**
|
||||||
|
* Set the value of the signal
|
||||||
|
*
|
||||||
|
* It recommend use `set` for primitive values
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
set(value: T): void;
|
||||||
|
/**
|
||||||
|
* Update the value of the signal using an updater function
|
||||||
|
*
|
||||||
|
* It recommend use `update` for non-primitive values, only the first level of the object will be reactive.
|
||||||
|
*
|
||||||
|
* @param updater
|
||||||
|
*/
|
||||||
|
update(updater: Updater<T>): void;
|
||||||
|
/**
|
||||||
|
* Mutate the value of the signal using a mutator function
|
||||||
|
*
|
||||||
|
* this action will call `triggerRef`, so the value will be tracked on `watchEffect`.
|
||||||
|
*
|
||||||
|
* It recommend use `mutate` for non-primitive values, all levels of the object will be reactive.
|
||||||
|
*
|
||||||
|
* @param mutator
|
||||||
|
*/
|
||||||
|
mutate(mutator: Mutator<T>): void;
|
||||||
|
/**
|
||||||
|
* Get the reference of the signal
|
||||||
|
*
|
||||||
|
* Sometimes it can be useful to make `v-model` work with the signal
|
||||||
|
*
|
||||||
|
* ```vue
|
||||||
|
* <template>
|
||||||
|
* <input v-model="model.count" />
|
||||||
|
* </template>;
|
||||||
|
*
|
||||||
|
* <script setup lang="ts">
|
||||||
|
* const state = useSignal({ count: 0 }, { useRef: true });
|
||||||
|
*
|
||||||
|
* const model = state.getRef();
|
||||||
|
* </script>
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
getRef(): Readonly<ShallowRef<Readonly<T>>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ReadonlySignal<T> {
|
||||||
|
(): Readonly<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SignalOptions {
|
||||||
|
/**
|
||||||
|
* Whether to use `ref` to store the value
|
||||||
|
*
|
||||||
|
* @default false use `sharedRef` to store the value
|
||||||
|
*/
|
||||||
|
useRef?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useSignal<T>(initialValue: T, options?: SignalOptions): Signal<T> {
|
||||||
|
const { useRef } = options || {};
|
||||||
|
|
||||||
|
const state = useRef ? (ref(initialValue) as Ref<T>) : shallowRef(initialValue);
|
||||||
|
|
||||||
|
return createSignal(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useComputed<T>(getter: ComputedGetter<T>, debugOptions?: DebuggerOptions): ReadonlySignal<T>;
|
||||||
|
export function useComputed<T>(options: WritableComputedOptions<T>, debugOptions?: DebuggerOptions): Signal<T>;
|
||||||
|
export function useComputed<T>(
|
||||||
|
getterOrOptions: ComputedGetter<T> | WritableComputedOptions<T>,
|
||||||
|
debugOptions?: DebuggerOptions
|
||||||
|
) {
|
||||||
|
const isGetter = typeof getterOrOptions === 'function';
|
||||||
|
|
||||||
|
const computedValue = computed(getterOrOptions as any, debugOptions);
|
||||||
|
|
||||||
|
if (isGetter) {
|
||||||
|
return () => computedValue.value as ReadonlySignal<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return createSignal(computedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createSignal<T>(state: ShallowRef<T> | WritableComputedRef<T>): Signal<T> {
|
||||||
|
const signal = () => state.value;
|
||||||
|
|
||||||
|
signal.set = (value: T) => {
|
||||||
|
state.value = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
signal.update = (updater: Updater<T>) => {
|
||||||
|
state.value = updater(state.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
signal.mutate = (mutator: Mutator<T>) => {
|
||||||
|
mutator(state.value);
|
||||||
|
triggerRef(state);
|
||||||
|
};
|
||||||
|
|
||||||
|
signal.getRef = () => state as Readonly<ShallowRef<Readonly<T>>>;
|
||||||
|
|
||||||
|
return signal;
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/materials",
|
"name": "@sa/materials",
|
||||||
"version": "1.0.5",
|
"version": "1.0.8",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/fetch",
|
"name": "@sa/fetch",
|
||||||
"version": "1.0.5",
|
"version": "1.0.8",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/scripts",
|
"name": "@sa/scripts",
|
||||||
"version": "1.0.5",
|
"version": "1.0.8",
|
||||||
"bin": {
|
"bin": {
|
||||||
"sa": "./bin.ts"
|
"sa": "./bin.ts"
|
||||||
},
|
},
|
||||||
@ -13,7 +13,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@soybeanjs/changelog": "0.3.22",
|
"@soybeanjs/changelog": "0.3.23",
|
||||||
"bumpp": "9.4.0",
|
"bumpp": "9.4.0",
|
||||||
"c12": "1.10.0",
|
"c12": "1.10.0",
|
||||||
"cac": "6.7.14",
|
"cac": "6.7.14",
|
||||||
@ -21,7 +21,7 @@
|
|||||||
"enquirer": "2.4.1",
|
"enquirer": "2.4.1",
|
||||||
"execa": "8.0.1",
|
"execa": "8.0.1",
|
||||||
"kolorist": "1.8.0",
|
"kolorist": "1.8.0",
|
||||||
"npm-check-updates": "16.14.18",
|
"npm-check-updates": "16.14.20",
|
||||||
"rimraf": "5.0.5"
|
"rimraf": "5.0.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ const defaultOptions: CliOption = {
|
|||||||
['style', 'Changes that do not affect the meaning of the code'],
|
['style', 'Changes that do not affect the meaning of the code'],
|
||||||
['refactor', 'A code change that neither fixes a bug nor adds a feature'],
|
['refactor', 'A code change that neither fixes a bug nor adds a feature'],
|
||||||
['perf', 'A code change that improves performance'],
|
['perf', 'A code change that improves performance'],
|
||||||
|
['optimize', 'A code change that optimizes code quality'],
|
||||||
['test', 'Adding missing tests or correcting existing tests'],
|
['test', 'Adding missing tests or correcting existing tests'],
|
||||||
['build', 'Changes that affect the build system or external dependencies'],
|
['build', 'Changes that affect the build system or external dependencies'],
|
||||||
['ci', 'Changes to our CI configuration files and scripts'],
|
['ci', 'Changes to our CI configuration files and scripts'],
|
||||||
@ -27,6 +28,7 @@ const defaultOptions: CliOption = {
|
|||||||
],
|
],
|
||||||
gitCommitScopes: [
|
gitCommitScopes: [
|
||||||
['projects', 'project'],
|
['projects', 'project'],
|
||||||
|
['packages', 'packages'],
|
||||||
['components', 'components'],
|
['components', 'components'],
|
||||||
['hooks', 'hook functions'],
|
['hooks', 'hook functions'],
|
||||||
['utils', 'utils functions'],
|
['utils', 'utils functions'],
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/uno-preset",
|
"name": "@sa/uno-preset",
|
||||||
"version": "1.0.5",
|
"version": "1.0.8",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/utils",
|
"name": "@sa/utils",
|
||||||
"version": "1.0.5",
|
"version": "1.0.8",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
1023
pnpm-lock.yaml
1023
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
60
src/assets/svg-icon/full-logo.svg
Normal file
60
src/assets/svg-icon/full-logo.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 11 KiB |
@ -36,7 +36,11 @@ const icon = computed(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ButtonIcon :tooltip-content="collapsed ? $t('icon.expand') : $t('icon.collapse')" tooltip-placement="bottom-start">
|
<ButtonIcon
|
||||||
|
:tooltip-content="collapsed ? $t('icon.expand') : $t('icon.collapse')"
|
||||||
|
tooltip-placement="bottom-start"
|
||||||
|
:z-index="99"
|
||||||
|
>
|
||||||
<SvgIcon :icon="icon" />
|
<SvgIcon :icon="icon" />
|
||||||
</ButtonIcon>
|
</ButtonIcon>
|
||||||
</template>
|
</template>
|
||||||
|
@ -15,7 +15,7 @@ const icon = computed(() => (props.pin ? 'mdi-pin-off' : 'mdi-pin'));
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ButtonIcon
|
<ButtonIcon
|
||||||
:tooltip-content="pin ? $t('icon.pin') : $t('icon.unpin')"
|
:tooltip-content="pin ? $t('icon.unpin') : $t('icon.pin')"
|
||||||
tooltip-placement="bottom-start"
|
tooltip-placement="bottom-start"
|
||||||
:z-index="100"
|
:z-index="100"
|
||||||
>
|
>
|
||||||
|
@ -18,6 +18,7 @@ defineOptions({
|
|||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const themeStore = useThemeStore();
|
const themeStore = useThemeStore();
|
||||||
|
const { menus } = setupMixMenuContext();
|
||||||
|
|
||||||
const layoutMode = computed(() => {
|
const layoutMode = computed(() => {
|
||||||
const vertical: LayoutMode = 'vertical';
|
const vertical: LayoutMode = 'vertical';
|
||||||
@ -65,7 +66,7 @@ function getSiderWidth() {
|
|||||||
|
|
||||||
let w = isVerticalMix.value || isHorizontalMix.value ? mixWidth : width;
|
let w = isVerticalMix.value || isHorizontalMix.value ? mixWidth : width;
|
||||||
|
|
||||||
if (isVerticalMix.value && appStore.mixSiderFixed) {
|
if (isVerticalMix.value && appStore.mixSiderFixed && menus.value.length) {
|
||||||
w += mixChildMenuWidth;
|
w += mixChildMenuWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,14 +78,12 @@ function getSiderCollapsedWidth() {
|
|||||||
|
|
||||||
let w = isVerticalMix.value || isHorizontalMix.value ? mixCollapsedWidth : collapsedWidth;
|
let w = isVerticalMix.value || isHorizontalMix.value ? mixCollapsedWidth : collapsedWidth;
|
||||||
|
|
||||||
if (isVerticalMix.value && appStore.mixSiderFixed) {
|
if (isVerticalMix.value && appStore.mixSiderFixed && menus.value.length) {
|
||||||
w += mixChildMenuWidth;
|
w += mixChildMenuWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
setupMixMenuContext();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -1,4 +1,47 @@
|
|||||||
|
import { computed, ref, watch } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
import { useContext } from '@sa/hooks';
|
import { useContext } from '@sa/hooks';
|
||||||
import { useMixMenu } from '../hooks';
|
import { useRouteStore } from '@/store/modules/route';
|
||||||
|
|
||||||
export const { setupStore: setupMixMenuContext, useStore: useMixMenuContext } = useContext('mix-menu', useMixMenu);
|
export const { setupStore: setupMixMenuContext, useStore: useMixMenuContext } = useContext('mix-menu', useMixMenu);
|
||||||
|
|
||||||
|
function useMixMenu() {
|
||||||
|
const route = useRoute();
|
||||||
|
const routeStore = useRouteStore();
|
||||||
|
|
||||||
|
const activeFirstLevelMenuKey = ref('');
|
||||||
|
|
||||||
|
function setActiveFirstLevelMenuKey(key: string) {
|
||||||
|
activeFirstLevelMenuKey.value = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getActiveFirstLevelMenuKey() {
|
||||||
|
const { hideInMenu, activeMenu } = route.meta;
|
||||||
|
const name = route.name as string;
|
||||||
|
|
||||||
|
const routeName = (hideInMenu ? activeMenu : name) || name;
|
||||||
|
|
||||||
|
const [firstLevelRouteName] = routeName.split('_');
|
||||||
|
|
||||||
|
setActiveFirstLevelMenuKey(firstLevelRouteName);
|
||||||
|
}
|
||||||
|
|
||||||
|
const menus = computed(
|
||||||
|
() => routeStore.menus.find(menu => menu.key === activeFirstLevelMenuKey.value)?.children || []
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => route.name,
|
||||||
|
() => {
|
||||||
|
getActiveFirstLevelMenuKey();
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
activeFirstLevelMenuKey,
|
||||||
|
setActiveFirstLevelMenuKey,
|
||||||
|
getActiveFirstLevelMenuKey,
|
||||||
|
menus
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -2,11 +2,10 @@
|
|||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { useBoolean } from '@sa/hooks';
|
import { useBoolean } from '@sa/hooks';
|
||||||
import { useAppStore } from '@/store/modules/app';
|
import { useAppStore } from '@/store/modules/app';
|
||||||
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 { $t } from '@/locales';
|
import { $t } from '@/locales';
|
||||||
import { useMixMenu } from '../../hooks';
|
import { useMixMenuContext } from '../../context';
|
||||||
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';
|
||||||
|
|
||||||
@ -16,16 +15,15 @@ defineOptions({
|
|||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const themeStore = useThemeStore();
|
const themeStore = useThemeStore();
|
||||||
const routeStore = useRouteStore();
|
|
||||||
const { routerPushByKey } = useRouterPush();
|
const { routerPushByKey } = useRouterPush();
|
||||||
const { bool: drawerVisible, setBool: setDrawerVisible } = useBoolean();
|
const { bool: drawerVisible, setBool: setDrawerVisible } = useBoolean();
|
||||||
const { activeFirstLevelMenuKey, setActiveFirstLevelMenuKey, getActiveFirstLevelMenuKey } = useMixMenu();
|
const { menus, activeFirstLevelMenuKey, setActiveFirstLevelMenuKey, getActiveFirstLevelMenuKey } = useMixMenuContext();
|
||||||
|
|
||||||
const siderInverted = computed(() => !themeStore.darkMode && themeStore.sider.inverted);
|
const siderInverted = computed(() => !themeStore.darkMode && themeStore.sider.inverted);
|
||||||
|
|
||||||
const menus = computed(() => routeStore.menus.find(menu => menu.key === activeFirstLevelMenuKey.value)?.children || []);
|
const hasMenus = computed(() => menus.value.length > 0);
|
||||||
|
|
||||||
const showDrawer = computed(() => (drawerVisible.value && menus.value.length) || appStore.mixSiderFixed);
|
const showDrawer = computed(() => hasMenus.value && (drawerVisible.value || appStore.mixSiderFixed));
|
||||||
|
|
||||||
function handleSelectMixMenu(menu: App.Global.Menu) {
|
function handleSelectMixMenu(menu: App.Global.Menu) {
|
||||||
setActiveFirstLevelMenuKey(menu.key);
|
setActiveFirstLevelMenuKey(menu.key);
|
||||||
@ -50,7 +48,7 @@ function handleResetActiveMenu() {
|
|||||||
</FirstLevelMenu>
|
</FirstLevelMenu>
|
||||||
<div
|
<div
|
||||||
class="relative h-full transition-width-300"
|
class="relative h-full transition-width-300"
|
||||||
:style="{ width: appStore.mixSiderFixed ? themeStore.sider.mixChildMenuWidth + 'px' : '0px' }"
|
:style="{ width: appStore.mixSiderFixed && hasMenus ? themeStore.sider.mixChildMenuWidth + 'px' : '0px' }"
|
||||||
>
|
>
|
||||||
<DarkModeContainer
|
<DarkModeContainer
|
||||||
class="absolute-lt h-full flex-col-stretch nowrap-hidden shadow-sm transition-all-300"
|
class="absolute-lt h-full flex-col-stretch nowrap-hidden shadow-sm transition-all-300"
|
||||||
|
@ -242,7 +242,16 @@ const local: App.I18n.Schema = {
|
|||||||
403: 'No Permission',
|
403: 'No Permission',
|
||||||
404: 'Page Not Found',
|
404: 'Page Not Found',
|
||||||
500: 'Server Error',
|
500: 'Server Error',
|
||||||
|
'iframe-page': 'Iframe',
|
||||||
home: 'Home',
|
home: 'Home',
|
||||||
|
document: 'Document',
|
||||||
|
document_project: 'Project Document',
|
||||||
|
'document_project-link': 'Project Document(External Link)',
|
||||||
|
document_vue: 'Vue Document',
|
||||||
|
document_vite: 'Vite Document',
|
||||||
|
document_unocss: 'UnoCSS Document',
|
||||||
|
document_naive: 'Naive UI Document',
|
||||||
|
document_antd: 'Ant Design Vue Document',
|
||||||
'user-center': 'User Center',
|
'user-center': 'User Center',
|
||||||
about: 'About',
|
about: 'About',
|
||||||
function: 'System Function',
|
function: 'System Function',
|
||||||
|
@ -242,7 +242,16 @@ const local: App.I18n.Schema = {
|
|||||||
403: '无权限',
|
403: '无权限',
|
||||||
404: '页面不存在',
|
404: '页面不存在',
|
||||||
500: '服务器错误',
|
500: '服务器错误',
|
||||||
|
'iframe-page': '外链页面',
|
||||||
home: '首页',
|
home: '首页',
|
||||||
|
document: '文档',
|
||||||
|
document_project: '项目文档',
|
||||||
|
'document_project-link': '项目文档(外链)',
|
||||||
|
document_vue: 'Vue文档',
|
||||||
|
document_vite: 'Vite文档',
|
||||||
|
document_unocss: 'UnoCSS文档',
|
||||||
|
document_naive: 'Naive UI文档',
|
||||||
|
document_antd: 'Ant Design Vue文档',
|
||||||
'user-center': '个人中心',
|
'user-center': '个人中心',
|
||||||
about: '关于',
|
about: '关于',
|
||||||
function: '系统功能',
|
function: '系统功能',
|
||||||
|
@ -18,6 +18,7 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
|
|||||||
403: () => import("@/views/_builtin/403/index.vue"),
|
403: () => import("@/views/_builtin/403/index.vue"),
|
||||||
404: () => import("@/views/_builtin/404/index.vue"),
|
404: () => import("@/views/_builtin/404/index.vue"),
|
||||||
500: () => import("@/views/_builtin/500/index.vue"),
|
500: () => import("@/views/_builtin/500/index.vue"),
|
||||||
|
"iframe-page": () => import("@/views/_builtin/iframe-page/[url].vue"),
|
||||||
login: () => import("@/views/_builtin/login/index.vue"),
|
login: () => import("@/views/_builtin/login/index.vue"),
|
||||||
about: () => import("@/views/about/index.vue"),
|
about: () => import("@/views/about/index.vue"),
|
||||||
"function_hide-child_one": () => import("@/views/function/hide-child/one/index.vue"),
|
"function_hide-child_one": () => import("@/views/function/hide-child/one/index.vue"),
|
||||||
|
@ -191,6 +191,19 @@ export const generatedRoutes: GeneratedRoute[] = [
|
|||||||
order: 1
|
order: 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'iframe-page',
|
||||||
|
path: '/iframe-page/:url',
|
||||||
|
component: 'layout.base$view.iframe-page',
|
||||||
|
props: true,
|
||||||
|
meta: {
|
||||||
|
title: 'iframe-page',
|
||||||
|
i18nKey: 'route.iframe-page',
|
||||||
|
constant: true,
|
||||||
|
hideInMenu: true,
|
||||||
|
keepAlive: true
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'job',
|
name: 'job',
|
||||||
path: '/job',
|
path: '/job',
|
||||||
|
@ -147,6 +147,14 @@ const routeMap: RouteMap = {
|
|||||||
"exception_403": "/exception/403",
|
"exception_403": "/exception/403",
|
||||||
"exception_404": "/exception/404",
|
"exception_404": "/exception/404",
|
||||||
"exception_500": "/exception/500",
|
"exception_500": "/exception/500",
|
||||||
|
"document": "/document",
|
||||||
|
"document_project": "/document/project",
|
||||||
|
"document_project-link": "/document/project-link",
|
||||||
|
"document_vue": "/document/vue",
|
||||||
|
"document_vite": "/document/vite",
|
||||||
|
"document_unocss": "/document/unocss",
|
||||||
|
"document_naive": "/document/naive",
|
||||||
|
"document_antd": "/document/antd",
|
||||||
"403": "/403",
|
"403": "/403",
|
||||||
"404": "/404",
|
"404": "/404",
|
||||||
"500": "/500",
|
"500": "/500",
|
||||||
@ -163,6 +171,7 @@ const routeMap: RouteMap = {
|
|||||||
"function_toggle-auth": "/function/toggle-auth",
|
"function_toggle-auth": "/function/toggle-auth",
|
||||||
"group": "/group",
|
"group": "/group",
|
||||||
"home": "/home",
|
"home": "/home",
|
||||||
|
"iframe-page": "/iframe-page/:url",
|
||||||
"job": "/job",
|
"job": "/job",
|
||||||
"job_batch": "/job/batch",
|
"job_batch": "/job/batch",
|
||||||
"job_task": "/job/task",
|
"job_task": "/job/task",
|
||||||
|
@ -52,6 +52,115 @@ const customRoutes: CustomRoute[] = [
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'document',
|
||||||
|
path: '/document',
|
||||||
|
component: 'layout.base',
|
||||||
|
meta: {
|
||||||
|
title: 'document',
|
||||||
|
i18nKey: 'route.document',
|
||||||
|
order: 2,
|
||||||
|
icon: 'mdi:file-document-multiple-outline'
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'document_antd',
|
||||||
|
path: '/document/antd',
|
||||||
|
component: 'view.iframe-page',
|
||||||
|
props: {
|
||||||
|
url: 'https://antdv.com/components/overview-cn'
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
title: 'document_antd',
|
||||||
|
i18nKey: 'route.document_antd',
|
||||||
|
order: 7,
|
||||||
|
icon: 'logos:ant-design'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'document_naive',
|
||||||
|
path: '/document/naive',
|
||||||
|
component: 'view.iframe-page',
|
||||||
|
props: {
|
||||||
|
url: 'https://www.naiveui.com/zh-CN/os-theme/docs/introduction'
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
title: 'document_naive',
|
||||||
|
i18nKey: 'route.document_naive',
|
||||||
|
order: 6,
|
||||||
|
icon: 'logos:naiveui'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'document_project',
|
||||||
|
path: '/document/project',
|
||||||
|
component: 'view.iframe-page',
|
||||||
|
props: {
|
||||||
|
url: 'https://docs.soybeanjs.cn/zh'
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
title: 'document_project',
|
||||||
|
i18nKey: 'route.document_project',
|
||||||
|
order: 1,
|
||||||
|
localIcon: 'logo'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'document_project-link',
|
||||||
|
path: '/document/project-link',
|
||||||
|
component: 'view.iframe-page',
|
||||||
|
meta: {
|
||||||
|
title: 'document_project-link',
|
||||||
|
i18nKey: 'route.document_project-link',
|
||||||
|
order: 2,
|
||||||
|
localIcon: 'logo',
|
||||||
|
href: 'https://docs.soybeanjs.cn/zh'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'document_unocss',
|
||||||
|
path: '/document/unocss',
|
||||||
|
component: 'view.iframe-page',
|
||||||
|
props: {
|
||||||
|
url: 'https://unocss.dev/'
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
title: 'document_unocss',
|
||||||
|
i18nKey: 'route.document_unocss',
|
||||||
|
order: 5,
|
||||||
|
icon: 'logos:unocss'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'document_vite',
|
||||||
|
path: '/document/vite',
|
||||||
|
component: 'view.iframe-page',
|
||||||
|
props: {
|
||||||
|
url: 'https://cn.vitejs.dev/'
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
title: 'document_vite',
|
||||||
|
i18nKey: 'route.document_vite',
|
||||||
|
order: 4,
|
||||||
|
icon: 'logos:vitejs'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'document_vue',
|
||||||
|
path: '/document/vue',
|
||||||
|
component: 'view.iframe-page',
|
||||||
|
props: {
|
||||||
|
url: 'https://cn.vuejs.org/'
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
title: 'document_vue',
|
||||||
|
i18nKey: 'route.document_vue',
|
||||||
|
order: 3,
|
||||||
|
icon: 'logos:vue'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { effectScope, onScopeDispose, ref, watch } from 'vue';
|
import { effectScope, nextTick, onScopeDispose, ref, watch } from 'vue';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { breakpointsTailwind, useBreakpoints, useTitle } from '@vueuse/core';
|
import { breakpointsTailwind, useBreakpoints, useEventListener, useTitle } from '@vueuse/core';
|
||||||
import { useBoolean } from '@sa/hooks';
|
import { useBoolean } from '@sa/hooks';
|
||||||
import { SetupStoreId } from '@/enum';
|
import { SetupStoreId } from '@/enum';
|
||||||
import { router } from '@/router';
|
import { router } from '@/router';
|
||||||
@ -22,7 +22,11 @@ export const useAppStore = defineStore(SetupStoreId.App, () => {
|
|||||||
const { bool: fullContent, toggle: toggleFullContent } = useBoolean();
|
const { bool: fullContent, toggle: toggleFullContent } = useBoolean();
|
||||||
const { bool: contentXScrollable, setBool: setContentXScrollable } = useBoolean();
|
const { bool: contentXScrollable, setBool: setContentXScrollable } = useBoolean();
|
||||||
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(localStg.get('mixSiderFixed') === 'Y');
|
||||||
|
|
||||||
/** Is mobile layout */
|
/** Is mobile layout */
|
||||||
const isMobile = breakpoints.smaller('sm');
|
const isMobile = breakpoints.smaller('sm');
|
||||||
@ -83,9 +87,26 @@ export const useAppStore = defineStore(SetupStoreId.App, () => {
|
|||||||
isMobile,
|
isMobile,
|
||||||
newValue => {
|
newValue => {
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
setSiderCollapse(true);
|
// backup theme setting before is mobile
|
||||||
|
localStg.set('backupThemeSettingBeforeIsMobile', {
|
||||||
|
layout: themeStore.layout.mode,
|
||||||
|
siderCollapse: siderCollapse.value
|
||||||
|
});
|
||||||
|
|
||||||
themeStore.setThemeLayout('vertical');
|
themeStore.setThemeLayout('vertical');
|
||||||
|
setSiderCollapse(true);
|
||||||
|
} else {
|
||||||
|
// when is not mobile, recover the backup theme setting
|
||||||
|
const backup = localStg.get('backupThemeSettingBeforeIsMobile');
|
||||||
|
|
||||||
|
if (backup) {
|
||||||
|
nextTick(() => {
|
||||||
|
themeStore.setThemeLayout(backup.layout);
|
||||||
|
setSiderCollapse(backup.siderCollapse);
|
||||||
|
|
||||||
|
localStg.remove('backupThemeSettingBeforeIsMobile');
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
@ -107,6 +128,11 @@ export const useAppStore = defineStore(SetupStoreId.App, () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// cache mixSiderFixed
|
||||||
|
useEventListener(window, 'beforeunload', () => {
|
||||||
|
localStg.set('mixSiderFixed', mixSiderFixed.value ? 'Y' : 'N');
|
||||||
|
});
|
||||||
|
|
||||||
/** On scope dispose */
|
/** On scope dispose */
|
||||||
onScopeDispose(() => {
|
onScopeDispose(() => {
|
||||||
scope.stop();
|
scope.stop();
|
||||||
|
@ -16,17 +16,24 @@ export function getAllTabs(tabs: App.Global.Tab[], homeTab?: App.Global.Tab) {
|
|||||||
|
|
||||||
const filterHomeTabs = tabs.filter(tab => tab.id !== homeTab.id);
|
const filterHomeTabs = tabs.filter(tab => tab.id !== homeTab.id);
|
||||||
|
|
||||||
const fixedTabs = filterHomeTabs
|
const fixedTabs = filterHomeTabs.filter(isFixedTab).sort((a, b) => a.fixedIndex! - b.fixedIndex!);
|
||||||
.filter(tab => tab.fixedIndex !== undefined)
|
|
||||||
.sort((a, b) => a.fixedIndex! - b.fixedIndex!);
|
|
||||||
|
|
||||||
const remainTabs = filterHomeTabs.filter(tab => tab.fixedIndex === undefined);
|
const remainTabs = filterHomeTabs.filter(tab => !isFixedTab(tab));
|
||||||
|
|
||||||
const allTabs = [homeTab, ...fixedTabs, ...remainTabs];
|
const allTabs = [homeTab, ...fixedTabs, ...remainTabs];
|
||||||
|
|
||||||
return updateTabsLabel(allTabs);
|
return updateTabsLabel(allTabs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is fixed tab
|
||||||
|
*
|
||||||
|
* @param tab
|
||||||
|
*/
|
||||||
|
function isFixedTab(tab: App.Global.Tab) {
|
||||||
|
return tab.fixedIndex !== undefined && tab.fixedIndex !== null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get tab id by route
|
* Get tab id by route
|
||||||
*
|
*
|
||||||
@ -177,7 +184,7 @@ export function extractTabsByAllRoutes(router: Router, tabs: App.Global.Tab[]) {
|
|||||||
* @param tabs
|
* @param tabs
|
||||||
*/
|
*/
|
||||||
export function getFixedTabs(tabs: App.Global.Tab[]) {
|
export function getFixedTabs(tabs: App.Global.Tab[]) {
|
||||||
return tabs.filter(tab => tab.fixedIndex !== undefined);
|
return tabs.filter(isFixedTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
2
src/typings/app.d.ts
vendored
2
src/typings/app.d.ts
vendored
@ -198,7 +198,7 @@ declare namespace App {
|
|||||||
/** The tab route full path */
|
/** The tab route full path */
|
||||||
fullPath: string;
|
fullPath: string;
|
||||||
/** The tab fixed index */
|
/** The tab fixed index */
|
||||||
fixedIndex?: number;
|
fixedIndex?: number | null;
|
||||||
/**
|
/**
|
||||||
* Tab icon
|
* Tab icon
|
||||||
*
|
*
|
||||||
|
2
src/typings/router.d.ts
vendored
2
src/typings/router.d.ts
vendored
@ -58,7 +58,7 @@ declare module 'vue-router' {
|
|||||||
/** By default, the same route path will use one tab, if set to true, it will use multiple tabs */
|
/** By default, the same route path will use one tab, if set to true, it will use multiple tabs */
|
||||||
multiTab?: boolean;
|
multiTab?: boolean;
|
||||||
/** If set, the route will be fixed in tabs, and the value is the order of fixed tabs */
|
/** If set, the route will be fixed in tabs, and the value is the order of fixed tabs */
|
||||||
fixedIndexInTab?: number;
|
fixedIndexInTab?: number | null;
|
||||||
/** if set query parameters, it will be automatically carried when entering the route */
|
/** if set query parameters, it will be automatically carried when entering the route */
|
||||||
query?: Record<string, string>;
|
query?: Record<string, string>;
|
||||||
}
|
}
|
||||||
|
7
src/typings/storage.d.ts
vendored
7
src/typings/storage.d.ts
vendored
@ -14,6 +14,8 @@ declare namespace StorageType {
|
|||||||
lang: App.I18n.LangType;
|
lang: App.I18n.LangType;
|
||||||
/** The token */
|
/** The token */
|
||||||
token: string;
|
token: string;
|
||||||
|
/** Fixed sider with mix-menu */
|
||||||
|
mixSiderFixed: CommonType.YesOrNo;
|
||||||
/** The refresh token */
|
/** The refresh token */
|
||||||
refreshToken: string;
|
refreshToken: string;
|
||||||
/** The version */
|
/** The version */
|
||||||
@ -34,5 +36,10 @@ declare namespace StorageType {
|
|||||||
overrideThemeFlag: string;
|
overrideThemeFlag: string;
|
||||||
/** The global tabs */
|
/** The global tabs */
|
||||||
globalTabs: App.Global.Tab[];
|
globalTabs: App.Global.Tab[];
|
||||||
|
/** The backup theme setting before is mobile */
|
||||||
|
backupThemeSettingBeforeIsMobile: {
|
||||||
|
layout: UnionKey.ThemeLayoutMode;
|
||||||
|
siderCollapse: boolean;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
25
src/views/_builtin/iframe-page/[url].vue
Normal file
25
src/views/_builtin/iframe-page/[url].vue
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { onActivated, onMounted } from 'vue';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineProps<Props>();
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
console.log('mounted');
|
||||||
|
});
|
||||||
|
|
||||||
|
onActivated(() => {
|
||||||
|
console.log('activated');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="h-full">
|
||||||
|
<iframe id="iframePage" class="size-full" :src="url"></iframe>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
Loading…
Reference in New Issue
Block a user