mirror of
https://github.com/soybeanjs/soybean-admin.git
synced 2025-12-24 21:40:22 +08:00
Compare commits
10 Commits
v2.0.0
...
605173a1cc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
605173a1cc | ||
|
|
73e9a0fe0b | ||
|
|
c6d97dba21 | ||
|
|
9da847fb6f | ||
|
|
c472a94395 | ||
|
|
91a261c1ef | ||
|
|
bb232bf884 | ||
|
|
f8dc639e05 | ||
|
|
46081c365c | ||
|
|
4a9cf6c3da |
1
.vscode/extensions.json
vendored
1
.vscode/extensions.json
vendored
@@ -5,7 +5,6 @@
|
||||
"antfu.unocss",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"editorconfig.editorconfig",
|
||||
"esbenp.prettier-vscode",
|
||||
"lokalise.i18n-ally",
|
||||
"mhutchie.git-graph",
|
||||
"mikestead.dotenv",
|
||||
|
||||
@@ -139,7 +139,7 @@ Refer to the [Code Synchronization](https://docs.soybeanjs.cn/guide/sync) docume
|
||||
|
||||
## Ecosystem
|
||||
|
||||
- [react-soybean-admin](https://github.com/mufeng889/react-soybean-admin): SoybeanAdmin based version of React.
|
||||
- [skyroc-admin](https://github.com/Ohh-889/skyroc-admin): SoybeanAdmin's React version implementation.
|
||||
- [electron-mock-admin](https://github.com/lixin59/electron-mock-api): A Mock Api management system that helps front-end developers quickly implement interface mocks.
|
||||
- [T-Shell](https://github.com/TheBlindM/T-Shell): A terminal emulator and SSH client with configurable command prompts.
|
||||
- [pea](https://github.com/haitang1894/pea) : Adopting SpringBoot3.2 + JDK21, MyBatis-Plus, SpringSecurity security framework, etc., suitable for the simple permission system developed by [soybean-admin](https://gitee.com/honghuangdc/soybean-admin).
|
||||
@@ -151,6 +151,8 @@ Refer to the [Code Synchronization](https://docs.soybeanjs.cn/guide/sync) docume
|
||||
- [ba](https://github.com/xiatianYa/Ba-Server): Backend service docking with soybean admin based on goFrame framework, adapted to dynamic routing, and interface authentication permissions.
|
||||
- [soybean-admin-go](https://github.com/WgoW/soybean-admin-go):A Go backend service developed based on the Gin and GORM frameworks, integrated with the example branch of Soybean Admin. It supports dynamic routing and API permission authentication.
|
||||
|
||||
More ecosystem please refer to [Ecosystem](https://docs.soybeanjs.cn/awesome) document.
|
||||
|
||||
|
||||
## How to Contribute
|
||||
|
||||
@@ -194,7 +196,7 @@ Here are the most active contributors from the past year. Thank you all for your
|
||||
|
||||
<div>
|
||||
<p>QQ Group</p>
|
||||
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/qq-soybean-admin-4.jpg" style="width:200px" />
|
||||
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/qq-soybean-admin-5.jpg" style="width:200px" />
|
||||
</div>
|
||||
<!-- <div>
|
||||
<p>WeChat Group</p>
|
||||
|
||||
@@ -165,7 +165,7 @@ pnpm build
|
||||
|
||||
## 周边生态
|
||||
|
||||
- [react-soybean-admin](https://github.com/mufeng889/react-soybean-admin): 基于SoybeanAdmin的React版本.
|
||||
- [skyroc-admin](https://github.com/Ohh-889/skyroc-admin): SoybeanAdmin的React版本实现.
|
||||
- [electron-mock-admin](https://github.com/lixin59/electron-mock-api): 一个 Mock Api 管理系统,帮助前端开发伙伴快速实现接口的 mock。
|
||||
- [T-Shell](https://github.com/TheBlindM/T-Shell): 是一个可配置命令提示的终端模拟器和 SSH 客户端。
|
||||
- [pea](https://github.com/haitang1894/pea) : 采用SpringBoot3.2 + JDK21、MyBatis-Plus、SpringSecurity安全框架等,适配 [soybean-admin](https://gitee.com/honghuangdc/soybean-admin) 开发的简单权限系统。
|
||||
@@ -177,6 +177,8 @@ pnpm build
|
||||
- [ba](https://github.com/xiatianYa/Ba-Server): 基于goFrame框架开发的后端服务对接soybean-admin,适配动态路由,接口鉴权限。
|
||||
- [soybean-admin-go](https://github.com/WgoW/soybean-admin-go):基于gin+gorm框架开发的go语言后端服务对接soybean-admin的example分支,适配动态路由,接口鉴权限。
|
||||
|
||||
更多周边生态请翻阅 [周边生态](https://docs.soybeanjs.cn/zh/awesome) 文档。
|
||||
|
||||
|
||||
## 如何贡献
|
||||
|
||||
@@ -222,7 +224,7 @@ pnpm build
|
||||
|
||||
<div>
|
||||
<p>QQ交流群</p>
|
||||
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/qq-soybean-admin-4.jpg" style="width:200px" />
|
||||
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/qq-soybean-admin-5.jpg" style="width:200px" />
|
||||
</div>
|
||||
<!-- <div>
|
||||
<p>微信群</p>
|
||||
|
||||
32
package.json
32
package.json
@@ -62,45 +62,45 @@
|
||||
"json5": "2.2.3",
|
||||
"naive-ui": "2.43.1",
|
||||
"nprogress": "0.2.0",
|
||||
"pinia": "3.0.3",
|
||||
"tailwind-merge": "3.3.1",
|
||||
"vue": "3.5.22",
|
||||
"pinia": "3.0.4",
|
||||
"tailwind-merge": "3.4.0",
|
||||
"vue": "3.5.24",
|
||||
"vue-draggable-plus": "0.6.0",
|
||||
"vue-i18n": "11.1.12",
|
||||
"vue-router": "4.6.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@elegant-router/vue": "0.3.8",
|
||||
"@iconify/json": "2.2.402",
|
||||
"@iconify/json": "2.2.407",
|
||||
"@sa/scripts": "workspace:*",
|
||||
"@sa/uno-preset": "workspace:*",
|
||||
"@soybeanjs/eslint-config": "1.7.1",
|
||||
"@types/node": "24.9.2",
|
||||
"@soybeanjs/eslint-config": "1.7.3",
|
||||
"@types/node": "24.10.1",
|
||||
"@types/nprogress": "0.2.3",
|
||||
"@unocss/eslint-config": "66.5.4",
|
||||
"@unocss/preset-icons": "66.5.4",
|
||||
"@unocss/preset-uno": "66.5.4",
|
||||
"@unocss/transformer-directives": "66.5.4",
|
||||
"@unocss/transformer-variant-group": "66.5.4",
|
||||
"@unocss/vite": "66.5.4",
|
||||
"@unocss/eslint-config": "66.5.6",
|
||||
"@unocss/preset-icons": "66.5.6",
|
||||
"@unocss/preset-uno": "66.5.6",
|
||||
"@unocss/transformer-directives": "66.5.6",
|
||||
"@unocss/transformer-variant-group": "66.5.6",
|
||||
"@unocss/vite": "66.5.6",
|
||||
"@vitejs/plugin-vue": "6.0.1",
|
||||
"@vitejs/plugin-vue-jsx": "5.1.1",
|
||||
"consola": "3.4.2",
|
||||
"eslint": "9.39.0",
|
||||
"eslint": "9.39.1",
|
||||
"eslint-plugin-vue": "10.5.1",
|
||||
"kolorist": "1.8.0",
|
||||
"sass": "1.93.3",
|
||||
"sass": "1.94.0",
|
||||
"simple-git-hooks": "2.13.1",
|
||||
"tsx": "4.20.6",
|
||||
"typescript": "5.9.3",
|
||||
"unplugin-icons": "22.5.0",
|
||||
"unplugin-vue-components": "30.0.0",
|
||||
"vite": "7.1.12",
|
||||
"vite": "7.2.2",
|
||||
"vite-plugin-progress": "0.0.7",
|
||||
"vite-plugin-svg-icons": "2.0.1",
|
||||
"vite-plugin-vue-devtools": "8.0.3",
|
||||
"vue-eslint-parser": "10.2.0",
|
||||
"vue-tsc": "3.1.2"
|
||||
"vue-tsc": "3.1.4"
|
||||
},
|
||||
"simple-git-hooks": {
|
||||
"commit-msg": "pnpm sa git-commit-verify",
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@sa/utils": "workspace:*",
|
||||
"axios": "1.13.1",
|
||||
"axios": "1.13.2",
|
||||
"axios-retry": "4.5.0",
|
||||
"qs": "6.14.0"
|
||||
},
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"devDependencies": {
|
||||
"@soybeanjs/changelog": "0.3.25",
|
||||
"bumpp": "10.3.1",
|
||||
"c12": "3.3.1",
|
||||
"c12": "3.3.2",
|
||||
"cac": "6.7.14",
|
||||
"consola": "3.4.2",
|
||||
"enquirer": "2.4.1",
|
||||
|
||||
1441
pnpm-lock.yaml
generated
1441
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { defu } from 'defu';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { themeSettings } from '@/theme/settings';
|
||||
import { $t } from '@/locales';
|
||||
|
||||
defineOptions({
|
||||
@@ -31,6 +33,8 @@ type ThemePreset = Pick<
|
||||
desc: string;
|
||||
i18nkey?: string;
|
||||
version: string;
|
||||
/** Optional NaiveUI theme overrides */
|
||||
naiveui?: App.Theme.NaiveUIThemeOverride;
|
||||
};
|
||||
|
||||
const presetModules = import.meta.glob('@/theme/preset/*.json', { eager: true, import: 'default' });
|
||||
@@ -76,7 +80,9 @@ const getPresetDesc = (preset: ThemePreset): string => {
|
||||
}
|
||||
};
|
||||
|
||||
const applyPreset = ({ themeScheme, grayscale, colourWeakness, layout, watermark, ...rest }: ThemePreset): void => {
|
||||
const applyPreset = (preset: ThemePreset): void => {
|
||||
const mergedPreset = defu(preset, themeSettings);
|
||||
const { themeScheme, grayscale, colourWeakness, layout, watermark, naiveui, ...rest } = mergedPreset;
|
||||
themeStore.setThemeScheme(themeScheme);
|
||||
themeStore.setGrayscale(grayscale);
|
||||
themeStore.setColourWeakness(colourWeakness);
|
||||
@@ -96,6 +102,9 @@ const applyPreset = ({ themeScheme, grayscale, colourWeakness, layout, watermark
|
||||
tokens: { ...rest.tokens }
|
||||
});
|
||||
|
||||
// Apply NaiveUI theme overrides if present
|
||||
themeStore.setNaiveThemeOverrides(naiveui);
|
||||
|
||||
window.$message?.success($t('theme.appearance.preset.applySuccess'));
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -24,6 +24,9 @@ export const useThemeStore = defineStore(SetupStoreId.Theme, () => {
|
||||
/** Theme settings */
|
||||
const settings: Ref<App.Theme.ThemeSetting> = ref(initThemeSettings());
|
||||
|
||||
/** Optional NaiveUI theme overrides from preset */
|
||||
const naiveThemeOverrides: Ref<App.Theme.NaiveUIThemeOverride | undefined> = ref(undefined);
|
||||
|
||||
/** Watermark time instance with controls */
|
||||
const { now: watermarkTime, pause: pauseWatermarkTime, resume: resumeWatermarkTime } = useNow({ controls: true });
|
||||
|
||||
@@ -53,7 +56,7 @@ export const useThemeStore = defineStore(SetupStoreId.Theme, () => {
|
||||
});
|
||||
|
||||
/** Naive theme */
|
||||
const naiveTheme = computed(() => getNaiveTheme(themeColors.value, settings.value));
|
||||
const naiveTheme = computed(() => getNaiveTheme(themeColors.value, settings.value, naiveThemeOverrides.value));
|
||||
|
||||
/**
|
||||
* Settings json
|
||||
@@ -198,6 +201,15 @@ export const useThemeStore = defineStore(SetupStoreId.Theme, () => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set NaiveUI theme overrides
|
||||
*
|
||||
* @param overrides NaiveUI theme overrides or undefined to clear
|
||||
*/
|
||||
function setNaiveThemeOverrides(overrides?: App.Theme.NaiveUIThemeOverride) {
|
||||
naiveThemeOverrides.value = overrides;
|
||||
}
|
||||
|
||||
/** Only run timer when watermark is visible and time display is enabled */
|
||||
function updateWatermarkTimer() {
|
||||
const { watermark } = settings.value;
|
||||
@@ -284,6 +296,7 @@ export const useThemeStore = defineStore(SetupStoreId.Theme, () => {
|
||||
updateThemeColors,
|
||||
setThemeLayout,
|
||||
setWatermarkEnableUserName,
|
||||
setWatermarkEnableTime
|
||||
setWatermarkEnableTime,
|
||||
setNaiveThemeOverrides
|
||||
};
|
||||
});
|
||||
|
||||
@@ -236,11 +236,15 @@ function getNaiveThemeColors(colors: App.Theme.ThemeColor, recommended = false)
|
||||
/**
|
||||
* Get naive theme
|
||||
*
|
||||
* @param settings Theme settings object.
|
||||
* @param settings.recommendColor Whether to use recommended color palette.
|
||||
* @param settings.themeRadius Border radius to use in the theme (in px).
|
||||
* @param colors Theme colors
|
||||
* @param settings Theme settings object
|
||||
* @param overrides Optional manual overrides from preset
|
||||
*/
|
||||
export function getNaiveTheme(colors: App.Theme.ThemeColor, settings: App.Theme.ThemeSetting) {
|
||||
export function getNaiveTheme(
|
||||
colors: App.Theme.ThemeColor,
|
||||
settings: App.Theme.ThemeSetting,
|
||||
overrides?: GlobalThemeOverrides
|
||||
) {
|
||||
const { primary: colorLoading } = colors;
|
||||
|
||||
const theme: GlobalThemeOverrides = {
|
||||
@@ -256,5 +260,7 @@ export function getNaiveTheme(colors: App.Theme.ThemeColor, settings: App.Theme.
|
||||
}
|
||||
};
|
||||
|
||||
return theme;
|
||||
// If there are overrides, merge them with priority
|
||||
// overrides has higher priority than auto-generated theme
|
||||
return overrides ? defu(overrides, theme) : theme;
|
||||
}
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
"name": "Azir's Preset",
|
||||
"desc": "It is a cold and elegant preset that Azir likes",
|
||||
"i18nkey": "theme.appearance.preset.azir",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"themeScheme": "light",
|
||||
"grayscale": false,
|
||||
"colourWeakness": false,
|
||||
"recommendColor": true,
|
||||
"themeColor": "#78a878",
|
||||
"otherColor": {
|
||||
@@ -14,57 +12,7 @@
|
||||
"warning": "#d4bb9d",
|
||||
"error": "#c49a9a"
|
||||
},
|
||||
"themeRadius": 6,
|
||||
"isInfoFollowPrimary": true,
|
||||
"layout": {
|
||||
"mode": "vertical-mix",
|
||||
"scrollMode": "wrapper"
|
||||
},
|
||||
"page": {
|
||||
"animate": true,
|
||||
"animateMode": "zoom-fade"
|
||||
},
|
||||
"header": {
|
||||
"height": 64,
|
||||
"breadcrumb": {
|
||||
"visible": true,
|
||||
"showIcon": true
|
||||
},
|
||||
"multilingual": {
|
||||
"visible": true
|
||||
},
|
||||
"globalSearch": {
|
||||
"visible": true
|
||||
}
|
||||
},
|
||||
"tab": {
|
||||
"visible": true,
|
||||
"cache": true,
|
||||
"height": 48,
|
||||
"mode": "chrome"
|
||||
},
|
||||
"fixedHeaderAndTab": true,
|
||||
"sider": {
|
||||
"inverted": false,
|
||||
"width": 220,
|
||||
"collapsedWidth": 64,
|
||||
"mixWidth": 90,
|
||||
"mixCollapsedWidth": 64,
|
||||
"mixChildMenuWidth": 200
|
||||
},
|
||||
"footer": {
|
||||
"visible": true,
|
||||
"fixed": true,
|
||||
"height": 56,
|
||||
"right": true
|
||||
},
|
||||
"watermark": {
|
||||
"visible": false,
|
||||
"text": "SoybeanAdmin",
|
||||
"enableUserName": false,
|
||||
"enableTime": true,
|
||||
"timeFormat": "YYYY-MM-DD HH:mm:ss"
|
||||
},
|
||||
"tokens": {
|
||||
"light": {
|
||||
"colors": {
|
||||
@@ -86,5 +34,19 @@
|
||||
"base-text": "rgb(224, 224, 224)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"naiveui": {
|
||||
"Alert": {
|
||||
"borderRadiusMedium": "12px",
|
||||
"fontWeightStrong": "600",
|
||||
"paddingMedium": "0 20px"
|
||||
},
|
||||
"Card": {
|
||||
"borderRadius": "16px",
|
||||
"paddingMedium": "24px"
|
||||
},
|
||||
"Input": {
|
||||
"borderRadius": "10px"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,33 +2,12 @@
|
||||
"name": "Compact Preset",
|
||||
"desc": "Compact layout preset for small screens",
|
||||
"i18nkey": "theme.appearance.preset.compact",
|
||||
"version": "1.0.0",
|
||||
"themeScheme": "light",
|
||||
"grayscale": false,
|
||||
"colourWeakness": false,
|
||||
"recommendColor": false,
|
||||
"themeColor": "#646cff",
|
||||
"otherColor": {
|
||||
"info": "#2080f0",
|
||||
"success": "#52c41a",
|
||||
"warning": "#faad14",
|
||||
"error": "#f5222d"
|
||||
},
|
||||
"version": "1.0.1",
|
||||
"themeRadius": 6,
|
||||
"isInfoFollowPrimary": true,
|
||||
"layout": {
|
||||
"mode": "vertical",
|
||||
"scrollMode": "content"
|
||||
},
|
||||
"page": {
|
||||
"animate": true,
|
||||
"animateMode": "fade-slide"
|
||||
},
|
||||
"header": {
|
||||
"height": 48,
|
||||
"breadcrumb": {
|
||||
"visible": true,
|
||||
"showIcon": true
|
||||
"visible": false
|
||||
},
|
||||
"multilingual": {
|
||||
"visible": false
|
||||
@@ -41,9 +20,9 @@
|
||||
"visible": true,
|
||||
"cache": true,
|
||||
"height": 36,
|
||||
"mode": "button"
|
||||
"mode": "button",
|
||||
"closeTabByMiddleClick": false
|
||||
},
|
||||
"fixedHeaderAndTab": true,
|
||||
"sider": {
|
||||
"inverted": false,
|
||||
"width": 180,
|
||||
@@ -53,38 +32,6 @@
|
||||
"mixChildMenuWidth": 180
|
||||
},
|
||||
"footer": {
|
||||
"visible": false,
|
||||
"fixed": false,
|
||||
"height": 40,
|
||||
"right": true
|
||||
},
|
||||
"watermark": {
|
||||
"visible": false,
|
||||
"text": "SoybeanAdmin",
|
||||
"enableUserName": false,
|
||||
"enableTime": false,
|
||||
"timeFormat": "YYYY-MM-DD HH:mm"
|
||||
},
|
||||
"tokens": {
|
||||
"light": {
|
||||
"colors": {
|
||||
"container": "rgb(255, 255, 255)",
|
||||
"layout": "rgb(247, 250, 252)",
|
||||
"inverted": "rgb(0, 20, 40)",
|
||||
"base-text": "rgb(31, 31, 31)"
|
||||
},
|
||||
"boxShadow": {
|
||||
"header": "0 1px 2px rgb(0, 21, 41, 0.08)",
|
||||
"sider": "2px 0 8px 0 rgb(29, 35, 41, 0.05)",
|
||||
"tab": "0 1px 2px rgb(0, 21, 41, 0.08)"
|
||||
}
|
||||
},
|
||||
"dark": {
|
||||
"colors": {
|
||||
"container": "rgb(28, 28, 28)",
|
||||
"layout": "rgb(18, 18, 18)",
|
||||
"base-text": "rgb(224, 224, 224)"
|
||||
}
|
||||
}
|
||||
"visible": false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
"name": "Dark Preset",
|
||||
"desc": "Dark theme preset for night time usage",
|
||||
"i18nkey": "theme.appearance.preset.dark",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"themeScheme": "dark",
|
||||
"grayscale": false,
|
||||
"colourWeakness": false,
|
||||
"recommendColor": false,
|
||||
"themeColor": "#409eff",
|
||||
"themeColor": "#646cff",
|
||||
"otherColor": {
|
||||
"info": "#2080f0",
|
||||
"success": "#52c41a",
|
||||
@@ -41,11 +41,12 @@
|
||||
"visible": true,
|
||||
"cache": true,
|
||||
"height": 44,
|
||||
"mode": "chrome"
|
||||
"mode": "chrome",
|
||||
"closeTabByMiddleClick": false
|
||||
},
|
||||
"fixedHeaderAndTab": true,
|
||||
"sider": {
|
||||
"inverted": true,
|
||||
"inverted": false,
|
||||
"width": 220,
|
||||
"collapsedWidth": 64,
|
||||
"mixWidth": 90,
|
||||
|
||||
@@ -41,7 +41,8 @@
|
||||
"visible": true,
|
||||
"cache": true,
|
||||
"height": 44,
|
||||
"mode": "chrome"
|
||||
"mode": "chrome",
|
||||
"closeTabByMiddleClick": false
|
||||
},
|
||||
"fixedHeaderAndTab": true,
|
||||
"sider": {
|
||||
|
||||
3
src/typings/app.d.ts
vendored
3
src/typings/app.d.ts
vendored
@@ -4,6 +4,9 @@ declare namespace App {
|
||||
namespace Theme {
|
||||
type ColorPaletteNumber = import('@sa/color').ColorPaletteNumber;
|
||||
|
||||
/** NaiveUI theme overrides that can be specified in preset */
|
||||
type NaiveUIThemeOverride = import('naive-ui').GlobalThemeOverrides;
|
||||
|
||||
/** Theme setting */
|
||||
interface ThemeSetting {
|
||||
/** Theme scheme */
|
||||
|
||||
@@ -15,7 +15,7 @@ const gap = computed(() => (appStore.isMobile ? 0 : 16));
|
||||
|
||||
<template>
|
||||
<NSpace vertical :size="16">
|
||||
<NAlert :title="$t('common.warning')" type="warning">
|
||||
<NAlert :title="$t('common.tip')" type="warning">
|
||||
{{ $t('page.home.branchDesc') }}
|
||||
</NAlert>
|
||||
<HeaderBanner />
|
||||
|
||||
Reference in New Issue
Block a user