chore(merge): Merge Soybean branch main into dev

This commit is contained in:
xlsea
2026-05-23 10:07:48 +08:00
23 changed files with 1617 additions and 1598 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
steps:
- name: Checkout Code
uses: actions/checkout@v3
uses: actions/checkout@v6
with:
fetch-depth: 0
+3 -3
View File
@@ -12,13 +12,13 @@ jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: actions/setup-node@v3
- uses: actions/setup-node@v6
with:
node-version: 18.x
node-version: lts/*
- run: npx githublogen
env:
+1
View File
@@ -33,6 +33,7 @@ package-lock.json
yarn.lock
.VSCodeCounter
src-tauri/target
# VibeCoding state
.ai_state/
-3
View File
@@ -1,4 +1 @@
registry=https://registry.npmmirror.com/
shamefully-hoist=true
ignore-workspace-root-check=true
link-workspace-packages=true
+4 -1
View File
@@ -13,7 +13,10 @@
"i18n-ally.keystyle": "nested",
"i18n-ally.localesPaths": ["src/locales/langs"],
"i18n-ally.parsers.typescript.compilerOptions": {
"moduleResolution": "node"
"moduleResolution": "node",
"ignoreDeprecations": "6.0",
"rootDir": ".",
"baseUrl": "."
},
"oxc.fmt.configPath": ".oxfmtrc.json",
"unocss.root": ["./"],
+22 -22
View File
@@ -1,13 +1,13 @@
{
"name": "ruoyi-vue-plus",
"version": "2.1.0",
"version": "2.2.0",
"description": "结合了 RuoYi-Vue-Plus 的强大后端功能和 Soybean Admin 的现代化前端特性,为开发者提供了完整的企业管理解决方案。",
"keywords": [
"RuoYi-Vue-Plus",
"Soybean Admin",
"TypeScript",
"UnoCSS",
"Vite7",
"Vite8",
"Vue3 admin ",
"ant-design-vue v4",
"naive-ui",
@@ -61,19 +61,19 @@
},
"dependencies": {
"@better-scroll/core": "2.5.1",
"@iconify/vue": "5.0.0",
"@iconify/vue": "5.0.1",
"@sa/axios": "workspace:*",
"@sa/color": "workspace:*",
"@sa/hooks": "workspace:*",
"@sa/materials": "workspace:*",
"@sa/utils": "workspace:*",
"@types/streamsaver": "^2.0.5",
"@vueuse/core": "14.2.1",
"@wangeditor-next/editor": "^5.6.49",
"@vueuse/core": "14.3.0",
"@wangeditor-next/editor": "^5.7.4",
"@wangeditor-next/editor-for-vue": "^5.1.14",
"clipboard": "2.0.11",
"dayjs": "1.11.20",
"defu": "6.1.4",
"defu": "6.1.7",
"echarts": "6.0.0",
"highlight.js": "^11.11.1",
"jsencrypt": "^3.5.4",
@@ -82,41 +82,41 @@
"nprogress": "0.2.0",
"pinia": "3.0.4",
"streamsaver": "^2.0.6",
"tailwind-merge": "3.5.0",
"vue": "3.5.31",
"tailwind-merge": "3.6.0",
"vue": "3.5.34",
"vue-advanced-cropper": "^2.8.9",
"vue-draggable-plus": "0.6.1",
"vue-i18n": "11.3.0",
"vue-router": "5.0.4"
"vue-i18n": "11.4.2",
"vue-router": "5.0.7"
},
"devDependencies": {
"@elegant-router/vue": "0.3.8",
"@iconify/json": "2.2.456",
"@iconify/json": "2.2.472",
"@sa/scripts": "workspace:*",
"@sa/uno-preset": "workspace:*",
"@soybeanjs/eslint-config-vue": "^0.0.2",
"@types/node": "25.5.0",
"@types/node": "25.7.0",
"@types/nprogress": "0.2.3",
"@vitejs/plugin-vue": "6.0.5",
"@vitejs/plugin-vue": "6.0.6",
"@vitejs/plugin-vue-jsx": "5.1.5",
"consola": "3.4.2",
"eslint": "10.1.0",
"eslint": "10.3.0",
"kolorist": "1.8.0",
"oxfmt": "^0.42.0",
"oxlint": "^1.57.0",
"sass": "1.98.0",
"oxfmt": "^0.49.0",
"oxlint": "^1.64.0",
"sass": "1.99.0",
"simple-git-hooks": "2.13.1",
"tsx": "4.21.0",
"typescript": "6.0.2",
"unocss": "^66.6.7",
"typescript": "6.0.3",
"unocss": "^66.6.8",
"unplugin-icons": "23.0.1",
"unplugin-vue-components": "32.0.0",
"vite": "8.0.3",
"vite": "8.0.12",
"vite-plugin-progress": "0.0.7",
"vite-plugin-svg-icons": "2.0.1",
"vite-plugin-vue-devtools": "8.1.1",
"vite-plugin-vue-devtools": "8.1.2",
"vite-plugin-vue-transition-root-validator": "^0.1.0",
"vue-tsc": "3.2.6"
"vue-tsc": "3.2.8"
},
"simple-git-hooks": {
"commit-msg": "pnpm sa git-commit-verify",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@sa/alova",
"version": "2.1.0",
"version": "2.2.0",
"typesVersions": {
"*": {
"*": [
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@sa/axios",
"version": "2.1.0",
"version": "2.2.0",
"typesVersions": {
"*": {
"*": [
@@ -13,11 +13,11 @@
},
"dependencies": {
"@sa/utils": "workspace:*",
"axios": "1.14.0",
"axios": "1.16.0",
"axios-retry": "4.5.0",
"qs": "6.15.0"
"qs": "6.15.1"
},
"devDependencies": {
"@types/qs": "6.15.0"
"@types/qs": "6.15.1"
}
}
+2 -2
View File
@@ -1,4 +1,4 @@
import axios, { AxiosError } from 'axios';
import { create, AxiosError } from 'axios';
import type { AxiosResponse, CreateAxiosDefaults, InternalAxiosRequestConfig } from 'axios';
import axiosRetry from 'axios-retry';
import { nanoid } from '@sa/utils';
@@ -22,7 +22,7 @@ function createCommonRequest<
const opts = createDefaultOptions<ResponseData, ApiData, State>(options);
const axiosConf = createAxiosConfig(axiosConfig);
const instance = axios.create(axiosConf);
const instance = create(axiosConf);
const abortControllerMap = new Map<string, AbortController>();
+1 -1
View File
@@ -32,7 +32,7 @@ export async function transformResponse(response: AxiosResponse) {
const responseType: ResponseType = (response.config?.responseType as ResponseType) || 'json';
if (responseType === 'json') return;
const isJson = response.headers['content-type']?.includes('application/json');
const isJson = (response.headers['content-type'] as string)?.includes('application/json');
if (!isJson) return;
if (responseType === 'blob') {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@sa/color",
"version": "2.1.0",
"version": "2.2.0",
"typesVersions": {
"*": {
"*": [
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@sa/hooks",
"version": "2.1.0",
"version": "2.2.0",
"typesVersions": {
"*": {
"*": [
+30 -69
View File
@@ -1,66 +1,31 @@
import { inject, provide } from 'vue';
type ContextName = string | { name: string; key: string | symbol };
type ContextValue<T> = T extends (...args: any[]) => any ? ReturnType<T> : T;
type ContextProvider<T> = T extends (...args: any[]) => any ? T : (arg: T) => T;
type ContextConsumer<Context> = <N extends string | null | undefined = undefined>(
consumerName?: N,
defaultValue?: Context
) => N extends null | undefined ? Context | null : Context;
/**
* Use context
* Creates a context provider and consumer pair.
*
* @example
* ```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
*
* // context.ts
* import { ref } from 'vue';
* import { useContext } from '@sa/hooks';
*
* export const [provideDemoContext, useDemoContext] = useContext('demo', () => {
* const count = ref(0);
*
* function increment() {
* count.value++;
* }
*
* function decrement() {
* count.value--;
* }
*
* return {
* count,
* increment,
* decrement
* };
* })
* ``` // A.vue
* ```vue
* <template>
* <div>A</div>
* </template>
* <script setup lang="ts">
* import { provideDemoContext } from './context';
*
* provideDemoContext();
* // const { increment } = provideDemoContext(); // also can control the store in the parent component
* </script>
* ``` // B.vue
* ```vue
* <template>
* <div>B</div>
* </template>
* <script setup lang="ts">
* import { useDemoContext } from './context';
*
* const { count, increment } = useDemoContext();
* </script>
* ```;
*
* // C.vue is same as B.vue
*
* @param contextName Context name
* @param fn Context function
* @param contextName - The name of the context. This can be a string or an object with a `name` and `key` property.
* @param composable - An optional composable function that returns the context value. If not provided, the context value will be the first argument passed to the provider.
*/
export default function useContext<Arguments extends Array<any>, T>(
contextName: string,
composable: (...args: Arguments) => T
export default function useContext<T>(
contextName: ContextName,
composable?: T extends (...args: any[]) => any ? T : never
) {
const key = Symbol(contextName);
type Context = ContextValue<T>;
const name = typeof contextName === 'string' ? contextName : contextName.name;
const key = typeof contextName === 'string' ? Symbol(contextName) : contextName.key;
/**
* Injects the context value.
@@ -70,27 +35,23 @@ export default function useContext<Arguments extends Array<any>, T>(
* @param defaultValue - The default value to return if the context is not provided.
* @returns The context value.
*/
const useInject = <N extends string | null | undefined = undefined>(
consumerName?: N,
defaultValue?: T
): N extends null | undefined ? T | null : T => {
const value = inject(key, defaultValue);
const useInject = (consumerName?: string | null, defaultValue?: any) => {
const value = inject(key, defaultValue) ?? null;
if (consumerName && !value) {
throw new Error(`\`${consumerName}\` must be used within \`${contextName}\``);
if (consumerName != null && value === null) {
throw new Error(`\`${consumerName}\` must be used within \`${name}\``);
}
// @ts-expect-error - we want to return null if the value is undefined or null
return value || null;
return value;
};
const useProvide = (...args: Arguments) => {
const value = composable(...args);
const useProvide = (...args: any[]) => {
const value = composable?.(...args) ?? args[0];
provide(key, value);
return value;
};
return [useProvide, useInject] as const;
return [useProvide, useInject] as [ContextProvider<T>, ContextConsumer<Context>];
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@sa/materials",
"version": "2.1.0",
"version": "2.2.0",
"typesVersions": {
"*": {
"*": [
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@sa/scripts",
"version": "2.1.0",
"version": "2.2.0",
"bin": {
"sa": "./bin.ts"
},
@@ -15,15 +15,15 @@
".": "./src/index.ts"
},
"devDependencies": {
"@soybeanjs/changelog": "0.4.5",
"bumpp": "11.0.1",
"c12": "3.3.3",
"@soybeanjs/changelog": "0.4.7",
"bumpp": "11.1.0",
"c12": "3.3.4",
"cac": "7.0.0",
"consola": "3.4.2",
"enquirer": "2.4.1",
"execa": "9.6.1",
"kolorist": "1.8.0",
"npm-check-updates": "19.6.6",
"npm-check-updates": "22.2.0",
"picomatch": "4.0.4",
"rimraf": "6.1.3"
}
+25 -2
View File
@@ -17,7 +17,14 @@ interface PromptObject {
* @param lang
*/
export async function gitCommit(lang: Lang = 'en-us') {
const { gitCommitMessages, gitCommitTypes, gitCommitScopes } = locales[lang];
const { gitCommitMessages, gitCommitNoStaged, gitCommitTypes, gitCommitScopes } = locales[lang];
const stagedFiles = await execCommand('git', ['diff', '--cached', '--name-only']);
if (!stagedFiles) {
console.error(gitCommitNoStaged);
process.exit(1);
}
const typesChoices = gitCommitTypes.map(([value, msg]) => {
const nameWithSuffix = `${value}:`;
@@ -35,7 +42,18 @@ export async function gitCommit(lang: Lang = 'en-us') {
message: `${value.padEnd(30)} (${msg})`
}));
const result = await prompt<PromptObject>([
// Suppress ERR_USE_AFTER_CLOSE thrown by enquirer's readline cleanup on Ctrl+C (Node.js v24+)
const errorHandler = (error: NodeJS.ErrnoException) => {
if (error.code === 'ERR_USE_AFTER_CLOSE') {
process.exit(0);
}
};
process.on('uncaughtException', errorHandler);
let result: PromptObject;
try {
result = await prompt<PromptObject>([
{
name: 'types',
type: 'select',
@@ -54,6 +72,11 @@ export async function gitCommit(lang: Lang = 'en-us') {
message: gitCommitMessages.description
}
]);
} catch {
process.exit(0);
} finally {
process.off('uncaughtException', errorHandler);
}
const breaking = result.description.startsWith('!') ? '!' : '';
+2
View File
@@ -37,6 +37,7 @@ export const locales = {
['release', '发布项目新版本'],
['other', '其他的变更']
] as [string, string][],
gitCommitNoStaged: `${bgRed(' 错误 ')} ${red('暂存区没有文件,请先使用 git add 添加文件后再提交!')}`,
gitCommitVerify: `${bgRed(' 错误 ')} ${red('git 提交信息必须符合 Conventional Commits 标准!')}\n\n${green(
'推荐使用命令 `pnpm commit` 生成符合 Conventional Commits 标准的提交信息。\n获取有关 Conventional Commits 的更多信息,请访问此链接: https://conventionalcommits.org'
)}`
@@ -75,6 +76,7 @@ export const locales = {
['release', 'release project'],
['other', 'other changes']
] as [string, string][],
gitCommitNoStaged: `${bgRed(' ERROR ')} ${red('No files in staging area, please use git add to stage files first!')}`,
gitCommitVerify: `${bgRed(' ERROR ')} ${red('git commit message must match the Conventional Commits standard!')}\n\n${green(
'Recommended to use the command `pnpm commit` to generate Conventional Commits compliant commit information.\nGet more info about Conventional Commits, follow this link: https://conventionalcommits.org'
)}`
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@sa/uno-preset",
"version": "2.1.0",
"version": "2.2.0",
"typesVersions": {
"*": {
"*": [
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@sa/utils",
"version": "2.1.0",
"version": "2.2.0",
"typesVersions": {
"*": {
"*": [
@@ -16,7 +16,7 @@
"crypto-js": "4.2.0",
"klona": "2.0.6",
"localforage": "1.10.0",
"nanoid": "5.1.7"
"nanoid": "5.1.11"
},
"devDependencies": {
"@types/crypto-js": "4.2.2"
+1478 -1459
View File
File diff suppressed because it is too large Load Diff
+8
View File
@@ -1,2 +1,10 @@
packages:
- 'packages/*'
allowBuilds:
'@parcel/watcher': false
esbuild: false
simple-git-hooks: false
vue-demi: false
shamefullyHoist: true
ignoreWorkspaceRootCheck: true
linkWorkspacePackages: true
-1
View File
@@ -37,7 +37,6 @@ const editorConfig: Partial<IEditorConfig> = {
fieldName: 'file',
meta: {},
headers: {
// @ts-expect-error ignore this type error
Authorization: `Bearer ${getToken()}`,
clientid: import.meta.env.VITE_APP_CLIENT_ID!
},
@@ -6,7 +6,13 @@ import { useRouteStore } from '@/store/modules/route';
import { useThemeStore } from '@/store/modules/theme';
import { useRouterPush } from '@/hooks/common/router';
export const [provideMixMenuContext, useMixMenuContext] = useContext('MixMenu', useMixMenu);
export const [provideMixMenuContext, useMixMenuContext] = useContext(
{
name: 'MixMenu',
key: Symbol.for('MixMenu')
},
useMixMenu
);
function useMixMenu() {
const route = useRoute();