diff --git a/.vscode/extensions.json b/.vscode/extensions.json index d2f675d7..00f22234 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -6,9 +6,6 @@ "dbaeumer.vscode-eslint", "editorconfig.editorconfig", "esbenp.prettier-vscode", - "formulahendry.auto-close-tag", - "formulahendry.auto-complete-tag", - "formulahendry.auto-rename-tag", "lokalise.i18n-ally", "mhutchie.git-graph", "mikestead.dotenv", diff --git a/package.json b/package.json index f9b34e9e..8a37c286 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,8 @@ { "name": "ruoyi-vue-plus", "type": "module", - "version": "1.3.6", + "version": "1.3.8", "description": "RuoYi-Vue-Plus多租户管理系统", - "author": { - "name": "xlsea", - "email": "xlsea@outlook.com", - "url": "https://blog.xlsea.cn" - }, "license": "MIT", "homepage": "https://gitee.com/xlsea/ruoyi-plus-soybean", "keywords": [ @@ -56,46 +51,46 @@ "echarts": "5.5.1", "jsencrypt": "^3.3.2", "json5": "2.2.3", - "monaco-editor": "^0.48.0", - "naive-ui": "2.39.0", + "monaco-editor": "^0.52.0", + "naive-ui": "2.40.1", "nprogress": "0.2.0", - "pinia": "2.2.2", - "tailwind-merge": "2.5.2", - "vue": "3.5.6", - "vue-draggable-plus": "0.5.3", - "vue-i18n": "10.0.1", + "pinia": "2.2.4", + "tailwind-merge": "2.5.4", + "vue": "3.5.12", + "vue-draggable-plus": "0.5.4", + "vue-i18n": "10.0.4", "vue-router": "4.4.5" }, "devDependencies": { "@elegant-router/vue": "0.3.8", - "@iconify/json": "2.2.250", + "@iconify/json": "2.2.263", "@sa/scripts": "workspace:*", "@sa/uno-preset": "workspace:*", - "@soybeanjs/eslint-config": "1.4.1", - "@types/node": "22.5.5", + "@soybeanjs/eslint-config": "1.4.2", + "@types/node": "22.7.9", "@types/nprogress": "0.2.3", - "@unocss/eslint-config": "0.62.4", - "@unocss/preset-icons": "0.62.4", - "@unocss/preset-uno": "0.62.4", - "@unocss/transformer-directives": "0.62.4", - "@unocss/transformer-variant-group": "0.62.4", - "@unocss/vite": "0.62.4", + "@unocss/eslint-config": "0.63.6", + "@unocss/preset-icons": "0.63.6", + "@unocss/preset-uno": "0.63.6", + "@unocss/transformer-directives": "0.63.6", + "@unocss/transformer-variant-group": "0.63.6", + "@unocss/vite": "0.63.6", "@vitejs/plugin-vue": "5.1.4", "@vitejs/plugin-vue-jsx": "4.0.1", - "eslint": "9.10.0", - "eslint-plugin-vue": "9.28.0", + "eslint": "9.13.0", + "eslint-plugin-vue": "9.29.1", "lint-staged": "15.2.10", - "sass": "1.79.2", + "sass": "1.80.4", "simple-git-hooks": "2.11.1", "tsx": "4.19.1", - "typescript": "5.6.2", + "typescript": "5.6.3", "unplugin-icons": "0.19.3", "unplugin-vue-components": "0.27.4", - "vite": "5.4.6", + "vite": "5.4.10", "vite-plugin-monaco-editor": "^1.1.0", "vite-plugin-progress": "0.0.7", "vite-plugin-svg-icons": "2.0.1", - "vite-plugin-vue-devtools": "7.4.5", + "vite-plugin-vue-devtools": "7.5.4", "vue-eslint-parser": "9.4.3", "vue-tsc": "2.1.6" }, @@ -105,6 +100,5 @@ }, "lint-staged": { "*": "eslint --fix" - }, - "website": "https://blog.xlsea.cn" + } } diff --git a/packages/alova/package.json b/packages/alova/package.json new file mode 100644 index 00000000..9f5de140 --- /dev/null +++ b/packages/alova/package.json @@ -0,0 +1,20 @@ +{ + "name": "@sa/alova", + "version": "1.3.8", + "exports": { + ".": "./src/index.ts", + "./fetch": "./src/fetch.ts", + "./client": "./src/client.ts", + "./mock": "./src/mock.ts" + }, + "typesVersions": { + "*": { + "*": ["./src/*"] + } + }, + "dependencies": { + "@alova/mock": "2.0.8", + "@sa/utils": "workspace:*", + "alova": "3.1.1" + } +} diff --git a/packages/alova/src/client.ts b/packages/alova/src/client.ts new file mode 100644 index 00000000..0d76ebb9 --- /dev/null +++ b/packages/alova/src/client.ts @@ -0,0 +1 @@ +export * from 'alova/client'; diff --git a/packages/alova/src/constant.ts b/packages/alova/src/constant.ts new file mode 100644 index 00000000..be5c43ca --- /dev/null +++ b/packages/alova/src/constant.ts @@ -0,0 +1,2 @@ +/** the backend error code key */ +export const BACKEND_ERROR_CODE = 'BACKEND_ERROR'; diff --git a/packages/alova/src/fetch.ts b/packages/alova/src/fetch.ts new file mode 100644 index 00000000..8511ce46 --- /dev/null +++ b/packages/alova/src/fetch.ts @@ -0,0 +1,2 @@ +import adapterFetch from 'alova/fetch'; +export default adapterFetch; diff --git a/packages/alova/src/index.ts b/packages/alova/src/index.ts new file mode 100644 index 00000000..42642535 --- /dev/null +++ b/packages/alova/src/index.ts @@ -0,0 +1,77 @@ +import { createAlova } from 'alova'; +import type { AlovaDefaultCacheAdapter, AlovaGenerics, AlovaGlobalCacheAdapter, AlovaRequestAdapter } from 'alova'; +import VueHook from 'alova/vue'; +import type { VueHookType } from 'alova/vue'; +import adapterFetch from 'alova/fetch'; +import { createServerTokenAuthentication } from 'alova/client'; +import type { FetchRequestInit } from 'alova/fetch'; +import { BACKEND_ERROR_CODE } from './constant'; +import type { CustomAlovaConfig, RequestOptions } from './type'; + +export const createAlovaRequest = < + RequestConfig = FetchRequestInit, + ResponseType = Response, + ResponseHeader = Headers, + L1Cache extends AlovaGlobalCacheAdapter = AlovaDefaultCacheAdapter, + L2Cache extends AlovaGlobalCacheAdapter = AlovaDefaultCacheAdapter +>( + customConfig: CustomAlovaConfig< + AlovaGenerics + >, + options: RequestOptions> +) => { + const { tokenRefresher } = options; + const { onAuthRequired, onResponseRefreshToken } = createServerTokenAuthentication< + VueHookType, + AlovaRequestAdapter + >({ + refreshTokenOnSuccess: { + isExpired: (response, method) => tokenRefresher?.isExpired(response, method) || false, + handler: async (response, method) => tokenRefresher?.handler(response, method) + }, + refreshTokenOnError: { + isExpired: (response, method) => tokenRefresher?.isExpired(response, method) || false, + handler: async (response, method) => tokenRefresher?.handler(response, method) + } + }); + + const instance = createAlova({ + ...customConfig, + timeout: customConfig.timeout ?? 10 * 1000, + requestAdapter: (customConfig.requestAdapter as any) ?? adapterFetch(), + statesHook: VueHook, + beforeRequest: onAuthRequired(options.onRequest as any), + responded: onResponseRefreshToken({ + onSuccess: async (response, method) => { + // check if http status is success + let error: any = null; + let transformedData: any = null; + try { + if (await options.isBackendSuccess(response)) { + transformedData = await options.transformBackendResponse(response); + } else { + error = new Error('the backend request error'); + error.code = BACKEND_ERROR_CODE; + } + } catch (err) { + error = err; + } + + if (error) { + await options.onError?.(error, response, method); + throw error; + } + + return transformedData; + }, + onComplete: options.onComplete, + onError: (error, method) => options.onError?.(error, null, method) + }) + }); + + return instance; +}; + +export { BACKEND_ERROR_CODE }; +export type * from './type'; +export type * from 'alova'; diff --git a/packages/alova/src/mock.ts b/packages/alova/src/mock.ts new file mode 100644 index 00000000..f3aaf087 --- /dev/null +++ b/packages/alova/src/mock.ts @@ -0,0 +1 @@ +export * from '@alova/mock'; diff --git a/packages/alova/src/type.ts b/packages/alova/src/type.ts new file mode 100644 index 00000000..27b84b25 --- /dev/null +++ b/packages/alova/src/type.ts @@ -0,0 +1,52 @@ +import type { AlovaGenerics, AlovaOptions, AlovaRequestAdapter, Method, ResponseCompleteHandler } from 'alova'; + +export type CustomAlovaConfig = Omit< + AlovaOptions, + 'statesHook' | 'beforeRequest' | 'responded' | 'requestAdapter' +> & { + /** request adapter. all request of alova will be sent by it. */ + requestAdapter?: AlovaRequestAdapter; +}; + +export interface RequestOptions { + /** + * The hook before request + * + * For example: You can add header token in this hook + * + * @param method alova Method Instance + */ + onRequest?: AlovaOptions['beforeRequest']; + /** + * The hook to check backend response is success or not + * + * @param response alova response + */ + isBackendSuccess: (response: AG['Response']) => Promise; + + /** The config to refresh token */ + tokenRefresher?: { + /** detect the token is expired */ + isExpired(response: AG['Response'], Method: Method): Promise | boolean; + /** refresh token handler */ + handler(response: AG['Response'], Method: Method): Promise; + }; + + /** The hook after backend request complete */ + onComplete?: ResponseCompleteHandler; + + /** + * The hook to handle error + * + * For example: You can show error message in this hook + * + * @param error + */ + onError?: (error: any, response: AG['Response'] | null, methodInstance: Method) => any | Promise; + /** + * transform backend response when the responseType is json + * + * @param response alova response + */ + transformBackendResponse: (response: AG['Response']) => any; +} diff --git a/packages/alova/tsconfig.json b/packages/alova/tsconfig.json new file mode 100644 index 00000000..5823ed54 --- /dev/null +++ b/packages/alova/tsconfig.json @@ -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"] +} diff --git a/packages/axios/package.json b/packages/axios/package.json index acf462fa..562cb97f 100644 --- a/packages/axios/package.json +++ b/packages/axios/package.json @@ -1,6 +1,6 @@ { "name": "@sa/axios", - "version": "1.3.6", + "version": "1.3.8", "exports": { ".": "./src/index.ts" }, diff --git a/packages/color/package.json b/packages/color/package.json index 107f10d1..8ecba11e 100644 --- a/packages/color/package.json +++ b/packages/color/package.json @@ -1,6 +1,6 @@ { "name": "@sa/color", - "version": "1.3.6", + "version": "1.3.8", "exports": { ".": "./src/index.ts" }, diff --git a/packages/hooks/package.json b/packages/hooks/package.json index ae22c3b7..e845c344 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@sa/hooks", - "version": "1.3.6", + "version": "1.3.8", "exports": { ".": "./src/index.ts" }, diff --git a/packages/materials/package.json b/packages/materials/package.json index 2c65729c..3ccd503d 100644 --- a/packages/materials/package.json +++ b/packages/materials/package.json @@ -1,6 +1,6 @@ { "name": "@sa/materials", - "version": "1.3.6", + "version": "1.3.8", "exports": { ".": "./src/index.ts" }, diff --git a/packages/materials/src/libs/page-tab/index.vue b/packages/materials/src/libs/page-tab/index.vue index dd4c5d13..0c0c6995 100644 --- a/packages/materials/src/libs/page-tab/index.vue +++ b/packages/materials/src/libs/page-tab/index.vue @@ -53,23 +53,10 @@ const bindProps = computed(() => { function handleClose() { emit('close'); } - -function handleMouseup(e: MouseEvent) { - // close tab by mouse wheel button click - if (e.button === 1) { - handleClose(); - } -}