diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 29f81d812f3e768fa89638d1f72920dbfd1413a8..0000000000000000000000000000000000000000
--- a/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/README.md b/README.md
index 5dd4e70697f662a259fe8a37baed722741ffe4c7..96f6aa151dd484d9c84cd4b53d74e2ba5cc57904 100644
--- a/README.md
+++ b/README.md
@@ -8,10 +8,148 @@ spring.datasource.password=
```
+模块依赖关系
+admin--->framework--->system | generator | batch--->common
-模块依赖关系
+# 注意事项
+1. 任何方法不要传入null, 不要返回null。
+2. 无法保证不传入null时,方法做判空处理。
+3. 前端传过来的参数可以在DTO上做注解校验,或者设置默认值
+4. service层仅调用自己的mapper,避免调用其他类的mapper,可调用其他类的service。
+
+# 已完成功能 V1.0.0
+
+## 系统管理
+
+### 登录与Session管理
+
+- [x] 登录后用户的session中包括用户基本信息和用户角色。
+- [x] 角色—权限、 角色—菜单 统一进行缓存。 权限、菜单发生变动后,清除相关角色的缓存即可
+
+### 菜单管理
+- [x] 新增、修改、删除菜单后,清除角色—菜单缓存
+- [ ] 超级管理员获取全部菜单不加缓存
+
+### 部门管理
+
+- [x] 部门列表查询
+- [x] 添加部门
+- [x] 编辑部门(ancestors、isLock)
+- [x] 删除部门 (禁止删除带子部门和带员工的部门)
+
+### 角色管理
+- [x] 分页查询列表
+- [x] 添加和编辑角色弹窗增加:角色排序、角色禁用
+- [x] 修改把禁用按钮去掉
+- [x] 修改角色基本信息、禁止修改超级管理员
+- [x] 修改角色权限
+- [ ] 修改角色数据权限
+- [x] 删除角色
+
+### 用户管理
+- [x] 查询部门树
+- [x] 查询部门数附带每个部门的人数
+- [x] 分页查询用户列表, 除了基本用户信息还包括用户的角色、部门信息
+- [x] 根据部门树查询用户
+- [x] 添加用户
+- [x] 添加用户、用户操作前端页面修改
+- [x] 检查前端按钮权限标识
+- [x] 修改用户
+ - [ ] 输入身份证、手机号校验、邮箱、【工号、用户名】规则校验
+- [x] 删除用户
+ - [x] 测试联动删除用户所有绑定角色信息
+- [x] 设置用户角色
+- [x] 批量设置角色部门
+- [x] 批量设置角色岗位
+- [x] 编辑用户功能加入岗位和部门编辑
+- [x] 用户信息把岗位信息也联表查询出来
+- [ ] 点击用户名显示用户详情
+- [x] 重置用户密码
+- [x] 用户名需保证唯一、nickname不需要唯一
+- [x] 按用户名/工号/身份证查询时加入limit 1 防止错误数据引发系统故障
+- [ ] 多次输错密码锁定用户几分钟 / 手动解锁用户
+- [ ] 头像上传
+
+
+
+### 字典管理
+若依拉取字典数据是这个页面需要什么就拉取什么,没刷新的话拉取一次就不拉了
+这个geekAdmin是一次性拉取所有字典数据,进入具体页面时不再拉取,刷新就又重新拉取所有字典数据。
+如果字典数据变得特别多,可以优化成若依的方式,不过一般字典数据不是很多,都无所谓,字典数据也可以放入缓存。一次性拉取后,系统更流畅,代码更简洁?
+
+- [x] 字典类型加一个业务类型字段、 分为系统字典和业务字典
+- [x] 字典类型列表
+ - [x] 字典类型对应字段列表
+ - [x] 字典添加
+ - [x] 字典修改
+ - [x] 字典删除
+ - [x] 字典锁定
+- [x] 新增字典类型
+- [x] 删除字典类型(逻辑删除,不同步删字典内容)
+- [x] 锁定字典类型
+- [x] 字典类型对应的字典列表
+
+
+### 参数管理
+
+
+
+### 文件管理
+
+- [ ] 文件上传、下载
+
+
+### 岗位管理
+- [x] 自动代码生成,增删改查
+
+## 日志管理
+
+### 操作日志
+
+
+
+### 登录日志
+
+
+
+## 系统工具
+
+### 代码生成
+- [x] 导入表列表查询
+- [ ] 导入表
+ - [x] 导入表信息
+ - [ ] 导入表的列信息
+- [x] 已导入的表列表查询
+ - [x] 编辑
+ - [x] 删除
+ - [x] 预览
+ - [x] 代码生成预览
+ - [x] 加入前端代码和SQL的预览
+ - [x] 代码生成模板修改
+ - [x] 生成代码
+
+
+- [x] 生成代码配置加一个swagger选项
+- [x] 加一个同步功能,而不是必须重新删除
+- [x] 覆盖生成
+- [ ] 自动插入菜单和按钮,插入菜单和按钮之后,记得更新菜单和按钮的缓存,不然用户感知不到
+
+
+### 表单构建
+
+
+
+
+
+## 定时任务
+
+
+
+
+
+
+
+## 前台官网
-admin--->framework--->system--->common
- --->generator------------->common
diff --git a/admin/pom.xml b/admin/pom.xml
index c8ac23c825d73d7c8bce538592ef551ea2bcee58..8b9e50a2a4493cf20d7590437cb66cbe37ef9df6 100644
--- a/admin/pom.xml
+++ b/admin/pom.xml
@@ -45,11 +45,7 @@
framework
-
-
- cn.lycode
- generator
-
+
\ No newline at end of file
diff --git a/admin/src/test/java/cn/lycode/system/SysUserPostServiceTest.java b/admin/src/test/java/cn/lycode/system/SysUserPostServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..2c91814e7bb666d326a7f2b15ec58ad2afc83efb
--- /dev/null
+++ b/admin/src/test/java/cn/lycode/system/SysUserPostServiceTest.java
@@ -0,0 +1,35 @@
+package cn.lycode.system;
+
+import cn.lycode.system.service.SysUserPostService;
+import org.junit.Ignore;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Title: SysUserPostServiceTest
+ * @Author lyg
+ * @Date 2024/11/29 17:10
+ * @description:
+ */
+@SpringBootTest
+public class SysUserPostServiceTest {
+
+ @Autowired
+ SysUserPostService sysUserPostService;
+
+ @Test
+ @Ignore
+ public void batchAddUserPost(){
+ List userIdList = new ArrayList<>();
+ userIdList.add(1L);
+ userIdList.add(14L);
+ List postIdList = new ArrayList<>();
+ postIdList.add(1L);
+ postIdList.add(2L);
+ sysUserPostService.batchAddUserPost(userIdList, postIdList);
+ }
+}
diff --git a/batch/pom.xml b/batch/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..67a3f1c70592ffa7a87d378fbf0365b68ac3b14e
--- /dev/null
+++ b/batch/pom.xml
@@ -0,0 +1,34 @@
+
+
+ 4.0.0
+
+ cn.lycode
+ lycode-base
+ 1.0.0
+
+
+ batch
+
+
+ 8
+ 8
+ UTF-8
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-batch
+
+
+
+ cn.lycode
+ common
+
+
+
+
+
\ No newline at end of file
diff --git a/batch/src/main/java/cn/lycode/batch/bean/ExcelData.java b/batch/src/main/java/cn/lycode/batch/bean/ExcelData.java
new file mode 100644
index 0000000000000000000000000000000000000000..7ae0a46edb2a2c00e1faa1aeacfa1df9feb471e2
--- /dev/null
+++ b/batch/src/main/java/cn/lycode/batch/bean/ExcelData.java
@@ -0,0 +1,16 @@
+package cn.lycode.batch.bean;
+
+import lombok.Data;
+
+/**
+ * @Title: ExcelData
+ * @Author lyg
+ * @Date 2024/12/11 10:50
+ * @description:
+ */
+
+@Data
+public class ExcelData {
+ private String name;
+ private String remark;
+}
diff --git a/batch/src/main/java/cn/lycode/batch/bean/TestData.java b/batch/src/main/java/cn/lycode/batch/bean/TestData.java
new file mode 100644
index 0000000000000000000000000000000000000000..f6563ac634dda8a65a8866f147681d165273e0fd
--- /dev/null
+++ b/batch/src/main/java/cn/lycode/batch/bean/TestData.java
@@ -0,0 +1,15 @@
+package cn.lycode.batch.bean;
+
+
+import lombok.Data;
+
+@Data
+public class TestData {
+
+ private Long id;
+ private String name;
+ private String process;
+ private String remark;
+
+
+}
diff --git a/batch/src/main/java/cn/lycode/batch/config/MyBatchConfig.java b/batch/src/main/java/cn/lycode/batch/config/MyBatchConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..c8e86017875379ee84bd34713bb998cc62934560
--- /dev/null
+++ b/batch/src/main/java/cn/lycode/batch/config/MyBatchConfig.java
@@ -0,0 +1,211 @@
+package cn.lycode.batch.config;
+
+
+import cn.lycode.batch.bean.TestData;
+import cn.lycode.batch.listener.MyJobListener;
+import cn.lycode.batch.listener.MyReadListener;
+import cn.lycode.batch.listener.MyWriteListener;
+import cn.lycode.batch.processor.MyItemProcessor;
+import cn.lycode.batch.validator.MyBeanValidator;
+import org.springframework.batch.core.Job;
+import org.springframework.batch.core.Step;
+import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
+import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
+import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
+import org.springframework.batch.core.launch.support.RunIdIncrementer;
+import org.springframework.batch.core.launch.support.SimpleJobLauncher;
+import org.springframework.batch.core.repository.JobRepository;
+import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
+import org.springframework.batch.item.ItemProcessor;
+import org.springframework.batch.item.ItemReader;
+import org.springframework.batch.item.ItemWriter;
+import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
+import org.springframework.batch.item.database.JdbcBatchItemWriter;
+import org.springframework.batch.item.file.FlatFileItemReader;
+import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
+import org.springframework.batch.item.file.mapping.DefaultLineMapper;
+import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.transaction.PlatformTransactionManager;
+
+import javax.sql.DataSource;
+
+@Configuration
+@EnableBatchProcessing
+public class MyBatchConfig {
+
+
+ /**
+ * JobRepository定义:Job的注册容器以及和数据库打交道(事务管理等)
+ * @param dataSource
+ * @param transactionManager
+ * @return
+ * @throws Exception
+ */
+ @Bean
+ public JobRepository myJobRepository(DataSource dataSource, PlatformTransactionManager transactionManager) throws Exception{
+ JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
+ jobRepositoryFactoryBean.setDatabaseType("mysql");
+ jobRepositoryFactoryBean.setTransactionManager(transactionManager);
+ jobRepositoryFactoryBean.setDataSource(dataSource);
+ return jobRepositoryFactoryBean.getObject();
+ }
+
+
+ /**
+ * jobLauncher定义:job的启动器,绑定相关的jobRepository
+ * @param dataSource
+ * @param transactionManager
+ * @return
+ * @throws Exception
+ */
+ @Bean
+ public SimpleJobLauncher myJobLauncher(DataSource dataSource, PlatformTransactionManager transactionManager) throws Exception{
+ SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
+ // 设置jobRepository
+ jobLauncher.setJobRepository(myJobRepository(dataSource, transactionManager));
+ return jobLauncher;
+ }
+
+
+ /**
+ * 定义job
+ * @param jobs
+ * @param myStep
+ * @return
+ */
+ @Bean
+ public Job myJob(JobBuilderFactory jobs, Step myStep){
+ return jobs.get("myJob")
+ .incrementer(new RunIdIncrementer())
+ .flow(myStep)
+ .end()
+ .listener(myJobListener())
+ .build();
+ }
+
+
+
+ /**
+ * 注册job监听器
+ * @return
+ */
+ @Bean
+ public MyJobListener myJobListener(){
+ return new MyJobListener();
+ }
+
+
+ /**
+ * ItemReader定义:读取文件数据+entirty实体类映射
+ * @return
+ */
+ @Bean
+ public ItemReader reader(){
+ // 使用FlatFileItemReader去读cvs文件,一行即一条数据
+ FlatFileItemReader reader = new FlatFileItemReader<>();
+ // 设置文件处在路径
+ reader.setResource(new ClassPathResource("static/testData.csv"));
+ // entity与csv数据做映射
+ reader.setLineMapper(new DefaultLineMapper() {
+ {
+ setLineTokenizer(new DelimitedLineTokenizer() {
+ {
+ setNames(new String[]{"name","process","remark"});
+ }
+ });
+ setFieldSetMapper(new BeanWrapperFieldSetMapper() {
+ {
+ setTargetType(TestData.class);
+ }
+ });
+ }
+ });
+ return reader;
+ }
+
+
+
+
+
+ /**
+ * 注册ItemProcessor: 处理数据+校验数据
+ * @return
+ */
+ @Bean
+ public ItemProcessor processor(){
+ MyItemProcessor myItemProcessor = new MyItemProcessor();
+ // 设置校验器
+ myItemProcessor.setValidator(myBeanValidator());
+ return myItemProcessor;
+ }
+
+
+ /**
+ * 注册校验器
+ * @return
+ */
+ @Bean
+ public MyBeanValidator myBeanValidator(){
+ return new MyBeanValidator();
+ }
+
+
+
+ /**
+ * ItemWriter定义:指定datasource,设置批量插入sql语句,写入数据库
+ * @param dataSource
+ * @return
+ */
+ @Bean
+ public ItemWriter writer(DataSource dataSource){
+ // 使用jdbcBcatchItemWrite写数据到数据库中
+ JdbcBatchItemWriter writer = new JdbcBatchItemWriter<>();
+ // 设置有参数的sql语句
+ writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider());
+ String sql = "insert into batch_test_data "+" (name,process,remark) "
+ +" values(:name,:process,:remark)";
+ writer.setSql(sql);
+ writer.setDataSource(dataSource);
+ return writer;
+ }
+
+
+
+ /**
+ * step定义:
+ * 包括
+ * ItemReader 读取
+ * ItemProcessor 处理
+ * ItemWriter 输出
+ * @param stepBuilderFactory
+ * @param reader
+ * @param writer
+ * @param processor
+ * @return
+ */
+
+ @Bean
+ public Step myStep(StepBuilderFactory stepBuilderFactory, ItemReader reader,
+ ItemWriter writer, ItemProcessor processor){
+ return stepBuilderFactory
+ .get("myStep")
+ .chunk(65000) // Chunk的机制(即每次读取一条数据,再处理一条数据,累积到一定数量后再一次性交给writer进行写入操作)
+ .reader(reader).faultTolerant().retryLimit(3).retry(Exception.class).skip(Exception.class).skipLimit(2)
+ .listener(new MyReadListener())
+ .processor(processor)
+ .writer(writer).faultTolerant().skip(Exception.class).skipLimit(2)
+ .listener(new MyWriteListener())
+ .build();
+ }
+
+
+
+
+
+
+
+
+}
diff --git a/batch/src/main/java/cn/lycode/batch/controller/TestController.java b/batch/src/main/java/cn/lycode/batch/controller/TestController.java
new file mode 100644
index 0000000000000000000000000000000000000000..0eb8df33c566360fcf6814c231d2f4d9c5a33c03
--- /dev/null
+++ b/batch/src/main/java/cn/lycode/batch/controller/TestController.java
@@ -0,0 +1,29 @@
+package cn.lycode.batch.controller;
+
+import org.springframework.batch.core.Job;
+import org.springframework.batch.core.JobParameters;
+import org.springframework.batch.core.JobParametersBuilder;
+import org.springframework.batch.core.JobParametersInvalidException;
+import org.springframework.batch.core.launch.support.SimpleJobLauncher;
+import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
+import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
+import org.springframework.batch.core.repository.JobRestartException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class TestController {
+ @Autowired
+ SimpleJobLauncher jobLauncher;
+
+ @Autowired
+ Job myJob;
+
+ @GetMapping("testJob")
+ public void testJob() throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
+ // 后置参数:使用JobParameters中绑定参数 addLong addString 等方法
+ JobParameters jobParameters = new JobParametersBuilder().toJobParameters();
+ jobLauncher.run(myJob, jobParameters);
+ }
+}
diff --git a/batch/src/main/java/cn/lycode/batch/listener/MyJobListener.java b/batch/src/main/java/cn/lycode/batch/listener/MyJobListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..ae4c7ad742fb5b9b595cade0955e0d44944aaf53
--- /dev/null
+++ b/batch/src/main/java/cn/lycode/batch/listener/MyJobListener.java
@@ -0,0 +1,25 @@
+package cn.lycode.batch.listener;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.batch.core.JobExecution;
+import org.springframework.batch.core.JobExecutionListener;
+
+/**
+ * @Author : JCccc
+ * @Description :监听Job执行情况,实现JobExecutorListener,且在batch配置类里,Job的Bean上绑定该监听器
+ **/
+
+@Slf4j
+public class MyJobListener implements JobExecutionListener {
+
+
+ @Override
+ public void beforeJob(JobExecution jobExecution) {
+ log.info("job 开始, id={}",jobExecution.getJobId());
+ }
+
+ @Override
+ public void afterJob(JobExecution jobExecution) {
+ log.info("job 结束, id={}",jobExecution.getJobId());
+ }
+}
diff --git a/batch/src/main/java/cn/lycode/batch/listener/MyReadListener.java b/batch/src/main/java/cn/lycode/batch/listener/MyReadListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..9a97e67e0e98e9aa16727e2bd94d888fb65cdfa5
--- /dev/null
+++ b/batch/src/main/java/cn/lycode/batch/listener/MyReadListener.java
@@ -0,0 +1,29 @@
+package cn.lycode.batch.listener;
+
+import cn.lycode.batch.bean.TestData;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.batch.core.ItemReadListener;
+
+import static java.lang.String.format;
+
+@Slf4j
+public class MyReadListener implements ItemReadListener {
+
+
+ @Override
+ public void beforeRead() {
+ }
+
+ @Override
+ public void afterRead(TestData item) {
+ }
+
+ @Override
+ public void onReadError(Exception ex) {
+ try {
+ log.info(format("%s%n", ex.getMessage()));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/batch/src/main/java/cn/lycode/batch/listener/MyWriteListener.java b/batch/src/main/java/cn/lycode/batch/listener/MyWriteListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..4a6e25dd51da8c575c414164ed4319cc711b0074
--- /dev/null
+++ b/batch/src/main/java/cn/lycode/batch/listener/MyWriteListener.java
@@ -0,0 +1,33 @@
+package cn.lycode.batch.listener;
+
+import cn.lycode.batch.bean.TestData;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.batch.core.ItemWriteListener;
+import java.util.List;
+import static java.lang.String.format;
+
+@Slf4j
+public class MyWriteListener implements ItemWriteListener {
+
+ @Override
+ public void beforeWrite(List extends TestData> items) {
+ }
+
+ @Override
+ public void afterWrite(List extends TestData> items) {
+ }
+
+ @Override
+ public void onWriteError(Exception exception, List extends TestData> items) {
+ try {
+ log.info(format("%s%n", exception.getMessage()));
+ for (TestData message : items) {
+ log.info(format("Failed writing BlogInfo : %s", message.toString()));
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+}
diff --git a/batch/src/main/java/cn/lycode/batch/processor/MyItemProcessor.java b/batch/src/main/java/cn/lycode/batch/processor/MyItemProcessor.java
new file mode 100644
index 0000000000000000000000000000000000000000..935aabac8907e39045acad2587f8e0cc25a3be30
--- /dev/null
+++ b/batch/src/main/java/cn/lycode/batch/processor/MyItemProcessor.java
@@ -0,0 +1,25 @@
+package cn.lycode.batch.processor;
+
+import cn.lycode.batch.bean.TestData;
+import org.springframework.batch.item.validator.ValidatingItemProcessor;
+import org.springframework.batch.item.validator.ValidationException;
+
+
+public class MyItemProcessor extends ValidatingItemProcessor {
+ @Override
+ public TestData process(TestData item) throws ValidationException {
+ /**
+ * 需要执行super.process(item)才会调用自定义校验器
+ */
+ super.process(item);
+ /**
+ * 对数据进行简单的处理
+ */
+ if (item.getName().equals("testBatch1")) {
+ item.setProcess("testBatch1 处理一下!!!");
+ } else {
+ item.setProcess("未知系列");
+ }
+ return item;
+ }
+}
diff --git a/batch/src/main/java/cn/lycode/batch/validator/MyBeanValidator.java b/batch/src/main/java/cn/lycode/batch/validator/MyBeanValidator.java
new file mode 100644
index 0000000000000000000000000000000000000000..b9f61009d86ba046202c205bddc04e32ffae6a67
--- /dev/null
+++ b/batch/src/main/java/cn/lycode/batch/validator/MyBeanValidator.java
@@ -0,0 +1,43 @@
+package cn.lycode.batch.validator;
+
+import org.springframework.batch.item.validator.ValidationException;
+import org.springframework.batch.item.validator.Validator;
+import org.springframework.beans.factory.InitializingBean;
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.ValidatorFactory;
+import java.util.Set;
+
+
+public class MyBeanValidator implements Validator, InitializingBean {
+
+ private javax.validation.Validator validator;
+
+ @Override
+ public void validate(T value) throws ValidationException {
+ /**
+ * 使用Validator的validate方法校验数据
+ */
+ Set> constraintViolations =
+ validator.validate(value);
+ if (constraintViolations.size() > 0) {
+ StringBuilder message = new StringBuilder();
+ for (ConstraintViolation constraintViolation : constraintViolations) {
+ message.append(constraintViolation.getMessage() + "\n");
+ }
+ throw new ValidationException(message.toString());
+ }
+ }
+
+ /**
+ * 使用JSR-303的Validator来校验我们的数据,在此进行JSR-303的Validator的初始化
+ * @throws Exception
+ */
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ ValidatorFactory validatorFactory =
+ Validation.buildDefaultValidatorFactory();
+ validator = validatorFactory.usingContext().getValidator();
+ }
+
+}
diff --git a/batch/src/main/resources/application-batch.yml b/batch/src/main/resources/application-batch.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1da53a13c8a420f8e2764347703c4a1f2a473d60
--- /dev/null
+++ b/batch/src/main/resources/application-batch.yml
@@ -0,0 +1,8 @@
+spring:
+ batch:
+ job:
+ #设置为 false -需要jobLaucher.run执行
+ enabled: false
+ jdbc:
+ initialize-schema: always
+# table-prefix: my-batch
\ No newline at end of file
diff --git a/batch/src/main/resources/static/testData.csv b/batch/src/main/resources/static/testData.csv
new file mode 100644
index 0000000000000000000000000000000000000000..d4080ca956f3ae959aa3a1afb0d446c6628853b7
--- /dev/null
+++ b/batch/src/main/resources/static/testData.csv
@@ -0,0 +1,3 @@
+lyg,,ces
+lyg,cdd,ces
+testBatch1,ff,d
\ No newline at end of file
diff --git a/common/src/main/java/cn/lycode/common/enums/ErrorEnum.java b/common/src/main/java/cn/lycode/common/enums/ErrorEnum.java
index ce679617ba65b91ff7171b402bc31884e3df6f2a..403d0497a3fcef92a9fc287537494e9cceb88e1f 100644
--- a/common/src/main/java/cn/lycode/common/enums/ErrorEnum.java
+++ b/common/src/main/java/cn/lycode/common/enums/ErrorEnum.java
@@ -50,6 +50,7 @@ public enum ErrorEnum implements ServiceExceptionCustomAssert {
EXIST_DICT("900346", "禁止插入重复字典!"),
PARAM_ERROR("900341", "参数错误!"),
FORBID_OPERATION("900342", "禁止操作!"),
+ EXIST_USERNAME("900344", "此用户名已存在!"),
SYSTEM_ERROR("900500", "系统错误");
diff --git a/common/src/main/java/cn/lycode/common/event/PermsChangeEvent.java b/common/src/main/java/cn/lycode/common/event/PermsChangeEvent.java
deleted file mode 100644
index 7a64a7a50f8829ef212d135bc4aa8db23b839712..0000000000000000000000000000000000000000
--- a/common/src/main/java/cn/lycode/common/event/PermsChangeEvent.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package cn.lycode.common.event;
-
-/**
- * 权限变更事件(用户角色变更、角色权限变更)
- * 由带@EventListener 注解的方法监听此事件
- */
-public class PermsChangeEvent extends BaseEvent {
- public PermsChangeEvent(Object source, PermsMeta payload) {
- super(source, payload);
- }
-}
diff --git a/common/src/main/java/cn/lycode/common/event/PermsMeta.java b/common/src/main/java/cn/lycode/common/event/PermsMeta.java
deleted file mode 100644
index 42412bcf602603a21c5d0959948d8e328fa121ae..0000000000000000000000000000000000000000
--- a/common/src/main/java/cn/lycode/common/event/PermsMeta.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package cn.lycode.common.event;
-
-import lombok.Data;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-@Data
-public class PermsMeta {
-
- public PermsMeta() {
- roleFlags = new ArrayList<>();
- }
-
- public PermsMeta(List> roleFlags) {
- this.roleFlags = roleFlags;
- }
-
- public PermsMeta(Object roleFlag) {
- if (roleFlag != null) {
- this.roleFlags = Collections.singletonList(roleFlag);
- }
- }
-
-
- private List> roleFlags;
-
-}
diff --git a/common/src/main/java/cn/lycode/common/event/SessionChangeEvent.java b/common/src/main/java/cn/lycode/common/event/SessionChangeEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..0684adba754537498e2c9eb8eb5de0fe9c592bda
--- /dev/null
+++ b/common/src/main/java/cn/lycode/common/event/SessionChangeEvent.java
@@ -0,0 +1,8 @@
+package cn.lycode.common.event;
+
+public class SessionChangeEvent extends BaseEvent {
+
+ public SessionChangeEvent(Object source, SessionChangeMeta payload) {
+ super(source, payload);
+ }
+}
diff --git a/common/src/main/java/cn/lycode/common/event/SessionChangeMeta.java b/common/src/main/java/cn/lycode/common/event/SessionChangeMeta.java
new file mode 100644
index 0000000000000000000000000000000000000000..2030aa9efb732805596f1330e887f6e0d73ed7dc
--- /dev/null
+++ b/common/src/main/java/cn/lycode/common/event/SessionChangeMeta.java
@@ -0,0 +1,53 @@
+package cn.lycode.common.event;
+
+import cn.lycode.common.core.domain.AjaxResult;
+import cn.lycode.common.enums.ErrorEnum;
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+@Data
+public class SessionChangeMeta {
+
+ private List> roleFlagList; //变动的角色
+ private List> userIdList; //变动的用户
+
+
+ public static SessionChangeMeta roleList(List> roleFlags) {
+ ErrorEnum.PARAM_NULL.assertNotNull(roleFlags);
+ SessionChangeMeta sessionChangeMeta = new SessionChangeMeta();
+ sessionChangeMeta.setRoleFlagList(roleFlags);
+ return sessionChangeMeta;
+ }
+
+ public static SessionChangeMeta role(Object roleFlag) {
+ SessionChangeMeta sessionChangeMeta = new SessionChangeMeta();
+ if (roleFlag != null) {
+ sessionChangeMeta.setRoleFlagList(Collections.singletonList(roleFlag));
+ }
+ return sessionChangeMeta;
+ }
+
+
+ public static SessionChangeMeta userList(List> userFlags) {
+ ErrorEnum.PARAM_NULL.assertNotNull(userFlags);
+ SessionChangeMeta sessionChangeMeta = new SessionChangeMeta();
+ sessionChangeMeta.setUserIdList(userFlags);
+ return sessionChangeMeta;
+ }
+
+ public static SessionChangeMeta user(Object userFlag) {
+ SessionChangeMeta sessionChangeMeta = new SessionChangeMeta();
+ if (userFlag != null) {
+ sessionChangeMeta.setUserIdList(Collections.singletonList(userFlag));
+ }
+ return sessionChangeMeta;
+ }
+
+ private SessionChangeMeta(){
+ roleFlagList = new ArrayList<>();
+ userIdList = new ArrayList<>();
+ }
+}
diff --git a/framework/pom.xml b/framework/pom.xml
index 28cf4ca7b38114f23fd2b5d9dce37536933b8e1d..6e22fb9e999e2140b088fd3a4697f5ed40b29fbb 100644
--- a/framework/pom.xml
+++ b/framework/pom.xml
@@ -58,7 +58,18 @@
cn.lycode
system
- 1.0.0
+
+
+
+
+ cn.lycode
+ generator
+
+
+
+
+ cn.lycode
+ batch
diff --git a/framework/src/main/java/cn/lycode/framework/constant/FrameworkConstant.java b/framework/src/main/java/cn/lycode/framework/constant/FrameworkConstant.java
new file mode 100644
index 0000000000000000000000000000000000000000..31d8a3460d16d40b292637e32c18e32c25dd20c5
--- /dev/null
+++ b/framework/src/main/java/cn/lycode/framework/constant/FrameworkConstant.java
@@ -0,0 +1,18 @@
+package cn.lycode.framework.constant;
+
+/**
+ * @Title: FrameworkConstant
+ * @Author lyg
+ * @Date 2024/11/29 16:07
+ * @description:
+ */
+public class FrameworkConstant {
+
+ /**
+ * session key
+ */
+ public static String SESSION_KEY_PERMS_LIST = "Perms_List";
+ public static String SESSION_KEY_MENU_LIST = "Menu_List";
+ public static String SESSION_KEY_ROLE_LIST = "Role_List";
+ public static String SESSION_KEY_ROLE_PREFIX = "Role_";
+}
diff --git a/framework/src/main/java/cn/lycode/framework/event/GlobalEventListener.java b/framework/src/main/java/cn/lycode/framework/event/GlobalEventListener.java
index 0ad7d21f72ae7e6f9caab7a181fbb809c908a295..a48b95663d667d73fe2031d98aa323a499972307 100644
--- a/framework/src/main/java/cn/lycode/framework/event/GlobalEventListener.java
+++ b/framework/src/main/java/cn/lycode/framework/event/GlobalEventListener.java
@@ -2,10 +2,10 @@ package cn.lycode.framework.event;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.SaSessionCustomUtil;
-import cn.lycode.common.event.PermsChangeEvent;
-import cn.lycode.common.event.PermsMeta;
-import cn.lycode.common.utils.SecurityUtils;
-import cn.lycode.framework.web.service.SysLoginService;
+import cn.dev33.satoken.stp.StpUtil;
+import cn.lycode.common.event.SessionChangeMeta;
+import cn.lycode.common.event.SessionChangeEvent;
+import cn.lycode.framework.constant.FrameworkConstant;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
@@ -13,6 +13,8 @@ import org.springframework.stereotype.Component;
import java.util.List;
+import static cn.lycode.framework.constant.FrameworkConstant.SESSION_KEY_ROLE_PREFIX;
+
/**
* @ClassName EventListener 事件监听器
*/
@@ -21,17 +23,32 @@ import java.util.List;
@Slf4j
public class GlobalEventListener {
- //监听到 PermsChangeEvent事件就会执行
+ /**
+ * 监听到 PermsChangeEvent事件就会执行
+ * 清空缓存的 当前角色对应的菜单列表和权限列表
+ * 菜单列表:根据角色菜单表查出的此角色拥有的菜单
+ * 权限列表:所有拥有的菜单中的权限标识
+ * @param event
+ */
@EventListener
- public void handlePermissionChangeEvent(PermsChangeEvent event) {
- PermsMeta permsMeta = event.getPayload();
- log.info("[事件监听]-权限变更, data: {}", permsMeta);
- List> roleFlags = permsMeta.getRoleFlags();
+ public void handleSessionChangeEvent(SessionChangeEvent event) {
+ SessionChangeMeta sessionChangeMeta = event.getPayload();
+ log.info("[事件监听]-权限Session变更, data: {}", sessionChangeMeta);
+ List> roleFlags = sessionChangeMeta.getRoleFlagList();
+
for (Object roleFlag : roleFlags) {
- SaSession roleSession = SaSessionCustomUtil.getSessionById("role-" + roleFlag);
- roleSession.delete("Perms_List");
- roleSession.delete("Menu_List");
+ SaSession roleSession = SaSessionCustomUtil.getSessionById(SESSION_KEY_ROLE_PREFIX + roleFlag);
+ roleSession.delete(FrameworkConstant.SESSION_KEY_PERMS_LIST);
+ roleSession.delete(FrameworkConstant.SESSION_KEY_MENU_LIST);
+ }
+
+ List> userIdList = sessionChangeMeta.getUserIdList();
+ for (Object userId : userIdList) {
+ SaSession session = StpUtil.getSessionByLoginId(userId);
+ session.delete(FrameworkConstant.SESSION_KEY_ROLE_LIST);
}
+
}
+
}
diff --git a/framework/src/main/java/cn/lycode/framework/satoken/MySaTokenListener.java b/framework/src/main/java/cn/lycode/framework/satoken/MySaTokenListener.java
index 29adfbf2a1b5c957abe0593462cdab25cbc46e61..36d4fb33daddceb2ec7e221ea503a0b521f3dd6e 100644
--- a/framework/src/main/java/cn/lycode/framework/satoken/MySaTokenListener.java
+++ b/framework/src/main/java/cn/lycode/framework/satoken/MySaTokenListener.java
@@ -3,7 +3,7 @@ package cn.lycode.framework.satoken;
import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
-import cn.lycode.rbac.service.SysUserService;
+import cn.lycode.system.service.SysUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
diff --git a/framework/src/main/java/cn/lycode/framework/satoken/SaTokenConfig.java b/framework/src/main/java/cn/lycode/framework/satoken/SaTokenConfig.java
index 0b3e16293a35f254ea918c76bfd1ee320357d229..ba94cf167b91c896790a37cb47865721e27648ce 100644
--- a/framework/src/main/java/cn/lycode/framework/satoken/SaTokenConfig.java
+++ b/framework/src/main/java/cn/lycode/framework/satoken/SaTokenConfig.java
@@ -27,7 +27,7 @@ public class SaTokenConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 打开注解鉴权
-// registry.addInterceptor(new SaInterceptor().isAnnotation(true)).addPathPatterns("/**").excludePathPatterns(whitelistProperties.getWhitelist());
+ // registry.addInterceptor(new SaInterceptor().isAnnotation(true)).addPathPatterns("/**").excludePathPatterns(whitelistProperties.getWhitelist());
// 注册 Sa-Token 拦截器,打开注解式鉴权功能
registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**").excludePathPatterns(whitelistProperties.getWhitelist());;
}
diff --git a/framework/src/main/java/cn/lycode/framework/web/controller/SysLoginController.java b/framework/src/main/java/cn/lycode/framework/web/controller/SysLoginController.java
index 8cfdc372d108ed3980070c5c019d1698216fb785..4933f464527e0ebceed3b6af07fa1173a461e9aa 100644
--- a/framework/src/main/java/cn/lycode/framework/web/controller/SysLoginController.java
+++ b/framework/src/main/java/cn/lycode/framework/web/controller/SysLoginController.java
@@ -6,7 +6,7 @@ import cn.lycode.common.core.controller.BaseController;
import cn.lycode.common.core.domain.AjaxResult;
import cn.lycode.common.core.domain.model.user.LoginBody;
import cn.lycode.framework.web.domain.LoginVO;
-import cn.lycode.rbac.domain.vo.SysMenuVO;
+import cn.lycode.system.domain.vo.SysMenuVO;
import cn.lycode.framework.web.service.SysLoginService;
import cn.lycode.framework.web.service.SysPermissionService;
import lombok.RequiredArgsConstructor;
diff --git a/framework/src/main/java/cn/lycode/framework/web/service/SysLoginService.java b/framework/src/main/java/cn/lycode/framework/web/service/SysLoginService.java
index caa56978d14510a551a1492ca97ff1dd34f2c4c1..119321d465cbe1118d790255a19983f884ccd601 100644
--- a/framework/src/main/java/cn/lycode/framework/web/service/SysLoginService.java
+++ b/framework/src/main/java/cn/lycode/framework/web/service/SysLoginService.java
@@ -10,7 +10,7 @@ import cn.lycode.common.core.domain.model.user.LoginUserInfo;
import cn.lycode.common.enums.ErrorEnum;
import cn.lycode.common.utils.SecurityUtils;
import cn.lycode.framework.web.domain.LoginVO;
-import cn.lycode.rbac.service.SysUserService;
+import cn.lycode.system.service.SysUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
diff --git a/framework/src/main/java/cn/lycode/framework/web/service/SysPermissionService.java b/framework/src/main/java/cn/lycode/framework/web/service/SysPermissionService.java
index 60646fd0183d4fd7fd5e240075f532a07c1ce823..7168bb2342083716d375ae10543b81b0cd96d577 100644
--- a/framework/src/main/java/cn/lycode/framework/web/service/SysPermissionService.java
+++ b/framework/src/main/java/cn/lycode/framework/web/service/SysPermissionService.java
@@ -4,9 +4,10 @@ import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.SaSessionCustomUtil;
import cn.dev33.satoken.stp.StpUtil;
import cn.lycode.common.constant.Constants;
-import cn.lycode.rbac.domain.vo.SysMenuVO;
-import cn.lycode.rbac.service.SysMenuService;
-import cn.lycode.rbac.service.SysRoleService;
+import cn.lycode.framework.constant.FrameworkConstant;
+import cn.lycode.system.domain.vo.SysMenuVO;
+import cn.lycode.system.service.SysMenuService;
+import cn.lycode.system.service.SysRoleService;
import cn.lycode.common.utils.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -17,9 +18,14 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import static cn.lycode.framework.constant.FrameworkConstant.*;
+
/**
* 用户权限处理
*
+ * 用户对应角色, 角色对应权限和菜单
+ * 每次更新角色的菜单 清除 Perms_List、Menu_List
+ * 每次更新用户对应的角色,应该清除当前用户的 Role_List
* @author lyCode
*/
@Slf4j
@@ -37,7 +43,7 @@ public class SysPermissionService {
public Set getRolePermFlag(Long userId) {
SaSession session = StpUtil.getSessionByLoginId(userId);
//session.get 方法有Sa-token提供缓存
- return session.get("Role_List", () -> {
+ return session.get(SESSION_KEY_ROLE_LIST, () -> {
Set roles = new HashSet();
// 管理员拥有所有权限
if (SecurityUtils.isSuperAdmin(userId)) {
@@ -66,9 +72,9 @@ public class SysPermissionService {
permissionSet.add(Constants.ALL_PERMISSION);
}else {
for (String roleFlag : rolePermFlagSet) {
- SaSession roleSession = SaSessionCustomUtil.getSessionById("role-" + roleFlag);
+ SaSession roleSession = SaSessionCustomUtil.getSessionById(SESSION_KEY_ROLE_PREFIX + roleFlag);
//roleSession.get 方法有Sa-token提供缓存
- List list = roleSession.get("Perms_List", () -> {
+ List list = roleSession.get(SESSION_KEY_PERMS_LIST, () -> {
return new ArrayList<>(menuService.selectMenuPermsByRoleFlag(roleFlag)); // 从数据库查询这个角色所拥有的权限列表
});
permissionSet.addAll(list);
@@ -92,13 +98,12 @@ public class SysPermissionService {
Set rolePermFlagSet = getRolePermFlag(loginUserId);
SaSession userSession = StpUtil.getSessionByLoginId(loginUserId);
if (rolePermFlagSet.contains(Constants.SUPER_ADMIN)) {
- //超级管理员拥有所有菜单.
- SaSession roleSession = SaSessionCustomUtil.getSessionById("role-" + Constants.SUPER_ADMIN);
- sysMenuVOList = roleSession.get("Menu_List", menuService::selectFrontMenuAll);
+ //超级管理员拥有所有菜单. 且不带缓存,每次刷新都会请求菜单
+ sysMenuVOList = menuService.selectFrontMenuAll();
}else {
for (String roleFlag : rolePermFlagSet) {
//roleSession.get 方法有Sa-token提供缓存
- List list = userSession.get("Menu_List", () -> {
+ List list = userSession.get(SESSION_KEY_MENU_LIST, () -> {
return menuService.selectFrontMenusByRoleName(roleFlag); // 从数据库查询这个角色所拥有的权限列表
});
sysMenuVOList.addAll(list);
diff --git a/framework/src/main/java/cn/lycode/framework/web/service/SysRegisterService.java b/framework/src/main/java/cn/lycode/framework/web/service/SysRegisterService.java
index 36abe07431acf59bab5635d4012a6c963032f620..b2eb4ddbe2cf9c20e6584a1f73d9c7f0daead67f 100644
--- a/framework/src/main/java/cn/lycode/framework/web/service/SysRegisterService.java
+++ b/framework/src/main/java/cn/lycode/framework/web/service/SysRegisterService.java
@@ -6,7 +6,7 @@ import cn.lycode.common.constant.UserConstants;
import cn.lycode.common.core.domain.model.user.RegisterBody;
import cn.lycode.common.utils.SecurityUtils;
import cn.lycode.common.utils.StringUtils;
-import cn.lycode.rbac.service.SysUserService;
+import cn.lycode.system.service.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
diff --git "a/generator/src/main/resources/templates/\346\250\241\346\235\277\345\217\230\351\207\217\345\220\215.md" "b/generator/src/main/resources/templates/\346\250\241\346\235\277\345\217\230\351\207\217\345\220\215.md"
index 3b417da5c276902bff299c17858b22a575514fec..1e0c708ca7ec663d5c64dcbef2d3ee94e5bdfcc6 100644
--- "a/generator/src/main/resources/templates/\346\250\241\346\235\277\345\217\230\351\207\217\345\220\215.md"
+++ "b/generator/src/main/resources/templates/\346\250\241\346\235\277\345\217\230\351\207\217\345\220\215.md"
@@ -27,7 +27,7 @@
| idType | String 主键ts类型, eg:number |
| hasSort | boolean 列表查询的时候是否引入sort排序 |
| **Java类名和包名** | ------------------------------------------------------------------------------------- |
-| entityPkg | String, 生成实体类的相对路径,eg:cn.lycode.rbac.domain.entity |
+| entityPkg | String, 生成实体类的相对路径,eg:cn.lycode.system.domain.entity |
| mapperPkg | String, 生成mapper的相对路径 |
| mapperXmlPkg | String, 生成mapper.xml的相对路径 |
| servicePkg | String, 生成service的相对路径 |
diff --git a/lycode_admin_vue/README.md b/lycode_admin_vue/README.md
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/lycode_admin_vue/env.d.ts b/lycode_admin_vue/env.d.ts
index 11f02fe2a0061d6e6e1f271b21da95423b448b32..d8479a52d41040b4be4c6d7e6e5d37e416689392 100644
--- a/lycode_admin_vue/env.d.ts
+++ b/lycode_admin_vue/env.d.ts
@@ -1 +1,7 @@
///
+declare module '*.vue' {
+ import type { DefineComponent } from 'vue'
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
+ const component: DefineComponent<{}, {}, any>
+ export default component
+}
diff --git a/lycode_admin_vue/pnpm-lock.yaml b/lycode_admin_vue/pnpm-lock.yaml
index a2ad7e762fb1a3e0d187eff7c59275c027e22522..b65e73eab0f87d22c611bf265b13d5279201036d 100644
--- a/lycode_admin_vue/pnpm-lock.yaml
+++ b/lycode_admin_vue/pnpm-lock.yaml
@@ -41,6 +41,9 @@ dependencies:
sortablejs:
specifier: ^1.15.1
version: 1.15.3
+ uuid:
+ specifier: ^10.0.0
+ version: 10.0.0
vite-plugin-svg-icons:
specifier: ^2.0.1
version: 2.0.1(vite@4.5.3)
@@ -70,6 +73,9 @@ devDependencies:
'@types/sortablejs':
specifier: ^1.15.7
version: 1.15.8
+ '@types/uuid':
+ specifier: ^10.0.0
+ version: 10.0.0
'@vitejs/plugin-vue':
specifier: ^4.4.0
version: 4.6.2(vite@4.5.3)(vue@3.4.38)
@@ -801,6 +807,10 @@ packages:
'@types/node': 18.19.48
dev: false
+ /@types/uuid@10.0.0:
+ resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==}
+ dev: true
+
/@types/web-bluetooth@0.0.16:
resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==}
dev: false
@@ -4076,6 +4086,11 @@ packages:
/util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+ /uuid@10.0.0:
+ resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==}
+ hasBin: true
+ dev: false
+
/vary@1.1.2:
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
engines: {node: '>= 0.8'}
diff --git a/lycode_admin_vue/src/api/interface/system/sysDept.ts b/lycode_admin_vue/src/api/interface/system/sysDept.ts
index c6d4422ba488da06e6582680e2728b1922350730..a3fc72ba1aea9cf87bcc5e3bf382b793908537d1 100644
--- a/lycode_admin_vue/src/api/interface/system/sysDept.ts
+++ b/lycode_admin_vue/src/api/interface/system/sysDept.ts
@@ -46,6 +46,6 @@ export namespace ISysDept {
export interface DeptSetting {
userIds: number[]
- deptIds: number[]
+ deptId: number
}
}
diff --git a/lycode_admin_vue/src/api/interface/system/sysPost.ts b/lycode_admin_vue/src/api/interface/system/sysPost.ts
index 9a26de42dfc5e3591239e98e3f28ec2be0d87f94..f6f5566977bc0aa54c1ea4151371563f09faa897 100644
--- a/lycode_admin_vue/src/api/interface/system/sysPost.ts
+++ b/lycode_admin_vue/src/api/interface/system/sysPost.ts
@@ -27,4 +27,9 @@ export namespace ISysPost {
remark?: string
}
+ export interface PostSetting {
+ userIds: number[]
+ postIds: number[]
+ }
+
}
\ No newline at end of file
diff --git a/lycode_admin_vue/src/api/interface/system/user.ts b/lycode_admin_vue/src/api/interface/system/user.ts
index efe8217f5d07dd04efa328f674e8669335136eb0..255b905100793bfaaf1173a596331a8d9d95f4ce 100644
--- a/lycode_admin_vue/src/api/interface/system/user.ts
+++ b/lycode_admin_vue/src/api/interface/system/user.ts
@@ -16,36 +16,59 @@ export namespace IUser {
export interface Form {
id?: number
username?: string
- pwd?: string
- phone: string
+ personNo: string
+ deptId: number
+ postIdList: number[]
nickName: string
- logo: string
- age: number
sex: number
- idCard: string
+ mobile: string
email: string
+ idCard: string
+ birthday: string
accountStatusCd: string
userTagCd: string
- birthday: string
+ avatar: string
}
export interface Info {
id?: number
+ deptId: number
+ personNo: string
username: string
- phone: string
nickName: string
- logo: string
- age: number
- sex: number
- idCard: string
+ userType: string
email: string
+ mobile: string
+ phone: string
+ idCard: string
+ avatar: string
+ birthday: string
+ sex: number
accountStatusCd: string
userTagCd: string
- lastLoginTime: string
+ loginIp: string
+ loginDate: string
createTime: string
updateTime: string
- delFlag: string
- birthday: string
+ remark: string
+ dept: DeptInfo
+ roleList: RoleInfo[]
+ postList: PostInfo[]
+ }
+
+ export interface DeptInfo {
+ id: number
+ pid: number
+ deptName: string
+ leader: string
+ mobile: string
+ email: string
+ }
+
+ export interface PostInfo {
+ id: number
+ postCode: string
+ postName: string
}
export interface RoleForm {
@@ -61,6 +84,7 @@ export namespace IUser {
export interface RoleInfo {
id: number
roleName: string
+ dataScope: string
}
export interface PasswordForm {
diff --git a/lycode_admin_vue/src/api/modules/system/sysPost.ts b/lycode_admin_vue/src/api/modules/system/sysPost.ts
index 7b8801d9f7fa86541a002ff5a87f0be69da3d437..0132ca240e5df02fe5c4851e4d259b18c06f8b6e 100644
--- a/lycode_admin_vue/src/api/modules/system/sysPost.ts
+++ b/lycode_admin_vue/src/api/modules/system/sysPost.ts
@@ -12,6 +12,10 @@ export const getSysPostListApi = (params: ISysPost.Query) => {
return http.get>(ADMIN_MODULE + `/sys-post/list`, params)
}
+export const getSysPostOptionApi = () => {
+ return http.get(ADMIN_MODULE + `/sys-post/option`)
+}
+
/**
* 添加
* @param params
@@ -36,7 +40,7 @@ export const updateSysPostApi = (params: ISysPost.Form) => {
* @returns {*}
*/
export const removeSysPostApi = (params: { ids: number[] }) => {
- return http.post(ADMIN_MODULE + `/sys-post/remove`, params)
+ return http.post(ADMIN_MODULE + `/sys-post/remove`, params)
}
/**
diff --git a/lycode_admin_vue/src/api/modules/system/user.ts b/lycode_admin_vue/src/api/modules/system/user.ts
index fcadbc0a71681dddf0e60d2cc6a2e6cceff90cb5..9afd77d466aad4a76df4e7bae3b217ef9944ecff 100644
--- a/lycode_admin_vue/src/api/modules/system/user.ts
+++ b/lycode_admin_vue/src/api/modules/system/user.ts
@@ -3,6 +3,7 @@ import { ADMIN_MODULE } from '@/api/helper/prefix'
import type { IUser } from '@/api/interface/system/user'
import type { IPage } from '@/api/interface'
import type { ISysDept } from '@/api/interface/system/sysDept'
+import type { ISysPost } from '@/api/interface/system/sysPost'
/**
* 获取用户列表
@@ -28,6 +29,8 @@ export const addUser = (params: IUser.Form) => {
* @returns {*}
*/
export const editUser = (params: IUser.Form) => {
+ console.log(params);
+
return http.post(ADMIN_MODULE + `/sys-user/update`, params)
}
@@ -64,7 +67,7 @@ export const setUserRole = (params: IUser.RoleForm) => {
* @returns {*}
*/
export const changePassword = (params: IUser.PasswordForm) => {
- return http.put(ADMIN_MODULE + `/sys-user/password`, params)
+ return http.post(ADMIN_MODULE + `/sys-user/password`, params)
}
/**
@@ -73,7 +76,7 @@ export const changePassword = (params: IUser.PasswordForm) => {
*/
export const resetPassword = (params: { id: number }) => {
const { id } = params
- return http.put(ADMIN_MODULE + `/sys-user/reset/password/${id}`, {})
+ return http.post(ADMIN_MODULE + `/sys-user/reset/password/${id}`, {})
}
/**
@@ -85,7 +88,7 @@ export const getUserinfo = () => {
}
/**
- * 添加
+ * 绑定部门
* @param params
* @returns {*}
*/
@@ -93,6 +96,15 @@ export const bindUserDeptApi = (params: ISysDept.DeptSetting) => {
return http.post(ADMIN_MODULE + `/sys-user/dept/bind`, params)
}
+/**
+ * 绑定岗位
+ * @param params
+ * @returns {*}
+ */
+export const bindUserPostApi = (params: ISysPost.PostSetting) => {
+ return http.post(ADMIN_MODULE + `/sys-user/post/bind`, params)
+}
+
/**
* 用户部门属性列表
*/
diff --git a/lycode_admin_vue/src/views/system/accountManage/components/UserAdd.vue b/lycode_admin_vue/src/views/system/accountManage/components/UserAdd.vue
index 27c376b9ca0820af86162ccb3c311d62029b5233..c37bed8c2701667598f841b255a3c75f473125c6 100644
--- a/lycode_admin_vue/src/views/system/accountManage/components/UserAdd.vue
+++ b/lycode_admin_vue/src/views/system/accountManage/components/UserAdd.vue
@@ -99,11 +99,11 @@
-
+
取消
diff --git a/lycode_admin_vue/src/views/system/accountManage/components/UserDeptForm.vue b/lycode_admin_vue/src/views/system/accountManage/components/UserDeptForm.vue
index aa7e5ae9dc79c6b2fce704bb9d1bdf4f3cd9b8ac..f57e4f25ffb7674090ac7193fcfda7ab318b7fb6 100644
--- a/lycode_admin_vue/src/views/system/accountManage/components/UserDeptForm.vue
+++ b/lycode_admin_vue/src/views/system/accountManage/components/UserDeptForm.vue
@@ -27,16 +27,15 @@
style="padding: 10px"
>
-
+
+ {{ user.username }}
+
-
+
([])
+const selectedList = ref([])
-const deptIds = ref([])
+const deptId = ref()
const visible = ref(false)
const paramsProps = ref({
@@ -89,10 +90,12 @@ const loadParentMenus = () => {
// 接收父组件传过来的参数
const acceptParams = (params: View.DefaultParams) => {
paramsProps.value = params
+
selectIds.value = params?.selectIds
- if (Array.isArray(params?.deptId)) {
+ selectedList.value = params?.selectedList
+ if (params?.deptId != -1 && params?.deptId != -2) {
// 过滤掉值为 0 -1 和 -2 的元素
- deptIds.value = params.deptId.filter((id) => id !== 0 && id !== -1 && id !== -2)
+ deptId.value = params.deptId
}
visible.value = true
loadParentMenus()
@@ -112,7 +115,7 @@ const handleSubmit = () => {
try {
const param = {
userIds: selectIds.value,
- deptIds: deptIds.value
+ deptId: deptId.value
}
await bindUserDeptApi(param).then(() => paramsProps.value.getTableList!())
ElMessage.success({ message: `${paramsProps.value.title}成功!` })
diff --git a/lycode_admin_vue/src/views/system/accountManage/components/UserEdit.vue b/lycode_admin_vue/src/views/system/accountManage/components/UserEdit.vue
index c1d81848d6f7a16b60432db8160be9fa721608ed..12362b654f4f68b4b6eb999902b4f3e2e483d412 100644
--- a/lycode_admin_vue/src/views/system/accountManage/components/UserEdit.vue
+++ b/lycode_admin_vue/src/views/system/accountManage/components/UserEdit.vue
@@ -32,6 +32,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -108,11 +136,11 @@
-
+
取消
@@ -124,6 +152,10 @@
+
+
diff --git a/lycode_admin_vue/src/views/system/accountManage/index.vue b/lycode_admin_vue/src/views/system/accountManage/index.vue
index c1696551d54ea07478df4ac59a9c3e812940999b..f99a349e928ee7b670203d7f415af493ea64e7c0 100644
--- a/lycode_admin_vue/src/views/system/accountManage/index.vue
+++ b/lycode_admin_vue/src/views/system/accountManage/index.vue
@@ -41,11 +41,26 @@
>
批量删除
-
-
+
+
+ 设置部门
+
+
+ 设置岗位
-
+
{{ tag.roleName }}
+
+
+ {{ tag.postName }}
+
+
+
+
+
+ 设置部门
+
+
+
+
+
+ 设置岗位
+
+
+
+
删除
@@ -141,6 +175,7 @@
+
@@ -153,7 +188,10 @@ import {
User,
Unlock,
Refresh,
- DArrowRight
+ DArrowRight,
+ School,
+ OfficeBuilding,
+ HomeFilled
} from '@element-plus/icons-vue'
import ProTable from '@/components/ProTable/index.vue'
import DeptTree from '@/views/system/accountManage/components/DeptTree.vue'
@@ -179,6 +217,7 @@ import type { IRole } from '@/api/interface/system/role'
import { reactive, ref } from 'vue'
import SvgIcon from '@/components/SvgIcon/index.vue'
import UserDeptForm from '@/views/system/accountManage/components/UserDeptForm.vue'
+import UserPostForm from '@/views/system/accountManage/components/UserPostForm.vue'
import { ElMessage, ElMessageBox } from 'element-plus'
defineOptions({
name: 'accountManage'
@@ -192,20 +231,14 @@ const optionsStore = useOptionsStore()
// ]
const accountStatusOption = optionsStore.getDictOptions('account_status')
-// 表格配置项
-const columns: ColumnProps[] = [
+// 表格配置项 prop: 可以自定义 template 也可以自动渲染对应返回值内容
+const columns: ColumnProps[] = [
{ type: 'selection', width: 55, selectable: (row) => row.id !== 1 },
- { prop: 'username', label: '账户', width: 150, align: 'left' },
- { prop: 'nickName', label: '昵称', width: 150, align: 'left' },
- { prop: 'mobile', label: '手机号', width: 120 },
- {
- prop: 'deptInfo',
- label: '部门'
- },
- {
- prop: 'roleInfo',
- label: '角色'
- },
+ { prop: 'username', label: '账户', width: 110, align: 'left' },
+ { prop: 'nickName', label: '昵称', width: 110, align: 'left' },
+ { prop: 'deptInfo', label: '部门', width: 100 },
+ { prop: 'roleInfo', label: '角色', width: 150 },
+ { prop: 'postInfo', label: '岗位', width: 150 },
{
prop: 'accountStatusCd',
label: '状态',
@@ -214,8 +247,9 @@ const columns: ColumnProps[] = [
width: 80,
fieldNames: { label: 'codeName', value: 'id', tagType: 'callbackShowStyle' }
},
- { prop: 'createTime', label: '创建时间', width: 165 },
- { prop: 'operation', label: '操作', width: 260, fixed: 'right' }
+ { prop: 'mobile', label: '手机号', width: 120 },
+ { prop: 'createTime', label: '创建时间', width: 125 },
+ { prop: 'operation', label: '操作', width: 230, fixed: 'right' }
]
const searchColumns: SearchProps[] = [
@@ -289,6 +323,7 @@ const batchDelete = async (ids: string[]) => {
refreshDeptTree()
}
const userDeptFormRef = ref>()
+const userPostFormRef = ref>()
const settingDept = (record: any) => {
if (record.selectedListIds) {
const params = {
@@ -303,13 +338,14 @@ const settingDept = (record: any) => {
}
userDeptFormRef.value?.acceptParams(params)
} else {
+ console.log(record)
const params = {
title: '设置部门',
row: {},
api: undefined,
getTableList: proTableRef.value?.getTableList,
selectedList: [record], //选中的行信息
- deptId: record.deptIds.split(',').map(Number),
+ deptId: record.deptId,
selectIds: [record.id],
isBatch: false
}
@@ -317,6 +353,36 @@ const settingDept = (record: any) => {
}
}
+const settingPost = (record: any) => {
+ if (record.selectedListIds) {
+ const params = {
+ title: '批量设置岗位',
+ row: {},
+ api: undefined,
+ getTableList: proTableRef.value?.getTableList,
+ selectedList: record.selectedList, //选中的行信息
+ selectIds: record.selectedListIds,
+ isBatch: true
+ }
+ userPostFormRef.value?.acceptParams(params)
+ } else {
+ console.log('设置岗位传入内容', record)
+ const params = {
+ title: '设置岗位',
+ row: {},
+ api: undefined,
+ getTableList: proTableRef.value?.getTableList,
+ selectedList: [record], //选中的行信息
+ postIds: record.postList.map((post: { id: number }) => post.id),
+ selectIds: [record.id],
+ isBatch: false
+ }
+ console.log(params)
+
+ userPostFormRef.value?.acceptParams(params)
+ }
+}
+
const unlock = async (id: string | string[]) => {
if (Array.isArray(id)) {
await unlockUser({ ids: id })
@@ -343,10 +409,11 @@ const resetPwd = async (row: any) => {
const initParam = reactive({ deptId: -1 })
-const selectTreeId = ref([])
+//全部,后端设置treeId=-1, 未设置部门, 后端设置treeId=-2
+const selectTreeId = ref()
const changeDeptTree = (val: number) => {
if (val) {
- selectTreeId.value = [val]
+ selectTreeId.value = val
initParam.deptId = val
proTableRef.value?.getTableList()
proTableRef.value?.clearSelection()
diff --git a/pom.xml b/pom.xml
index c1333937c8d23eb14c84959f9a02a64c68c551c0..1cd16dcb2dc511a7328405289c4a22f09712732e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
cn.lycode
lycode-base
- ${lycode.version}
+ 1.0.0
pom
lycode-base
@@ -18,6 +18,7 @@
framework
system
generator
+ batch
@@ -193,6 +194,12 @@
${lycode.version}
+
+ cn.lycode
+ batch
+ ${lycode.version}
+
+
diff --git a/static/spring-batch-mysql.sql b/static/spring-batch-mysql.sql
new file mode 100644
index 0000000000000000000000000000000000000000..3378a9a75e8c432c7b6d2fd77737d5d559de09de
--- /dev/null
+++ b/static/spring-batch-mysql.sql
@@ -0,0 +1,101 @@
+-- Autogenerated: do not edit this file
+
+CREATE TABLE BATCH_JOB_INSTANCE (
+ JOB_INSTANCE_ID BIGINT NOT NULL PRIMARY KEY ,
+ VERSION BIGINT ,
+ JOB_NAME VARCHAR(100) NOT NULL,
+ JOB_KEY VARCHAR(32) NOT NULL,
+ constraint JOB_INST_UN unique (JOB_NAME, JOB_KEY)
+) ENGINE=InnoDB;
+
+CREATE TABLE BATCH_JOB_EXECUTION (
+ JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY ,
+ VERSION BIGINT ,
+ JOB_INSTANCE_ID BIGINT NOT NULL,
+ CREATE_TIME DATETIME(6) NOT NULL,
+ START_TIME DATETIME(6) DEFAULT NULL ,
+ END_TIME DATETIME(6) DEFAULT NULL ,
+ STATUS VARCHAR(10) ,
+ EXIT_CODE VARCHAR(2500) ,
+ EXIT_MESSAGE VARCHAR(2500) ,
+ LAST_UPDATED DATETIME(6),
+ JOB_CONFIGURATION_LOCATION VARCHAR(2500) NULL,
+ constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
+ references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
+) ENGINE=InnoDB;
+
+CREATE TABLE BATCH_JOB_EXECUTION_PARAMS (
+ JOB_EXECUTION_ID BIGINT NOT NULL ,
+ TYPE_CD VARCHAR(6) NOT NULL ,
+ KEY_NAME VARCHAR(100) NOT NULL ,
+ STRING_VAL VARCHAR(250) ,
+ DATE_VAL DATETIME(6) DEFAULT NULL ,
+ LONG_VAL BIGINT ,
+ DOUBLE_VAL DOUBLE PRECISION ,
+ IDENTIFYING CHAR(1) NOT NULL ,
+ constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
+ references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
+) ENGINE=InnoDB;
+
+CREATE TABLE BATCH_STEP_EXECUTION (
+ STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY ,
+ VERSION BIGINT NOT NULL,
+ STEP_NAME VARCHAR(100) NOT NULL,
+ JOB_EXECUTION_ID BIGINT NOT NULL,
+ START_TIME DATETIME(6) NOT NULL ,
+ END_TIME DATETIME(6) DEFAULT NULL ,
+ STATUS VARCHAR(10) ,
+ COMMIT_COUNT BIGINT ,
+ READ_COUNT BIGINT ,
+ FILTER_COUNT BIGINT ,
+ WRITE_COUNT BIGINT ,
+ READ_SKIP_COUNT BIGINT ,
+ WRITE_SKIP_COUNT BIGINT ,
+ PROCESS_SKIP_COUNT BIGINT ,
+ ROLLBACK_COUNT BIGINT ,
+ EXIT_CODE VARCHAR(2500) ,
+ EXIT_MESSAGE VARCHAR(2500) ,
+ LAST_UPDATED DATETIME(6),
+ constraint JOB_EXEC_STEP_FK foreign key (JOB_EXECUTION_ID)
+ references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
+) ENGINE=InnoDB;
+
+CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT (
+ STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY,
+ SHORT_CONTEXT VARCHAR(2500) NOT NULL,
+ SERIALIZED_CONTEXT TEXT ,
+ constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID)
+ references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID)
+) ENGINE=InnoDB;
+
+CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT (
+ JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY,
+ SHORT_CONTEXT VARCHAR(2500) NOT NULL,
+ SERIALIZED_CONTEXT TEXT ,
+ constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID)
+ references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
+) ENGINE=InnoDB;
+
+CREATE TABLE BATCH_STEP_EXECUTION_SEQ (
+ ID BIGINT NOT NULL,
+ UNIQUE_KEY CHAR(1) NOT NULL,
+ constraint UNIQUE_KEY_UN unique (UNIQUE_KEY)
+) ENGINE=InnoDB;
+
+INSERT INTO BATCH_STEP_EXECUTION_SEQ (ID, UNIQUE_KEY) select * from (select 0 as ID, '0' as UNIQUE_KEY) as tmp where not exists(select * from BATCH_STEP_EXECUTION_SEQ);
+
+CREATE TABLE BATCH_JOB_EXECUTION_SEQ (
+ ID BIGINT NOT NULL,
+ UNIQUE_KEY CHAR(1) NOT NULL,
+ constraint UNIQUE_KEY_UN unique (UNIQUE_KEY)
+) ENGINE=InnoDB;
+
+INSERT INTO BATCH_JOB_EXECUTION_SEQ (ID, UNIQUE_KEY) select * from (select 0 as ID, '0' as UNIQUE_KEY) as tmp where not exists(select * from BATCH_JOB_EXECUTION_SEQ);
+
+CREATE TABLE BATCH_JOB_SEQ (
+ ID BIGINT NOT NULL,
+ UNIQUE_KEY CHAR(1) NOT NULL,
+ constraint UNIQUE_KEY_UN unique (UNIQUE_KEY)
+) ENGINE=InnoDB;
+
+INSERT INTO BATCH_JOB_SEQ (ID, UNIQUE_KEY) select * from (select 0 as ID, '0' as UNIQUE_KEY) as tmp where not exists(select * from BATCH_JOB_SEQ);
diff --git a/static/testData.csv b/static/testData.csv
new file mode 100644
index 0000000000000000000000000000000000000000..d4080ca956f3ae959aa3a1afb0d446c6628853b7
--- /dev/null
+++ b/static/testData.csv
@@ -0,0 +1,3 @@
+lyg,,ces
+lyg,cdd,ces
+testBatch1,ff,d
\ No newline at end of file
diff --git a/system/src/main/java/cn/lycode/rbac/constant/ParamConstant.java b/system/src/main/java/cn/lycode/system/constant/ParamConstant.java
similarity index 72%
rename from system/src/main/java/cn/lycode/rbac/constant/ParamConstant.java
rename to system/src/main/java/cn/lycode/system/constant/ParamConstant.java
index e8aa781574604a66843a83729f2db78c6791ef1b..9070bb858469e898c374a3390e374c3b95c8ecf7 100644
--- a/system/src/main/java/cn/lycode/rbac/constant/ParamConstant.java
+++ b/system/src/main/java/cn/lycode/system/constant/ParamConstant.java
@@ -1,4 +1,4 @@
-package cn.lycode.rbac.constant;
+package cn.lycode.system.constant;
public class ParamConstant {
diff --git a/system/src/main/java/cn/lycode/system/constant/SystemConstant.java b/system/src/main/java/cn/lycode/system/constant/SystemConstant.java
new file mode 100644
index 0000000000000000000000000000000000000000..09105b60f5659aed677270a1958b5a32939db278
--- /dev/null
+++ b/system/src/main/java/cn/lycode/system/constant/SystemConstant.java
@@ -0,0 +1,18 @@
+package cn.lycode.system.constant;
+
+/**
+ * @Title: SystemContanst
+ * @Author lyg
+ * @Date 2024/11/22 14:07
+ * @description: 系统常量
+ */
+public class SystemConstant {
+
+ // 部门树常量
+ public static Long ALL_DEPT_TREE_ID = -1L;
+ public static String ALL_DEPT_TREE_NAME = "全部";
+
+ public static Long NO_DEPT_TREE_ID = -2L;
+ public static String NO_DEPT_TREE_NAME = "全部";
+
+}
diff --git a/system/src/main/java/cn/lycode/rbac/controller/SysDeptController.java b/system/src/main/java/cn/lycode/system/controller/SysDeptController.java
similarity index 88%
rename from system/src/main/java/cn/lycode/rbac/controller/SysDeptController.java
rename to system/src/main/java/cn/lycode/system/controller/SysDeptController.java
index abddb3875356f6615a9e436ab11e045ae943ef4b..d8138c1fd1618c43572d73e8fe8b10a0e5b6c428 100644
--- a/system/src/main/java/cn/lycode/rbac/controller/SysDeptController.java
+++ b/system/src/main/java/cn/lycode/system/controller/SysDeptController.java
@@ -1,14 +1,14 @@
-package cn.lycode.rbac.controller;
+package cn.lycode.system.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.lycode.common.core.controller.BaseController;
import cn.lycode.common.core.domain.AjaxResult;
import cn.lycode.common.core.domain.model.SelectIdsDTO;
-import cn.lycode.rbac.domain.dto.sysdept.SysDeptAddDTO;
-import cn.lycode.rbac.domain.dto.sysdept.SysDeptUpDTO;
-import cn.lycode.rbac.domain.vo.DeptTreeVO;
-import cn.lycode.rbac.domain.vo.SysDeptVO;
-import cn.lycode.rbac.service.SysDeptService;
+import cn.lycode.system.domain.dto.sysdept.SysDeptAddDTO;
+import cn.lycode.system.domain.dto.sysdept.SysDeptUpDTO;
+import cn.lycode.system.domain.vo.DeptTreeVO;
+import cn.lycode.system.domain.vo.SysDeptVO;
+import cn.lycode.system.service.SysDeptService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
diff --git a/system/src/main/java/cn/lycode/rbac/controller/SysDictController.java b/system/src/main/java/cn/lycode/system/controller/SysDictController.java
similarity index 85%
rename from system/src/main/java/cn/lycode/rbac/controller/SysDictController.java
rename to system/src/main/java/cn/lycode/system/controller/SysDictController.java
index f5b339260e4fda0876b578ea7832a6c96f4d7649..2fea237f69bc021f08c6e3b00954135d47f2a86f 100644
--- a/system/src/main/java/cn/lycode/rbac/controller/SysDictController.java
+++ b/system/src/main/java/cn/lycode/system/controller/SysDictController.java
@@ -1,4 +1,4 @@
-package cn.lycode.rbac.controller;
+package cn.lycode.system.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaIgnore;
@@ -6,12 +6,12 @@ import cn.lycode.common.core.controller.BaseController;
import cn.lycode.common.core.domain.AjaxResult;
import cn.lycode.common.core.domain.model.SelectIdsDTO;
import cn.lycode.common.core.page.PageResult;
-import cn.lycode.rbac.domain.dto.sysdict.SysDictAddDTO;
-import cn.lycode.rbac.domain.dto.sysdict.SysDictListDTO;
-import cn.lycode.rbac.domain.dto.sysdict.SysDictUpDTO;
-import cn.lycode.rbac.domain.entity.SysDict;
-import cn.lycode.rbac.domain.vo.DictCustomVO;
-import cn.lycode.rbac.service.SysDictService;
+import cn.lycode.system.domain.dto.sysdict.SysDictAddDTO;
+import cn.lycode.system.domain.dto.sysdict.SysDictListDTO;
+import cn.lycode.system.domain.dto.sysdict.SysDictUpDTO;
+import cn.lycode.system.domain.entity.SysDict;
+import cn.lycode.system.domain.vo.DictCustomVO;
+import cn.lycode.system.service.SysDictService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
diff --git a/system/src/main/java/cn/lycode/rbac/controller/SysDictTypeController.java b/system/src/main/java/cn/lycode/system/controller/SysDictTypeController.java
similarity index 89%
rename from system/src/main/java/cn/lycode/rbac/controller/SysDictTypeController.java
rename to system/src/main/java/cn/lycode/system/controller/SysDictTypeController.java
index 57095bbb74075a3db52bb7bf30502b5057ec2414..5959689b7a82178d07f915399eed79b9ed4bdfc4 100644
--- a/system/src/main/java/cn/lycode/rbac/controller/SysDictTypeController.java
+++ b/system/src/main/java/cn/lycode/system/controller/SysDictTypeController.java
@@ -1,4 +1,4 @@
-package cn.lycode.rbac.controller;
+package cn.lycode.system.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.lycode.common.core.controller.BaseController;
@@ -6,10 +6,10 @@ import cn.lycode.common.core.domain.AjaxResult;
import cn.lycode.common.core.domain.model.ConditionDTO;
import cn.lycode.common.core.domain.model.SelectIdsDTO;
import cn.lycode.common.core.page.PageResult;
-import cn.lycode.rbac.domain.dto.sysdict.SysDictTypeAddDTO;
-import cn.lycode.rbac.domain.dto.sysdict.SysDictTypeUpDTO;
-import cn.lycode.rbac.domain.entity.SysDictType;
-import cn.lycode.rbac.service.SysDictTypeService;
+import cn.lycode.system.domain.dto.sysdict.SysDictTypeAddDTO;
+import cn.lycode.system.domain.dto.sysdict.SysDictTypeUpDTO;
+import cn.lycode.system.domain.entity.SysDictType;
+import cn.lycode.system.service.SysDictTypeService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
diff --git a/system/src/main/java/cn/lycode/rbac/controller/SysMenuController.java b/system/src/main/java/cn/lycode/system/controller/SysMenuController.java
similarity index 92%
rename from system/src/main/java/cn/lycode/rbac/controller/SysMenuController.java
rename to system/src/main/java/cn/lycode/system/controller/SysMenuController.java
index e83a207275c82ef32333dc1e3b13ffff4e4b9421..7b9e930ccfca9fc80bc06c7612923a93bc776582 100644
--- a/system/src/main/java/cn/lycode/rbac/controller/SysMenuController.java
+++ b/system/src/main/java/cn/lycode/system/controller/SysMenuController.java
@@ -1,4 +1,4 @@
-package cn.lycode.rbac.controller;
+package cn.lycode.system.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaIgnore;
@@ -7,10 +7,10 @@ import cn.lycode.common.core.domain.AjaxResult;
import cn.lycode.common.core.domain.entity.SysMenu;
import cn.lycode.common.core.domain.model.ConditionDTO;
import cn.lycode.common.core.domain.model.SelectIdsDTO;
-import cn.lycode.rbac.domain.dto.sysmenu.MenuPermissionDTO;
-import cn.lycode.rbac.domain.vo.MenuTreeVO;
-import cn.lycode.rbac.domain.vo.SysMenuVO;
-import cn.lycode.rbac.service.SysMenuService;
+import cn.lycode.system.domain.dto.sysmenu.MenuPermissionDTO;
+import cn.lycode.system.domain.vo.MenuTreeVO;
+import cn.lycode.system.domain.vo.SysMenuVO;
+import cn.lycode.system.service.SysMenuService;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
diff --git a/system/src/main/java/cn/lycode/rbac/controller/SysPostController.java b/system/src/main/java/cn/lycode/system/controller/SysPostController.java
similarity index 76%
rename from system/src/main/java/cn/lycode/rbac/controller/SysPostController.java
rename to system/src/main/java/cn/lycode/system/controller/SysPostController.java
index 113bea3953bada361269f14d6bc3cee1dd5d2c51..5d04089f77524fe1a77e53d4308b1c35ec432376 100644
--- a/system/src/main/java/cn/lycode/rbac/controller/SysPostController.java
+++ b/system/src/main/java/cn/lycode/system/controller/SysPostController.java
@@ -1,19 +1,20 @@
-package cn.lycode.rbac.controller;
+package cn.lycode.system.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.lycode.common.core.controller.BaseController;
import cn.lycode.common.core.domain.AjaxResult;
import cn.lycode.common.core.domain.model.SelectIdsDTO;
import cn.lycode.common.core.page.PageResult;
-import cn.lycode.rbac.domain.dto.syspost.SysPostAddDTO;
-import cn.lycode.rbac.domain.dto.syspost.SysPostListDTO;
-import cn.lycode.rbac.domain.dto.syspost.SysPostUpdateDTO;
-import cn.lycode.rbac.domain.vo.SysPostVO;
-import cn.lycode.rbac.service.SysPostService;
+import cn.lycode.system.domain.dto.syspost.SysPostAddDTO;
+import cn.lycode.system.domain.dto.syspost.SysPostListDTO;
+import cn.lycode.system.domain.dto.syspost.SysPostUpdateDTO;
+import cn.lycode.system.domain.vo.SysPostVO;
+import cn.lycode.system.service.SysPostService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
+import java.util.List;
/**
* 岗位信息表 Controller
@@ -34,6 +35,13 @@ public class SysPostController extends BaseController{
return AjaxResult.success(sysPostService.listPage(dto));
}
+ //列表分页条件查询
+ @SaCheckPermission(value = "sys:post:list")
+ @GetMapping("/option")
+ public AjaxResult> option() {
+ return AjaxResult.success(sysPostService.listOption());
+ }
+
//新增
@SaCheckPermission(value = "sys:post:add")
@PostMapping("/add")
diff --git a/system/src/main/java/cn/lycode/rbac/controller/SysRoleController.java b/system/src/main/java/cn/lycode/system/controller/SysRoleController.java
similarity index 95%
rename from system/src/main/java/cn/lycode/rbac/controller/SysRoleController.java
rename to system/src/main/java/cn/lycode/system/controller/SysRoleController.java
index 00a2906fa2e0acd43bb95c039c2e8213cafc2eca..d37bf7b0c8b2fb5b9f82c559c37e89c3d39f3005 100644
--- a/system/src/main/java/cn/lycode/rbac/controller/SysRoleController.java
+++ b/system/src/main/java/cn/lycode/system/controller/SysRoleController.java
@@ -1,4 +1,4 @@
-package cn.lycode.rbac.controller;
+package cn.lycode.system.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.lycode.common.core.controller.BaseController;
@@ -7,11 +7,11 @@ import cn.lycode.common.core.domain.entity.SysRole;
import cn.lycode.common.core.domain.model.ConditionDTO;
import cn.lycode.common.core.domain.model.SelectIdsDTO;
import cn.lycode.common.core.page.PageResult;
-import cn.lycode.rbac.domain.dto.ChangeStatusDTO;
-import cn.lycode.rbac.domain.dto.sysrole.SysRoleAddDTO;
-import cn.lycode.rbac.domain.dto.sysrole.SysRoleMenuDTO;
-import cn.lycode.rbac.domain.dto.sysrole.SysRoleUpDTO;
-import cn.lycode.rbac.service.SysRoleService;
+import cn.lycode.system.domain.dto.ChangeStatusDTO;
+import cn.lycode.system.domain.dto.sysrole.SysRoleAddDTO;
+import cn.lycode.system.domain.dto.sysrole.SysRoleMenuDTO;
+import cn.lycode.system.domain.dto.sysrole.SysRoleUpDTO;
+import cn.lycode.system.service.SysRoleService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
diff --git a/system/src/main/java/cn/lycode/rbac/controller/SysUserController.java b/system/src/main/java/cn/lycode/system/controller/SysUserController.java
similarity index 75%
rename from system/src/main/java/cn/lycode/rbac/controller/SysUserController.java
rename to system/src/main/java/cn/lycode/system/controller/SysUserController.java
index 3fa857ade2239800766e97f59f990f4d504a091e..60c4ff4d776de89a89255419e26a6efaeaf718a1 100644
--- a/system/src/main/java/cn/lycode/rbac/controller/SysUserController.java
+++ b/system/src/main/java/cn/lycode/system/controller/SysUserController.java
@@ -1,5 +1,6 @@
-package cn.lycode.rbac.controller;
+package cn.lycode.system.controller;
+import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.lycode.common.annotation.valid.NotZero;
@@ -10,16 +11,13 @@ import cn.lycode.common.core.domain.model.ConditionDTO;
import cn.lycode.common.core.domain.model.SelectIdsDTO;
import cn.lycode.common.core.page.PageResult;
import cn.lycode.common.utils.SecurityUtils;
-import cn.lycode.rbac.domain.dto.sysmenu.SysUserRoleDTO;
-import cn.lycode.rbac.domain.dto.sysuser.SysUserAddDTO;
-import cn.lycode.rbac.domain.dto.sysuser.SysUserPasswordDTO;
-import cn.lycode.rbac.domain.dto.sysuser.SysUserUpDTO;
-import cn.lycode.rbac.domain.dto.sysuser.UserDeptDTO;
-import cn.lycode.rbac.domain.vo.DeptTreeVO;
-import cn.lycode.rbac.domain.vo.SysUserRoleVO;
-import cn.lycode.rbac.domain.vo.SysUserVO;
-import cn.lycode.rbac.service.SysDeptService;
-import cn.lycode.rbac.service.SysUserService;
+import cn.lycode.system.domain.dto.sysmenu.SysUserRoleDTO;
+import cn.lycode.system.domain.dto.sysuser.*;
+import cn.lycode.system.domain.vo.DeptTreeVO;
+import cn.lycode.system.domain.vo.SysUserRoleVO;
+import cn.lycode.system.domain.vo.SysUserVO;
+import cn.lycode.system.service.SysDeptService;
+import cn.lycode.system.service.SysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
@@ -40,6 +38,7 @@ public class SysUserController extends BaseController {
* 用户管理-部门树形列表
* @return DeptTreeVO
*/
+ @SaCheckLogin
@GetMapping("/dept/tree")
public AjaxResult> tree() {
return AjaxResult.success(sysDeptService.getDeptTreeWithAdditionalNodes());
@@ -67,7 +66,7 @@ public class SysUserController extends BaseController {
@SaCheckPermission(value = "system:user:info")
@GetMapping("/{id}")
- public AjaxResult detail(@PathVariable Long id) {
+ public AjaxResult detail(@PathVariable Long id) {
return AjaxResult.success(sysUserService.detail(id));
}
@@ -111,15 +110,10 @@ public class SysUserController extends BaseController {
return AjaxResult.success();
}
-
-
-
-
-
/**
* 登录用户信息查询
*/
- @SaIgnore
+ @SaCheckLogin
@GetMapping("/userinfo")
public AjaxResult getUserInfo() {
return AjaxResult.success(sysUserService.getUserInfo(SecurityUtils.getLoginUserId()));
@@ -130,7 +124,8 @@ public class SysUserController extends BaseController {
* @param dto 原密码和新密码
* @return 是否成功
*/
- @PutMapping("/password")
+ @SaCheckLogin
+ @PostMapping("/password")
public AjaxResult