12 Commits

15 changed files with 623 additions and 579 deletions

View File

@ -1,63 +1,88 @@
# Changelog
# 更新日志 # 更新日志
## [v1.1.2](https://gitee.com/xlsea/ruoyi-plus-soybean/compare/v1.1.1...v1.1.2) (2025-07-24)
###    🐞 Bug 修复
- 修复 api.d.ts.vm 代码生成模板bug &nbsp;-&nbsp; by **zygalaxy** [<samp>(4e8c8)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/4e8c8715)
- **projects**:
- 修复刷新时跳转至登录页问题 &nbsp;-&nbsp; by **AN** [<samp>(2587f)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/2587f8cb)
- 修复登录过期不弹窗问题 &nbsp;-&nbsp; by **AN** [<samp>(e485f)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/e485f680)
- 修复菜单结构变动后路由无法进入问题 &nbsp;-&nbsp; by @m-xlsea [<samp>(f4038)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/f4038a2d)
### &nbsp;&nbsp;&nbsp;🛠 优化
- **projects**: 优化搜索框FormItem &nbsp;-&nbsp; by **AN** [<samp>(a1336)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/a1336d15)
### &nbsp;&nbsp;&nbsp;🏡 杂项
- **deps**: update deps &nbsp;-&nbsp; by @soybeanjs [<samp>(e89b8)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/e89b86ce)
### &nbsp;&nbsp;&nbsp;🎨 样式
- **projects**: 搜索FormItem占比调整 &nbsp;-&nbsp; by **AN** [<samp>(cc29e)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/cc29ea85)
### &nbsp;&nbsp;&nbsp;❤️ 贡献者
[![m-xlsea](https://github.com/m-xlsea.png?size=48)](https://github.com/m-xlsea)&nbsp;&nbsp;[![Elio-An](https://github.com/Elio-An.png?size=48)](https://gitee.com/elio-an)&nbsp;&nbsp;[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)&nbsp;&nbsp;
[zygalaxy](mailto:zygalaxy@qq.com)
## [v1.1.1](https://gitee.com/xlsea/ruoyi-plus-soybean/compare/v1.1.0...v1.1.1) (2025-07-11) ## [v1.1.1](https://gitee.com/xlsea/ruoyi-plus-soybean/compare/v1.1.0...v1.1.1) (2025-07-11)
### &nbsp;&nbsp;&nbsp;🚀 新功能 ### &nbsp;&nbsp;&nbsp;🚀 新功能
- **hooks**: - **hooks**:
- 重构下载方法,支持流式下载 &nbsp;-&nbsp; by @m-xlsea [<samp>(65067)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/650673e2) - 重构下载方法,支持流式下载 &nbsp;-&nbsp; by @m-xlsea [<samp>(65067)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/650673e2)
- **projects**: - **projects**:
- 角色分配用户新增部门与时间查询条件 &nbsp;-&nbsp; by @m-xlsea [<samp>(ad48d)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/ad48d8e8) - 角色分配用户新增部门与时间查询条件 &nbsp;-&nbsp; by @m-xlsea [<samp>(ad48d)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/ad48d8e8)
- 修改操作后列表查询方式 &nbsp;-&nbsp; by @m-xlsea [<samp>(d8542)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/d85424ee) - 修改操作后列表查询方式 &nbsp;-&nbsp; by @m-xlsea [<samp>(d8542)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/d85424ee)
### &nbsp;&nbsp;&nbsp;🐞 Bug 修复 ### &nbsp;&nbsp;&nbsp;🐞 Bug 修复
- **hooks**: - **hooks**:
- 解决 streamsaver 访问不到 Github 资源问题 &nbsp;-&nbsp; by @m-xlsea [<samp>(566b2)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/566b2c2d) - 解决 streamsaver 访问不到 Github 资源问题 &nbsp;-&nbsp; by @m-xlsea [<samp>(566b2)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/566b2c2d)
- **other**: - **other**:
- 修复代码生成类型定义文件重复问题 &nbsp;-&nbsp; by @m-xlsea [<samp>(f7c7f)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/f7c7fc41) - 修复代码生成类型定义文件重复问题 &nbsp;-&nbsp; by @m-xlsea [<samp>(f7c7f)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/f7c7fc41)
- **packages**: - **packages**:
- 修复 cleanup 会删除富文本编辑器资源问题 &nbsp;-&nbsp; by @m-xlsea [<samp>(9ca7c)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/9ca7ca8f) - 修复 cleanup 会删除富文本编辑器资源问题 &nbsp;-&nbsp; by @m-xlsea [<samp>(9ca7c)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/9ca7ca8f)
- **projects**: - **projects**:
- 修复字典数据重复获取问题 &nbsp;-&nbsp; by @m-xlsea [<samp>(3628c)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/3628c249) - 修复字典数据重复获取问题 &nbsp;-&nbsp; by @m-xlsea [<samp>(3628c)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/3628c249)
- 修改强退在线设备接口 &nbsp;-&nbsp; by **AN** [<samp>(dbcf8)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/dbcf8d42) - 修改强退在线设备接口 &nbsp;-&nbsp; by **AN** [<samp>(dbcf8)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/dbcf8d42)
- 修复代码生成逻辑判断问题 &nbsp;-&nbsp; by **AN** [<samp>(6fc7b)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/6fc7b11b) - 修复代码生成逻辑判断问题 &nbsp;-&nbsp; by **AN** [<samp>(6fc7b)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/6fc7b11b)
- 修复部门字典 sys_normal_disable 重复获取 Merge pull request !11 from 素还真/N/A &nbsp;-&nbsp; by @m-xlsea [<samp>(ad938)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/ad9386eb) - 修复部门字典 sys_normal_disable 重复获取 Merge pull request !11 from 素还真/N/A &nbsp;-&nbsp; by @m-xlsea [<samp>(ad938)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/ad9386eb)
- 修复未清空文件列表,上传回显问题 &nbsp;-&nbsp; by **AN** [<samp>(229e0)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/229e0044) - 修复未清空文件列表,上传回显问题 &nbsp;-&nbsp; by **AN** [<samp>(229e0)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/229e0044)
- Fix i18n-ally not working when setting moduleResolution to bundler. fixed #780 &nbsp;-&nbsp; by @xiaobao0505 in https://github.com/m-xlsea/ruoyi-plus-soybean/issues/780 [<samp>(41191)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/41191d54) - Fix i18n-ally not working when setting moduleResolution to bundler. fixed #780 &nbsp;-&nbsp; by @xiaobao0505 in https://gitee.com/xlsea/ruoyi-plus-soybean/issues/780 [<samp>(41191)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/41191d54)
- 修复角色列表操作栏展示不全问题 &nbsp;-&nbsp; by @m-xlsea [<samp>(62f2c)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/62f2c6d5) - 修复角色列表操作栏展示不全问题 &nbsp;-&nbsp; by @m-xlsea [<samp>(62f2c)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/62f2c6d5)
- 修复用户导入结果信息未渲染标签问题 &nbsp;-&nbsp; by **AN** [<samp>(efc95)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/efc953c0) - 修复用户导入结果信息未渲染标签问题 &nbsp;-&nbsp; by **AN** [<samp>(efc95)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/efc953c0)
- 修复角色用户分配未调用接口问题 &nbsp;-&nbsp; by @m-xlsea [<samp>(ff874)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/ff87415d) - 修复角色用户分配未调用接口问题 &nbsp;-&nbsp; by @m-xlsea [<samp>(ff874)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/ff87415d)
- **styles**: - **styles**:
- 修复登录页平板界面滚动问题 &nbsp;-&nbsp; by @m-xlsea [<samp>(90145)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/90145fa5) - 修复登录页平板界面滚动问题 &nbsp;-&nbsp; by @m-xlsea [<samp>(90145)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/90145fa5)
- **utils**: - **utils**:
- 修复isNull和IsNotNull判断方法潜在问题 &nbsp;-&nbsp; by **AN** [<samp>(90d32)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/90d32ee2) - 修复isNull和IsNotNull判断方法潜在问题 &nbsp;-&nbsp; by **AN** [<samp>(90d32)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/90d32ee2)
### &nbsp;&nbsp;&nbsp;💅 重构 ### &nbsp;&nbsp;&nbsp;💅 重构
- **projects**: 调整租户套餐菜单接口 &nbsp;-&nbsp; by **AN** [<samp>(b9999)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/b9999935) - **projects**: 调整租户套餐菜单接口 &nbsp;-&nbsp; by **AN** [<samp>(b9999)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/b9999935)
### &nbsp;&nbsp;&nbsp;📖 文档 ### &nbsp;&nbsp;&nbsp;📖 文档
- **other**: 修改文档内容 &nbsp;-&nbsp; by @m-xlsea [<samp>(3ae99)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/3ae9922d) - **other**: 修改文档内容 &nbsp;-&nbsp; by @m-xlsea [<samp>(3ae99)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/3ae9922d)
- **projects**: 优化 cursor 规则及 mcp &nbsp;-&nbsp; by @m-xlsea [<samp>(a3199)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/a31994dc) - **projects**: 优化 cursor 规则及 mcp &nbsp;-&nbsp; by @m-xlsea [<samp>(a3199)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/a31994dc)
- **readme**: 更新 README.md 文件 &nbsp;-&nbsp; by @m-xlsea [<samp>(99675)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/99675cbc) - **readme**: 更新 README.md 文件 &nbsp;-&nbsp; by @m-xlsea [<samp>(99675)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/99675cbc)
### &nbsp;&nbsp;&nbsp;🏡 杂项 ### &nbsp;&nbsp;&nbsp;🏡 杂项
- **deps**: - **deps**:
- update NodeJS and pnpm version requirements in package.json and documentation &nbsp;-&nbsp; by **Junior25306** [<samp>(a5c4b)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/a5c4b4e3) - update NodeJS and pnpm version requirements in package.json and documentation &nbsp;-&nbsp; by **Junior25306** [<samp>(a5c4b)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/a5c4b4e3)
- update deps &nbsp;-&nbsp; by @soybeanjs [<samp>(5cb1c)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/5cb1cebd) - update deps &nbsp;-&nbsp; by @soybeanjs [<samp>(5cb1c)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/5cb1cebd)
- update deps &nbsp;-&nbsp; by @soybeanjs [<samp>(aeb63)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/aeb63690) - update deps &nbsp;-&nbsp; by @soybeanjs [<samp>(aeb63)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/aeb63690)
- update deps &nbsp;-&nbsp; by @m-xlsea [<samp>(89c71)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/89c716e1) - update deps &nbsp;-&nbsp; by @m-xlsea [<samp>(89c71)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/89c716e1)
- **packages**: - **packages**:
- update Vite version to 7 in package.json and documentation. &nbsp;-&nbsp; by **Azir** [<samp>(03dd6)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/03dd64c5) - update Vite version to 7 in package.json and documentation. &nbsp;-&nbsp; by **Azir** [<samp>(03dd6)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/03dd64c5)
- **projects**: - **projects**:
- update pnpm-lock.yaml &nbsp;-&nbsp; by @m-xlsea [<samp>(7c6ca)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/7c6ca91e) - update pnpm-lock.yaml &nbsp;-&nbsp; by @m-xlsea [<samp>(7c6ca)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/7c6ca91e)
- **vscode**: - **vscode**:
- remove unused vue.server.hybridMode setting from .vscode/settings.json &nbsp;-&nbsp; by @soybeanjs [<samp>(13319)</samp>](https://github.com/m-xlsea/ruoyi-plus-soybean/commit/133196f3) - remove unused vue.server.hybridMode setting from .vscode/settings.json &nbsp;-&nbsp; by @soybeanjs [<samp>(13319)</samp>](https://gitee.com/xlsea/ruoyi-plus-soybean/commit/133196f3)
### &nbsp;&nbsp;&nbsp;❤️ 贡献值 ### &nbsp;&nbsp;&nbsp;❤️ 贡献值

View File

@ -22,13 +22,12 @@
# 📢 重要通知 # 📢 重要通知
1.1.1 版本已发布,但仍然建议: 1.1.2 版本已经正式发布,工作流版本迎来首个版本(请切换 [flow](https://gitee.com/xlsea/ruoyi-plus-soybean/tree/flow/) 分支查看),但仍然建议:
- 在生产环境使用前进行充分测试 - 在生产环境使用前进行充分测试
- 关注项目更新,及时获取最新版本 - 关注项目更新,及时获取最新版本
- 积极反馈问题,帮助我们快速迭代 - 积极反馈问题,帮助我们快速迭代
**后续规划** **后续规划**
- 工作流引擎集成
- 多语言国际化完善 - 多语言国际化完善
- 性能优化和稳定性提升 - 性能优化和稳定性提升

View File

@ -1,44 +1,51 @@
#set($BaseEntity = ['createDept', 'createBy', 'createTime', 'updateBy', 'updateTime']) #set($BaseEntity = ['createDept', 'createBy', 'createTime', 'updateBy', 'updateTime'])
#set($ModuleName = $moduleName.substring(0, 1).toUpperCase() + $moduleName.substring(1)) #set($ModuleName = $moduleName.substring(0, 1).toUpperCase() + $moduleName.substring(1))
/** /**
* namespace ${ModuleName} * Namespace Api
* *
* backend api module: "${ModuleName}" * All backend api type
*/ */
namespace ${ModuleName} { declare namespace Api {
/** ${businessname} */ /**
type ${BusinessName} = Common.CommonRecord<{ * namespace ${ModuleName}
#foreach($column in $columns)#if(!$BaseEntity.contains($column.javaField)) *
/** $column.columnComment */ * backend api module: "${ModuleName}"
$column.javaField:#if($column.javaField.indexOf("id") != -1 || $column.javaField.indexOf("Id") != -1) CommonType.IdType; #elseif($column.javaType == 'Long' || $column.javaType == 'Integer' || $column.javaType == 'Double' || $column.javaType == 'Float' || $column.javaType == 'BigDecimal') number; #elseif($column.javaType == 'Boolean') boolean; #else string; #end */
#end#end namespace ${ModuleName} {
}>; /** ${businessname} */
type ${BusinessName} = Common.CommonRecord<{
#foreach($column in $columns)#if(!$BaseEntity.contains($column.javaField))
/** $column.columnComment */
$column.javaField:#if($column.javaField.indexOf("id") != -1 || $column.javaField.indexOf("Id") != -1) CommonType.IdType; #elseif($column.javaType == 'Long' || $column.javaType == 'Integer' || $column.javaType == 'Double' || $column.javaType == 'Float' || $column.javaType == 'BigDecimal') number; #elseif($column.javaType == 'Boolean') boolean; #else string; #end
#end#end
}>;
/** ${businessname} search params */ /** ${businessname} search params */
type ${BusinessName}SearchParams = CommonType.RecordNullable< type ${BusinessName}SearchParams = CommonType.RecordNullable<
Pick< Pick<
Api.${ModuleName}.${BusinessName}, Api.${ModuleName}.${BusinessName},
#foreach($column in $columns) #foreach($column in $columns)
#if($column.query && $column.queryType != 'BETWEEN') #if($column.query && $column.queryType != 'BETWEEN')
| '${column.javaField}' | '${column.javaField}'
#end #end
#end #end
> & > &
Api.Common.CommonSearchParams Api.Common.CommonSearchParams
>; >;
/** ${businessname} operate params */ /** ${businessname} operate params */
type ${BusinessName}OperateParams = CommonType.RecordNullable< type ${BusinessName}OperateParams = CommonType.RecordNullable<
Pick< Pick<
Api.${ModuleName}.${BusinessName}, Api.${ModuleName}.${BusinessName},
#foreach($column in $columns) #foreach($column in $columns)
#if($column.insert || $column.edit) #if($column.insert || $column.edit)
| '${column.javaField}' | '${column.javaField}'
#end #end
#end #end
> >
>; >;
/** ${businessname} list */ /** ${businessname} list */
type ${BusinessName}List = Api.Common.PaginatingQueryRecord<${BusinessName}>; type ${BusinessName}List = Api.Common.PaginatingQueryRecord<${BusinessName}>;
}
} }

View File

@ -1,7 +1,7 @@
{ {
"name": "ruoyi-vue-plus", "name": "ruoyi-vue-plus",
"type": "module", "type": "module",
"version": "1.1.1", "version": "1.1.2",
"description": "结合了 RuoYi-Vue-Plus 的强大后端功能和 Soybean Admin 的现代化前端特性,为开发者提供了完整的企业管理解决方案。", "description": "结合了 RuoYi-Vue-Plus 的强大后端功能和 Soybean Admin 的现代化前端特性,为开发者提供了完整的企业管理解决方案。",
"author": { "author": {
"name": "xlsea", "name": "xlsea",
@ -88,22 +88,22 @@
}, },
"devDependencies": { "devDependencies": {
"@elegant-router/vue": "0.3.8", "@elegant-router/vue": "0.3.8",
"@iconify/json": "2.2.354", "@iconify/json": "2.2.357",
"@sa/scripts": "workspace:*", "@sa/scripts": "workspace:*",
"@sa/uno-preset": "workspace:*", "@sa/uno-preset": "workspace:*",
"@soybeanjs/eslint-config": "1.7.0", "@soybeanjs/eslint-config": "1.7.1",
"@types/node": "24.0.10", "@types/node": "24.0.13",
"@types/nprogress": "0.2.3", "@types/nprogress": "0.2.3",
"@unocss/eslint-config": "66.3.2", "@unocss/eslint-config": "66.3.3",
"@unocss/preset-icons": "66.3.2", "@unocss/preset-icons": "66.3.3",
"@unocss/preset-uno": "66.3.2", "@unocss/preset-uno": "66.3.3",
"@unocss/transformer-directives": "66.3.2", "@unocss/transformer-directives": "66.3.3",
"@unocss/transformer-variant-group": "66.3.2", "@unocss/transformer-variant-group": "66.3.3",
"@unocss/vite": "66.3.2", "@unocss/vite": "66.3.3",
"@vitejs/plugin-vue": "6.0.0", "@vitejs/plugin-vue": "6.0.0",
"@vitejs/plugin-vue-jsx": "5.0.1", "@vitejs/plugin-vue-jsx": "5.0.1",
"consola": "3.4.2", "consola": "3.4.2",
"eslint": "9.30.1", "eslint": "9.31.0",
"eslint-plugin-vue": "10.3.0", "eslint-plugin-vue": "10.3.0",
"kolorist": "1.8.0", "kolorist": "1.8.0",
"sass": "1.89.2", "sass": "1.89.2",
@ -112,7 +112,7 @@
"typescript": "5.8.3", "typescript": "5.8.3",
"unplugin-icons": "22.1.0", "unplugin-icons": "22.1.0",
"unplugin-vue-components": "28.8.0", "unplugin-vue-components": "28.8.0",
"vite": "7.0.1", "vite": "7.0.4",
"vite-plugin-monaco-editor": "^1.1.0", "vite-plugin-monaco-editor": "^1.1.0",
"vite-plugin-progress": "0.0.7", "vite-plugin-progress": "0.0.7",
"vite-plugin-static-copy": "^3.1.0", "vite-plugin-static-copy": "^3.1.0",

896
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -65,37 +65,46 @@ export const request = createFlatRequest<App.Service.Response, RequestInstanceSt
request.state.errMsgStack = request.state.errMsgStack.filter(msg => msg !== response.data.msg); request.state.errMsgStack = request.state.errMsgStack.filter(msg => msg !== response.data.msg);
} }
const isLogin = Boolean(localStg.get('token'));
// when the backend response code is in `logoutCodes`, it means the user will be logged out and redirected to login page // when the backend response code is in `logoutCodes`, it means the user will be logged out and redirected to login page
// const logoutCodes = import.meta.env.VITE_SERVICE_LOGOUT_CODES?.split(',') || []; const logoutCodes = import.meta.env.VITE_SERVICE_LOGOUT_CODES?.split(',') || [];
// if (logoutCodes.includes(responseCode)) { if (logoutCodes.includes(responseCode) && !isLogin) {
// handleLogout(); logoutAndCleanup();
// return null; return null;
// } }
// when the backend response code is in `modalLogoutCodes`, it means the user will be logged out by displaying a modal // when the backend response code is in `modalLogoutCodes`, it means the user will be logged out by displaying a modal
const modalLogoutCodes = import.meta.env.VITE_SERVICE_MODAL_LOGOUT_CODES?.split(',') || []; const modalLogoutCodes = import.meta.env.VITE_SERVICE_MODAL_LOGOUT_CODES?.split(',') || [];
if (modalLogoutCodes.includes(responseCode)) { if (modalLogoutCodes.includes(responseCode) && isLogin) {
const isExist = request.state.errMsgStack && request.state.errMsgStack.includes(response.data.msg);
if (isExist) {
return null;
}
if (window.location.pathname?.startsWith('/login')) {
logoutAndCleanup();
return null;
}
request.state.errMsgStack = [...(request.state.errMsgStack || []), response.data.msg]; request.state.errMsgStack = [...(request.state.errMsgStack || []), response.data.msg];
// prevent the user from refreshing the page // prevent the user from refreshing the page
window.addEventListener('beforeunload', handleLogout); window.addEventListener('beforeunload', handleLogout);
if (!window.location.pathname?.startsWith('/login')) { window.$dialog?.warning({
window.$dialog?.warning({ title: '系统提示',
title: '系统提示', content: '登录状态已过期,您可以继续留在该页面,或者重新登录',
content: '登录状态已过期,您可以继续留在该页面,或者重新登录', positiveText: '重新登录',
positiveText: '重新登录', negativeText: '取消',
negativeText: '取消', maskClosable: false,
maskClosable: false, closeOnEsc: false,
closeOnEsc: false, onPositiveClick() {
onPositiveClick() { logoutAndCleanup();
logoutAndCleanup(); },
} onClose() {
}); window.removeEventListener('beforeunload', handleLogout);
request.state.errMsgStack = request.state.errMsgStack.filter(msg => msg !== response.data.msg);
request.cancelAllRequest(); }
} });
request.cancelAllRequest();
return null; return null;
} }

View File

@ -65,11 +65,13 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
routes.forEach(route => { routes.forEach(route => {
if (authRouteMode.value === 'dynamic') { if (authRouteMode.value === 'dynamic') {
if (route.path === '/') { if (route.path === '/' && route.children?.length) {
route.children?.forEach(child => { const child = route.children[0];
parseRouter(child); parseRouter(child);
authRoutesMap.set(child.name, child); child.name = Math.random().toString(36).slice(2, 12);
}); Object.assign(route, child);
delete route.children;
authRoutesMap.set(route.name, route);
return; return;
} }
parseRouter(route); parseRouter(route);

View File

@ -34,13 +34,13 @@ async function search() {
<NCollapseItem :title="$t('common.search')" name="user-search"> <NCollapseItem :title="$t('common.search')" name="user-search">
<NForm ref="formRef" :model="model" label-placement="left" :label-width="80"> <NForm ref="formRef" :model="model" label-placement="left" :label-width="80">
<NGrid responsive="screen" item-responsive> <NGrid responsive="screen" item-responsive>
<NFormItemGi span="24 s:12 m:6" label="IP地址" path="ipaddr" class="pr-24px"> <NFormItemGi span="24 s:12 m:8" label="IP地址" path="ipaddr" class="pr-24px">
<NInput v-model:value="model.ipaddr" placeholder="请输入IP地址" /> <NInput v-model:value="model.ipaddr" placeholder="请输入IP地址" />
</NFormItemGi> </NFormItemGi>
<NFormItemGi span="24 s:12 m:6" label="用户账号" path="userName" class="pr-24px"> <NFormItemGi span="24 s:12 m:8" label="用户账号" path="userName" class="pr-24px">
<NInput v-model:value="model.userName" placeholder="请输入用户账号" /> <NInput v-model:value="model.userName" placeholder="请输入用户账号" />
</NFormItemGi> </NFormItemGi>
<NFormItemGi span="24" class="pr-24px"> <NFormItemGi span="24 s:24 m:8" class="pr-24px">
<NSpace class="w-full" justify="end"> <NSpace class="w-full" justify="end">
<NButton @click="reset"> <NButton @click="reset">
<template #icon> <template #icon>

View File

@ -61,7 +61,7 @@ async function search() {
clearable clearable
/> />
</NFormItemGi> </NFormItemGi>
<NFormItemGi span="24" class="pr-24px"> <NFormItemGi span="24 s:12 m:6" class="pr-24px">
<NSpace class="w-full" justify="end"> <NSpace class="w-full" justify="end">
<NButton @click="reset"> <NButton @click="reset">
<template #icon> <template #icon>

View File

@ -77,7 +77,7 @@ async function search() {
clearable clearable
/> />
</NFormItemGi> </NFormItemGi>
<NFormItemGi span="24 s:12 m:12" label="创建时间" path="createTime" class="pr-24px"> <NFormItemGi span="24 s:12 m:6" label="创建时间" path="createTime" class="pr-24px">
<NDatePicker <NDatePicker
v-model:formatted-value="dateRangeCreateTime" v-model:formatted-value="dateRangeCreateTime"
type="datetimerange" type="datetimerange"
@ -86,7 +86,7 @@ async function search() {
@update:formatted-value="onDateRangeCreateTimeUpdate" @update:formatted-value="onDateRangeCreateTimeUpdate"
/> />
</NFormItemGi> </NFormItemGi>
<NFormItemGi span="24 s:12 m:12" class="pr-24px"> <NFormItemGi span="24" class="pr-24px">
<NSpace class="w-full" justify="end"> <NSpace class="w-full" justify="end">
<NButton @click="reset"> <NButton @click="reset">
<template #icon> <template #icon>

View File

@ -36,10 +36,10 @@ async function search() {
<NCollapseItem :title="$t('common.search')" name="user-search"> <NCollapseItem :title="$t('common.search')" name="user-search">
<NForm ref="formRef" :model="model" label-placement="left" :label-width="80"> <NForm ref="formRef" :model="model" label-placement="left" :label-width="80">
<NGrid responsive="screen" item-responsive> <NGrid responsive="screen" item-responsive>
<NFormItemGi span="8" :label="$t('page.system.dept.deptName')" path="deptName" class="pr-24px"> <NFormItemGi span="24 s:12 m:8" :label="$t('page.system.dept.deptName')" path="deptName" class="pr-24px">
<NInput v-model:value="model.deptName" :placeholder="$t('page.system.dept.form.deptName.required')" /> <NInput v-model:value="model.deptName" :placeholder="$t('page.system.dept.form.deptName.required')" />
</NFormItemGi> </NFormItemGi>
<NFormItemGi span="8 " :label="$t('page.system.dept.status')" path="status" class="pr-24px"> <NFormItemGi span="24 s:12 m:8 " :label="$t('page.system.dept.status')" path="status" class="pr-24px">
<NSelect <NSelect
v-model:value="model.status" v-model:value="model.status"
:placeholder="$t('page.system.dept.form.status.required')" :placeholder="$t('page.system.dept.form.status.required')"
@ -47,7 +47,7 @@ async function search() {
clearable clearable
/> />
</NFormItemGi> </NFormItemGi>
<NFormItemGi span="8" class="pr-24px"> <NFormItemGi span="24 s:12 m:8" class="pr-24px">
<NSpace class="w-full" justify="end"> <NSpace class="w-full" justify="end">
<NButton @click="reset"> <NButton @click="reset">
<template #icon> <template #icon>

View File

@ -33,17 +33,16 @@ async function search() {
<NCollapse> <NCollapse>
<NCollapseItem :title="$t('common.search')" name="user-search"> <NCollapseItem :title="$t('common.search')" name="user-search">
<NForm ref="formRef" :model="model" label-placement="left" :label-width="80"> <NForm ref="formRef" :model="model" label-placement="left" :label-width="80">
<NGrid responsive="self" item-responsive> <NGrid responsive="screen" item-responsive>
<NFormItemGi <NFormItemGi
:show-feedback="false" span="24 s:12 m:12"
span="12"
:label="$t('page.system.dict.data.label')" :label="$t('page.system.dict.data.label')"
path="dictLabel" path="dictLabel"
class="pr-24px" class="pr-24px"
> >
<NInput v-model:value="model.dictLabel" :placeholder="$t('page.system.dict.form.dictLabel.required')" /> <NInput v-model:value="model.dictLabel" :placeholder="$t('page.system.dict.form.dictLabel.required')" />
</NFormItemGi> </NFormItemGi>
<NFormItemGi :show-feedback="false" span="12" class="pr-24px"> <NFormItemGi span="24 s:12 m:12" class="pr-24px">
<NSpace class="w-full" justify="end"> <NSpace class="w-full" justify="end">
<NButton @click="reset"> <NButton @click="reset">
<template #icon> <template #icon>

View File

@ -33,13 +33,13 @@ async function search() {
<NCollapseItem :title="$t('common.search')" name="user-search"> <NCollapseItem :title="$t('common.search')" name="user-search">
<NForm ref="formRef" :model="model" label-placement="left" :label-width="80"> <NForm ref="formRef" :model="model" label-placement="left" :label-width="80">
<NGrid responsive="screen" item-responsive> <NGrid responsive="screen" item-responsive>
<NFormItemGi span="8" label="公告标题" path="noticeTitle" class="pr-24px"> <NFormItemGi span="24 s:12 m:8" label="公告标题" path="noticeTitle" class="pr-24px">
<NInput v-model:value="model.noticeTitle" placeholder="请输入公告标题" /> <NInput v-model:value="model.noticeTitle" placeholder="请输入公告标题" />
</NFormItemGi> </NFormItemGi>
<NFormItemGi span="8" label="公告类型" path="noticeType" class="pr-24px"> <NFormItemGi span="24 s:12 m:8" label="公告类型" path="noticeType" class="pr-24px">
<DictSelect v-model:value="model.noticeType" dict-code="sys_notice_type" placeholder="请选择公告类型" /> <DictSelect v-model:value="model.noticeType" dict-code="sys_notice_type" placeholder="请选择公告类型" />
</NFormItemGi> </NFormItemGi>
<NFormItemGi span="8" class="pr-24px"> <NFormItemGi span="24 s:12 m:8" class="pr-24px">
<NSpace class="w-full" justify="end"> <NSpace class="w-full" justify="end">
<NButton @click="reset"> <NButton @click="reset">
<template #icon> <template #icon>

View File

@ -36,13 +36,13 @@ async function search() {
<NCollapseItem :title="$t('common.search')" name="user-search"> <NCollapseItem :title="$t('common.search')" name="user-search">
<NForm ref="formRef" :model="model" label-placement="left" :label-width="80"> <NForm ref="formRef" :model="model" label-placement="left" :label-width="80">
<NGrid responsive="screen" item-responsive> <NGrid responsive="screen" item-responsive>
<NFormItemGi span="6 s:12 m:6" label="岗位编码" path="postCode" class="pr-24px"> <NFormItemGi span="24 s:12 m:6" label="岗位编码" path="postCode" class="pr-24px">
<NInput v-model:value="model.postCode" placeholder="请输入岗位编码" /> <NInput v-model:value="model.postCode" placeholder="请输入岗位编码" />
</NFormItemGi> </NFormItemGi>
<NFormItemGi span="6 s:12 m:6" label="岗位名称" path="postName" class="pr-24px"> <NFormItemGi span="24 s:12 m:6" label="岗位名称" path="postName" class="pr-24px">
<NInput v-model:value="model.postName" placeholder="请输入岗位名称" /> <NInput v-model:value="model.postName" placeholder="请输入岗位名称" />
</NFormItemGi> </NFormItemGi>
<NFormItemGi span="6 s:12 m:6" label="状态" path="status" class="pr-24px"> <NFormItemGi span="24 s:12 m:6" label="状态" path="status" class="pr-24px">
<NSelect <NSelect
v-model:value="model.status" v-model:value="model.status"
placeholder="请选择状态" placeholder="请选择状态"
@ -50,7 +50,7 @@ async function search() {
clearable clearable
/> />
</NFormItemGi> </NFormItemGi>
<NFormItemGi span="6" class="pr-24px"> <NFormItemGi span="24 s:12 m:6" class="pr-24px">
<NSpace class="w-full" justify="end"> <NSpace class="w-full" justify="end">
<NButton @click="reset"> <NButton @click="reset">
<template #icon> <template #icon>

View File

@ -38,7 +38,7 @@ async function search() {
<NForm ref="formRef" :model="model" label-placement="left" :label-width="80"> <NForm ref="formRef" :model="model" label-placement="left" :label-width="80">
<NGrid responsive="screen" item-responsive> <NGrid responsive="screen" item-responsive>
<NFormItemGi <NFormItemGi
span="8" span="24 s:12 m:8"
:label="$t('page.system.tenantPackage.packageName')" :label="$t('page.system.tenantPackage.packageName')"
path="packageName" path="packageName"
class="pr-24px" class="pr-24px"
@ -48,7 +48,12 @@ async function search() {
:placeholder="$t('page.system.tenantPackage.form.packageName.required')" :placeholder="$t('page.system.tenantPackage.form.packageName.required')"
/> />
</NFormItemGi> </NFormItemGi>
<NFormItemGi span="8" :label="$t('page.system.tenantPackage.status')" path="status" class="pr-24px"> <NFormItemGi
span="24 s:12 m:8"
:label="$t('page.system.tenantPackage.status')"
path="status"
class="pr-24px"
>
<NSelect <NSelect
v-model:value="model.status" v-model:value="model.status"
:placeholder="$t('page.system.tenantPackage.form.status.required')" :placeholder="$t('page.system.tenantPackage.form.status.required')"
@ -56,7 +61,7 @@ async function search() {
clearable clearable
/> />
</NFormItemGi> </NFormItemGi>
<NFormItemGi span="8" class="pr-24px"> <NFormItemGi span="24 s:24 m:8" class="pr-24px">
<NSpace class="w-full" justify="end"> <NSpace class="w-full" justify="end">
<NButton @click="reset"> <NButton @click="reset">
<template #icon> <template #icon>