Compare commits

...

6 Commits

Author SHA1 Message Date
疯狂的狮子Li
259325b4ee update 删除无用依赖 2026-09-10 11:57:39 +08:00
疯狂的狮子Li
dd98d6ceac update 升级 依赖版本并替换废弃依赖 crypto-js
- 替换已废弃的 crypto-js 为 @noble/ciphers@2.4.0(零依赖、经过安全审计),
    重写 src/utils/crypto.ts,密文格式保持 AES-256-ECB/PKCS7Padding + Base64,
    与后端 Hutool AES 完全兼容,后端零改动(已通过 openssl 比对验证)
  - 升级 @wangeditor-next/editor 5.7.16 -> 6.4.1、
    @wangeditor-next/editor-for-vue 5.1.14 -> 6.4.1(版本严格对齐,
    v6 唯一不兼容点为视频对齐 HTML 结构,导入时自动迁移)
  - 升级 vue 3.5.40 -> 3.5.42、element-plus 2.14.3 -> 2.14.5、
    vxe-table 4.20.8 -> 4.21.9、vxe-pc-ui 4.16.22 -> 4.18.9、
    axios 1.18.1 -> 1.20.0、pinia 4.0.2 -> 4.0.3、vue-router 5.2.0 -> 5.3.1、
    @vueuse/core 14.3.0 -> 14.4.0、highlight.js 11.11.1 -> 11.12.0、
    vue-i18n 11.4.8 -> 11.4.10 及 unocss、sass、oxlint 等开发依赖
2026-09-10 11:57:00 +08:00
疯狂的狮子Li
a85fa0aee4 fix 修复 文件包名错误 2026-09-01 16:36:40 +08:00
疯狂的狮子Li
0870ce1751 update 优化 按钮与筛选框 接入圆角设置统一调整 2026-08-11 10:28:59 +08:00
疯狂的狮子Li
461dd3218f fix 修复 开启全高表格后 表格数据少时 表格右侧的边框异常 https://gitee.com/dromara/RuoYi-Vue-Plus/issues/IK7IFQ 2026-08-10 10:11:40 +08:00
疯狂的狮子Li
914e4dcdb9 update README.md 2026-08-07 13:08:32 +08:00
13 changed files with 1665 additions and 1082 deletions

View File

@ -1,7 +1,7 @@
## 平台简介
- 本仓库为前端技术栈 [Vue3](https://v3.cn.vuejs.org) + [TS](https://www.typescriptlang.org/) + [Element Plus](https://element-plus.org/zh-CN) + [Vite](https://cn.vitejs.dev) 版本。
- 官方项目: 基于 React + Ant Design 版本前端项目 [plus-ui-react](https://gitee.com/JavaLionLi/plus-ui/tree/6.X-react/)
- 官方项目: 基于 React + Ant Design 版本前端项目 [plus-ui-react](https://gitee.com/JavaLionLi/plus-ui/tree/6.X-React/)
- 成员项目: 基于 vben5(ant-design-vue) 的前端项目 [ruoyi-plus-vben5](https://gitee.com/dapppp/ruoyi-plus-vben5)
- 成员项目: 基于soybean 的前端项目 [ruoyi-plus-soybean](https://gitee.com/xlsea/ruoyi-plus-soybean)

View File

@ -25,50 +25,49 @@
"@element-plus/icons-vue": "2.3.2",
"@highlightjs/vue-plugin": "2.1.2",
"@iconify/vue": "^5.0.1",
"@vueuse/core": "14.3.0",
"@wangeditor-next/editor": "5.7.16",
"@wangeditor-next/editor-for-vue": "5.1.14",
"@noble/ciphers": "^2.4.0",
"@vueuse/core": "14.4.0",
"@wangeditor-next/editor": "6.4.1",
"@wangeditor-next/editor-for-vue": "6.4.1",
"animate.css": "4.1.1",
"await-to-js": "3.0.0",
"axios": "1.18.1",
"crypto-js": "4.2.0",
"axios": "1.20.0",
"echarts": "6.1.0",
"element-plus": "2.14.3",
"highlight.js": "11.11.1",
"element-plus": "2.14.5",
"highlight.js": "11.12.0",
"image-conversion": "2.1.1",
"jsencrypt": "3.5.4",
"nprogress": "0.2.0",
"pinia": "4.0.2",
"vue": "3.5.40",
"pinia": "4.0.3",
"vue": "3.5.42",
"vue-cropper": "1.1.4",
"vue-i18n": "11.4.8",
"vue-i18n": "11.4.10",
"vue-json-pretty": "2.6.0",
"vue-router": "5.2.0",
"vue-router": "5.3.1",
"vue-types": "7.0.0",
"vxe-pc-ui": "4.16.22",
"vxe-table": "4.20.8"
"vxe-pc-ui": "4.18.9",
"vxe-table": "4.21.9"
},
"devDependencies": {
"@types/crypto-js": "4.2.2",
"@types/node": "^26.1.1",
"@types/nprogress": "0.2.3",
"@unocss/preset-attributify": "66.7.5",
"@unocss/preset-wind3": "66.7.5",
"@unocss/preset-attributify": "66.10.1",
"@unocss/preset-wind3": "66.10.1",
"@vitejs/plugin-vue": "^6.0.8",
"@vue/compiler-sfc": "3.5.40",
"autoprefixer": "10.5.4",
"oxfmt": "^0.60.0",
"oxlint": "^1.75.0",
"sass": "1.102.0",
"@vue/compiler-sfc": "3.5.42",
"autoprefixer": "10.5.5",
"oxfmt": "^0.67.0",
"oxlint": "^1.82.0",
"sass": "1.104.0",
"typescript": "^6.0.3",
"unocss": "66.7.5",
"unplugin-auto-import": "21.0.0",
"unocss": "66.10.1",
"unplugin-auto-import": "21.1.0",
"unplugin-vue-components": "32.1.0",
"unplugin-vue-setup-extend-plus": "1.0.1",
"vite": "^8.1.5",
"vite-plugin-svg-icons-ng": "^1.9.2",
"vitest": "4.1.10",
"vue-tsc": "^3.3.8"
"vite": "^8.2.2",
"vite-plugin-svg-icons-ng": "^1.9.3",
"vitest": "4.1.11",
"vue-tsc": "^3.3.11"
},
"browserslist": [
"Chrome >= 87",

2603
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -77,11 +77,11 @@
.query-form .el-input-number,
.query-form .el-input-number__decrease,
.query-form .el-input-number__increase {
border-radius: 12px !important;
border-radius: var(--app-radius-md) !important;
}
.query-form .el-button {
border-radius: 10px !important;
border-radius: var(--app-radius-md) !important;
}
html.dark .query-form .el-button--primary {

View File

@ -6,7 +6,7 @@
height: 28px !important;
min-width: 28px !important;
padding: 0 !important;
border-radius: 10px !important;
border-radius: var(--app-radius-md) !important;
background: var(--app-accent-soft) !important;
}

View File

@ -80,5 +80,5 @@
}
.table-panel .toolbar-actions .el-button:not(.is-circle):not(.is-link) {
border-radius: 10px !important;
border-radius: var(--app-radius-md) !important;
}

View File

@ -26,8 +26,8 @@
--tags-view-active-border-color: var(--el-color-primary);
// --- 应用壳圆角阴影表面导航强调色与文案色 ---
--app-radius-sm: calc(var(--app-radius-base) - 8px);
--app-radius-md: calc(var(--app-radius-base) - 4px);
--app-radius-sm: max(0px, calc(var(--app-radius-base) - 8px));
--app-radius-md: max(0px, calc(var(--app-radius-base) - 4px));
--app-radius-lg: var(--app-radius-base);
--app-radius-base: 14px;

View File

@ -61,7 +61,7 @@
.el-radio-button__inner,
.el-checkbox-button__inner {
border-radius: 10px !important;
border-radius: var(--app-radius-md) !important;
box-shadow: none !important;
}
@ -69,5 +69,5 @@
.el-checkbox-button:first-child .el-checkbox-button__inner,
.el-radio-button:last-child .el-radio-button__inner,
.el-checkbox-button:last-child .el-checkbox-button__inner {
border-radius: 10px !important;
border-radius: var(--app-radius-md) !important;
}

View File

@ -54,6 +54,19 @@ html.dark {
border-right: 0;
}
// 全高表格的外壳会延伸到分页区域左边框改由实际表头/数据行首列绘制避免少量数据时边框悬空
.el-table.is-full-height-table.el-table--border {
border-left: 0;
> .el-table__inner-wrapper > .el-table__header-wrapper,
> .el-table__inner-wrapper > .el-table__body-wrapper,
> .el-table__inner-wrapper > .el-table__footer-wrapper {
tr > .el-table__cell:first-child {
border-left: var(--el-table-border);
}
}
}
// --- 表格内操作列固定宽按钮下拉链接色 ---
.el-table .fixed-width .el-button--small {
padding-left: 0;

View File

@ -1,6 +1,4 @@
import * as CryptoJSModule from 'crypto-js';
const CryptoJS = ('default' in CryptoJSModule ? CryptoJSModule.default : CryptoJSModule) as typeof CryptoJSModule;
import { ecb } from '@noble/ciphers/aes.js';
/**
* 32
@ -14,41 +12,58 @@ const generateRandomString = (): string => {
.slice(0, 32);
};
const encoder = new TextEncoder();
const decoder = new TextDecoder();
const bytesToBase64 = (bytes: Uint8Array): string => {
let binary = '';
for (const byte of bytes) {
binary += String.fromCharCode(byte);
}
return btoa(binary);
};
const base64ToBytes = (str: string): Uint8Array => {
const binary = atob(str);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return bytes;
};
/**
* aes
* @returns {string}
* @returns {Uint8Array}
*/
export const generateAesKey = (): CryptoJSModule.lib.WordArray => {
return CryptoJS.enc.Utf8.parse(generateRandomString());
export const generateAesKey = (): Uint8Array => {
return encoder.encode(generateRandomString());
};
/**
* base64
* @returns {string}
*/
export const encryptBase64 = (str: CryptoJSModule.lib.WordArray): string => {
return CryptoJS.enc.Base64.stringify(str);
export const encryptBase64 = (bytes: Uint8Array): string => {
return bytesToBase64(bytes);
};
/**
* base64
*/
export const decryptBase64 = (str: string) => {
return CryptoJS.enc.Base64.parse(str);
export const decryptBase64 = (str: string): Uint8Array => {
return base64ToBytes(str);
};
/**
* 使
* 使 (AES/ECB/PKCS7Padding )
* @param message
* @param aesKey
* @returns {string}
*/
export const encryptWithAes = (message: string, aesKey: CryptoJSModule.lib.WordArray): string => {
const encrypted = CryptoJS.AES.encrypt(message, aesKey, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
return encrypted.toString();
export const encryptWithAes = (message: string, aesKey: Uint8Array): string => {
const encrypted = ecb(aesKey).encrypt(encoder.encode(message));
return bytesToBase64(encrypted);
};
/**
@ -57,10 +72,7 @@ export const encryptWithAes = (message: string, aesKey: CryptoJSModule.lib.WordA
* @param aesKey
* @returns {string}
*/
export const decryptWithAes = (message: string, aesKey: CryptoJSModule.lib.WordArray): string => {
const decrypted = CryptoJS.AES.decrypt(message, aesKey, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
return decrypted.toString(CryptoJS.enc.Utf8);
export const decryptWithAes = (message: string, aesKey: Uint8Array): string => {
const decrypted = ecb(aesKey).decrypt(base64ToBytes(message));
return decoder.decode(decrypted);
};

View File

@ -6,7 +6,7 @@ import createComponents from './components';
import createSvgIconsPlugin from './svg-icon';
import createCompression from './compression';
import createSetupExtend from './setup-extend';
import { viteCheckTransitionPlugin } from "./check-transition";
import { viteCheckTransitionPlugin } from './check-transition';
export default (viteEnv: any, isBuild = false): [] => {
const vitePlugins: any = [];