Compare commits

..

15 Commits

Author SHA1 Message Date
Soybean
4f19cc02ef chore(release): release tauri v1.0.6 2024-04-25 22:13:58 +08:00
Soybean
1c3b4734fa chore(projects): release v1.0.6 2024-04-25 22:09:59 +08:00
Soybean
93c7ff7122 fix(projects): fix mix-menu blank. fixed #389 & cache mixMenuFixed 2024-04-25 22:07:23 +08:00
Soybean
1e14293d67 refactor(projects): useMixMenuContext replace useMixMenu 2024-04-25 21:49:14 +08:00
Soybean
19e65c1a9f chore(projects): update pnpm version requirement 2024-04-25 21:27:59 +08:00
Soybean
e57bf0b076 chore(deps): update deps 2024-04-25 15:01:23 +08:00
Soybean
5d45cef1f0 perf(hooks): perf useSignal 2024-04-25 15:00:47 +08:00
Soybean
d460e5cc6d perf(projects): add tsconfig.json for @sa/color-palette 2024-04-25 13:09:26 +08:00
Soybean
3b5e4b3405 refactor(hooks): refactor useSignal, useComputed 2024-04-25 13:08:38 +08:00
Soybean
dcd51f4cda chore(projects): use engines replace packageManager 2024-04-25 10:24:48 +08:00
Soybean
09f6464678 feat(hooks): add state hooks: useRef, useState, useSignal 2024-04-25 01:39:59 +08:00
Soybean
fdde679c70 perf(projects): remove useless prop title of NDrawer 2024-04-25 00:23:07 +08:00
Soybean
b266035800 fix(projects): supply $t import statement 2024-04-25 00:20:26 +08:00
Soybean
a1e432f81e Merge pull request #399 from alleycharming/main
fix(projects): added responseType judgment. #396
2024-04-24 18:41:24 +08:00
alleycharming
82eabab753 fix(projects): added responseType judgment. #396 2024-04-24 17:58:46 +08:00
49 changed files with 4398 additions and 296 deletions

View File

@@ -1,6 +1,45 @@
# Changelog
## [v1.0.6](https://github.com/soybeanjs/soybean-admin/compare/v1.0.5...v1.0.6) (2024-04-25)
###    🚀 Features
- **hooks**: add state hooks: useRef, useState, useSignal &nbsp;-&nbsp; by @honghuangdc [<samp>(09f64)</samp>](https://github.com/soybeanjs/soybean-admin/commit/09f6464)
### &nbsp;&nbsp;&nbsp;🐞 Bug Fixes
- **projects**:
- added responseType judgment. #396 &nbsp;-&nbsp; by **alleycharming** in https://github.com/soybeanjs/soybean-admin/issues/396 [<samp>(82eab)</samp>](https://github.com/soybeanjs/soybean-admin/commit/82eabab)
- supply $t import statement &nbsp;-&nbsp; by @honghuangdc [<samp>(b2660)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b266035)
- fix mix-menu blank. fixed #389 & cache mixMenuFixed &nbsp;-&nbsp; by @honghuangdc in https://github.com/soybeanjs/soybean-admin/issues/389 [<samp>(93c7f)</samp>](https://github.com/soybeanjs/soybean-admin/commit/93c7ff7)
### &nbsp;&nbsp;&nbsp;🔥 Performance
- **hooks**:
- perf useSignal &nbsp;-&nbsp; by @honghuangdc [<samp>(5d45c)</samp>](https://github.com/soybeanjs/soybean-admin/commit/5d45cef)
- **projects**:
- remove useless prop `title` of `NDrawer` &nbsp;-&nbsp; by @honghuangdc [<samp>(fdde6)</samp>](https://github.com/soybeanjs/soybean-admin/commit/fdde679)
- add tsconfig.json for @sa/color-palette &nbsp;-&nbsp; by @honghuangdc [<samp>(d460e)</samp>](https://github.com/soybeanjs/soybean-admin/commit/d460e5c)
### &nbsp;&nbsp;&nbsp;💅 Refactors
- **hooks**: refactor useSignal, useComputed &nbsp;-&nbsp; by @honghuangdc [<samp>(3b5e4)</samp>](https://github.com/soybeanjs/soybean-admin/commit/3b5e4b3)
- **projects**: useMixMenuContext replace useMixMenu &nbsp;-&nbsp; by @honghuangdc [<samp>(1e142)</samp>](https://github.com/soybeanjs/soybean-admin/commit/1e14293)
### &nbsp;&nbsp;&nbsp;🏡 Chore
- **deps**:
- update deps &nbsp;-&nbsp; by @honghuangdc [<samp>(e57bf)</samp>](https://github.com/soybeanjs/soybean-admin/commit/e57bf0b)
- **projects**:
- use `engines` replace `packageManager` &nbsp;-&nbsp; by @honghuangdc [<samp>(dcd51)</samp>](https://github.com/soybeanjs/soybean-admin/commit/dcd51f4)
- update pnpm version requirement &nbsp;-&nbsp; by @honghuangdc [<samp>(19e65)</samp>](https://github.com/soybeanjs/soybean-admin/commit/19e65c1)
### &nbsp;&nbsp;&nbsp;❤️ Contributors
[![honghuangdc](https://github.com/honghuangdc.png?size=48)](https://github.com/honghuangdc)&nbsp;&nbsp;
[alleycharming](mailto:alleycharming@gmail.com)
## [v1.0.5](https://github.com/honghuangdc/soybean-admin/compare/v1.0.4...v1.0.5) (2024-04-24)
### &nbsp;&nbsp;&nbsp;📖 Documentation

View File

@@ -1,7 +1,7 @@
import { defineConfig } from '@soybeanjs/eslint-config';
export default defineConfig(
{ vue: true, unocss: true },
{ vue: true, unocss: true, ignores: ['src-tauri/target'] },
{
rules: {
'vue/multi-word-component-names': [

View File

@@ -1,8 +1,7 @@
{
"name": "soybean-admin",
"type": "module",
"version": "1.0.5",
"packageManager": "pnpm@9.0.5",
"version": "1.0.6",
"description": "A fresh and elegant admin template, based on Vue3、Vite3、TypeScript、NaiveUI and UnoCSS. 一个基于Vue3、Vite3、TypeScript、NaiveUI and UnoCSS的清新优雅的中后台模版。",
"author": {
"name": "Soybean",
@@ -27,18 +26,25 @@
"ant-design-vue v4",
"UnoCSS"
],
"engines": {
"node": ">=18.12.0",
"pnpm": ">=8.7.0"
},
"scripts": {
"build": "vite build --mode prod",
"build:tauri": "pnpm tauri build",
"build:test": "vite build --mode test",
"cleanup": "sa cleanup",
"commit": "sa git-commit",
"dev": "vite --mode test",
"dev:prod": "vite --mode prod",
"dev:tauri": "pnpm tauri dev",
"gen-route": "sa gen-route",
"lint": "eslint . --fix",
"prepare": "simple-git-hooks",
"preview": "vite preview",
"release": "sa release",
"tauri-icon": "pnpm tauri icon ./public/logo.png",
"typecheck": "vue-tsc --noEmit --skipLibCheck",
"update-pkg": "sa update-pkg"
},
@@ -58,17 +64,18 @@
"naive-ui": "2.38.1",
"nprogress": "0.2.0",
"pinia": "2.1.7",
"vue": "3.4.23",
"vue": "3.4.25",
"vue-draggable-plus": "0.4.0",
"vue-i18n": "9.13.1",
"vue-router": "4.3.2"
},
"devDependencies": {
"@elegant-router/vue": "0.3.6",
"@iconify/json": "2.2.203",
"@iconify/json": "2.2.204",
"@sa/scripts": "workspace:*",
"@sa/uno-preset": "workspace:*",
"@soybeanjs/eslint-config": "1.3.2",
"@tauri-apps/cli": "1.5.11",
"@types/lodash-es": "4.17.12",
"@types/node": "20.12.7",
"@types/nprogress": "0.2.3",

View File

@@ -1,6 +1,6 @@
{
"name": "@sa/axios",
"version": "1.0.5",
"version": "1.0.6",
"exports": {
".": "./src/index.ts"
},

View File

@@ -48,7 +48,9 @@ function createCommonRequest<ResponseData = any>(
instance.interceptors.response.use(
async response => {
if (opts.isBackendSuccess(response)) {
const responseType: ResponseType = (response.config?.responseType as ResponseType) || 'json';
if (responseType !== 'json' || opts.isBackendSuccess(response)) {
return Promise.resolve(response);
}

View File

@@ -1,6 +1,6 @@
{
"name": "@sa/color-palette",
"version": "1.0.5",
"version": "1.0.6",
"exports": {
".": "./src/index.ts"
},

View 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"]
}

View File

@@ -1,6 +1,6 @@
{
"name": "@sa/hooks",
"version": "1.0.5",
"version": "1.0.6",
"exports": {
".": "./src/index.ts"
},

View File

@@ -7,4 +7,5 @@ import useHookTable from './use-table';
export { useBoolean, useLoading, useCountDown, useContext, useSvgIconRender, useHookTable };
export * from './use-signal';
export * from './use-table';

View 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;
}

View File

@@ -1,6 +1,6 @@
{
"name": "@sa/materials",
"version": "1.0.5",
"version": "1.0.6",
"exports": {
".": "./src/index.ts"
},

View File

@@ -1,6 +1,6 @@
{
"name": "@sa/fetch",
"version": "1.0.5",
"version": "1.0.6",
"exports": {
".": "./src/index.ts"
},

View File

@@ -1,6 +1,6 @@
{
"name": "@sa/scripts",
"version": "1.0.5",
"version": "1.0.6",
"bin": {
"sa": "./bin.ts"
},

View File

@@ -1,6 +1,6 @@
{
"name": "@sa/uno-preset",
"version": "1.0.5",
"version": "1.0.6",
"exports": {
".": "./src/index.ts"
},

View File

@@ -1,6 +1,6 @@
{
"name": "@sa/utils",
"version": "1.0.5",
"version": "1.0.6",
"exports": {
".": "./src/index.ts"
},

557
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

BIN
public/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

3
src-tauri/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
# Generated by Cargo
# will have compiled files and executables
/target/

3664
src-tauri/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

26
src-tauri/Cargo.toml Normal file
View File

@@ -0,0 +1,26 @@
[package]
name = "app"
version = "0.1.0"
description = "A Tauri App"
authors = ["you"]
license = ""
repository = ""
default-run = "app"
edition = "2021"
rust-version = "1.60"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies]
tauri-build = { version = "1.5.1", features = [] }
[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
tauri = { version = "1.6.1", features = [] }
[features]
# this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled.
# If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `build` modes.
# DO NOT REMOVE!!
custom-protocol = [ "tauri/custom-protocol" ]

3
src-tauri/build.rs Normal file
View File

@@ -0,0 +1,3 @@
fn main() {
tauri_build::build()
}

BIN
src-tauri/icons/128x128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
src-tauri/icons/32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
src-tauri/icons/icon.icns Normal file

Binary file not shown.

BIN
src-tauri/icons/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
src-tauri/icons/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

8
src-tauri/src/main.rs Normal file
View File

@@ -0,0 +1,8 @@
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
fn main() {
tauri::Builder::default()
.run(tauri::generate_context!())
.expect("error while running tauri application");
}

60
src-tauri/tauri.conf.json Normal file
View File

@@ -0,0 +1,60 @@
{
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
"build": {
"beforeBuildCommand": "npm run build",
"beforeDevCommand": "npm run dev",
"devPath": "http://localhost:9527",
"distDir": "../dist"
},
"package": {
"productName": "soybean-admin",
"version": "1.0.0"
},
"tauri": {
"allowlist": {
"all": false
},
"bundle": {
"active": true,
"category": "DeveloperTool",
"copyright": "",
"deb": {
"depends": []
},
"externalBin": [],
"icon": ["icons/32x32.png", "icons/128x128.png", "icons/128x128@2x.png", "icons/icon.icns", "icons/icon.ico"],
"identifier": "cn.soybeanjs.admin",
"longDescription": "",
"macOS": {
"entitlements": null,
"exceptionDomain": "",
"frameworks": [],
"providerShortName": null,
"signingIdentity": null
},
"resources": [],
"shortDescription": "",
"targets": "all",
"windows": {
"certificateThumbprint": null,
"digestAlgorithm": "sha256",
"timestampUrl": ""
}
},
"security": {
"csp": null
},
"updater": {
"active": false
},
"windows": [
{
"fullscreen": false,
"height": 768,
"resizable": true,
"title": "SoybeanAdmin",
"width": 1366
}
]
}
}

View File

@@ -1,4 +1,6 @@
<script setup lang="ts">
import { $t } from '@/locales';
defineOptions({
name: 'TableHeaderOperation'
});

View File

@@ -18,6 +18,7 @@ defineOptions({
const appStore = useAppStore();
const themeStore = useThemeStore();
const { menus } = setupMixMenuContext();
const layoutMode = computed(() => {
const vertical: LayoutMode = 'vertical';
@@ -65,7 +66,7 @@ function getSiderWidth() {
let w = isVerticalMix.value || isHorizontalMix.value ? mixWidth : width;
if (isVerticalMix.value && appStore.mixSiderFixed) {
if (isVerticalMix.value && appStore.mixSiderFixed && menus.value.length) {
w += mixChildMenuWidth;
}
@@ -77,14 +78,12 @@ function getSiderCollapsedWidth() {
let w = isVerticalMix.value || isHorizontalMix.value ? mixCollapsedWidth : collapsedWidth;
if (isVerticalMix.value && appStore.mixSiderFixed) {
if (isVerticalMix.value && appStore.mixSiderFixed && menus.value.length) {
w += mixChildMenuWidth;
}
return w;
}
setupMixMenuContext();
</script>
<template>

View File

@@ -1,4 +1,47 @@
import { computed, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
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);
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
};
}

View File

@@ -1,44 +0,0 @@
import { computed, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import { useRouteStore } from '@/store/modules/route';
export 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
};
}

View File

@@ -2,10 +2,10 @@
import { computed } from 'vue';
import { useBoolean } from '@sa/hooks';
import { useAppStore } from '@/store/modules/app';
import { useRouteStore } from '@/store/modules/route';
import { useThemeStore } from '@/store/modules/theme';
import { useRouterPush } from '@/hooks/common/router';
import { useMixMenu } from '../../hooks';
import { $t } from '@/locales';
import { useMixMenuContext } from '../../context';
import FirstLevelMenu from './first-level-menu.vue';
import BaseMenu from './base-menu.vue';
@@ -15,16 +15,15 @@ defineOptions({
const appStore = useAppStore();
const themeStore = useThemeStore();
const routeStore = useRouteStore();
const { routerPushByKey } = useRouterPush();
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 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) {
setActiveFirstLevelMenuKey(menu.key);
@@ -49,7 +48,7 @@ function handleResetActiveMenu() {
</FirstLevelMenu>
<div
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
class="absolute-lt h-full flex-col-stretch nowrap-hidden shadow-sm transition-all-300"

View File

@@ -1,6 +1,6 @@
import { effectScope, onScopeDispose, ref, watch } from 'vue';
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 { SetupStoreId } from '@/enum';
import { router } from '@/router';
@@ -22,7 +22,11 @@ export const useAppStore = defineStore(SetupStoreId.App, () => {
const { bool: fullContent, toggle: toggleFullContent } = useBoolean();
const { bool: contentXScrollable, setBool: setContentXScrollable } = 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 */
const isMobile = breakpoints.smaller('sm');
@@ -107,6 +111,11 @@ export const useAppStore = defineStore(SetupStoreId.App, () => {
});
});
// cache mixSiderFixed
useEventListener(window, 'beforeunload', () => {
localStg.set('mixSiderFixed', mixSiderFixed.value ? 'Y' : 'N');
});
/** On scope dispose */
onScopeDispose(() => {
scope.stop();

View File

@@ -14,6 +14,8 @@ declare namespace StorageType {
lang: App.I18n.LangType;
/** The token */
token: string;
/** Fixed sider with mix-menu */
mixSiderFixed: CommonType.YesOrNo;
/** The refresh token */
refreshToken: string;
/** The user info */

View File

@@ -182,7 +182,7 @@ watch(visible, () => {
</script>
<template>
<NDrawer v-model:show="visible" :title="title" display-directive="show" :width="360">
<NDrawer v-model:show="visible" display-directive="show" :width="360">
<NDrawerContent :title="title" :native-scrollbar="false" closable>
<NForm ref="formRef" :model="model" :rules="rules" label-placement="left" :label-width="80">
<NFormItem :label="$t('page.manage.menu.menuType')" path="menuType">

View File

@@ -100,7 +100,7 @@ watch(visible, () => {
</script>
<template>
<NDrawer v-model:show="visible" :title="title" display-directive="show" :width="360">
<NDrawer v-model:show="visible" display-directive="show" :width="360">
<NDrawerContent :title="title" :native-scrollbar="false" closable>
<NForm ref="formRef" :model="model" :rules="rules">
<NFormItem :label="$t('page.manage.role.roleName')" path="roleName">

View File

@@ -122,7 +122,7 @@ watch(visible, () => {
</script>
<template>
<NDrawer v-model:show="visible" :title="title" display-directive="show" :width="360">
<NDrawer v-model:show="visible" display-directive="show" :width="360">
<NDrawerContent :title="title" :native-scrollbar="false" closable>
<NForm ref="formRef" :model="model" :rules="rules">
<NFormItem :label="$t('page.manage.user.userName')" path="userName">