| | |
| | | |
| | | |
| | | // 接口请求地址 |
| | | // ftpUrl: 'http://172.16.20.9:8083/lowConsum',//开发 |
| | | // apiBaseURL: 'http://172.16.20.9:8083/lowConsum',//开发 |
| | | ftpUrl: 'http://127.0.0.1:8083/lowConsum',//开发 |
| | | apiBaseURL: 'http://127.0.0.1:8083/lowConsum',//开发 |
| | | |
| | | |
| | | // apiBaseURL: 'http://172.16.60.110:8083/lowConsum',//开发 |
| | |
| | | // apiBaseURL: protocol + '//'+ host + '/lowapi',// 正式, |
| | | |
| | | |
| | | ftpUrl: protocol + '//'+ host + '/lowapi',// 正式, |
| | | apiBaseURL: protocol + '//'+ host + '/lowapi',// 正式, |
| | | // ftpUrl: protocol + '//'+ host + '/lowapi',// 正式, |
| | | // apiBaseURL: protocol + '//'+ host + '/lowapi',// 正式, |
| | | |
| | | debug: false //调试开关 true时会输出请求日志 |
| | | }; |
| | |
| | | /* |
| | | * 物品详情 |
| | | * */ |
| | | export function goodsDetail(data) { |
| | | export function goodsDetail(params) { |
| | | return request({ |
| | | url: `/pc/base/goods/template/detail/?id=${data}`, |
| | | url: `/pc/base/goods/template/detail`, |
| | | method: 'get', |
| | | params |
| | | }) |
| | | } |
| | | |
| | |
| | | }, |
| | | async created() { |
| | | if (this.setting.id) { |
| | | await goodsDetail(this.setting.id).then(res => { |
| | | await goodsDetail({'id': this.setting.id}).then(res => { |
| | | this.formData = res |
| | | if (!this.formData.agencyId) { |
| | | this.formData.agencyId = this.userInfo.tenantId |
| | |
| | | <artifactId>snakeyaml</artifactId> |
| | | <groupId>org.yaml</groupId> |
| | | </exclusion> |
| | | <exclusion> |
| | | <artifactId>jjwt</artifactId> |
| | | <groupId>io.jsonwebtoken</groupId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>io.jsonwebtoken</groupId> |
| | | <artifactId>jjwt</artifactId> |
| | | <version>0.12.6</version> |
| | | </dependency> |
| | | <!-- EasyExcel 核心库 --> |
| | | <dependency> |
| | | <groupId>com.alibaba</groupId> |
| | | <artifactId>easyexcel</artifactId> |
| | | <version>3.2.1</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.yaml</groupId> |
| | |
| | | </dependency> |
| | | <!-- 引入web安全认证模块,如果不引入则不会做任何权限拦截(这种模式通常可用于快速测试), 2022/10/31 --> |
| | | <dependency> |
| | | <groupId>com.iplatform</groupId> |
| | | <groupId>com.consum</groupId> |
| | | <artifactId>iplatform-base-security-consum</artifactId> |
| | | <version>3.2.0</version> |
| | | <exclusions> |
| | | <exclusion> |
| | | <artifactId>spring-security-crypto</artifactId> |
| | |
| | | <dependency> |
| | | <artifactId>spring-security-crypto</artifactId> |
| | | <groupId>org.springframework.security</groupId> |
| | | <version>5.7.12</version> |
| | | <version>6.2.7</version> |
| | | </dependency> |
| | | <dependency> |
| | | <artifactId>spring-security-core</artifactId> |
| | |
| | | </exclusion> |
| | | </exclusions> |
| | | <groupId>org.springframework.security</groupId> |
| | | <version>5.7.12</version> |
| | | </dependency> |
| | | <dependency> |
| | | <artifactId>spring-security-config</artifactId> |
| | |
| | | </exclusion> |
| | | </exclusions> |
| | | <groupId>org.springframework.security</groupId> |
| | | <version>5.7.12</version> |
| | | <version>6.2.7</version> |
| | | </dependency> |
| | | <dependency> |
| | | <artifactId>spring-security-web</artifactId> |
| | |
| | | </exclusion> |
| | | </exclusions> |
| | | <groupId>org.springframework.security</groupId> |
| | | <version>5.7.12</version> |
| | | <version>6.2.7</version> |
| | | </dependency> |
| | | |
| | | <!-- 系统基础模块界面管理控制模块,如果不引入也不会有swagger文档功能!,2023/03/05 --> |
| | |
| | | <dependency> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-support-redis</artifactId> |
| | | <optional>true</optional> |
| | | <version>3.2.0</version> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/walker-support-redis-3.2.0.jar</systemPath> |
| | | <scope>system</scope> |
| | | <exclusions> |
| | | <exclusion> |
| | | <groupId>com.walkersoft</groupId> |
| | |
| | | package com.consum.base.aop; |
| | | |
| | | import cn.hutool.core.util.ReflectUtil; |
| | | import com.consum.base.core.utils.IdUtil; |
| | | import com.iplatform.base.cache.DictCacheProvider; |
| | | import com.iplatform.core.BeanContextAware; |
| | | import com.iplatform.model.po.S_dict_data; |
| | |
| | | try { |
| | | S_dict_data dictData = (S_dict_data) args[0]; |
| | | if (dictData.getDict_code() == null) { |
| | | dictData.setDict_code(NumberGenerator.getLongSequenceNumber()); |
| | | dictData.setDict_code(IdUtil.generateId()); |
| | | } |
| | | } catch (Exception e) { |
| | | e.getMessage(); |
| | |
| | | import com.walker.db.page.GenericPager; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.web.ResponseValue; |
| | | import io.swagger.annotations.Api; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | /** |
| | |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/10/23 |
| | | */ |
| | | @Api(value = "物品分类", tags = "物品分类") |
| | | // @Api(value = "物品分类", tags = "物品分类") |
| | | @RestController |
| | | @RequestMapping("/pc/base/category") |
| | | public class BaseCategoryController extends BaseController { |
| | |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.web.ResponseValue; |
| | | |
| | | import io.swagger.annotations.Api; |
| | | |
| | | /** |
| | | * @Description 规格型号 |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/10/25 |
| | | */ |
| | | @Api(value = "规格型号", tags = "规格型号") |
| | | // @Api(value = "规格型号", tags = "规格型号") |
| | | @RestController |
| | | @RequestMapping("/pc/base/goods/models") |
| | | public class BaseGoodsModelsController extends BaseController { |
| | |
| | | |
| | | /** |
| | | * 修改状态 |
| | | * |
| | | * |
| | | * @author 卢庆阳 |
| | | * @date 2023/10/25 |
| | | */ |
| | |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.web.ResponseValue; |
| | | |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | | import io.swagger.annotations.ApiOperation; |
| | | |
| | | /** |
| | | * @Description 物品模板 |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/10/24 |
| | | */ |
| | | @Api(value = "物品模板", tags = "物品模板") |
| | | // @Api(value = "物品模板", tags = "物品模板") |
| | | @RestController |
| | | @RequestMapping("/pc/base/goods/template") |
| | | public class BaseGoodsTemplateController extends BaseController { |
| | |
| | | return ResponseValue.success("查询成功!", list); |
| | | } |
| | | |
| | | @ApiOperation(value = "调拨查询机构下所有仓库下的分类模板信息", notes = "调拨查询机构下所有仓库下的分类模板信息") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "agencyId", value = "父级机构id", required = true, dataType = "java.lang.Long", |
| | | paramType = "query"), |
| | | @ApiImplicitParam(name = "categoryId", value = "分类id", required = true, dataType = "Long", |
| | | paramType = "query")}) |
| | | // // @ApiOperation(value = "调拨查询机构下所有仓库下的分类模板信息", notes = "调拨查询机构下所有仓库下的分类模板信息") |
| | | // @ApiImplicitParams({ |
| | | // @ApiImplicitParam(name = "agencyId", value = "父级机构id", required = true, dataType = "java.lang.Long", |
| | | // paramType = "query"), |
| | | // @ApiImplicitParam(name = "categoryId", value = "分类id", required = true, dataType = "Long", |
| | | // paramType = "query")}) |
| | | @GetMapping("/query/warehouse/goods") |
| | | public ResponseValue queryWarehouseGoods(Long agencyId, Long categoryId) { |
| | | |
| | |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.web.ResponseValue; |
| | | |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | | import io.swagger.annotations.ApiOperation; |
| | | |
| | | /** |
| | | * @Description 仓库管理 |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/10/26 |
| | | */ |
| | | @Api(value = "仓库管理", tags = "仓库管理") |
| | | // @Api(value = "仓库管理", tags = "仓库管理") |
| | | @RestController |
| | | @RequestMapping("/pc/base/warehouse") |
| | | @Slf4j |
| | |
| | | return ResponseValue.success("查询成功!", list); |
| | | } |
| | | |
| | | @ApiOperation(value = "根据仓库id和型号id 查询库存", notes = "根据仓库id和型号id 查询库存") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "warehouseQry", value = "仓库id和型号id", required = true, |
| | | dataType = "WarehouseQry", paramType = "query")}) |
| | | // // @ApiOperation(value = "根据仓库id和型号id 查询库存", notes = "根据仓库id和型号id 查询库存") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "warehouseQry", value = "仓库id和型号id", required = true, |
| | | // dataType = "WarehouseQry", paramType = "query")}) |
| | | @GetMapping("/select/number") |
| | | public ResponseValue selectNumber() { |
| | | WarehouseQry warehouseQry = CommonUtil.getObjFromReq(WarehouseQry.class); |
| | |
| | | return ResponseValue.success(num); |
| | | } |
| | | |
| | | @ApiOperation(value = "根据仓库id和型号id 查询库存", notes = "根据仓库id和型号id 查询库存") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "warehouseQry", value = "仓库id和型号id", required = true, |
| | | dataType = "WarehouseQry", paramType = "query")}) |
| | | // // @ApiOperation(value = "根据仓库id和型号id 查询库存", notes = "根据仓库id和型号id 查询库存") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "warehouseQry", value = "仓库id和型号id", required = true, |
| | | // dataType = "WarehouseQry", paramType = "query")}) |
| | | @GetMapping("/select/in/warehouse/num") |
| | | public ResponseValue selectAllNumber() { |
| | | WarehouseQry warehouseQry = CommonUtil.getObjFromReq(WarehouseQry.class); |
| | |
| | | import com.consum.base.core.utils.CommonUtil; |
| | | import com.consum.base.pojo.request.WarehouseManagerParam; |
| | | import com.walker.web.ResponseValue; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | | import io.swagger.annotations.ApiOperation; |
| | | |
| | | /** |
| | | * @Description 库管员 |
| | |
| | | * @Date 2023/10/26 |
| | | * <p> |
| | | */ |
| | | @Api(value = "库管员", tags = "库管员") |
| | | // @Api(value = "库管员", tags = "库管员") |
| | | @RestController |
| | | @RequestMapping("/pc/base/warehouse/manager") |
| | | @Slf4j |
| | |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/10/26 |
| | | */ |
| | | @ApiOperation(value = "新增", notes = "新增") |
| | | @ApiImplicitParam(name = "warehouseManagerParam", value = "库管员信息", required = true, |
| | | dataType = "WarehouseManagerParam", paramType = "body") |
| | | // // @ApiOperation(value = "新增", notes = "新增") |
| | | // @ApiImplicitParam(name = "warehouseManagerParam", value = "库管员信息", required = true, |
| | | // dataType = "WarehouseManagerParam", paramType = "body") |
| | | @PostMapping("/save") |
| | | public ResponseValue add() throws Exception { |
| | | WarehouseManagerParam param = CommonUtil.getObjFromReqBody(WarehouseManagerParam.class); |
| | |
| | | } |
| | | |
| | | |
| | | @ApiOperation(value = "根据仓库id查询库管员", notes = "根据仓库id查询库管员") |
| | | @ApiImplicitParam(name = "warehouseId", value = "仓库id", required = true, dataType = "Long") |
| | | // // @ApiOperation(value = "根据仓库id查询库管员", notes = "根据仓库id查询库管员") |
| | | // @ApiImplicitParam(name = "warehouseId", value = "仓库id", required = true, dataType = "Long") |
| | | @GetMapping("/list") |
| | | public ResponseValue select(Long warehouseId) { |
| | | List<BaseWarehouseManager> baseWarehouseManagerList = |
| | |
| | | return ResponseValue.success(baseWarehouseManagerList); |
| | | } |
| | | |
| | | @ApiOperation(value = "根据仓库,机构id查询库管员", notes = "根据仓库,机构id查询库管员") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "warehouseId", value = "仓库id", required = true, dataType = "Long"), |
| | | @ApiImplicitParam(name = "agencyId", value = "机构id", required = true, dataType = "Long")}) |
| | | // // @ApiOperation(value = "根据仓库,机构id查询库管员", notes = "根据仓库,机构id查询库管员") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "warehouseId", value = "仓库id", required = true, dataType = "Long"), |
| | | // @ApiImplicitParam(name = "agencyId", value = "机构id", required = true, dataType = "Long")}) |
| | | @GetMapping("/query") |
| | | public ResponseValue selectManagerList(Long warehouseId, Long agencyId) { |
| | | List<BaseWarehouseManager> baseWarehouseManagerList = |
| | |
| | | package com.consum.base.controller; |
| | | |
| | | import java.io.OutputStream; |
| | | import java.net.URLEncoder; |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | import javax.annotation.Resource; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import org.apache.poi.ss.usermodel.Workbook; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | |
| | | import cn.afterturn.easypoi.excel.entity.TemplateExportParams; |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.util.ReflectUtil; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | | import io.swagger.annotations.ApiOperation; |
| | | |
| | | /** |
| | | * @ClassName DepFormScrappedController |
| | |
| | | * @Description |
| | | * @Version 1.0 |
| | | **/ |
| | | @Api(value = "部门报废", tags = "部门报废") |
| | | // @Api(value = "部门报废", tags = "部门报废") |
| | | @RestController |
| | | @RequestMapping("/pc/l/wh/form/scrapped") |
| | | public class DepFormScrappedController extends BaseController { |
| | | @Resource |
| | | private DepFormScrappedService depFormScrappedService; |
| | | |
| | | @ApiOperation(value = "新增报废单", notes = "新增报废单") |
| | | // @ApiOperation(value = "新增报废单", notes = "新增报废单") |
| | | @PostMapping("/deptAdd") |
| | | public ResponseValue deptAdd() throws Exception { |
| | | LDeptFormScrappedParam param = CommonUtil.getObjFromReqBody(LDeptFormScrappedParam.class); |
| | |
| | | * @Description 列表查询 1.查询报废单 2.查询报废单物品 |
| | | * @Date |
| | | */ |
| | | @ApiOperation(value = "列表查询", notes = "列表查询") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "param", value = "查询条件", dataType = "LWhFormScrappedQry", paramType = "query")}) |
| | | // @ApiOperation(value = "列表查询", notes = "列表查询") |
| | | // @ApiImplicitParams({ |
| | | // @ApiImplicitParam(name = "param", value = "查询条件", dataType = "LWhFormScrappedQry", paramType = "query")}) |
| | | @GetMapping("/deptList") |
| | | public ResponseValue queryList() { |
| | | LDeptFormScrappedQry param = CommonUtil.getObjFromReq(LDeptFormScrappedQry.class); |
| | |
| | | /** |
| | | * @Description 根据id查询详情 |
| | | */ |
| | | @ApiOperation(value = "根据id查询详情", notes = "根据id查询详情") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "报废单id", dataType = "Long", paramType = "query")}) |
| | | // @ApiOperation(value = "根据id查询详情", notes = "根据id查询详情") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "报废单id", dataType = "Long", paramType = "query")}) |
| | | @GetMapping("/deptDetail") |
| | | public ResponseValue getById(Long id) { |
| | | if (id == null) { |
| | |
| | | return ResponseValue.success(this.depFormScrappedService.getById(id)); |
| | | } |
| | | |
| | | @ApiOperation(value = "导出报废单", notes = "导出报废单") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "报废单id", dataType = "Long", paramType = "query")}) |
| | | // @ApiOperation(value = "导出报废单", notes = "导出报废单") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "报废单id", dataType = "Long", paramType = "query")}) |
| | | @GetMapping("/deptList/export") |
| | | public ResponseValue<String> export(Long id, HttpServletResponse response) throws Exception { |
| | | if (id == null) { |
| | |
| | | import com.iplatform.model.po.S_user_core; |
| | | import com.walker.db.page.GenericPager; |
| | | import com.walker.web.ResponseValue; |
| | | import io.swagger.annotations.Api; |
| | | import jakarta.annotation.Resource; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import org.apache.poi.ss.usermodel.Workbook; |
| | | import org.apache.poi.xssf.usermodel.XSSFWorkbook; |
| | | import org.springframework.core.io.ClassPathResource; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import javax.annotation.Resource; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.InputStream; |
| | | import java.io.OutputStream; |
| | | import java.net.URLEncoder; |
| | |
| | | /** |
| | | * 部门台账 |
| | | */ |
| | | @Api(value = "部门台账", tags = "部门台账") |
| | | // @Api(value = "部门台账", tags = "部门台账") |
| | | @RestController |
| | | @RequestMapping("/pc/fin/warehouse/departLedger") |
| | | public class FinDepartLedgerController extends BaseController { |
| | |
| | | import com.consum.base.BaseController; |
| | | import com.consum.base.service.FinFileService; |
| | | import com.consum.model.po.FinFile; |
| | | import com.iplatform.base.IdUtil; |
| | | import com.walker.file.FileInfo; |
| | | import com.walker.infrastructure.utils.DateUtils; |
| | | import com.walker.infrastructure.utils.NumberGenerator; |
| | | import com.walker.web.ResponseValue; |
| | | import io.swagger.annotations.Api; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | |
| | | * @Author wh |
| | | * @Date 2023/8/1 10:33 |
| | | */ |
| | | @Api(value = "文件上传", tags = "文件上传") |
| | | // @Api(value = "文件上传", tags = "文件上传") |
| | | @RestController |
| | | @RequestMapping("/pc/fin/file") |
| | | public class FinFileController extends BaseController { |
| | |
| | | } |
| | | if (fileInfo != null) { |
| | | FinFile finFile = new FinFile(); |
| | | finFile.setId(NumberGenerator.getLongSequenceNumberNano()); |
| | | finFile.setId(IdUtil.generateId()); |
| | | finFile.setCreateTime(DateUtils.getDateTimeNumber(System.currentTimeMillis())); |
| | | finFile.setUserName("-1"); |
| | | finFile.setContentType(finFile.getContentType()); |
| | |
| | | for (int i = 0; i < uploadfs.length; i++) { |
| | | FileInfo fileInfo = uploadfs[i]; |
| | | FinFile finFile = new FinFile(); |
| | | finFile.setId(NumberGenerator.getLongSequenceNumberNano()); |
| | | finFile.setId(IdUtil.generateId()); |
| | | finFile.setCreateTime(DateUtils.getDateTimeNumber(System.currentTimeMillis())); |
| | | finFile.setUserName("-1"); |
| | | finFile.setContentType(finFile.getContentType()); |
| | |
| | | |
| | | import java.util.List; |
| | | |
| | | import com.consum.base.core.utils.IdUtil; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | |
| | | import com.walker.infrastructure.utils.NumberGenerator; |
| | | import com.walker.web.ResponseValue; |
| | | |
| | | import io.swagger.annotations.Api; |
| | | // |
| | | |
| | | @Api(value = "系统服务信息", tags = "系统服务信息") |
| | | // @Api(value = "系统服务信息", tags = "系统服务信息") |
| | | @RestController |
| | | @RequestMapping("/pc/fin/sys/server") |
| | | public class FinSysServerController extends BaseController { |
| | |
| | | if (param == null) { |
| | | return ResponseValue.error("参数为空"); |
| | | } |
| | | param.setId(NumberGenerator.getLongSequenceNumber()); |
| | | param.setId(IdUtil.generateId()); |
| | | param.setCreatedTime(DateUtils.getDateTimeNumber(System.currentTimeMillis())); |
| | | param.setCreatedBy(this.getCurrentUser().getUser_name()); |
| | | param.setLv(param.getParentId() + 1); |
| | |
| | | import java.util.Objects; |
| | | import java.util.TreeMap; |
| | | |
| | | import cn.hutool.core.convert.Convert; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.core.io.ClassPathResource; |
| | |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.web.ResponseValue; |
| | | |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | | import io.swagger.annotations.ApiOperation; |
| | | |
| | | /** |
| | | * @Description 机构 |
| | | * @Author wh |
| | | * @Date 2023/7/13 19:51 |
| | | */ |
| | | @Api(value = "机构管理", tags = "机构管理") |
| | | // @Api(value = "机构管理", tags = "机构管理") |
| | | @RestController |
| | | @RequestMapping("/pc/fin/sys/tenant") |
| | | public class FinSysTenantController extends BaseController { |
| | |
| | | // 获取当前用户信息 |
| | | String tenantId = user.getTenantId(); |
| | | FinSysTenant finSysTenant = new FinSysTenant(); |
| | | finSysTenant.setId(new Long(tenantId)); |
| | | finSysTenant.setId(Convert.toLong(tenantId)); |
| | | // 主键是TempId |
| | | finSysTenant.setTempId(new Long(tenantId)); |
| | | finSysTenant.setTempId(Convert.toLong(tenantId)); |
| | | // 查询当前用户的机构 |
| | | FinSysTenant userTenant = finSysTenantService.get(finSysTenant); |
| | | // 树列表 |
| | |
| | | if (userTenant.getLv() != 1 && userTenant.getParentId() != 0) { |
| | | rootMap.clear(); |
| | | this.childMap.clear(); |
| | | this.defaultParentId = new Long(user.getTenantId()); |
| | | this.defaultParentId = Convert.toLong(user.getTenantId()); |
| | | // 根据父级获取子集 |
| | | setEntityList(finSysTenantList); |
| | | treeRootList = getTreeRootList(); |
| | |
| | | return ResponseValue.success(finSysTenantUserResults); |
| | | } |
| | | |
| | | @ApiOperation(value = "获取父级机构", notes = "获取父级机构") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "Authorization", value = "token", dataType = "String", paramType = "header"),}) |
| | | // @ApiOperation(value = "获取父级机构", notes = "获取父级机构") |
| | | @GetMapping("/get/parent/tenant") |
| | | public ResponseValue getParentTenant() { |
| | | FinSysTenantUser sysInfo = getSysInfo(); |
| | |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.web.ResponseValue; |
| | | |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | | import io.swagger.annotations.ApiOperation; |
| | | |
| | | /** |
| | | * @Description 部门管理 |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/10/26 |
| | | */ |
| | | @Api(value = "部门管理", tags = "部门管理") |
| | | // @Api(value = "部门管理", tags = "部门管理") |
| | | @RestController |
| | | @RequestMapping("/pc/fin/sys/tenant/department") |
| | | public class FinSysTenantDepartmentController extends BaseController { |
| | |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/10/26 |
| | | */ |
| | | @ApiOperation(value = "新增", notes = "新增") |
| | | @ApiImplicitParams(value = { |
| | | @ApiImplicitParam(name = "param", value = "部门信息", required = true, dataType = "FinSysTenantDepartmentParam")}) |
| | | // @ApiOperation(value = "新增", notes = "新增") |
| | | // @ApiImplicitParams(value = { |
| | | // @ApiImplicitParam(name = "param", value = "部门信息", required = true, dataType = "FinSysTenantDepartmentParam")}) |
| | | @PostMapping("/add") |
| | | public ResponseValue add() { |
| | | FinSysTenantDepartmentParam param = CommonUtil.getObjFromReqBody(FinSysTenantDepartmentParam.class); |
| | |
| | | return ResponseValue.success(pager); |
| | | } |
| | | |
| | | @ApiOperation(value = "根据机构id查询所有部门列表信息", notes = "根据机构id查询所有部门列表信息") |
| | | @ApiImplicitParams(value = { |
| | | @ApiImplicitParam(name = "param", value = "部门信息", required = true, dataType = "FinSysTenantDepartmentParam")}) |
| | | // @ApiOperation(value = "根据机构id查询所有部门列表信息", notes = "根据机构id查询所有部门列表信息") |
| | | // @ApiImplicitParams(value = { |
| | | // @ApiImplicitParam(name = "param", value = "部门信息", required = true, dataType = "FinSysTenantDepartmentParam")}) |
| | | @GetMapping("/list/all") |
| | | public ResponseValue queryAllDepartment(Long tenantId) { |
| | | FinSysTenantUser sysInfo = this.getSysInfo(); |
| | |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.TypeReference; |
| | | import com.consum.base.core.utils.IdUtil; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.compress.utils.Lists; |
| | | import org.apache.commons.lang3.ObjectUtils; |
| | |
| | | import com.walker.infrastructure.utils.PhoneNumberUtils; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.web.ResponseValue; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | | import io.swagger.annotations.ApiOperation; |
| | | |
| | | /** |
| | | * @Description 系统用户 |
| | | * @Author wh |
| | | * @Date 2023/7/17 14:16 |
| | | */ |
| | | @Api(value = "机构用户信息", tags = "机构用户信息") |
| | | @RestController |
| | | @RequestMapping("/pc/fin/sys/tenant/user") |
| | | @Slf4j |
| | |
| | | return ResponseValue.success(pager); |
| | | } |
| | | |
| | | @ApiOperation(value = "根据机构id查询用户", notes = "根据机构id查询用户") |
| | | @ApiImplicitParam(name = "tenantId", value = "机构id", required = true, dataType = "Long", paramType = "query") |
| | | @GetMapping("/query/user") |
| | | // @ApiOperation(value = "根据机构id查询用户", notes = "根据机构id查询用户") |
| | | @GetMapping("/query/user") |
| | | public ResponseValue queryUserByTenantId(Long tenantId) { |
| | | |
| | | FinSysTenantUser finSysTenantUser = new FinSysTenantUser(); |
| | |
| | | |
| | | |
| | | private void buildTenantUser(FinSysTenantUser tenantUser, FinSysTenantUser sysInfo) { |
| | | tenantUser.setId(NumberGenerator.getLongSequenceNumber()); |
| | | tenantUser.setId(IdUtil.generateId()); |
| | | tenantUser.setCreateTime(DateUtils.getDateTimeNumber(System.currentTimeMillis())); |
| | | tenantUser.setCreateBy(this.getCurrentUser().getUser_name()); |
| | | tenantUser.setUpdateTime(DateUtils.getDateTimeNumber(System.currentTimeMillis())); |
| | | tenantUser.setUpdateBy(this.getCurrentUser().getUser_name()); |
| | | // 是否删除 0是 1否 |
| | | tenantUser.setIsDelete(0); |
| | | tenantUser.setSysUserId(NumberGenerator.getLongSequenceNumber()); |
| | | tenantUser.setSysUserId(IdUtil.generateId()); |
| | | setUserPhone(tenantUser, tenantUser.getUserPhone()); |
| | | String tenantId = tenantUser.getTenantId(); |
| | | FinSysTenant finSysTenant = finSysTenantService.selectById(Long.valueOf(tenantId)); |
| | |
| | | roles.stream().filter(role -> role.getRole_name().equals(data.getRoleName())).findFirst(); |
| | | user.setRoleList(Arrays.asList(sRole.orElse(new S_role()).getRole_id())); |
| | | |
| | | user.setId(NumberGenerator.getLongSequenceNumber()); |
| | | user.setId(IdUtil.generateId()); |
| | | user.setCreateTime(DateUtils.getDateTimeNumber(System.currentTimeMillis())); |
| | | user.setCreateBy(currentUser.getUser_name()); |
| | | user.setUpdateTime(DateUtils.getDateTimeNumber(System.currentTimeMillis())); |
| | | user.setUpdateBy(currentUser.getUser_name()); |
| | | user.setStatus(1);// 0禁用 1启用 |
| | | user.setIsDelete(0);// 是否删除 0是 1否 |
| | | user.setSysUserId(NumberGenerator.getLongSequenceNumber()); |
| | | user.setSysUserId(IdUtil.generateId()); |
| | | user.setRemark("批量导入"); |
| | | // 加密手机号 |
| | | setUserPhone(user, data.getUserPhone()); |
| | |
| | | return ResponseValue.success(1); |
| | | } |
| | | |
| | | @ApiOperation(value = "根据机构id查询部门中的用户", notes = "根据机构id查询部门中的用户") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "agencyId", value = "机构id", required = true, dataType = "Long", paramType = "query")}) |
| | | // @ApiOperation(value = "根据机构id查询部门中的用户", notes = "根据机构id查询部门中的用户") |
| | | @GetMapping("/select/department") |
| | | public ResponseValue selectDepartment(Long agencyId, String isFilter) { |
| | | FinSysTenantVO finSysTenantVO = new FinSysTenantVO(); |
| | |
| | | import com.iplatform.model.po.S_user_core; |
| | | import com.walker.db.page.GenericPager; |
| | | import com.walker.web.ResponseValue; |
| | | import io.swagger.annotations.Api; |
| | | import jakarta.annotation.Resource; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import org.apache.poi.ss.usermodel.Workbook; |
| | | import org.apache.poi.xssf.usermodel.XSSFWorkbook; |
| | | import org.springframework.core.io.ClassPathResource; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import javax.annotation.Resource; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.InputStream; |
| | | import java.io.OutputStream; |
| | | import java.net.URLEncoder; |
| | |
| | | * @Description 仓库台账 |
| | | * @Version 1.0 |
| | | **/ |
| | | @Api(value = "仓库台账", tags = "仓库台账") |
| | | @RestController |
| | | @RequestMapping("/pc/fin/warehouse/ledger") |
| | | public class FinWarehouseLedgerController extends BaseController { |
| | |
| | | import com.consum.base.service.LOrgSupplierServiceImpl; |
| | | import com.iplatform.model.po.S_user_core; |
| | | import com.walker.web.ResponseValue; |
| | | import io.swagger.annotations.Api; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | /** |
| | | * @ClassName LOrgSupplierController |
| | |
| | | * @Description |
| | | * @Version 1.0 |
| | | **/ |
| | | @Api(value = "供应商", tags = "供应商") |
| | | // @Api(value = "供应商", tags = "供应商") |
| | | @RestController |
| | | @RequestMapping("/pc/orgSupplier") |
| | | public class LOrgSupplierController extends BaseController { |
| | |
| | | import java.util.ArrayList; |
| | | import java.util.Map; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import org.apache.commons.compress.utils.Lists; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | |
| | | import com.walker.web.ResponseValue; |
| | | |
| | | import cn.hutool.core.util.ReflectUtil; |
| | | import io.swagger.annotations.Api; |
| | | |
| | | /** |
| | | * @ClassName lWarehouseFlowController |
| | |
| | | * @Description |
| | | * @Version 1.0 |
| | | **/ |
| | | @Api(value = "仓库流水", tags = "仓库流水") |
| | | // @Api(value = "仓库流水", tags = "仓库流水") |
| | | @RestController |
| | | @RequestMapping("/pc/warehouse/flow") |
| | | public class LWarehouseFlowController extends BaseController { |
| | |
| | | import java.util.Objects; |
| | | import java.util.Optional; |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import org.apache.poi.ss.usermodel.Workbook; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | |
| | | import cn.afterturn.easypoi.excel.ExcelExportUtil; |
| | | import cn.afterturn.easypoi.excel.entity.TemplateExportParams; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import io.swagger.annotations.ApiResponse; |
| | | |
| | | /** |
| | | * @Description 盘点 |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/10/23 |
| | | */ |
| | | @Api(value = "盘点", tags = "盘点") |
| | | // @Api(value = "盘点", tags = "盘点") |
| | | @RestController |
| | | @RequestMapping("/pc/l/wh/form/inventory") |
| | | public class LWhFormInventoryController extends BaseController { |
| | |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/10/31 |
| | | */ |
| | | @ApiOperation(value = "新增盘点", notes = "新增盘点") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "param", value = "盘点单信息", dataType = "FormInventoryParam")}) |
| | | // @ApiOperation(value = "新增盘点", notes = "新增盘点") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "param", value = "盘点单信息", dataType = "FormInventoryParam")}) |
| | | @PostMapping("/add") |
| | | public ResponseValue add() { |
| | | |
| | |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/10/31 |
| | | */ |
| | | @ApiOperation(value = "盘点单列表查询", notes = "盘点单列表查询") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "param", value = "盘点条件", dataType = "LWhFormInventoryParam", |
| | | required = true, paramType = "query")}) |
| | | // @ApiOperation(value = "盘点单列表查询", notes = "盘点单列表查询") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "param", value = "盘点条件", dataType = "LWhFormInventoryParam", |
| | | // required = true, paramType = "query")}) |
| | | @GetMapping("/list") |
| | | public ResponseValue queryList() { |
| | | LWhFormInventoryQry param = CommonUtil.getObjFromReq(LWhFormInventoryQry.class); |
| | |
| | | * |
| | | * @return |
| | | */ |
| | | @ApiOperation(value = "查询此账号角色,是否现在还可以增加盘点任务", notes = "查询此账号角色,是否现在还可以增加盘点任务") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "param", value = "盘点条件", dataType = "LWhFormInventoryParam", |
| | | required = true, paramType = "query")}) |
| | | // @ApiOperation(value = "查询此账号角色,是否现在还可以增加盘点任务", notes = "查询此账号角色,是否现在还可以增加盘点任务") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "param", value = "盘点条件", dataType = "LWhFormInventoryParam", |
| | | // required = true, paramType = "query")}) |
| | | @GetMapping("/isAddInventory") |
| | | public ResponseValue isAddInventory() { |
| | | LWhFormInventoryQry param = CommonUtil.getObjFromReq(LWhFormInventoryQry.class); |
| | |
| | | return ResponseValue.success(res); |
| | | } |
| | | |
| | | @ApiOperation(value = "盘点单物品列表查询", notes = "盘点单物品列表查询", response = FormInventoryVO.class) |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "id", value = "盘点单id", dataType = "Long", required = true, paramType = "query")}) |
| | | @ApiResponse(code = 200, message = "成功", response = FormInventoryVO.class) |
| | | // @ApiOperation(value = "盘点单物品列表查询", notes = "盘点单物品列表查询", response = FormInventoryVO.class) |
| | | // @ApiImplicitParams({ |
| | | // @ApiImplicitParam(name = "id", value = "盘点单id", dataType = "Long", required = true, paramType = "query")}) |
| | | // @ApiResponse(code = 200, message = "成功", response = FormInventoryVO.class) |
| | | @GetMapping("/query") |
| | | public ResponseValue queryInventBaseGoodTemplate(Long id) { |
| | | FinSysTenantUser sysInfo = this.getSysInfo(); |
| | |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/10/31 |
| | | */ |
| | | @ApiOperation(value = "编辑盘点", notes = "编辑盘点") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "param", value = "盘点单信息", dataType = "FormInventoryParam")}) |
| | | // @ApiOperation(value = "编辑盘点", notes = "编辑盘点") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "param", value = "盘点单信息", dataType = "FormInventoryParam")}) |
| | | @PostMapping("/edit") |
| | | public ResponseValue edit() { |
| | | FormInventoryParam param = CommonUtil.getObjFromReqBody(FormInventoryParam.class); |
| | |
| | | /** |
| | | * @Description 根据id删除 |
| | | */ |
| | | @ApiOperation(value = "根据id删除盘点", notes = "根据id删除盘点") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "id", value = "盘点单id", dataType = "Long", required = true, paramType = "query")}) |
| | | // @ApiOperation(value = "根据id删除盘点", notes = "根据id删除盘点") |
| | | // @ApiImplicitParams({ |
| | | // @ApiImplicitParam(name = "id", value = "盘点单id", dataType = "Long", required = true, paramType = "query")}) |
| | | @DeleteMapping("/del") |
| | | public ResponseValue delById(Long id) { |
| | | if (id == null) { |
| | |
| | | * @author 卢庆阳 |
| | | * @date 2023/10/31 |
| | | */ |
| | | @ApiOperation(value = "盘点暂存", notes = "盘点暂存") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "param", value = "盘点单信息", dataType = "LWhFormInventoryDto")}) |
| | | // @ApiOperation(value = "盘点暂存", notes = "盘点暂存") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "param", value = "盘点单信息", dataType = "LWhFormInventoryDto")}) |
| | | @PostMapping("/temporary/storage") |
| | | public ResponseValue updateTemporaryStorage() { |
| | | LWhFormInventoryParam param = CommonUtil.getObjFromReqBody(LWhFormInventoryParam.class); |
| | |
| | | * @author 卢庆阳 |
| | | * @date 2023/10/31 |
| | | */ |
| | | @ApiOperation(value = "完成盘点", notes = "完成盘点") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "param", value = "盘点单信息", dataType = "LWhFormInventoryDto")}) |
| | | // @ApiOperation(value = "完成盘点", notes = "完成盘点") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "param", value = "盘点单信息", dataType = "LWhFormInventoryDto")}) |
| | | @PostMapping("/finish") |
| | | public ResponseValue updateFinishPd() { |
| | | LWhFormInventoryParam param = CommonUtil.getObjFromReqBody(LWhFormInventoryParam.class); |
| | |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/11/1 |
| | | */ |
| | | @ApiOperation(value = "异常明细列表查询", notes = "异常明细列表查询") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "param", value = "盘点条件", dataType = "LWhFormInventoryParam", paramType = "query")}) |
| | | // @ApiOperation(value = "异常明细列表查询", notes = "异常明细列表查询") |
| | | // @ApiImplicitParams({ |
| | | // @ApiImplicitParam(name = "param", value = "盘点条件", dataType = "LWhFormInventoryParam", paramType = "query")}) |
| | | @GetMapping("/list/PdDetail") |
| | | public ResponseValue queryPdDetailList() { |
| | | LWhFormInventoryQry param = CommonUtil.getObjFromReq(LWhFormInventoryQry.class); |
| | |
| | | return ResponseValue.success(result); |
| | | } |
| | | |
| | | @ApiOperation(value = "根据id查询盘点物品详细信息", notes = "根据id查询盘点物品详细信息") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "id", value = "盘点id", dataType = "Long", required = true, paramType = "query")}) |
| | | // @ApiOperation(value = "根据id查询盘点物品详细信息", notes = "根据id查询盘点物品详细信息") |
| | | // @ApiImplicitParams({ |
| | | // @ApiImplicitParam(name = "id", value = "盘点id", dataType = "Long", required = true, paramType = "query")}) |
| | | @GetMapping("/detail") |
| | | public ResponseValue selectDetailById(Long id) { |
| | | FinSysTenantUser sysInfo = this.getSysInfo(); |
| | |
| | | return ResponseValue.success(formInventoryVO); |
| | | } |
| | | |
| | | @ApiOperation(value = "盘点单导出", notes = "盘点单导出") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "id", value = "盘点单id", dataType = "Long", required = true, paramType = "query")}) |
| | | // @ApiOperation(value = "盘点单导出", notes = "盘点单导出") |
| | | // @ApiImplicitParams({ |
| | | // @ApiImplicitParam(name = "id", value = "盘点单id", dataType = "Long", required = true, paramType = "query")}) |
| | | @GetMapping("/list/export") |
| | | public ResponseValue<String> export(Long id, HttpServletResponse response) throws Exception { |
| | | |
| | |
| | | import com.consum.model.po.LWhFormInventoryGoods; |
| | | import com.walker.web.ResponseValue; |
| | | |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | |
| | | /** |
| | | * @Description 盘点单物品 |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/10/31 |
| | | */ |
| | | @Api(value = "盘点", tags = "盘点") |
| | | // @Api(value = "盘点", tags = "盘点") |
| | | @RestController |
| | | @RequestMapping("/pc/l/wh/form/inventory/goods") |
| | | public class LWhFormInventoryGoodsController extends BaseController { |
| | |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/10/31 |
| | | */ |
| | | @ApiOperation(value = "查询盘点单物品(继续盘点)", notes = "查询盘点单物品(继续盘点)") |
| | | // @ApiOperation(value = "查询盘点单物品(继续盘点)", notes = "查询盘点单物品(继续盘点)") |
| | | @GetMapping("/list") |
| | | public ResponseValue queryList(Long id) { |
| | | FinSysTenantUser sysInfo = this.getSysInfo(); |
| | |
| | | import java.util.Optional; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import javax.annotation.Resource; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import org.apache.commons.compress.utils.Lists; |
| | | import org.apache.poi.hssf.usermodel.HSSFWorkbook; |
| | | import org.apache.poi.ss.usermodel.Workbook; |
| | |
| | | import cn.afterturn.easypoi.excel.ExcelExportUtil; |
| | | import cn.afterturn.easypoi.excel.entity.TemplateExportParams; |
| | | import cn.hutool.core.util.ReflectUtil; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | | import io.swagger.annotations.ApiOperation; |
| | | |
| | | |
| | | /** |
| | | * @Description 出库单 |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/10/27 |
| | | */ |
| | | @Api(value = "出库单", tags = "出库单") |
| | | // @Api(value = "出库单", tags = "出库单") |
| | | @RestController |
| | | @RequestMapping("/pc/l/wh/form/output") |
| | | public class LWhFormOutputController extends BaseController { |
| | |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/10/27 |
| | | */ |
| | | @ApiOperation(value = "新增出库单", notes = "新增出库单") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "param", value = "出库单实体", dataType = "lWhFormOutputParam", |
| | | dataTypeClass = LWhFormOutputParam.class, paramType = "body")}) |
| | | // @ApiOperation(value = "新增出库单", notes = "新增出库单") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "param", value = "出库单实体", dataType = "lWhFormOutputParam", |
| | | // dataTypeClass = LWhFormOutputParam.class, paramType = "body")}) |
| | | @PostMapping("/add") |
| | | public ResponseValue add() { |
| | | LWhFormOutputParam param = CommonUtil.getObjFromReqBody(LWhFormOutputParam.class); |
| | |
| | | /** |
| | | * @Description 列表查询 |
| | | */ |
| | | @ApiOperation(value = "列表查询", notes = "列表查询") |
| | | @ApiImplicitParam(name = "param", value = "出库单实体", required = true, dataType = "LWhFormOutputParam", |
| | | paramType = "query") |
| | | // @ApiOperation(value = "列表查询", notes = "列表查询") |
| | | // @ApiImplicitParam(name = "param", value = "出库单实体", required = true, dataType = "LWhFormOutputParam", |
| | | // paramType = "query") |
| | | @GetMapping("/list") |
| | | public ResponseValue queryFormOutputList() { |
| | | LWhFormOutputQry param = CommonUtil.getObjFromReq(LWhFormOutputQry.class); |
| | |
| | | /** |
| | | * 根据id查询详情 |
| | | */ |
| | | @ApiOperation(value = "根据id查询详情", notes = "根据id查询详情") |
| | | @ApiImplicitParam(name = "id", value = "出库单id", required = true, dataType = "Long", paramType = "query") |
| | | // @ApiOperation(value = "根据id查询详情", notes = "根据id查询详情") |
| | | // @ApiImplicitParam(name = "id", value = "出库单id", required = true, dataType = "Long", paramType = "query") |
| | | @GetMapping("/detail") |
| | | public ResponseValue getById(Long id) throws Exception { |
| | | if (id == null) { |
| | |
| | | return goodsTemplateInfoVO; |
| | | } |
| | | |
| | | @ApiOperation(value = "查询出库单详情明细", notes = "查询出库单详情明细") |
| | | @ApiImplicitParam(name = "formOutputQry", value = "出库单详情查询条件", required = true, dataType = "LWhFormOutputQry", |
| | | paramType = "query") |
| | | // @ApiOperation(value = "查询出库单详情明细", notes = "查询出库单详情明细") |
| | | // @ApiImplicitParam(name = "formOutputQry", value = "出库单详情查询条件", required = true, dataType = "LWhFormOutputQry", |
| | | // paramType = "query") |
| | | @GetMapping("/detail/list") |
| | | public ResponseValue queryFormOutputDetailList() { |
| | | LWhFormOutputQry formOutputQry = CommonUtil.getObjFromReq(LWhFormOutputQry.class); |
| | |
| | | return ResponseValue.success(genericPager); |
| | | } |
| | | |
| | | @ApiOperation(value = "出库单导出", notes = "出库单导出") |
| | | @ApiImplicitParam(name = "id", value = "出库单id", required = true, dataType = "Long", paramType = "query") |
| | | // @ApiOperation(value = "出库单导出", notes = "出库单导出") |
| | | // @ApiImplicitParam(name = "id", value = "出库单id", required = true, dataType = "Long", paramType = "query") |
| | | @GetMapping("/list/export") |
| | | public ResponseValue export(Long id, HttpServletResponse response) throws Exception { |
| | | FinSysTenantUser sysInfo = this.getSysInfo(); |
| | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Optional; |
| | | import javax.annotation.Resource; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | |
| | | import cn.hutool.core.collection.CollectionUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | |
| | | import com.consum.base.service.*; |
| | | import com.consum.base.util.DateUtil; |
| | | import com.consum.model.po.*; |
| | | import jakarta.annotation.Resource; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import org.apache.commons.compress.utils.Lists; |
| | | import org.apache.poi.ss.usermodel.Workbook; |
| | | import org.springframework.beans.BeanUtils; |
| | |
| | | import cn.afterturn.easypoi.excel.ExcelExportUtil; |
| | | import cn.afterturn.easypoi.excel.entity.TemplateExportParams; |
| | | import cn.hutool.core.util.ReflectUtil; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | | import io.swagger.annotations.ApiOperation; |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * @ClassName LWhFormProcureController |
| | |
| | | * @Description |
| | | * @Version 1.0 |
| | | **/ |
| | | @Api(value = "仓库表单采购", tags = "仓库表单采购") |
| | | //@Api(value = "仓库表单采购", tags = "仓库表单采购") |
| | | @RestController |
| | | @RequestMapping("/pc/whForm/procure") |
| | | public class LWhFormProcureController extends BaseController { |
| | |
| | | /** |
| | | * @Description 列表查询 |
| | | */ |
| | | @ApiOperation(value = "采购单列表查询", notes = "采购单列表查询") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "param", value = "采购查询条件", required = true, |
| | | dataType = "FormProcureQryDto", paramType = "query")}) |
| | | // @ApiOperation(value = "采购单列表查询", notes = "采购单列表查询") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "param", value = "采购查询条件", required = true, |
| | | // dataType = "FormProcureQryDto", paramType = "query")}) |
| | | @GetMapping("/list") |
| | | public ResponseValue queryFormProcureList() { |
| | | FormProcureQry param = CommonUtil.getObjFromReq(FormProcureQry.class); |
| | |
| | | return goodsModelVO; |
| | | } |
| | | |
| | | @ApiOperation(value = "采购单明细查询", notes = "采购单明细查询") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "param", value = "采购单明细查询", required = true, |
| | | dataType = "FormProcureQryDto", paramType = "query")}) |
| | | // @ApiOperation(value = "采购单明细查询", notes = "采购单明细查询") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "param", value = "采购单明细查询", required = true, |
| | | // dataType = "FormProcureQryDto", paramType = "query")}) |
| | | @GetMapping("detail/list") |
| | | public ResponseValue queryFormProcureDetailList() { |
| | | FormProcureQry formProcureQry = CommonUtil.getObjFromReq(FormProcureQry.class); |
| | |
| | | return ResponseValue.success(genericPager); |
| | | } |
| | | |
| | | @ApiOperation(value = "采购单导出", notes = "采购单导出") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "id", value = "采购单id", required = true, dataType = "Long", paramType = "query")}) |
| | | // @ApiOperation(value = "采购单导出", notes = "采购单导出") |
| | | // @ApiImplicitParams({ |
| | | // @ApiImplicitParam(name = "id", value = "采购单id", required = true, dataType = "Long", paramType = "query")}) |
| | | @GetMapping("/list/export") |
| | | public ResponseValue<String> export(Long id, HttpServletResponse response) throws Exception { |
| | | TemplateExportParams params = new TemplateExportParams("import/采购入库单.xls"); |
| | |
| | | * @param file |
| | | * @return |
| | | */ |
| | | @ApiOperation(value = "采购单导入", notes = "采购单导入") |
| | | // @ApiOperation(value = "采购单导入", notes = "采购单导入") |
| | | @PostMapping("/import") |
| | | public ResponseValue upload(MultipartFile file) { |
| | | String originalFilename = file.getOriginalFilename(); |
| | |
| | | import java.util.Map; |
| | | import java.util.Optional; |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import org.apache.commons.compress.utils.Lists; |
| | | import org.apache.poi.ss.usermodel.Workbook; |
| | | import org.springframework.beans.BeanUtils; |
| | |
| | | |
| | | import cn.afterturn.easypoi.excel.ExcelExportUtil; |
| | | import cn.afterturn.easypoi.excel.entity.TemplateExportParams; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | | import io.swagger.annotations.ApiOperation; |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * @Description 报废单 |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/11/1 |
| | | */ |
| | | @Api(value = "报废单", tags = "报废单") |
| | | // @Api(value = "报废单", tags = "报废单") |
| | | @RestController |
| | | @RequestMapping("/pc/l/wh/form/scrapped") |
| | | public class LWhFormScrappedController extends BaseController { |
| | |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/11/1 |
| | | */ |
| | | @ApiOperation(value = "新增报废单", notes = "新增报废单") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "param")}) |
| | | // @ApiOperation(value = "新增报废单", notes = "新增报废单") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "param")}) |
| | | @PostMapping("/add") |
| | | public ResponseValue add() { |
| | | LWhFormScrappedParam param = CommonUtil.getObjFromReqBody(LWhFormScrappedParam.class); |
| | |
| | | * <p> |
| | | * </>1.查询报废单 2.查询报废单物品 |
| | | */ |
| | | @ApiOperation(value = "列表查询", notes = "列表查询") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "param", value = "查询条件", dataType = "LWhFormScrappedQry", paramType = "query")}) |
| | | // @ApiOperation(value = "列表查询", notes = "列表查询") |
| | | // @ApiImplicitParams({ |
| | | // @ApiImplicitParam(name = "param", value = "查询条件", dataType = "LWhFormScrappedQry", paramType = "query")}) |
| | | @GetMapping("/list") |
| | | public ResponseValue queryList() { |
| | | LWhFormScrappedQry param = CommonUtil.getObjFromReq(LWhFormScrappedQry.class); |
| | |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/11/2 |
| | | */ |
| | | @ApiOperation(value = "根据id查询详情", notes = "根据id查询详情") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "报废单id", dataType = "Long", paramType = "query")}) |
| | | // @ApiOperation(value = "根据id查询详情", notes = "根据id查询详情") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "报废单id", dataType = "Long", paramType = "query")}) |
| | | @GetMapping("/detail") |
| | | public ResponseValue getById(Long id) { |
| | | if (id == null) { |
| | |
| | | * @param |
| | | * @return |
| | | */ |
| | | @ApiOperation(value = "报废明细", notes = "报废明细") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "param", value = "查询条件", dataType = "LWhFormScrappedQry", paramType = "query")}) |
| | | // @ApiOperation(value = "报废明细", notes = "报废明细") |
| | | // @ApiImplicitParams({ |
| | | // @ApiImplicitParam(name = "param", value = "查询条件", dataType = "LWhFormScrappedQry", paramType = "query")}) |
| | | @GetMapping("/list/detailList") |
| | | public ResponseValue queryDetailList() { |
| | | LWhFormScrappedQry param = CommonUtil.getObjFromReq(LWhFormScrappedQry.class); |
| | |
| | | return ResponseValue.success(pageUtil); |
| | | } |
| | | |
| | | @ApiOperation(value = "导出报废单", notes = "导出报废单") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "报废单id", dataType = "Long", paramType = "query")}) |
| | | // @ApiOperation(value = "导出报废单", notes = "导出报废单") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "报废单id", dataType = "Long", paramType = "query")}) |
| | | @GetMapping("/list/export") |
| | | public ResponseValue<String> export(Long id, HttpServletResponse response) throws Exception { |
| | | if (id == null) { |
| | |
| | | package com.consum.base.controller; |
| | | |
| | | import java.lang.reflect.Field; |
| | | import java.math.BigDecimal; |
| | | import java.util.ArrayList; |
| | | import java.util.Comparator; |
| | | import java.util.HashMap; |
| | |
| | | import java.util.Optional; |
| | | import java.util.Set; |
| | | import java.util.stream.Collectors; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | |
| | | import cn.hutool.core.collection.CollectionUtil; |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.alibaba.excel.EasyExcelFactory; |
| | |
| | | import com.alibaba.excel.exception.ExcelDataConvertException; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.consum.base.pojo.*; |
| | | import com.consum.base.pojo.excel.ImportProcureOrderTemplate; |
| | | import com.consum.base.pojo.excel.LWhFormTransferTemplate; |
| | | import com.consum.base.pojo.query.WarehouseQry; |
| | | import com.consum.base.service.*; |
| | | import com.consum.base.util.DateUtil; |
| | | import com.consum.base.util.ExcelStyleUtil; |
| | | import com.consum.model.po.*; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import org.apache.commons.compress.utils.Lists; |
| | | import org.apache.commons.lang3.ObjectUtils; |
| | | import org.apache.poi.ss.usermodel.Workbook; |
| | |
| | | import cn.afterturn.easypoi.excel.ExcelExportUtil; |
| | | import cn.afterturn.easypoi.excel.entity.TemplateExportParams; |
| | | import cn.hutool.core.util.ReflectUtil; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | /** |
| | |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/pc/l/wh/form/transfer") |
| | | @Api(value = "调拨分发管理", tags = "调拨分发管理") |
| | | // @Api(value = "调拨分发管理", tags = "调拨分发管理") |
| | | public class LWhFormTransferController extends BaseController { |
| | | |
| | | @Autowired |
| | |
| | | /** |
| | | * @Description 新增 |
| | | */ |
| | | @ApiOperation(value = "单据新增", notes = "单据新增") |
| | | @ApiImplicitParam(name = "param", value = "单据新增", required = true, dataType = "LWhFormTransferParam") |
| | | // @ApiOperation(value = "单据新增", notes = "单据新增") |
| | | // @ApiImplicitParam(name = "param", value = "单据新增", required = true, dataType = "LWhFormTransferParam") |
| | | @PostMapping("/add") |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public ResponseValue add() throws Exception { |
| | |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "调拨单id", required = true, dataType = "Long"),}) |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "调拨单id", required = true, dataType = "Long"),}) |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @PostMapping("import") |
| | | public ResponseValue upload(@RequestBody String idStr) throws Exception { |
| | |
| | | * <p> |
| | | * 2.查询物品型号 |
| | | */ |
| | | @ApiOperation(value = "单据列表查询", notes = "单据列表查询") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "page", value = "页码", required = true, dataType = "int"), |
| | | @ApiImplicitParam(name = "size", value = "每页条数", required = true, dataType = "int"), |
| | | @ApiImplicitParam(name = "param", value = "条件参数", required = true, dataType = "TransferQry"),}) |
| | | // @ApiOperation(value = "单据列表查询", notes = "单据列表查询") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "page", value = "页码", required = true, dataType = "int"), |
| | | // @ApiImplicitParam(name = "size", value = "每页条数", required = true, dataType = "int"), |
| | | // @ApiImplicitParam(name = "param", value = "条件参数", required = true, dataType = "TransferQry"),}) |
| | | @GetMapping("/list") |
| | | public ResponseValue queryFormTransferList() { |
| | | TransferQry param = CommonUtil.getObjFromReq(TransferQry.class); |
| | |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/10/30 |
| | | */ |
| | | @ApiOperation(value = "根据id查询详情", notes = "根据id查询详情") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "调拨单id", required = true, dataType = "Long"),}) |
| | | // @ApiOperation(value = "根据id查询详情", notes = "根据id查询详情") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "调拨单id", required = true, dataType = "Long"),}) |
| | | @GetMapping("/detail") |
| | | public ResponseValue getById(Long id) { |
| | | if (id == null) { |
| | |
| | | return ResponseValue.success(vo); |
| | | } |
| | | |
| | | @ApiOperation(value = "调拨明细列表", notes = "调拨明细列表") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "param", value = "条件", required = true, dataType = "TransferQry"),}) |
| | | // @ApiOperation(value = "调拨明细列表", notes = "调拨明细列表") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "param", value = "条件", required = true, dataType = "TransferQry"),}) |
| | | @GetMapping("/detail/list") |
| | | public ResponseValue queryFormTransferDetailList() { |
| | | TransferQry param = CommonUtil.getObjFromReq(TransferQry.class); |
| | |
| | | * @author 卢庆阳 |
| | | * @date 2023/10/31 |
| | | */ |
| | | @ApiOperation(value = "撤销", notes = "撤销") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "调拨单id", required = true, dataType = "Long"),}) |
| | | // @ApiOperation(value = "撤销", notes = "撤销") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "调拨单id", required = true, dataType = "Long"),}) |
| | | @PostMapping("/updStatus") |
| | | public ResponseValue updateStatus(Long id) { |
| | | if (id == null) { |
| | |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/10/31 |
| | | */ |
| | | @ApiOperation(value = "调拨入库", notes = "调拨入库") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "调拨单id", required = true, dataType = "Long"),}) |
| | | // @ApiOperation(value = "调拨入库", notes = "调拨入库") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "调拨单id", required = true, dataType = "Long"),}) |
| | | @PostMapping("/income") |
| | | public ResponseValue income(Long id) throws Exception { |
| | | lWhFormTransferCoreService.doTransferInPut(id, getCurrentUser(), null); |
| | |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/10/31 |
| | | */ |
| | | @ApiOperation(value = "调拨出库", notes = "调拨出库") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "调拨单id", required = true, dataType = "Long"),}) |
| | | // @ApiOperation(value = "调拨出库", notes = "调拨出库") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "调拨单id", required = true, dataType = "Long"),}) |
| | | @PostMapping("/output") |
| | | public ResponseValue output(Long id) throws Exception { |
| | | |
| | |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @ApiOperation(value = "调拨单导出", notes = "调拨单导出") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "调拨单id", required = true, dataType = "Long"), |
| | | @ApiImplicitParam(name = "type", value = "导出类型 1 入库 2 出库", required = true, dataType = "Integer"),}) |
| | | // @ApiOperation(value = "调拨单导出", notes = "调拨单导出") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "调拨单id", required = true, dataType = "Long"), |
| | | // @ApiImplicitParam(name = "type", value = "导出类型 1 入库 2 出库", required = true, dataType = "Integer"),}) |
| | | @GetMapping("/list/export") |
| | | public ResponseValue<String> export(Long id, Integer type, HttpServletResponse response) throws Exception { |
| | | |
| | |
| | | * @param |
| | | * @return |
| | | */ |
| | | @ApiOperation(value = "部门物品分发列表明细", notes = "部门物品分发列表明细") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "transferQryDto", value = "调拨单查询条件", required = true)}) |
| | | // @ApiOperation(value = "部门物品分发列表明细", notes = "部门物品分发列表明细") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "transferQryDto", value = "调拨单查询条件", required = true)}) |
| | | @GetMapping("/department/list") |
| | | public ResponseValue departmentTransferList() { |
| | | TransferQry param = CommonUtil.getObjFromReq(TransferQry.class); |
| | |
| | | return ResponseValue.success(transferInfoDetailsVoGenericPager); |
| | | } |
| | | |
| | | @ApiOperation(value = "使用人修改", notes = "使用人修改") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "procureModelInfoDto", value = "使用信息", required = true)}) |
| | | // @ApiOperation(value = "使用人修改", notes = "使用人修改") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "procureModelInfoDto", value = "使用信息", required = true)}) |
| | | @PostMapping("/useInfo/update") |
| | | public ResponseValue infoUpdate() { |
| | | |
| | |
| | | * @param transferOrderId |
| | | * @return |
| | | */ |
| | | @ApiOperation(value = "部门物品使用人记录", notes = "部门物品使用人记录") |
| | | @ApiImplicitParams({@ApiImplicitParam(name = "transferOrderId", value = "调拨单id", required = true)}) |
| | | // @ApiOperation(value = "部门物品使用人记录", notes = "部门物品使用人记录") |
| | | // @ApiImplicitParams({@ApiImplicitParam(name = "transferOrderId", value = "调拨单id", required = true)}) |
| | | @GetMapping("/use/record") |
| | | public ResponseValue useRecord(Long transferOrderId) { |
| | | S_user_core currentUser = this.getCurrentUser(); |
| | |
| | | return ResponseValue.success(goodsUseRecordList); |
| | | } |
| | | |
| | | @ApiOperation(value = "查询部门下的分发单", notes = "查询部门下的分发单") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "agencyId", value = "机构id", required = true, dataType = "Long", paramType = "query")}) |
| | | // @ApiOperation(value = "查询部门下的分发单", notes = "查询部门下的分发单") |
| | | // @ApiImplicitParams({ |
| | | // @ApiImplicitParam(name = "agencyId", value = "机构id", required = true, dataType = "Long", paramType = "query")}) |
| | | @GetMapping("/query/transfList") |
| | | public ResponseValue queryDepartmentTransferOrderList() { |
| | | |
| | |
| | | * @param file |
| | | * @return |
| | | */ |
| | | @ApiOperation(value = "分发单导入", notes = "分发单导入") |
| | | // @ApiOperation(value = "分发单导入", notes = "分发单导入") |
| | | @PostMapping("/import2") |
| | | public ResponseValue import2(MultipartFile file) { |
| | | String originalFilename = file.getOriginalFilename(); |
| | |
| | | LWhProcureModelUserParam lWhProcureModelUserParam = new LWhProcureModelUserParam(); |
| | | lWhProcureModelUserParam.setGoodsNum(Integer.valueOf(num)); |
| | | lWhProcureModelUserParam.setNowUserName(user); |
| | | lWhProcureModelUserParam.setNowUserPhone(new Long(userContactPhone)); |
| | | lWhProcureModelUserParam.setNowUserPhone(Convert.toLong(userContactPhone)); |
| | | Integer counts1 = optional3.get().getCounts(); |
| | | Integer num1 = optional3.get().getNum(); |
| | | optional3.get().setCounts(Integer.valueOf(num) + counts1); |
| | |
| | | |
| | | // 查询库存数量 |
| | | Integer nowNum = selectAllNumber(lWhFormTransferParam.getOutAgencyId(), selByModelNameAndGoodsTemplatesId.getId()); |
| | | if(nowNum<new Integer(num)){ |
| | | if(nowNum< Convert.toInt(num)){ |
| | | throw new ExcelAnalysisException("第" + index + "条数据" + "品名:[" + goodsName + "] 规格型号:[" + goodModelName + "] 库存数量不足:["+nowNum+"]"); |
| | | } |
| | | lWhProcureModelUserParam.setNowUserName(user); |
| | | lWhProcureModelUserParam.setNowUserPhone(new Long(userContactPhone)); |
| | | lWhProcureModelUserParam.setNowUserPhone(Convert.toLong(userContactPhone)); |
| | | addLWhProcureModelUserParam.add(lWhProcureModelUserParam); |
| | | lWhTransferModelParam.setProcureModelUserList(addLWhProcureModelUserParam); |
| | | optional.get().getModels().add(lWhTransferModelParam); |
| | |
| | | // 规格id |
| | | lWhTransferModelParam.setBaseGoodsModelsId(selByModelNameAndGoodsTemplatesId.getId()); |
| | | // 新增的时候默认一条 |
| | | lWhTransferModelParam.setCounts(new Integer(num)); |
| | | lWhTransferModelParam.setNum(new Integer(num)); |
| | | lWhTransferModelParam.setCounts(Convert.toInt(num)); |
| | | lWhTransferModelParam.setNum(Convert.toInt(num)); |
| | | List<LWhProcureModelUserParam> lWhFormProcureGoodsInfoParam = new ArrayList<>(); |
| | | LWhProcureModelUserParam lWhProcureModelUserParam = new LWhProcureModelUserParam(); |
| | | lWhProcureModelUserParam.setGoodsNum(Integer.valueOf(num)); |
| | | |
| | | // 查询库存数量 |
| | | Integer nowNum = selectAllNumber(lWhFormTransferParam.getOutAgencyId(), selByModelNameAndGoodsTemplatesId.getId()); |
| | | if(nowNum<new Integer(num)){ |
| | | if(nowNum<Convert.toInt(num)){ |
| | | throw new ExcelAnalysisException("第" + index + "条数据 " + "品名:[" + goodsName + "] 规格型号:[" + goodModelName + "] 库存数量不足:["+nowNum+"]"); |
| | | } |
| | | |
| | | lWhProcureModelUserParam.setNowUserName(user); |
| | | lWhProcureModelUserParam.setNowUserPhone(new Long(userContactPhone)); |
| | | lWhProcureModelUserParam.setNowUserPhone(Convert.toLong(userContactPhone)); |
| | | lWhFormProcureGoodsInfoParam.add(lWhProcureModelUserParam); |
| | | lWhTransferModelParam.setProcureModelUserList(lWhFormProcureGoodsInfoParam); |
| | | lWhTransferModelParam.setBaseGoodsModelsName(goodModelName); |
| | |
| | | package com.consum.base.controller; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | |
| | | import com.iplatform.model.po.S_user_core; |
| | | import com.walker.web.ResponseValue; |
| | | |
| | | import io.swagger.annotations.Api; |
| | | |
| | | |
| | | /** |
| | | * @ClassName LWhGoodsStatisticsController |
| | |
| | | * @Description 物品统计 |
| | | * @Version 1.0 |
| | | **/ |
| | | @Api(value = "物品统计", tags = "物品统计") |
| | | // @Api(value = "物品统计", tags = "物品统计") |
| | | @RestController |
| | | @RequestMapping("/pc/warehouse/goodsStatistics") |
| | | public class LWhGoodsStatisticsController extends BaseController { |
| | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | |
| | | import com.walker.web.ResponseValue; |
| | | |
| | | import cn.hutool.core.convert.Convert; |
| | | import io.swagger.annotations.Api; |
| | | |
| | | |
| | | /** |
| | | * @ClassName LWhHomeStatisticsController |
| | |
| | | |
| | | @RestController |
| | | @RequestMapping("/pc/warehouse/homeStatistics") |
| | | @Api(value = "首页统计", tags = "首页统计") |
| | | // @Api(value = "首页统计", tags = "首页统计") |
| | | public class LWhHomeStatisticsController extends BaseController { |
| | | @Resource |
| | | private LWhGoodsService lWhGoodsService; |
| | |
| | | import java.util.Map; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | |
| | | import com.walker.infrastructure.utils.CollectionUtils; |
| | | import com.walker.web.ResponseValue; |
| | | |
| | | import io.swagger.annotations.Api; |
| | | |
| | | @Api(value = "物品型号", tags = "物品型号") |
| | | // @Api(value = "物品型号", tags = "物品型号") |
| | | @RestController |
| | | @RequestMapping("/pc/warehouse/procureModel") |
| | | public class LWhProcureModelController extends BaseController { |
| | |
| | | import java.util.Map; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.core.io.ClassPathResource; |
| | | import org.springframework.core.io.InputStreamResource; |
| | |
| | | import cn.afterturn.easypoi.excel.entity.ImportParams; |
| | | import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult; |
| | | import cn.hutool.core.convert.Convert; |
| | | import io.swagger.annotations.Api; |
| | | |
| | | |
| | | /** |
| | | * @ClassName LWhWarningConfigController |
| | |
| | | **/ |
| | | @RestController |
| | | @RequestMapping("/pc/warehouse/warningConfig") |
| | | @Api(value = "库存阀值", tags = "库存阀值") |
| | | // @Api(value = "库存阀值", tags = "库存阀值") |
| | | public class LWhWarningConfigController extends BaseController { |
| | | |
| | | @Resource |
| | |
| | | |
| | | import java.util.Map; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | |
| | | import com.walker.infrastructure.utils.DateUtils; |
| | | import com.walker.web.ResponseValue; |
| | | |
| | | import io.swagger.annotations.Api; |
| | | |
| | | |
| | | /** |
| | | * @ClassName LWhWarningConfigController |
| | |
| | | **/ |
| | | @RestController |
| | | @RequestMapping("/pc/warehouse/warning") |
| | | @Api(value = "预警查询", tags = "预警查询") |
| | | // @Api(value = "预警查询", tags = "预警查询") |
| | | public class LWhWarningController extends BaseController { |
| | | |
| | | @Resource |
| | |
| | | import com.consum.model.po.FinSysTenantUser; |
| | | import com.walker.web.ResponseValue; |
| | | |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | |
| | | |
| | | |
| | | /** |
| | | * @author asus |
| | |
| | | * @description: 部门物品退回单 |
| | | * @date 2023/12/1 11:36 |
| | | */ |
| | | @Api(value = "部门物品退回", tags = "部门物品退回") |
| | | // @Api(value = "部门物品退回", tags = "部门物品退回") |
| | | @RestController |
| | | @RequestMapping("/pc/l/wh/using/form/back") |
| | | public class UsingFormBackController extends BaseController { |
| | |
| | | @Autowired |
| | | private UsingFormBackService usingFormBackService; |
| | | |
| | | @ApiOperation(value = "部门物品退回单新增接口", notes = "部门物品退回单新增接口") |
| | | // @ApiOperation(value = "部门物品退回单新增接口", notes = "部门物品退回单新增接口") |
| | | @PostMapping("/add") |
| | | public ResponseValue add() { |
| | | UsingFormBackParam usingFormBackParam = CommonUtil.getObjFromReqBody(UsingFormBackParam.class); |
| | |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @ApiOperation(value = "部门物品退回单查询接口", notes = "部门物品退回单查询接口") |
| | | // @ApiOperation(value = "部门物品退回单查询接口", notes = "部门物品退回单查询接口") |
| | | @GetMapping("/list") |
| | | public ResponseValue query() { |
| | | UsingFormBackQry usingFormBackParam = CommonUtil.getObjFromReq(UsingFormBackQry.class); |
| | |
| | | return ResponseValue.success(page); |
| | | } |
| | | |
| | | @ApiOperation(value = "部门物品退回单详情接口", notes = "部门物品退回单详情接口") |
| | | // @ApiOperation(value = "部门物品退回单详情接口", notes = "部门物品退回单详情接口") |
| | | @GetMapping("/detail") |
| | | public ResponseValue detail(Long id) { |
| | | FinSysTenantUser sysInfo = getSysInfo(); |
| | |
| | | return ResponseValue.success(detail); |
| | | } |
| | | |
| | | @ApiOperation(value = "部门物品退回明细查询接口", notes = "部门物品退回明细查询接口") |
| | | // @ApiOperation(value = "部门物品退回明细查询接口", notes = "部门物品退回明细查询接口") |
| | | @GetMapping("/list/detail") |
| | | public ResponseValue queryListDetail() { |
| | | UsingFormBackQry usingFormBackParam = CommonUtil.getObjFromReq(UsingFormBackQry.class); |
| | |
| | | package com.consum.base.core; |
| | | |
| | | import com.consum.base.core.utils.IdUtil; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Propagation; |
| | |
| | | get(sql, new SqlParameter().put("CODE_PREFIX", CODE_PREFIX), new BaseCodeIndexing()); |
| | | if (codeIndexing == null) { |
| | | codeIndexing = new BaseCodeIndexing(); |
| | | codeIndexing.setId(NumberGenerator.getLongSequenceNumber()); |
| | | codeIndexing.setId(IdUtil.generateId()); |
| | | codeIndexing.setCodePrefix(CODE_PREFIX); |
| | | codeIndexing.setCodeIndex(1); |
| | | insert(codeIndexing); |
| | |
| | | import cn.hutool.core.util.ReflectUtil; |
| | | import com.fasterxml.jackson.databind.DeserializationFeature; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import org.springframework.beans.BeanUtils; |
| | | import jakarta.servlet.ServletInputStream;import jakarta.servlet.http.HttpServletRequest;import jakarta.servlet.http.HttpServletResponse;import org.springframework.beans.BeanUtils; |
| | | import org.springframework.web.context.request.RequestContextHolder; |
| | | import org.springframework.web.context.request.ServletRequestAttributes; |
| | | |
| | | import javax.servlet.ServletInputStream; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.BufferedReader; |
| | | import java.io.IOException; |
| | | import java.io.InputStreamReader; |
| | |
| | | |
| | | import java.util.List; |
| | | |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | @Data |
| | | public class DepFormScrappedGoodsParam { |
| | | |
| | | @ApiModelProperty("分类id") |
| | | // @ApiModelProperty("分类id") |
| | | private Long baseCategoryId; |
| | | |
| | | @ApiModelProperty("物品模版编号") |
| | | // @ApiModelProperty("物品模版编号") |
| | | private Long baseGoodsTemplateId; |
| | | private String goodsTemplateName; |
| | | |
| | | @ApiModelProperty("调拨单Id") |
| | | // @ApiModelProperty("调拨单Id") |
| | | private Long transBusinessId; |
| | | |
| | | /** |
| | |
| | | package com.consum.base.pojo; |
| | | |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | **/ |
| | | @Data |
| | | public class DepFormScrappedModelParam { |
| | | @ApiModelProperty("物品型号id") |
| | | // @ApiModelProperty("物品型号id") |
| | | private Long baseGoodsModelsId; |
| | | |
| | | @ApiModelProperty("价值类型") |
| | | // @ApiModelProperty("价值类型") |
| | | private String classification;// "B类" |
| | | |
| | | @ApiModelProperty("报废数量") |
| | | // @ApiModelProperty("报废数量") |
| | | private Integer counts; |
| | | |
| | | @ApiModelProperty("分发数量") |
| | | // @ApiModelProperty("分发数量") |
| | | private Integer goodsNum; |
| | | |
| | | @ApiModelProperty("在用数量") |
| | | // @ApiModelProperty("在用数量") |
| | | private Integer userUseCount; |
| | | |
| | | @ApiModelProperty("物品id") |
| | | // @ApiModelProperty("物品id") |
| | | private Long goodsTemplatesId; |
| | | |
| | | @ApiModelProperty("物品型号") |
| | | // @ApiModelProperty("物品型号") |
| | | private String modelName; |
| | | |
| | | @ApiModelProperty("调拨使用人表中ID(A类物品填)") |
| | | // @ApiModelProperty("调拨使用人表中ID(A类物品填)") |
| | | private Long modelUserId; |
| | | |
| | | @ApiModelProperty("使用人员名称(可不填)") |
| | | // @ApiModelProperty("使用人员名称(可不填)") |
| | | private String nowUserName; |
| | | |
| | | @ApiModelProperty("报废原因CODE") |
| | | // @ApiModelProperty("报废原因CODE") |
| | | private Long scrappedCode; |
| | | |
| | | @ApiModelProperty("计量单位") |
| | | // @ApiModelProperty("计量单位") |
| | | private String unit; |
| | | |
| | | } |
| | |
| | | package com.consum.base.pojo; |
| | | |
| | | import com.walker.web.param.ParamRequest; |
| | | import io.swagger.annotations.ApiModel; |
| | | |
| | | @ApiModel(value = "FinSysTenantDepartmentParam") |
| | | // // @ApiModel(value = "FinSysTenantDepartmentParam") |
| | | public class FinSysTenantDepartmentParam extends ParamRequest { |
| | | |
| | | /** |
| | |
| | | package com.consum.base.pojo; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | @ApiModel(value = "新增报废单信息") |
| | | // // @ApiModel(value = "新增报废单信息") |
| | | public class LDeptFormScrappedParam { |
| | | |
| | | @ApiModelProperty(value = "部门id") |
| | | // // @ApiModelProperty(value = "部门id") |
| | | private Long departmentId; |
| | | |
| | | /** |
| | | * 报废时间 |
| | | */ |
| | | @ApiModelProperty(value = "报废时间") |
| | | // // @ApiModelProperty(value = "报废时间") |
| | | private Long dealTime; |
| | | /** |
| | | * 手续 |
| | | */ |
| | | @ApiModelProperty(value = "手续") |
| | | // // @ApiModelProperty(value = "手续") |
| | | private String procureDoc; |
| | | |
| | | /** |
| | | * 操作人 |
| | | */ |
| | | // @ApiModelProperty(value = "操作人") |
| | | // // @ApiModelProperty(value = "操作人") |
| | | // private String operatorName; |
| | | |
| | | @ApiModelProperty(value = "报废商品信息") |
| | | // // @ApiModelProperty(value = "报废商品信息") |
| | | private List<DepFormScrappedGoodsParam> goods; |
| | | |
| | | |
| | |
| | | package com.consum.base.pojo; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import java.util.List; |
| | | import lombok.Data; |
| | | |
| | |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/11/2 |
| | | */ |
| | | @ApiModel(value = "记录物品信息和规格型号") |
| | | // // @ApiModel(value = "记录物品信息和规格型号") |
| | | @Data |
| | | public class LWFormsOutputGoodsInfoParam { |
| | | |
| | |
| | | /** |
| | | * 物品id |
| | | */ |
| | | @ApiModelProperty(value = "物品id") |
| | | // @ApiModelProperty(value = "物品id") |
| | | private Long baseGoodsTemplateId; |
| | | /** |
| | | * 物品模版名称 |
| | | */ |
| | | @ApiModelProperty(value = "物品模版名称") |
| | | // @ApiModelProperty(value = "物品模版名称") |
| | | private String goodsTemplateName; |
| | | |
| | | /** |
| | | * 分类id |
| | | */ |
| | | @ApiModelProperty(value = "分类id") |
| | | // @ApiModelProperty(value = "分类id") |
| | | private Long baseCategoryId; |
| | | |
| | | /** |
| | |
| | | package com.consum.base.pojo; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @date 2023/11/13 11:29 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "出库物品型号") |
| | | // // @ApiModel(value = "出库物品型号") |
| | | public class LWFormsOutputGoodsModelParam { |
| | | |
| | | //规格型号编号 |
| | | @ApiModelProperty(value = "规格型号编号") |
| | | // // @ApiModelProperty(value = "规格型号编号") |
| | | private Long baseGoodsModelsId; |
| | | // 计量单位 |
| | | @ApiModelProperty(value = "计量单位") |
| | | // // @ApiModelProperty(value = "计量单位") |
| | | private String baseUnit; |
| | | //库存数量 |
| | | @ApiModelProperty(value = "库存数量") |
| | | // @ApiModelProperty(value = "库存数量") |
| | | private Long warehouseNum; |
| | | //数量 |
| | | @ApiModelProperty(value = "操作数量") |
| | | // @ApiModelProperty(value = "操作数量") |
| | | private Integer counts; |
| | | |
| | | @ApiModelProperty(value = "采购类型") |
| | | // @ApiModelProperty(value = "采购类型") |
| | | private Integer procureModelBusinessType; |
| | | |
| | | } |
| | |
| | | package com.consum.base.pojo; |
| | | |
| | | import com.walker.web.param.ParamRequest; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @Description |
| | | * @Version 1.0 |
| | | **/ |
| | | @ApiModel(value = "库存流水查询参数") |
| | | // @ApiModel(value = "库存流水查询参数") |
| | | @Data |
| | | public class LWarehouseFlowParam extends ParamRequest { |
| | | |
| | | //单据类型 1 采购2 调拨 3出库4部门分发 5报废 |
| | | @ApiModelProperty(value = "单据类型 1 采购2 调拨 3出库4部门分发 5报废") |
| | | // @ApiModelProperty(value = "单据类型 1 采购2 调拨 3出库4部门分发 5报废") |
| | | private Short businessType; |
| | | // 业务单据编号 |
| | | @ApiModelProperty(value = "业务单据编号") |
| | | // @ApiModelProperty(value = "业务单据编号") |
| | | private String businessFormCode; |
| | | //物品名称 |
| | | @ApiModelProperty(value = "物品名称") |
| | | // @ApiModelProperty(value = "物品名称") |
| | | private String goodsTemplateName; |
| | | private Long goodsTemplateId; |
| | | //规格型号 |
| | | @ApiModelProperty(value = "规格型号") |
| | | // @ApiModelProperty(value = "规格型号") |
| | | private String baseGoodsModelsName; |
| | | |
| | | // 机构 |
| | | @ApiModelProperty(value = "机构") |
| | | // @ApiModelProperty(value = "机构") |
| | | private Long agencyId; |
| | | |
| | | @ApiModelProperty("部门ID") |
| | | // @ApiModelProperty("部门ID") |
| | | private Long departmentId; |
| | | |
| | | @ApiModelProperty("仓库类型") |
| | | // @ApiModelProperty("仓库类型") |
| | | private Long warehouseType; |
| | | |
| | | @ApiModelProperty("仓库id") |
| | | // @ApiModelProperty("仓库id") |
| | | private Long baseWarehouseId; |
| | | |
| | | @ApiModelProperty("规格型号") |
| | | // @ApiModelProperty("规格型号") |
| | | private Long baseGoodsModelsId; |
| | | |
| | | @ApiModelProperty("价值类型") |
| | | // @ApiModelProperty("价值类型") |
| | | private Short costType; |
| | | |
| | | @ApiModelProperty("同码表,1采购入库 2退还入库 3调拨入库 4盘盈入库 5申领出库 6调拨出库 7盘亏出库 8报废出库 9其他出库") |
| | | // @ApiModelProperty("同码表,1采购入库 2退还入库 3调拨入库 4盘盈入库 5申领出库 6调拨出库 7盘亏出库 8报废出库 9其他出库") |
| | | private Short flowType; |
| | | |
| | | @ApiModelProperty("同码表,1 物品申领 2 物品分发 3 物品退还 4 物品报废") |
| | | // @ApiModelProperty("同码表,1 物品申领 2 物品分发 3 物品退还 4 物品报废") |
| | | private Short depFlowType; |
| | | |
| | | //创建人 |
| | | @ApiModelProperty(value = "创建人") |
| | | // @ApiModelProperty(value = "创建人") |
| | | private String createdName; |
| | | |
| | | // 操作时间 |
| | | @ApiModelProperty(value = "操作时间") |
| | | // @ApiModelProperty(value = "操作时间") |
| | | private Long dealTimeStart; |
| | | @ApiModelProperty(value = "操作时间") |
| | | // @ApiModelProperty(value = "操作时间") |
| | | private Long dealTimeEnd; |
| | | |
| | | |
| | | @ApiModelProperty(value = "每页显示条数") |
| | | // @ApiModelProperty(value = "每页显示条数") |
| | | private Integer pageSize = 10; |
| | | @ApiModelProperty(value = "当前页数") |
| | | // @ApiModelProperty(value = "当前页数") |
| | | private Integer pageNum = 1; |
| | | |
| | | } |
| | |
| | | package com.consum.base.pojo; |
| | | |
| | | import com.walker.web.param.ParamRequest; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import java.util.List; |
| | | import lombok.Data; |
| | | |
| | |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/10/27 |
| | | */ |
| | | @ApiModel |
| | | // @ApiModel |
| | | @Data |
| | | public class LWhFormOutputParam extends ParamRequest { |
| | | |
| | | /** |
| | | * 仓库id |
| | | */ |
| | | @ApiModelProperty(value = "仓库id") |
| | | // @ApiModelProperty(value = "仓库id") |
| | | private Long warehouseId; |
| | | /** |
| | | * 出库时间 |
| | | */ |
| | | @ApiModelProperty(value = "出库时间") |
| | | // @ApiModelProperty(value = "出库时间") |
| | | private Long dealTime; |
| | | /** |
| | | * 出库手续 |
| | | */ |
| | | @ApiModelProperty(value = "出库手续") |
| | | // @ApiModelProperty(value = "出库手续") |
| | | private String doc; |
| | | /** |
| | | * 记录物品信息和规格型号 |
| | | */ |
| | | @ApiModelProperty(value = "记录物品信息和规格型号") |
| | | // @ApiModelProperty(value = "记录物品信息和规格型号") |
| | | private List<LWFormsOutputGoodsInfoParam> goods; |
| | | |
| | | |
| | |
| | | package com.consum.base.pojo; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import java.util.List; |
| | | import lombok.Data; |
| | | |
| | |
| | | * @date 2023/11/21 16:06 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "LWhFormScrappedGoodsInfoParam", description = "报废单物品信息") |
| | | // @ApiModel(value = "LWhFormScrappedGoodsInfoParam", description = "报废单物品信息") |
| | | public class LWhFormScrappedGoodsInfoParam { |
| | | |
| | | /** |
| | |
| | | * 物品id |
| | | */ |
| | | private Long baseGoodsTemplateId; |
| | | @ApiModelProperty(value = "规格型号编号") |
| | | // @ApiModelProperty(value = "规格型号编号") |
| | | private Long baseGoodsModelsId; |
| | | /** |
| | | * 报废单物品 |
| | |
| | | package com.consum.base.pojo; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | @ApiModel(value = "LWhFormScrappedGoodsParams", description = "报废商品参数") |
| | | // @ApiModel(value = "LWhFormScrappedGoodsParams", description = "报废商品参数") |
| | | public class LWhFormScrappedGoodsModelParams { |
| | | |
| | | //规格型号编号 |
| | |
| | | package com.consum.base.pojo; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | @ApiModel(value = "新增报废单信息") |
| | | // @ApiModel(value = "新增报废单信息") |
| | | public class LWhFormScrappedParam { |
| | | |
| | | /** |
| | | * 机构id |
| | | */ |
| | | @ApiModelProperty(value = "机构id") |
| | | // @ApiModelProperty(value = "机构id") |
| | | private Long agencyId; |
| | | |
| | | @ApiModelProperty(value = "部门id") |
| | | // @ApiModelProperty(value = "部门id") |
| | | private Long departmentId; |
| | | |
| | | /** |
| | | * 仓库编号 |
| | | */ |
| | | @ApiModelProperty(value = "仓库编号") |
| | | // @ApiModelProperty(value = "仓库编号") |
| | | private Long warehouseId; |
| | | /** |
| | | * 操作人 |
| | | */ |
| | | @ApiModelProperty(value = "操作人") |
| | | // @ApiModelProperty(value = "操作人") |
| | | private Long operatorId; |
| | | /** |
| | | * 报废时间 |
| | | */ |
| | | @ApiModelProperty(value = "报废时间") |
| | | // @ApiModelProperty(value = "报废时间") |
| | | private Long dealTime; |
| | | /** |
| | | * 附件 |
| | | */ |
| | | @ApiModelProperty(value = "附件") |
| | | // @ApiModelProperty(value = "附件") |
| | | private String uploadFiles; |
| | | |
| | | @ApiModelProperty(value = "报废商品信息") |
| | | // @ApiModelProperty(value = "报废商品信息") |
| | | private List<LWhFormScrappedGoodsInfoParam> scrappedGoodsInfo; |
| | | |
| | | |
| | |
| | | package com.consum.base.pojo; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import java.util.List; |
| | | import lombok.Data; |
| | | |
| | |
| | | * @Version 1.0 |
| | | **/ |
| | | @Data |
| | | @ApiModel(value = "调拨单型号") |
| | | // @ApiModel(value = "调拨单型号") |
| | | public class LWhFormTransferGoodsInfoParam { |
| | | |
| | | // 主键 |
| | |
| | | //供应商 |
| | | private String supplier; |
| | | |
| | | @ApiModelProperty(value = "单据类型 1 采购2 调拨 3出库4部门分发") |
| | | // @ApiModelProperty(value = "单据类型 1 采购2 调拨 3出库4部门分发") |
| | | private Integer procureModelBusinessType; |
| | | |
| | | @ApiModelProperty(value = "规格型号编号") |
| | | // @ApiModelProperty(value = "规格型号编号") |
| | | private Long baseGoodsModelsId; |
| | | |
| | | private List<LWhTransferModelParam> models; |
| | |
| | | package com.consum.base.pojo; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import java.util.List; |
| | | import lombok.Data; |
| | | |
| | |
| | | * @Description |
| | | * @Version 1.0 |
| | | **/ |
| | | @ApiModel(value = "调拨单规格型号") |
| | | // @ApiModel(value = "调拨单规格型号") |
| | | @Data |
| | | public class LWhProcureModelParam { |
| | | |
| | | //规格型号编号 |
| | | @ApiModelProperty(value = "规格型号编号") |
| | | // @ApiModelProperty(value = "规格型号编号") |
| | | private Long baseGoodsModelsId; |
| | | //价格 |
| | | @ApiModelProperty(value = "价格") |
| | | // @ApiModelProperty(value = "价格") |
| | | private Long price; |
| | | //数量 |
| | | @ApiModelProperty(value = "数量") |
| | | // @ApiModelProperty(value = "数量") |
| | | private Integer counts; |
| | | // 单据类型 1 采购2 调拨 3出库4部门分发 |
| | | @ApiModelProperty(value = "单据类型 1 采购2 调拨 3出库4部门分发") |
| | | // @ApiModelProperty(value = "单据类型 1 采购2 调拨 3出库4部门分发") |
| | | private Integer procureModelBusinessType; |
| | | // 计量单位 |
| | | @ApiModelProperty(value = "计量单位") |
| | | // @ApiModelProperty(value = "计量单位") |
| | | private String baseUnit; |
| | | |
| | | @ApiModelProperty(value = "用户规格型号") |
| | | // @ApiModelProperty(value = "用户规格型号") |
| | | private List<LWhProcureModelUserParam> procureModelUserList; |
| | | |
| | | } |
| | |
| | | package com.consum.base.pojo; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | |
| | | @Data |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | @ApiModel(value = "物品分发使用人信息") |
| | | // // @ApiModel(value = "物品分发使用人信息") |
| | | public class LWhProcureModelUserParam { |
| | | |
| | | /** |
| | |
| | | package com.consum.base.pojo; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import java.util.List; |
| | | import lombok.Data; |
| | | |
| | |
| | | * @description: 调拨单规格型号 |
| | | * @date 2023/11/6 9:28 |
| | | */ |
| | | @ApiModel(value = "调拨单规格型号") |
| | | // @ApiModel(value = "调拨单规格型号") |
| | | @Data |
| | | public class LWhTransferModelParam { |
| | | |
| | | // //规格型号编号 |
| | | @ApiModelProperty(value = "规格型号编号") |
| | | // @ApiModelProperty(value = "规格型号编号") |
| | | private Long baseGoodsModelsId; |
| | | @ApiModelProperty(value = "规格型号名字") |
| | | // @ApiModelProperty(value = "规格型号名字") |
| | | private String baseGoodsModelsName; |
| | | //价格 |
| | | @ApiModelProperty(value = "价格") |
| | | // @ApiModelProperty(value = "价格") |
| | | private Long price; |
| | | //数量 |
| | | @ApiModelProperty(value = "数量") |
| | | // @ApiModelProperty(value = "数量") |
| | | private Integer counts; |
| | | // 单据类型 1 采购2 调拨 3出库4部门分发 |
| | | @ApiModelProperty(value = "单据类型 1 采购2 调拨 3出库4部门分发") |
| | | // @ApiModelProperty(value = "单据类型 1 采购2 调拨 3出库4部门分发") |
| | | private Integer procureModelBusinessType; |
| | | // 计量单位 |
| | | @ApiModelProperty(value = "计量单位") |
| | | // @ApiModelProperty(value = "计量单位") |
| | | private String baseUnit; |
| | | @ApiModelProperty(value = "剩余数量") |
| | | // @ApiModelProperty(value = "剩余数量") |
| | | private Integer num; |
| | | |
| | | @ApiModelProperty(value = "用户规格型号") |
| | | // @ApiModelProperty(value = "用户规格型号") |
| | | private List<LWhProcureModelUserParam> procureModelUserList; |
| | | |
| | | } |
| | |
| | | package com.consum.base.pojo; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @date 2023/11/17 13:07 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "库管员信息") |
| | | // @ApiModel(value = "库管员信息") |
| | | public class WarehouseManagerInfo { |
| | | |
| | | @ApiModelProperty(value = "库管员id") |
| | | // @ApiModelProperty(value = "库管员id") |
| | | private Long managerId; |
| | | @ApiModelProperty(value = "库管员姓名") |
| | | // @ApiModelProperty(value = "库管员姓名") |
| | | private String managerName; |
| | | |
| | | } |
| | |
| | | import cn.afterturn.easypoi.excel.annotation.Excel; |
| | | import cn.afterturn.easypoi.handler.inter.IExcelDataModel; |
| | | import cn.afterturn.easypoi.handler.inter.IExcelModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | @Data |
| | | public class WarnConfImEntity implements IExcelDataModel, IExcelModel { |
| | | |
| | | @ApiModelProperty("仓库名称") |
| | | // @ApiModelProperty("仓库名称") |
| | | @Excel(name = "仓库名称") |
| | | private String warehouseName; |
| | | |
| | | @Excel(name = "物品名称") |
| | | @ApiModelProperty(value = "物品名称") |
| | | // @ApiModelProperty(value = "物品名称") |
| | | private String goodsTemplateName; |
| | | |
| | | @Excel(name = "型号名称") |
| | | @ApiModelProperty("型号名称") |
| | | // @ApiModelProperty("型号名称") |
| | | private String goodsModelName; |
| | | |
| | | @Excel(name = "保底库存") |
| | | @ApiModelProperty("保底库存") |
| | | // @ApiModelProperty("保底库存") |
| | | private Integer lowerLimit; |
| | | |
| | | @Excel(name = "封顶库存") |
| | | @ApiModelProperty("封顶库存") |
| | | // @ApiModelProperty("封顶库存") |
| | | private Integer upperLimit; |
| | | |
| | | @ApiModelProperty("物品id") |
| | | // @ApiModelProperty("物品id") |
| | | private Long goodsTemplateId; |
| | | |
| | | @ApiModelProperty("仓库id") |
| | | // @ApiModelProperty("仓库id") |
| | | private Long baseWarehouseId; |
| | | |
| | | @ApiModelProperty("物品型号id") |
| | | // @ApiModelProperty("物品型号id") |
| | | private Long baseGoodsModelsId; |
| | | |
| | | |
| | |
| | | package com.consum.base.pojo; |
| | | |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | **/ |
| | | @Data |
| | | public class WhWarningConfigParam { |
| | | @ApiModelProperty("仓库类型") |
| | | // @ApiModelProperty("仓库类型") |
| | | private Long warehouseType; |
| | | |
| | | @ApiModelProperty("仓库id") |
| | | // @ApiModelProperty("仓库id") |
| | | private Long baseWarehouseId; |
| | | |
| | | private Long baseGoodsTemplateId; |
| | |
| | | package com.consum.base.pojo.query; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @description: 采购查询条件 |
| | | * @date 2023/11/10 16:51 |
| | | */ |
| | | @ApiModel(value = "采购查询条件") |
| | | // @ApiModel(value = "采购查询条件") |
| | | @Data |
| | | public class FormProcureQry { |
| | | |
| | | @ApiModelProperty(value = "主键") |
| | | // @ApiModelProperty(value = "主键") |
| | | private Long id; |
| | | /** |
| | | * 仓库编号 |
| | | */ |
| | | @ApiModelProperty(value = "仓库编号") |
| | | // @ApiModelProperty(value = "仓库编号") |
| | | |
| | | private Long warehouseId; |
| | | /** |
| | | * 入库单号 |
| | | */ |
| | | @ApiModelProperty(value = "入库单号") |
| | | // @ApiModelProperty(value = "入库单号") |
| | | private String businessFormCode; |
| | | /** |
| | | * 物品模版名称 |
| | | */ |
| | | @ApiModelProperty(value = "物品模版名称") |
| | | // @ApiModelProperty(value = "物品模版名称") |
| | | private String goodsTemplateName; |
| | | /** |
| | | * 机构 |
| | | */ |
| | | @ApiModelProperty(value = "机构") |
| | | // @ApiModelProperty(value = "机构") |
| | | private Long agencyId; |
| | | /** |
| | | * 创建人 |
| | | */ |
| | | @ApiModelProperty(value = "创建人") |
| | | // @ApiModelProperty(value = "创建人") |
| | | private String createName; |
| | | /** |
| | | * 1=待入库;2=已入库 |
| | | */ |
| | | @ApiModelProperty(value = "1=待入库;2=已入库") |
| | | // @ApiModelProperty(value = "1=待入库;2=已入库") |
| | | private Integer states; |
| | | |
| | | /** |
| | | * 入库时间 开始 |
| | | */ |
| | | @ApiModelProperty(value = "入库时间 开始") |
| | | // @ApiModelProperty(value = "入库时间 开始") |
| | | @JsonFormat(pattern = "yyyyMMdd", timezone = "GMT+8") |
| | | private Long startTime; |
| | | /** |
| | | * 入库时间 结束 |
| | | */ |
| | | @ApiModelProperty(value = "入库时间 结束") |
| | | // @ApiModelProperty(value = "入库时间 结束") |
| | | @JsonFormat(pattern = "yyyyMMdd", timezone = "GMT+8") |
| | | private Long endTime; |
| | | /** |
| | | * 规格型号id |
| | | */ |
| | | @ApiModelProperty(value = "规格型号id") |
| | | // @ApiModelProperty(value = "规格型号id") |
| | | private Long baseGoodsModelsId; |
| | | |
| | | @ApiModelProperty(value = "每页显示条数") |
| | | // @ApiModelProperty(value = "每页显示条数") |
| | | private Integer pageSize = 10; |
| | | @ApiModelProperty(value = "当前页数") |
| | | // @ApiModelProperty(value = "当前页数") |
| | | private Integer pageNum = 1; |
| | | } |
| | |
| | | package com.consum.base.pojo.query; |
| | | |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | */ |
| | | private String agencyId; |
| | | |
| | | @ApiModelProperty("规格型号") |
| | | // @ApiModelProperty("规格型号") |
| | | private Long baseGoodsModelsId; |
| | | |
| | | @ApiModelProperty("部门ID") |
| | | // @ApiModelProperty("部门ID") |
| | | private Long departmentId; |
| | | |
| | | private Integer pageSize = 10; |
| | |
| | | package com.consum.base.pojo.query; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | @ApiModel(value = "盘点单条件参数") |
| | | // @ApiModel(value = "盘点单条件参数") |
| | | public class LWhFormInventoryQry { |
| | | |
| | | private Long id; |
| | |
| | | package com.consum.base.pojo.query; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @Date 2023/10/27 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "出库单参数") |
| | | // @ApiModel(value = "出库单参数") |
| | | public class LWhFormOutputQry { |
| | | |
| | | @ApiModelProperty(value = "主键") |
| | | // @ApiModelProperty(value = "主键") |
| | | private Long id; |
| | | /** |
| | | * 仓库编号 |
| | | */ |
| | | @ApiModelProperty(value = "仓库编号") |
| | | // @ApiModelProperty(value = "仓库编号") |
| | | private Long warehouseId; |
| | | /** |
| | | * 入库单号 |
| | | */ |
| | | @ApiModelProperty(value = "入库单号") |
| | | // @ApiModelProperty(value = "入库单号") |
| | | private String businessFormCode; |
| | | /** |
| | | * 物品模版名称 |
| | | */ |
| | | @ApiModelProperty(value = "物品模版名称") |
| | | // @ApiModelProperty(value = "物品模版名称") |
| | | private String goodsTempName; |
| | | /** |
| | | * 物品模版名称 |
| | | */ |
| | | @ApiModelProperty(value = "物品模版id") |
| | | // @ApiModelProperty(value = "物品模版id") |
| | | private String goodsTemplateId; |
| | | /** |
| | | * 物品模版名称 |
| | | */ |
| | | @ApiModelProperty(value = "物品模版名称") |
| | | // @ApiModelProperty(value = "物品模版名称") |
| | | private String goodsName; |
| | | /** |
| | | * 物品模版名称 |
| | | */ |
| | | @ApiModelProperty(value = "物品模版id") |
| | | // @ApiModelProperty(value = "物品模版id") |
| | | private String baseGoodsId; |
| | | |
| | | /** |
| | | * 机构 |
| | | */ |
| | | @ApiModelProperty(value = "机构") |
| | | // @ApiModelProperty(value = "机构") |
| | | private Long agencyId; |
| | | /** |
| | | * 创建人 |
| | | */ |
| | | @ApiModelProperty(value = "创建人") |
| | | // @ApiModelProperty(value = "创建人") |
| | | private String createName; |
| | | /** |
| | | * 采购入库 map.put("1" + "1", "1") |
| | |
| | | * 退还入库 map.put("4" + "1", "6") |
| | | * 申领出库 map.put("4" + "2", "7") |
| | | */ |
| | | @ApiModelProperty(value = "1采购入库 2退还入库 3调拨入库 4盘盈入库 5申领出库 6调拨出库 7盘亏出库 8报废出库 9其他出库") |
| | | // @ApiModelProperty(value = "1采购入库 2退还入库 3调拨入库 4盘盈入库 5申领出库 6调拨出库 7盘亏出库 8报废出库 9其他出库") |
| | | private Integer flowType; |
| | | |
| | | @ApiModelProperty(value = "状态") |
| | | // @ApiModelProperty(value = "状态") |
| | | private Integer states; |
| | | |
| | | /** |
| | | * 入库时间 开始 |
| | | */ |
| | | @ApiModelProperty(value = "开始时间") |
| | | // @ApiModelProperty(value = "开始时间") |
| | | private Long startTime; |
| | | /** |
| | | * 入库时间 结束 |
| | | */ |
| | | @ApiModelProperty(value = "结束时间") |
| | | // @ApiModelProperty(value = "结束时间") |
| | | private Long endTime; |
| | | /** |
| | | * 规格型号id |
| | | */ |
| | | @ApiModelProperty(value = "规格型号id") |
| | | // @ApiModelProperty(value = "规格型号id") |
| | | private Long baseGoodsModelsId; |
| | | |
| | | @ApiModelProperty(value = "每页显示条数") |
| | | // @ApiModelProperty(value = "每页显示条数") |
| | | private Integer pageSize = 10; |
| | | @ApiModelProperty(value = "当前页数") |
| | | // @ApiModelProperty(value = "当前页数") |
| | | private Integer pageNum = 1; |
| | | |
| | | } |
| | |
| | | package com.consum.base.pojo.query; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @date 2023/11/21 15:00 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "LWhFormScrappedQry", description = "报废单查询条件") |
| | | // @ApiModel(value = "LWhFormScrappedQry", description = "报废单查询条件") |
| | | public class LWhFormScrappedQry { |
| | | |
| | | /** |
| | |
| | | package com.consum.base.pojo.query; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @Description |
| | | * @Version 1.0 |
| | | **/ |
| | | @ApiModel(value = "物品统计查询参数") |
| | | // @ApiModel(value = "物品统计查询参数") |
| | | @Data |
| | | public class LWhGoodsStatisQry { |
| | | |
| | | @ApiModelProperty(value = "机构") |
| | | // @ApiModelProperty(value = "机构") |
| | | private Long agencyId; |
| | | |
| | | @ApiModelProperty(value = "部门id") |
| | | // @ApiModelProperty(value = "部门id") |
| | | private Long departmentId; |
| | | |
| | | @ApiModelProperty("仓库id") |
| | | // @ApiModelProperty("仓库id") |
| | | private Long baseWarehouseId; |
| | | |
| | | @ApiModelProperty(value = "物品名称") |
| | | // @ApiModelProperty(value = "物品名称") |
| | | private String goodsTemplateName; |
| | | private Long goodsTemplateId; |
| | | |
| | | @ApiModelProperty(value = "规格型号") |
| | | // @ApiModelProperty(value = "规格型号") |
| | | private String baseGoodsModelsName; |
| | | |
| | | @ApiModelProperty("规格型号") |
| | | // @ApiModelProperty("规格型号") |
| | | private Long baseGoodsModelsId; |
| | | |
| | | @ApiModelProperty("价值类型") |
| | | // @ApiModelProperty("价值类型") |
| | | private Short costType; |
| | | |
| | | @ApiModelProperty(value = "操作时间") |
| | | // @ApiModelProperty(value = "操作时间") |
| | | private Long dealTimeStart; |
| | | @ApiModelProperty(value = "操作时间") |
| | | // @ApiModelProperty(value = "操作时间") |
| | | private Long dealTimeEnd; |
| | | |
| | | } |
| | |
| | | package com.consum.base.pojo.query; |
| | | |
| | | import com.walker.web.param.ParamRequest; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | |
| | | * @Version 1.0 |
| | | **/ |
| | | @Data |
| | | @ApiModel(value = "机构台账参数") |
| | | // @ApiModel(value = "机构台账参数") |
| | | public class LWhLedgerQry extends ParamRequest { |
| | | @ApiModelProperty("机构") |
| | | // @ApiModelProperty("机构") |
| | | private Long agencyId; |
| | | |
| | | @ApiModelProperty("部门ID") |
| | | // @ApiModelProperty("部门ID") |
| | | private Long departmentId; |
| | | |
| | | @ApiModelProperty("仓库类型") |
| | | // @ApiModelProperty("仓库类型") |
| | | private Short warehouseType; |
| | | |
| | | @ApiModelProperty("仓库id") |
| | | // @ApiModelProperty("仓库id") |
| | | private Long warehouseId; |
| | | |
| | | @ApiModelProperty("物品名称") |
| | | // @ApiModelProperty("物品名称") |
| | | private String goodsTemplateName; |
| | | private Long goodsTemplateId; |
| | | |
| | | @ApiModelProperty("分类") |
| | | // @ApiModelProperty("分类") |
| | | private Long categoryId; |
| | | |
| | | @ApiModelProperty("价值类型") |
| | | // @ApiModelProperty("价值类型") |
| | | private Short costType; |
| | | |
| | | @ApiModelProperty("状态(0=在途调拨;1=入库未分发;2=已下发;3=报废 4 零星出库)") |
| | | // @ApiModelProperty("状态(0=在途调拨;1=入库未分发;2=已下发;3=报废 4 零星出库)") |
| | | private Short states; |
| | | private List<Short> statesList; |
| | | |
| | | @ApiModelProperty(value = "每页显示条数") |
| | | // @ApiModelProperty(value = "每页显示条数") |
| | | private Integer pageSize = 10; |
| | | |
| | | @ApiModelProperty(value = "当前页数") |
| | | // @ApiModelProperty(value = "当前页数") |
| | | private Integer pageNum = 1; |
| | | |
| | | } |
| | |
| | | package com.consum.base.pojo.query; |
| | | |
| | | import com.walker.web.param.ParamRequest; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @Version 1.0 |
| | | **/ |
| | | @Data |
| | | @ApiModel(value = "参数") |
| | | // @ApiModel(value = "参数") |
| | | public class LWhProcureModelQry extends ParamRequest { |
| | | |
| | | @ApiModelProperty("物品名称") |
| | | // @ApiModelProperty("物品名称") |
| | | private String goodsTemplateName; |
| | | private Long baseGoodsTemplateId; |
| | | |
| | | @ApiModelProperty("部门ID") |
| | | // @ApiModelProperty("部门ID") |
| | | private Long departmentId; |
| | | |
| | | @ApiModelProperty("分发单ID") |
| | | // @ApiModelProperty("分发单ID") |
| | | private Long transBusinessId; |
| | | } |
| | |
| | | package com.consum.base.pojo.query; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @description: 调拨单查询条件 |
| | | * @date 2023/11/6 11:47 |
| | | */ |
| | | @ApiModel(value = "调拨单查询条件") |
| | | // @ApiModel(value = "调拨单查询条件") |
| | | @Data |
| | | public class TransferQry { |
| | | |
| | | /** |
| | | * 调拨单号/分发单号 |
| | | */ |
| | | @ApiModelProperty(value = "调拨单号/分发单号") |
| | | // @ApiModelProperty(value = "调拨单号/分发单号") |
| | | private String businessFormCode; |
| | | /** |
| | | * 物品模版名称 |
| | | */ |
| | | @ApiModelProperty(value = "物品模版名称") |
| | | // @ApiModelProperty(value = "物品模版名称") |
| | | private String goodsTemplateName; |
| | | /** |
| | | * 物品模版id |
| | | */ |
| | | @ApiModelProperty(value = "物品模版id") |
| | | // @ApiModelProperty(value = "物品模版id") |
| | | private Long goodsTemplateId; |
| | | |
| | | /** |
| | | * 出库仓库机构编号(调拨机构) |
| | | */ |
| | | @ApiModelProperty(value = "出库仓库机构编号(调拨机构)") |
| | | // @ApiModelProperty(value = "出库仓库机构编号(调拨机构)") |
| | | private Long outAgencyId; |
| | | /** |
| | | * 接收机构 |
| | | */ |
| | | @ApiModelProperty(value = "接收机构") |
| | | // @ApiModelProperty(value = "接收机构") |
| | | private Long inAgencyId; |
| | | /** |
| | | * 状态 0=待出库;1=待接收;2=已入库库:4=已撤销 |
| | | */ |
| | | @ApiModelProperty(value = "状态 0=待出库;1=待接收;2=已入库库:4=已撤销") |
| | | // @ApiModelProperty(value = "状态 0=待出库;1=待接收;2=已入库库:4=已撤销") |
| | | private Short states; |
| | | /** |
| | | * 创建人/分发人 |
| | | */ |
| | | @ApiModelProperty(value = "创建人/分发人") |
| | | // @ApiModelProperty(value = "创建人/分发人") |
| | | private String operatorName; |
| | | /** |
| | | * 申请时间 开始 |
| | | */ |
| | | @ApiModelProperty(value = "申请时间 开始") |
| | | // @ApiModelProperty(value = "申请时间 开始") |
| | | private Long createTimeStart; |
| | | /** |
| | | * 申请时间 结束 |
| | | */ |
| | | @ApiModelProperty(value = "申请时间 结束") |
| | | // @ApiModelProperty(value = "申请时间 结束") |
| | | private Long createTimeEnd; |
| | | /** |
| | | * 接收时间 开始 |
| | | */ |
| | | @ApiModelProperty(value = "接收时间 开始") |
| | | // @ApiModelProperty(value = "接收时间 开始") |
| | | private Long startTime; |
| | | /** |
| | | * 接收时间 结束 |
| | | */ |
| | | @ApiModelProperty(value = "接收时间 结束") |
| | | // @ApiModelProperty(value = "接收时间 结束") |
| | | private Long endTime; |
| | | |
| | | /** |
| | | * 规格型号id |
| | | */ |
| | | @ApiModelProperty(value = "规格型号id") |
| | | // @ApiModelProperty(value = "规格型号id") |
| | | private Long baseGoodsModelsId; |
| | | |
| | | /** |
| | | * 页码 |
| | | */ |
| | | @ApiModelProperty(value = "页码") |
| | | // @ApiModelProperty(value = "页码") |
| | | private Integer pageNum; |
| | | /** |
| | | * 页大小 |
| | | */ |
| | | @ApiModelProperty(value = "页大小") |
| | | // @ApiModelProperty(value = "页大小") |
| | | private Integer pageSize; |
| | | |
| | | @ApiModelProperty(value = "查询类型") |
| | | // @ApiModelProperty(value = "查询类型") |
| | | private Integer qryType; |
| | | |
| | | @ApiModelProperty(value = "分发部门,部门分发时仓库id就是分发部门") |
| | | // @ApiModelProperty(value = "分发部门,部门分发时仓库id就是分发部门") |
| | | private Long departmentId; |
| | | |
| | | } |
| | |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @date 2023/12/1 15:32 |
| | | */ |
| | | @Data |
| | | @ApiModel |
| | | // @ApiModel |
| | | @JsonIgnoreProperties(ignoreUnknown = true) |
| | | public class UsingFormBackQry { |
| | | |
| | | @ApiModelProperty(value = "主键") |
| | | // @ApiModelProperty(value = "主键") |
| | | private Long id; |
| | | /** |
| | | * 退回单号 |
| | | */ |
| | | @ApiModelProperty(value = "退回单号") |
| | | // @ApiModelProperty(value = "退回单号") |
| | | private String businessFormCode; |
| | | /** |
| | | * 分发部门id |
| | | */ |
| | | @ApiModelProperty(value = "分发部门id") |
| | | // @ApiModelProperty(value = "分发部门id") |
| | | private Long departmentId; |
| | | /** |
| | | * 物品模版名称 |
| | | */ |
| | | @ApiModelProperty(value = "物品模版名称") |
| | | // @ApiModelProperty(value = "物品模版名称") |
| | | private String goodsTemplateName; |
| | | /** |
| | | * 物品模版id |
| | | */ |
| | | @ApiModelProperty(value = "物品模版id") |
| | | // @ApiModelProperty(value = "物品模版id") |
| | | private String goodsTemplateId; |
| | | /** |
| | | * 开始时间 |
| | | */ |
| | | @ApiModelProperty(value = "开始时间") |
| | | // @ApiModelProperty(value = "开始时间") |
| | | private Long startTime; |
| | | /** |
| | | * 结束时间 |
| | | */ |
| | | @ApiModelProperty(value = "结束时间") |
| | | // @ApiModelProperty(value = "结束时间") |
| | | private Long endTime; |
| | | /** |
| | | * 规格型号id |
| | | */ |
| | | @ApiModelProperty(value = "规格型号id") |
| | | // @ApiModelProperty(value = "规格型号id") |
| | | private Long baseGoodsModelsId; |
| | | /** |
| | | * 机构 |
| | | */ |
| | | @ApiModelProperty(value = "机构") |
| | | // @ApiModelProperty(value = "机构") |
| | | private Long agencyId; |
| | | |
| | | /** |
| | | * 创建人 |
| | | */ |
| | | @ApiModelProperty(value = "创建人") |
| | | // @ApiModelProperty(value = "创建人") |
| | | private String createName; |
| | | |
| | | /** |
| | | * 页码 |
| | | */ |
| | | @ApiModelProperty(value = "页码") |
| | | // @ApiModelProperty(value = "页码") |
| | | private Integer pageNum; |
| | | /** |
| | | * 页大小 |
| | | */ |
| | | @ApiModelProperty(value = "页大小") |
| | | // @ApiModelProperty(value = "页大小") |
| | | private Integer pageSize; |
| | | } |
| | |
| | | package com.consum.base.pojo.query; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import javax.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | |
| | |
| | | * @date 2023/11/16 10:18 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "库存查询条件") |
| | | // @ApiModel(value = "库存查询条件") |
| | | public class WarehouseQry { |
| | | |
| | | @ApiModelProperty(value = "仓库id") |
| | | // @ApiModelProperty(value = "仓库id") |
| | | private Long warehouseId; |
| | | @ApiModelProperty(value = "商品型号id") |
| | | // @ApiModelProperty(value = "商品型号id") |
| | | @NotNull(message = "商品型号id不能为空") |
| | | private Long baseGoodsModelsId; |
| | | //仓库类型 0机构1部门 |
| | | @ApiModelProperty(value = "仓库类型 0机构1部门") |
| | | // @ApiModelProperty(value = "仓库类型 0机构1部门") |
| | | private Integer warehouseType; |
| | | //(0=在途调拨;1=入库未分发;2=已下发;3=报废) |
| | | @ApiModelProperty(value = "(0=在途调拨;1=入库未分发;2=已下发;3=报废)") |
| | | // @ApiModelProperty(value = "(0=在途调拨;1=入库未分发;2=已下发;3=报废)") |
| | | private Integer states; |
| | | //采购方式(1:集采;2=自采) |
| | | @ApiModelProperty(value = "采购方式(1:集采;2=自采)") |
| | | // @ApiModelProperty(value = "采购方式(1:集采;2=自采)") |
| | | private Integer buyType; |
| | | @ApiModelProperty(value = "机构id") |
| | | // @ApiModelProperty(value = "机构id") |
| | | private Long agencyId; |
| | | |
| | | } |
| | |
| | | package com.consum.base.pojo.query; |
| | | |
| | | import com.walker.web.param.ParamRequest; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @Description |
| | | * @Version 1.0 |
| | | **/ |
| | | @ApiModel(value = "预警设置查询参数") |
| | | // @ApiModel(value = "预警设置查询参数") |
| | | @Data |
| | | public class WhWarningConfigQry extends ParamRequest { |
| | | // 主键 |
| | |
| | | private Long baseGoodsTemplateId; |
| | | private Long baseGoodsModelsId; |
| | | private Integer goodsType; |
| | | @ApiModelProperty("机构") |
| | | // @ApiModelProperty("机构") |
| | | private Long agencyId; |
| | | @ApiModelProperty("仓库类型") |
| | | // @ApiModelProperty("仓库类型") |
| | | private Long warehouseType; |
| | | |
| | | @ApiModelProperty("仓库id") |
| | | // @ApiModelProperty("仓库id") |
| | | private Long baseWarehouseId; |
| | | |
| | | @ApiModelProperty("物品名称") |
| | | // @ApiModelProperty("物品名称") |
| | | private String goodsTemplateName; |
| | | |
| | | @ApiModelProperty("分类") |
| | | // @ApiModelProperty("分类") |
| | | private Long categoryId; |
| | | |
| | | @ApiModelProperty("价值类型") |
| | | // @ApiModelProperty("价值类型") |
| | | private Short costType; |
| | | |
| | | @ApiModelProperty(value = "每页显示条数") |
| | | // @ApiModelProperty(value = "每页显示条数") |
| | | private Integer pageSize = 10; |
| | | |
| | | @ApiModelProperty(value = "当前页数") |
| | | // @ApiModelProperty(value = "当前页数") |
| | | private Integer pageNum = 1; |
| | | } |
| | |
| | | package com.consum.base.pojo.query; |
| | | |
| | | import com.walker.web.param.ParamRequest; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @Description |
| | | * @Version 1.0 |
| | | **/ |
| | | @ApiModel(value = "预警设置查询参数") |
| | | // @ApiModel(value = "预警设置查询参数") |
| | | @Data |
| | | public class WhWarningQry extends ParamRequest { |
| | | @ApiModelProperty("物品名称") |
| | | // @ApiModelProperty("物品名称") |
| | | private String goodsTemplateName; |
| | | private String goodsTemplateId; |
| | | |
| | | @ApiModelProperty("规格型号") |
| | | // @ApiModelProperty("规格型号") |
| | | private Long baseGoodsModelsId; |
| | | |
| | | @ApiModelProperty("分类") |
| | | // @ApiModelProperty("分类") |
| | | private Long categoryId; |
| | | |
| | | @ApiModelProperty("价值类型") |
| | | // @ApiModelProperty("价值类型") |
| | | private Short costType; |
| | | |
| | | @ApiModelProperty("机构") |
| | | // @ApiModelProperty("机构") |
| | | private Long agencyId; |
| | | |
| | | @ApiModelProperty("仓库类型") |
| | | // @ApiModelProperty("仓库类型") |
| | | private Short warehouseType; |
| | | |
| | | @ApiModelProperty("仓库id") |
| | | // @ApiModelProperty("仓库id") |
| | | private Long baseWarehouseId; |
| | | |
| | | @ApiModelProperty("状态(1=未查看;2=已查看)") |
| | | // @ApiModelProperty("状态(1=未查看;2=已查看)") |
| | | private Integer states; |
| | | |
| | | @ApiModelProperty("预警类型(1=超上限;2=超下限)") |
| | | // @ApiModelProperty("预警类型(1=超上限;2=超下限)") |
| | | private Short warningType; |
| | | |
| | | @ApiModelProperty(value = "每页显示条数") |
| | | // @ApiModelProperty(value = "每页显示条数") |
| | | private Integer pageSize = 10; |
| | | |
| | | @ApiModelProperty(value = "当前页数") |
| | | // @ApiModelProperty(value = "当前页数") |
| | | private Integer pageNum = 1; |
| | | } |
| | |
| | | package com.consum.base.pojo.request; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | |
| | |
| | | * @date 2023/11/20 13:49 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "新增盘点单信息") |
| | | // @ApiModel(value = "新增盘点单信息") |
| | | public class FormInventoryParam { |
| | | |
| | | private Long id; |
| | | /** |
| | | * 盘点单名 |
| | | */ |
| | | @ApiModelProperty(value = "盘点单名") |
| | | // @ApiModelProperty(value = "盘点单名") |
| | | private String businessFormName; |
| | | /** |
| | | * 仓库编号 |
| | | */ |
| | | @ApiModelProperty(value = "仓库编号") |
| | | // @ApiModelProperty(value = "仓库编号") |
| | | private Long warehouseId; |
| | | /** |
| | | * 操作人 |
| | | */ |
| | | @ApiModelProperty(value = "操作人") |
| | | // @ApiModelProperty(value = "操作人") |
| | | private Long operatorUserId; |
| | | /** |
| | | * 监盘人 |
| | | */ |
| | | @ApiModelProperty(value = "监盘人") |
| | | // @ApiModelProperty(value = "监盘人") |
| | | private Long monitorUserId; |
| | | /** |
| | | * 备注 |
| | | */ |
| | | @ApiModelProperty(value = "备注") |
| | | // @ApiModelProperty(value = "备注") |
| | | private String remark; |
| | | |
| | | |
| | |
| | | package com.consum.base.pojo.request; |
| | | |
| | | import com.consum.base.pojo.response.FormInventoryGoodsVO; |
| | | import io.swagger.annotations.ApiModel; |
| | | import java.util.List; |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | @ApiModel(value = "盘点单") |
| | | // @ApiModel(value = "盘点单") |
| | | public class LWhFormInventoryParam { |
| | | |
| | | // 主键 |
| | |
| | | package com.consum.base.pojo.request; |
| | | |
| | | import com.consum.base.pojo.LWhFormTransferGoodsInfoParam; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import java.util.List; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | |
| | | * @Author 卢庆阳 |
| | | * @Date 2023/10/30 |
| | | */ |
| | | @ApiModel(value = "调拨单据新增信息") |
| | | // @ApiModel(value = "调拨单据新增信息") |
| | | @Data |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class LWhFormTransferParam { |
| | | |
| | | @ApiModelProperty(value = "主键") |
| | | // @ApiModelProperty(value = "主键") |
| | | private Long id; |
| | | /** |
| | | * 入库仓库编号 |
| | | */ |
| | | @ApiModelProperty(value = "入库仓库编号") |
| | | // @ApiModelProperty(value = "入库仓库编号") |
| | | private Long inWarehouseId; |
| | | /** |
| | | * 出库仓库机构编号(调拨机构) |
| | | */ |
| | | @ApiModelProperty(value = "出库仓库机构编号(调拨机构)") |
| | | // @ApiModelProperty(value = "出库仓库机构编号(调拨机构)") |
| | | private Long outAgencyId; |
| | | /** |
| | | * 调拨时间 |
| | | */ |
| | | @ApiModelProperty(value = "调拨时间") |
| | | // @ApiModelProperty(value = "调拨时间") |
| | | private Long createTime; |
| | | /** |
| | | * 调拨手续 |
| | | */ |
| | | @ApiModelProperty(value = "调拨手续") |
| | | // @ApiModelProperty(value = "调拨手续") |
| | | private String procureDoc; |
| | | /** |
| | | * 单据类型。0仓库调拨;1部门分发;2部门物品回退 |
| | | */ |
| | | @ApiModelProperty(value = "单据类型。0仓库调拨;1部门分发;2部门物品回退") |
| | | // @ApiModelProperty(value = "单据类型。0仓库调拨;1部门分发;2部门物品回退") |
| | | private Integer transferBusinessType; |
| | | |
| | | @ApiModelProperty(value = "部门id") |
| | | // @ApiModelProperty(value = "部门id") |
| | | private Long departmentId; |
| | | |
| | | @ApiModelProperty(value = "部门名字") |
| | | // @ApiModelProperty(value = "部门名字") |
| | | private String departmentName; |
| | | |
| | | @ApiModelProperty(value = "领取人名字") |
| | | // @ApiModelProperty(value = "领取人名字") |
| | | private String operatorName; |
| | | |
| | | @ApiModelProperty(value = "联系电话") |
| | | // @ApiModelProperty(value = "联系电话") |
| | | private Long tel; |
| | | /** |
| | | * 调拨单型号 |
| | | */ |
| | | @ApiModelProperty(value = "调拨单型号") |
| | | // @ApiModelProperty(value = "调拨单型号") |
| | | private List<LWhFormTransferGoodsInfoParam> transferGoods; |
| | | |
| | | |
| | |
| | | package com.consum.base.pojo.request; |
| | | |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | import java.util.List; |
| | | import lombok.Data; |
| | | |
| | |
| | | @Data |
| | | public class RecordInfoParam { |
| | | |
| | | @ApiModelProperty("使用人修改记录") |
| | | // @ApiModelProperty("使用人修改记录") |
| | | List<ProcureModelInfoParam> recordInfoList; |
| | | |
| | | } |
| | |
| | | |
| | | import java.util.List; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @date 2023/12/1 13:16 |
| | | */ |
| | | @Data |
| | | @ApiModel |
| | | // @ApiModel |
| | | public class UsingFormBackGoodsInfo { |
| | | |
| | | // 分类编号 |
| | |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | |
| | | */ |
| | | @NoArgsConstructor |
| | | @Data |
| | | @ApiModel |
| | | // @ApiModel |
| | | @JsonIgnoreProperties(ignoreUnknown = true) |
| | | public class UsingFormBackParam { |
| | | |
| | | @ApiModelProperty(value = "物品退回部门id") |
| | | // @ApiModelProperty(value = "物品退回部门id") |
| | | private Long departmentId; |
| | | |
| | | @ApiModelProperty(value = "物品退回部门名字") |
| | | // @ApiModelProperty(value = "物品退回部门名字") |
| | | private String departmentName; |
| | | |
| | | @ApiModelProperty(value = "退回人id") |
| | | // @ApiModelProperty(value = "退回人id") |
| | | private Long operatorId; |
| | | @ApiModelProperty(value = "退回人名字") |
| | | // @ApiModelProperty(value = "退回人名字") |
| | | private String operatorName; |
| | | |
| | | @ApiModelProperty(value = "物品退回时间") |
| | | // @ApiModelProperty(value = "物品退回时间") |
| | | private Long dealTime; |
| | | |
| | | @ApiModelProperty(value = "手续") |
| | | // @ApiModelProperty(value = "手续") |
| | | private String procureDoc; |
| | | |
| | | @ApiModelProperty(value = "分发物品信息") |
| | | // @ApiModelProperty(value = "分发物品信息") |
| | | private List<UsingFormBackGoodsInfo> goods; |
| | | |
| | | } |
| | |
| | | package com.consum.base.pojo.request; |
| | | |
| | | import com.consum.base.pojo.WarehouseManagerInfo; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | // |
| | | // |
| | | import java.util.List; |
| | | import lombok.Data; |
| | | |
| | |
| | | * @date 2023/11/17 13:05 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "库管员信息") |
| | | // @ApiModel(value = "库管员信息") |
| | | public class WarehouseManagerParam { |
| | | |
| | | @ApiModelProperty(value = "仓库id") |
| | | // // @ApiModelProperty(value = "仓库id") |
| | | private Long warehouseId; |
| | | |
| | | @ApiModelProperty(value = "库管员信息") |
| | | // @ApiModelProperty(value = "库管员信息") |
| | | List<WarehouseManagerInfo> warehouseManagerInfoList; |
| | | |
| | | } |
| | |
| | | package com.consum.base.pojo.request; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @date 2023/12/1 13:21 |
| | | */ |
| | | @Data |
| | | @ApiModel |
| | | // @ApiModel |
| | | public class baseGoodModel { |
| | | |
| | | @ApiModelProperty(value = "商品模型id") |
| | | // @ApiModelProperty(value = "商品模型id") |
| | | private Long baseGoodsModelsId; |
| | | @ApiModelProperty(value = "单位") |
| | | // @ApiModelProperty(value = "单位") |
| | | private String unit; |
| | | @ApiModelProperty(value = "物品类型 A,B,C") |
| | | // @ApiModelProperty(value = "物品类型 A,B,C") |
| | | private String classification; |
| | | |
| | | private Long goodsTemplatesId; |
| | |
| | | package com.consum.base.pojo.response; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @date 2023/11/23 15:30 |
| | | */ |
| | | @Data |
| | | @ApiModel |
| | | // @ApiModel |
| | | public class DepartGoodsUseInfo { |
| | | |
| | | private Long id; |
| | |
| | | package com.consum.base.pojo.response; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @date 2023/11/16 15:46 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "FinSysTenantUserVO", description = "机构用户信息") |
| | | // // @ApiModel(value = "FinSysTenantUserVO", description = "机构用户信息") |
| | | public class FinSysTenantUserVO { |
| | | |
| | | // 主键 |
| | | @ApiModelProperty(value = "主键") |
| | | // // @ApiModelProperty(value = "主键") |
| | | private Long id; |
| | | |
| | | @ApiModelProperty(value = "用户编码") |
| | | // // @ApiModelProperty(value = "用户编码") |
| | | private String userCode; |
| | | |
| | | @ApiModelProperty(value = "用户姓名") |
| | | // // @ApiModelProperty(value = "用户姓名") |
| | | private String userName; |
| | | |
| | | @ApiModelProperty(value = "用户登录名") |
| | | // // @ApiModelProperty(value = "用户登录名") |
| | | private String userPhone; |
| | | |
| | | @ApiModelProperty(value = "机构id") |
| | | // // @ApiModelProperty(value = "机构id") |
| | | private String tenantId; |
| | | |
| | | @ApiModelProperty(value = "机构名称") |
| | | // // @ApiModelProperty(value = "机构名称") |
| | | private String tenantName; |
| | | |
| | | @ApiModelProperty(value = "部门名称") |
| | | // // @ApiModelProperty(value = "部门名称") |
| | | private String sysDeptName; |
| | | |
| | | @ApiModelProperty(value = "状态 (0禁用1启用)") |
| | | // // @ApiModelProperty(value = "状态 (0禁用1启用)") |
| | | private Integer status; |
| | | |
| | | } |
| | |
| | | package com.consum.base.pojo.response; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @date 2023/11/21 13:20 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "盘点异常明细信息") |
| | | // @ApiModel(value = "盘点异常明细信息") |
| | | public class FormInventoryDetailVO { |
| | | |
| | | private Long id; |
| | |
| | | package com.consum.base.pojo.response; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @date 2023/11/20 14:45 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "盘点物品信息") |
| | | // @ApiModel(value = "盘点物品信息") |
| | | public class FormInventoryGoodsVO { |
| | | |
| | | // 主键 |
| | | @ApiModelProperty(value = "id") |
| | | // @ApiModelProperty(value = "id") |
| | | private Long id; |
| | | |
| | | private Long whFormInventoryId; |
| | |
| | | |
| | | private Long baseGoodsTemplateId; |
| | | |
| | | @ApiModelProperty(value = "商品模板名称") |
| | | // @ApiModelProperty(value = "商品模板名称") |
| | | private String goodsTemplateName; |
| | | |
| | | @ApiModelProperty(value = "商品型号名称") |
| | | // @ApiModelProperty(value = "商品型号名称") |
| | | private String baseGoodsModelsName; |
| | | |
| | | @ApiModelProperty(value = "商品类别") |
| | | // @ApiModelProperty(value = "商品类别") |
| | | private String type; |
| | | |
| | | @ApiModelProperty(value = "单位") |
| | | // @ApiModelProperty(value = "单位") |
| | | private String unit; |
| | | |
| | | @ApiModelProperty(value = "库存数量") |
| | | // @ApiModelProperty(value = "库存数量") |
| | | private Integer inventoryCount; |
| | | |
| | | @ApiModelProperty(value = "单价") |
| | | // @ApiModelProperty(value = "单价") |
| | | private Integer price; |
| | | |
| | | @ApiModelProperty(value = "总价") |
| | | // @ApiModelProperty(value = "总价") |
| | | private Long totalAmount; |
| | | |
| | | @ApiModelProperty(value = "实盘数量") |
| | | // @ApiModelProperty(value = "实盘数量") |
| | | private Integer realNum; |
| | | |
| | | @ApiModelProperty(value = "状态,") |
| | | // @ApiModelProperty(value = "状态,") |
| | | private Integer status; |
| | | |
| | | |
| | |
| | | package com.consum.base.pojo.response; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import java.util.List; |
| | | import lombok.Data; |
| | | |
| | |
| | | * @date 2023/11/20 14:43 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "盘点物品单详细信息") |
| | | // @ApiModel(value = "盘点物品单详细信息") |
| | | public class FormInventoryVO { |
| | | |
| | | |
| | | /** |
| | | * 盘点单号 |
| | | */ |
| | | @ApiModelProperty(value = "盘点单号") |
| | | // @ApiModelProperty(value = "盘点单号") |
| | | private String businessFormCode; |
| | | /** |
| | | * 盘点单名 |
| | | */ |
| | | @ApiModelProperty(value = "盘点单名") |
| | | // @ApiModelProperty(value = "盘点单名") |
| | | private String businessFormName; |
| | | /** |
| | | * 仓库编号 |
| | | */ |
| | | @ApiModelProperty(value = "仓库编号") |
| | | // @ApiModelProperty(value = "仓库编号") |
| | | private Long warehouseId; |
| | | /** |
| | | * 仓库名字 |
| | | */ |
| | | @ApiModelProperty(value = "仓库名字") |
| | | // @ApiModelProperty(value = "仓库名字") |
| | | private String warehouseName; |
| | | /** |
| | | * 盘点物品信息 |
| | | */ |
| | | @ApiModelProperty(value = "盘点物品信息") |
| | | // @ApiModelProperty(value = "盘点物品信息") |
| | | private List<FormInventoryGoodsVO> formInventoryGoodsList; |
| | | |
| | | } |
| | |
| | | package com.consum.base.pojo.response; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | |
| | | import java.util.List; |
| | | import lombok.Data; |
| | | |
| | |
| | | * @description: 出库列表信息 |
| | | * @date 2023/11/10 11:37 |
| | | */ |
| | | @ApiModel(value = "出库列表信息") |
| | | // @ApiModel(value = "出库列表信息") |
| | | @Data |
| | | public class FormOutputVO { |
| | | |
| | |
| | | |
| | | import java.util.List; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @description: 采购列表明细信息 |
| | | * @date 2023/11/10 11:37 |
| | | */ |
| | | @ApiModel(value = "采购列表明细信息") |
| | | // @ApiModel(value = "采购列表明细信息") |
| | | @Data |
| | | public class FormProcureVO { |
| | | |
| | |
| | | package com.consum.base.pojo.response; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonProperty; |
| | | import io.swagger.annotations.ApiModel; |
| | | |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | |
| | | */ |
| | | @NoArgsConstructor |
| | | @Data |
| | | @ApiModel(value = "FormScrappedGoodsDetailVO") |
| | | // @ApiModel(value = "FormScrappedGoodsDetailVO") |
| | | public class FormScrappedGoodsDetailVO { |
| | | |
| | | @JsonProperty("id") |
| | |
| | | |
| | | import java.util.List; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @date 2023/11/15 17:27 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "调拨单列表信息") |
| | | // @ApiModel(value = "调拨单列表信息") |
| | | public class FormTransferVO { |
| | | |
| | | // 主键 |
| | |
| | | |
| | | import java.util.List; |
| | | |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | @Data |
| | | public class GoodsModelVO { |
| | | |
| | | @ApiModelProperty(value = "id") |
| | | // @ApiModelProperty(value = "id") |
| | | private Long id; |
| | | @ApiModelProperty(value = "型号名称") |
| | | // @ApiModelProperty(value = "型号名称") |
| | | private String baseGoodsModelsName; |
| | | @ApiModelProperty(value = "单位信息") |
| | | // @ApiModelProperty(value = "单位信息") |
| | | private String unit; |
| | | |
| | | @ApiModelProperty(value = "数量") |
| | | // @ApiModelProperty(value = "数量") |
| | | private Integer counts; |
| | | @ApiModelProperty(value = "总金额") |
| | | // @ApiModelProperty(value = "总金额") |
| | | private Double totalAmount; |
| | | |
| | | /*采购信息*/ |
| | | @ApiModelProperty(value = "库存数量") |
| | | // @ApiModelProperty(value = "库存数量") |
| | | private Integer worehouseCount; |
| | | @ApiModelProperty(value = "单价") |
| | | // @ApiModelProperty(value = "单价") |
| | | private Long price; |
| | | private Long baseGoodsModelsId; |
| | | |
| | | /*报废信息*/ |
| | | private String scrappedName; |
| | | |
| | | @ApiModelProperty(value = "部门分发使用人信息") |
| | | // @ApiModelProperty(value = "部门分发使用人信息") |
| | | private List<DepartGoodsUseInfo> useInfo; |
| | | |
| | | } |
| | |
| | | package com.consum.base.pojo.response; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | |
| | | */ |
| | | @NoArgsConstructor |
| | | @Data |
| | | @ApiModel |
| | | // @ApiModel |
| | | public class GoodsStatisticsInfoVO { |
| | | |
| | | @ApiModelProperty(value = "机构") |
| | | // @ApiModelProperty(value = "机构") |
| | | private String orgName; |
| | | @ApiModelProperty(value = "调拨数量") |
| | | // @ApiModelProperty(value = "调拨数量") |
| | | private Integer diaoBoNum; |
| | | @ApiModelProperty(value = "总数量") |
| | | // @ApiModelProperty(value = "总数量") |
| | | private Integer totalNum; |
| | | @ApiModelProperty(value = "在库数量") |
| | | // @ApiModelProperty(value = "在库数量") |
| | | private Integer zaiKuNum; |
| | | @ApiModelProperty(value = "物品型号类别(A类,B类..)") |
| | | // @ApiModelProperty(value = "物品型号类别(A类,B类..)") |
| | | private String costType; |
| | | @ApiModelProperty(value = "报废数量") |
| | | // @ApiModelProperty(value = "报废数量") |
| | | private Integer baoFeiNum; |
| | | @ApiModelProperty(value = "物品型号名称") |
| | | // @ApiModelProperty(value = "物品型号名称") |
| | | private String baseGoodsModelsName; |
| | | @ApiModelProperty(value = "物品编码") |
| | | // @ApiModelProperty(value = "物品编码") |
| | | private String goodsCode; |
| | | @ApiModelProperty(value = "仓库/部门名称") |
| | | // @ApiModelProperty(value = "仓库/部门名称") |
| | | private String warehouseName; |
| | | @ApiModelProperty(value = "物品模板名称") |
| | | // @ApiModelProperty(value = "物品模板名称") |
| | | private String goodsTemplateName; |
| | | } |
| | |
| | | package com.consum.base.pojo.response; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @description: 物品统计信息 |
| | | * @date 2023/11/10 11:37 |
| | | */ |
| | | @ApiModel |
| | | // @ApiModel |
| | | @Data |
| | | public class GoodsTemplateCountVO { |
| | | |
| | | @ApiModelProperty(value = "id") |
| | | // @ApiModelProperty(value = "id") |
| | | private Long id; |
| | | @ApiModelProperty(value = "物品模板名称") |
| | | // @ApiModelProperty(value = "物品模板名称") |
| | | private String goodsName; |
| | | @ApiModelProperty(value = "物品模板名称") |
| | | // @ApiModelProperty(value = "物品模板名称") |
| | | private String goodsTemplateName; |
| | | @ApiModelProperty(value = "物品模板名称") |
| | | // @ApiModelProperty(value = "物品模板名称") |
| | | private String baseGoodsTemplateName; |
| | | @ApiModelProperty(value = "商品模板id") |
| | | // @ApiModelProperty(value = "商品模板id") |
| | | private Long baseGoodsTemplateId; |
| | | @ApiModelProperty(value = "物品内全部型号统计数量") |
| | | // @ApiModelProperty(value = "物品内全部型号统计数量") |
| | | private Integer count; |
| | | @ApiModelProperty(value = "单位") |
| | | // @ApiModelProperty(value = "单位") |
| | | private String unit; |
| | | |
| | | } |
| | |
| | | |
| | | import java.util.List; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @date 2023/11/14 13:13 |
| | | */ |
| | | @Data |
| | | @ApiModel(description = "输出物品信息") |
| | | // @ApiModel(description = "输出物品信息") |
| | | public class GoodsTemplateInfoVO { |
| | | |
| | | // 主键 |
| | |
| | | package com.consum.base.pojo.response; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @date 2023/11/15 13:38 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "物品模板信息") |
| | | // @ApiModel(value = "物品模板信息") |
| | | public class GoodsTemplateVO { |
| | | |
| | | private Long id; |
| | |
| | | |
| | | import java.util.List; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @date 2023/11/15 18:02 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "调拨单扩展详细信息") |
| | | // @ApiModel(value = "调拨单扩展详细信息") |
| | | public class LWHFromTransferExtendVO { |
| | | |
| | | // 主键 |
| | | private Long id; |
| | | |
| | | @ApiModelProperty(value = "出入库id") |
| | | // @ApiModelProperty(value = "出入库id") |
| | | private Long inWarehouseFormId; |
| | | |
| | | @ApiModelProperty(value = "入库流水id") |
| | | // @ApiModelProperty(value = "入库流水id") |
| | | private Long inWarehouseFlowId; |
| | | |
| | | @ApiModelProperty(value = "出库流水id") |
| | | // @ApiModelProperty(value = "出库流水id") |
| | | private Long outWarehouseFlowId; |
| | | |
| | | @ApiModelProperty(value = "出库单id") |
| | | // @ApiModelProperty(value = "出库单id") |
| | | private Long outWarehouseFormId; |
| | | |
| | | @ApiModelProperty(value = "业务类型0仓库调拨;1部门分发;2部门物品回退") |
| | | // @ApiModelProperty(value = "业务类型0仓库调拨;1部门分发;2部门物品回退") |
| | | private Integer businessType; |
| | | |
| | | @ApiModelProperty(value = "业务单号") |
| | | // @ApiModelProperty(value = "业务单号") |
| | | private String businessFormCode; |
| | | |
| | | @ApiModelProperty(value = "入库单类型0机构1部门") |
| | | // @ApiModelProperty(value = "入库单类型0机构1部门") |
| | | private Integer inWarehouseType; |
| | | |
| | | @ApiModelProperty(value = "入库仓库id") |
| | | // @ApiModelProperty(value = "入库仓库id") |
| | | private Long inWarehouseId; |
| | | |
| | | @ApiModelProperty(value = "入库仓库名称") |
| | | // @ApiModelProperty(value = "入库仓库名称") |
| | | private String inWarehouseName; |
| | | |
| | | @ApiModelProperty(value = "出库单类型0机构1部门") |
| | | // @ApiModelProperty(value = "出库单类型0机构1部门") |
| | | private Integer outWarehouseType; |
| | | |
| | | @ApiModelProperty(value = "出库仓库id") |
| | | // @ApiModelProperty(value = "出库仓库id") |
| | | private Long outWarehouseId; |
| | | |
| | | @ApiModelProperty(value = "出库仓库名称") |
| | | // @ApiModelProperty(value = "出库仓库名称") |
| | | private String outWarehouseName; |
| | | |
| | | @ApiModelProperty(value = "入库机构id") |
| | | // @ApiModelProperty(value = "入库机构id") |
| | | private Long inAgencyId; |
| | | |
| | | @ApiModelProperty(value = "入库机构名称") |
| | | // @ApiModelProperty(value = "入库机构名称") |
| | | private String inAgencyName; |
| | | |
| | | @ApiModelProperty(value = "出库机构id") |
| | | // @ApiModelProperty(value = "出库机构id") |
| | | private Long outAgencyId; |
| | | |
| | | @ApiModelProperty(value = "出库机构名称") |
| | | // @ApiModelProperty(value = "出库机构名称") |
| | | private String outAgencyName; |
| | | |
| | | @ApiModelProperty(value = "操作人id") |
| | | // @ApiModelProperty(value = "操作人id") |
| | | private Long operatorId; |
| | | |
| | | @ApiModelProperty(value = "操作人名称") |
| | | // @ApiModelProperty(value = "操作人名称") |
| | | private String operatorName; |
| | | |
| | | @ApiModelProperty(value = "创建时间") |
| | | // @ApiModelProperty(value = "创建时间") |
| | | private Long createTime; |
| | | |
| | | @ApiModelProperty(value = "0=待出库;1=待接收;2=已入库库:4=已撤销") |
| | | // @ApiModelProperty(value = "0=待出库;1=待接收;2=已入库库:4=已撤销") |
| | | private Integer states; |
| | | |
| | | @ApiModelProperty(value = "入库操作人id") |
| | | // @ApiModelProperty(value = "入库操作人id") |
| | | private Long inOperatorId; |
| | | |
| | | @ApiModelProperty(value = "入库操作人名称") |
| | | // @ApiModelProperty(value = "入库操作人名称") |
| | | private String inOperatorName; |
| | | |
| | | @ApiModelProperty(value = "入库时间") |
| | | // @ApiModelProperty(value = "入库时间") |
| | | private Long inTime; |
| | | |
| | | @ApiModelProperty(value = "出库操作人id") |
| | | // @ApiModelProperty(value = "出库操作人id") |
| | | private Long outOperatorId; |
| | | |
| | | @ApiModelProperty(value = "出库操作人名称") |
| | | // @ApiModelProperty(value = "出库操作人名称") |
| | | private String outOperatorName; |
| | | |
| | | @ApiModelProperty(value = "出库时间") |
| | | // @ApiModelProperty(value = "出库时间") |
| | | private Long outputTime; |
| | | |
| | | @ApiModelProperty(value = "手续") |
| | | // @ApiModelProperty(value = "手续") |
| | | private String procureDoc; |
| | | |
| | | @ApiModelProperty(value = "部门名称") |
| | | // @ApiModelProperty(value = "部门名称") |
| | | private String departmentName; |
| | | |
| | | @ApiModelProperty(value = "电话") |
| | | // @ApiModelProperty(value = "电话") |
| | | private Long tel; |
| | | |
| | | private List<GoodsTemplateInfoVO> formTransferGoods; |
| | |
| | | package com.consum.base.pojo.response; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | |
| | | import java.util.List; |
| | | import lombok.Data; |
| | | |
| | |
| | | * @date 2023/11/13 16:45 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "出库单信息扩展") |
| | | // @ApiModel(value = "出库单信息扩展") |
| | | public class LWhFormOutputExtendVO { |
| | | |
| | | |
| | |
| | | package com.consum.base.pojo.response; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | |
| | | import java.util.List; |
| | | import lombok.Data; |
| | | |
| | |
| | | * @Date 2023/11/2 |
| | | */ |
| | | @Data |
| | | @ApiModel |
| | | // @ApiModel |
| | | public class LWhFormScrappedExtendVO { |
| | | |
| | | |
| | |
| | | |
| | | import java.util.List; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @date 2023/11/22 16:29 |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "LWhFormScrappedVO", description = "LWhFormScrappedVO") |
| | | // @ApiModel(value = "LWhFormScrappedVO", description = "LWhFormScrappedVO") |
| | | public class LWhFormScrappedVO { |
| | | |
| | | // 主键 |
| | |
| | | package com.consum.base.pojo.response; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @description: 机构分发单信息 |
| | | * @date 2023/11/10 15:35 |
| | | */ |
| | | @ApiModel(value = "机构分发单信息") |
| | | // @ApiModel(value = "机构分发单信息") |
| | | @Data |
| | | public class TransferInfoVO { |
| | | |
| | | @ApiModelProperty(value = "id") |
| | | // @ApiModelProperty(value = "id") |
| | | private String id; |
| | | @ApiModelProperty(value = "单号") |
| | | // @ApiModelProperty(value = "单号") |
| | | private String businessFormCode; |
| | | @ApiModelProperty(value = "物品名称") |
| | | // @ApiModelProperty(value = "物品名称") |
| | | private String goodsTemplatesName; |
| | | @ApiModelProperty(value = "分发数量") |
| | | // @ApiModelProperty(value = "分发数量") |
| | | private String num; |
| | | @ApiModelProperty(value = "可退数量") |
| | | // @ApiModelProperty(value = "可退数量") |
| | | private String refundNum; |
| | | @ApiModelProperty(value = "分发时间") |
| | | // @ApiModelProperty(value = "分发时间") |
| | | private String createDate; |
| | | } |
| | |
| | | package com.consum.base.pojo.response; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | * @date 2023/12/2 9:34 |
| | | */ |
| | | @Data |
| | | @ApiModel |
| | | // @ApiModel |
| | | public class UseInfo { |
| | | |
| | | private String useName; |
| | |
| | | package com.consum.base.pojo.response; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | |
| | | */ |
| | | @NoArgsConstructor |
| | | @Data |
| | | @ApiModel |
| | | // @ApiModel |
| | | public class UsingFormBackDetailListVO { |
| | | |
| | | private Long id; |
| | |
| | | package com.consum.base.pojo.response; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | |
| | | import java.util.List; |
| | | import lombok.Data; |
| | | |
| | |
| | | * @date 2023/12/2 9:18 |
| | | */ |
| | | @Data |
| | | @ApiModel |
| | | // @ApiModel |
| | | public class UsingFormBackGoodsTemplateInfo { |
| | | |
| | | private Long id; |
| | |
| | | package com.consum.base.pojo.response; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | |
| | | import java.util.List; |
| | | import lombok.Data; |
| | | |
| | |
| | | * @date 2023/12/2 9:24 |
| | | */ |
| | | @Data |
| | | @ApiModel |
| | | // @ApiModel |
| | | public class UsingFormBackModelInfo { |
| | | |
| | | private Long id; |
| | |
| | | package com.consum.base.pojo.response; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | |
| | | |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | |
| | | * @description: 仓库流水明细信息 |
| | | * @date 2023/11/11 11:26 |
| | | */ |
| | | @ApiModel(value = "仓库流水明细信息") |
| | | // @ApiModel(value = "仓库流水明细信息") |
| | | @NoArgsConstructor |
| | | @Data |
| | | public class WarehouseFlowVO { |
| | | |
| | | |
| | | @ApiModelProperty(value = "商品模板名称") |
| | | // @ApiModelProperty(value = "商品模板名称") |
| | | private String goodsTemplateName; |
| | | @ApiModelProperty(value = "规格名称") |
| | | // @ApiModelProperty(value = "规格名称") |
| | | private String baseGoodsModelsName; |
| | | @ApiModelProperty(value = "交易时间") |
| | | // @ApiModelProperty(value = "交易时间") |
| | | private Long dealTime; |
| | | @ApiModelProperty(value = "交易类型") |
| | | // @ApiModelProperty(value = "交易类型") |
| | | private Integer businessType; |
| | | @ApiModelProperty(value = "创建人") |
| | | // @ApiModelProperty(value = "创建人") |
| | | private String createdName; |
| | | @ApiModelProperty(value = "数量") |
| | | // @ApiModelProperty(value = "数量") |
| | | private Integer thisCount; |
| | | @ApiModelProperty(value = "交易单号") |
| | | // @ApiModelProperty(value = "交易单号") |
| | | private String businessFormCode; |
| | | @ApiModelProperty(value = "经营单位") |
| | | // @ApiModelProperty(value = "经营单位") |
| | | private String agencyName; |
| | | @ApiModelProperty(value = "交易单ID") |
| | | // @ApiModelProperty(value = "交易单ID") |
| | | private Long businessFormId; |
| | | @ApiModelProperty(value = "交易类型") |
| | | // @ApiModelProperty(value = "交易类型") |
| | | private Integer thisType; |
| | | } |
| | |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.transaction.interceptor.TransactionAspectSupport; |
| | |
| | | import java.util.Objects; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Propagation; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | import java.util.Map; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Propagation; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | import java.util.Map; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import javax.annotation.PostConstruct; |
| | | |
| | | import jakarta.annotation.PostConstruct; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.jdbc.core.JdbcTemplate; |
| | |
| | | if (CollectionUtils.isEmpty(inventoryGoodsList)) { |
| | | return null; |
| | | } |
| | | Long whFormProcureId = NumberGenerator.getLongSequenceNumber(); |
| | | Long whFormProcureId = IdUtil.generateId(); |
| | | BaseWarehouse baseWarehouse = baseWarehouseService.getById(warehouseId); |
| | | LWhFormProcure lWhFormProcure = new LWhFormProcure(); |
| | | lWhFormProcure.setId(whFormProcureId); |
| | |
| | | Long baseCategoryId = Long.valueOf(tempGoodsInfo.get("categoryid") + ""); |
| | | |
| | | LWhFormProcureGoods procureGood = new LWhFormProcureGoods(); |
| | | long fromProcureGoodsId = NumberGenerator.getLongSequenceNumber(); |
| | | long fromProcureGoodsId = IdUtil.generateId(); |
| | | procureGood.setId(fromProcureGoodsId); |
| | | procureGood.setWhFormProcureId(whFormProcureId); |
| | | procureGood.setBaseCategoryId(baseCategoryId); |
| | |
| | | return outWarehouseFormId; |
| | | } |
| | | // 出库单ID |
| | | outWarehouseFormId = NumberGenerator.getLongSequenceNumberNano(); |
| | | outWarehouseFormId = IdUtil.generateId(); |
| | | |
| | | // 申请调拨的物品 |
| | | List<LWhProcureModel> goodsModelNumList = lWhProcureModelService.getModelByForm(businessEnum, whFormTransferId); |
| | |
| | | String nickName = currentUser.getNick_name(); |
| | | |
| | | // 流水记录总表ID |
| | | long lWarehouseFlowId = NumberGenerator.getLongSequenceNumberNano(); |
| | | long lWarehouseFlowId = IdUtil.generateId(); |
| | | long lWarehouseFlowBusinessId = outWarehouseFormId; |
| | | Integer queryModelStatus = 1; |
| | | Integer buyType = null; |
| | |
| | | String modelName = (String)tempGoodsInfo.get("modelname"); |
| | | |
| | | // 插入 各规格物品的进出库记录 L_WH_GOODS_RECORD |
| | | long whGoodsRecordId = NumberGenerator.getLongSequenceNumberNano(); |
| | | long whGoodsRecordId = IdUtil.generateId(); |
| | | LWhGoodsRecord whGoodsRecord = new LWhGoodsRecord(); |
| | | whGoodsRecord.setId(whGoodsRecordId); |
| | | whGoodsRecord.setWarehouseId(outWarehouseId); |
| | |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | import com.iplatform.base.IdUtil; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Propagation; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | lWhProcureModelService.getModelByForm1(WhBusinessEnum.CAIGOU, whFormProcureId); |
| | | // 流水记录总表ID |
| | | Long warehouseId = lWhFormProcure.getWarehouseId(); |
| | | long lWarehouseFlowId = NumberGenerator.getLongSequenceNumberNano(); |
| | | long lWarehouseFlowId = IdUtil.generateId(); |
| | | LWarehouseFlow warehouseFlow = new LWarehouseFlow(); |
| | | warehouseFlow.setId(lWarehouseFlowId); |
| | | warehouseFlow.setWarehouseType(0); |
| | |
| | | import java.util.Map; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Propagation; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | String inWarehouseName = lWhFormTransfer.getInWarehouseName(); |
| | | |
| | | // 流水记录总表ID |
| | | long lWarehouseFlowId = NumberGenerator.getLongSequenceNumberNano(); |
| | | long lWarehouseFlowId = IdUtil.generateId(); |
| | | // 流水记录总表中 业务ID 。调拨单时 保存调拨单id 出库单时 保存出库单id |
| | | long lWarehouseFlowBusinessId = whFormTransferId; |
| | | |
| | |
| | | String modelName = (String)tempGoodsInfo.get("modelname"); |
| | | |
| | | // 插入 各规格物品的进出库记录 L_WH_GOODS_RECORD |
| | | long whGoodsRecordId = NumberGenerator.getLongSequenceNumberNano(); |
| | | long whGoodsRecordId = IdUtil.generateId(); |
| | | LWhGoodsRecord whGoodsRecord = new LWhGoodsRecord(); |
| | | whGoodsRecord.setId(whGoodsRecordId); |
| | | whGoodsRecord.setWarehouseId(outWarehouseId); |
| | |
| | | long dealTime = DateUtils.getDateTimeNumber(System.currentTimeMillis()); |
| | | |
| | | // 流水记录总表ID |
| | | long inWarehouseFlowId = NumberGenerator.getLongSequenceNumber(); |
| | | long inWarehouseFlowId = IdUtil.generateId(); |
| | | // 单据类型。0仓库调拨;1部门分发;2部门物品回退 |
| | | Integer businessType = lWhFormTransfer.getBusinessType(); |
| | | // 状态(0=在途调拨;1=入库未分发;2=已下发;3=报废 4 零星出库) |
| | |
| | | import java.util.Map; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import org.apache.commons.collections4.CollectionUtils; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Propagation; |
| | |
| | | import java.util.Map; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | import cn.hutool.core.collection.CollectionUtil; |
| | | import com.consum.base.pojo.query.LWhLedgerQry; |
| | | import com.consum.base.service.*; |
| | | import jakarta.annotation.Resource; |
| | | import org.apache.commons.compress.utils.Lists; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | import com.walker.infrastructure.utils.DateUtils; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.jdbc.service.BaseServiceImpl; |
| | | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | /** |
| | | * @Description 盘点 |
| | |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | import jakarta.annotation.Resource; |
| | | import org.apache.commons.compress.utils.Lists; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | import javax.annotation.PostConstruct; |
| | | |
| | | import jakarta.annotation.PostConstruct; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | |
| | | import com.walker.infrastructure.utils.DateUtils; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.jdbc.service.BaseServiceImpl; |
| | | import jakarta.annotation.Resource; |
| | | import org.apache.commons.compress.utils.Lists; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | |
| | | <dependency> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-jdbc-common</artifactId> |
| | | <scope>provided</scope> |
| | | <version>${walker-jdbc-common.version}</version> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/walker-jdbc-common-3.2.0.jar</systemPath> |
| | | <scope>system</scope> |
| | | </dependency> |
| | | <!-- json注解:属性绑定依赖 --> |
| | | <dependency> |
| | |
| | | <artifactId>jackson-databind</artifactId> |
| | | <scope>provided</scope> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springframework</groupId> |
| | | <artifactId>spring-jdbc</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | </project> |
| | |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>mysql</groupId> |
| | | <artifactId>mysql-connector-java</artifactId> |
| | | <version>8.0.31</version> <!-- 使用适合您项目的版本号 --> |
| | | </dependency> |
| | | <!-- 通过界面下载po生成文件,2023/03/16 --> |
| | | <dependency> |
| | | <groupId>com.iplatform</groupId> |
| | | <artifactId>iplatform-jdbc-generator</artifactId> |
| | | <version>3.2.0</version> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/iplatform-jdbc-generator-2.3.0-SNAPSHOT.jar</systemPath> |
| | | <scope>system</scope> |
| | | </dependency> |
| | | |
| | | <!-- 阿里druid数据库连接池,如果使用直接引入到业务发布模块中,2023-03-15 --> |
| | |
| | | <artifactId>druid</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- 如果使用Redis缓存,则引入支持模块 --> |
| | | <!-- redis支持 --> |
| | | <dependency> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-support-redis</artifactId> |
| | | <exclusions> |
| | | <exclusion> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-cache</artifactId> |
| | | </exclusion> |
| | | </exclusions> |
| | | <version>${walker-support-redis.version}</version> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/walker-support-redis-3.2.0.jar</systemPath> |
| | | <scope>system</scope> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-jdbc</artifactId> |
| | | <version>3.2.0</version> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/walker-jdbc-3.2.0.jar</systemPath> |
| | | <scope>system</scope> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-autoconfigure</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-test</artifactId> |
| | | <version>2.1.6.RELEASE</version> |
| | | <exclusions> |
| | | <exclusion> |
| | | <artifactId>snakeyaml</artifactId> |
| | | <groupId>org.yaml</groupId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | |
| | | <dependency> |
| | | <groupId>org.apache.tomcat.embed</groupId> |
| | | <artifactId>tomcat-embed-core</artifactId> |
| | | <version>9.0.89</version> |
| | | <version>10.1.31</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.apache.tomcat.embed</groupId> |
| | | <artifactId>tomcat-embed-el</artifactId> |
| | | <version>9.0.89</version> |
| | | <version>10.1.31</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.apache.tomcat.embed</groupId> |
| | | <artifactId>tomcat-embed-websocket</artifactId> |
| | | <version>9.0.89</version> |
| | | <version>10.1.31</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.apache.tomcat</groupId> |
| | | <artifactId>tomcat-annotations-api</artifactId> |
| | | <version>9.0.89</version> |
| | | <version>10.1.31</version> |
| | | </dependency> |
| | | |
| | | |
| | | <!-- <!– 2023-06-25 使用Oracle数据库需要配置,不需要直接注释即可。 –>--> |
| | | <!-- <dependency>--> |
| | | <!-- <groupId>com.walkersoft</groupId>--> |
| | | <!-- <artifactId>walker-jdbc-support-oracle</artifactId>--> |
| | | <!-- </dependency>--> |
| | | |
| | | <!-- elastic search 需要单独引入模块, 2023/07/31 --> |
| | | <!-- <dependency>--> |
| | | <!-- <groupId>org.springframework.boot</groupId>--> |
| | | <!-- <artifactId>spring-boot-starter-web</artifactId>--> |
| | | <!-- <exclusions>--> |
| | | <!-- <exclusion>--> |
| | | <!-- <groupId>org.elasticsearch.client</groupId>--> |
| | | <!-- <artifactId>elasticsearch-rest-high-level-client</artifactId>--> |
| | | <!-- </exclusion>--> |
| | | <!-- <exclusion>--> |
| | | <!-- <groupId>org.elasticsearch</groupId>--> |
| | | <!-- <artifactId>elasticsearch</artifactId>--> |
| | | <!-- </exclusion>--> |
| | | <!-- </exclusions>--> |
| | | <!-- </dependency>--> |
| | | |
| | | <!-- 2023-08-07 为现场调试,暂时关闭检索模块 --> |
| | | <!-- <dependency>--> |
| | | <!-- <groupId>org.elasticsearch.client</groupId>--> |
| | | <!-- <artifactId>elasticsearch-rest-high-level-client</artifactId>--> |
| | | <!-- <version>${es.version}</version>--> |
| | | <!-- </dependency>--> |
| | | <!-- <dependency>--> |
| | | <!-- <groupId>org.elasticsearch</groupId>--> |
| | | <!-- <artifactId>elasticsearch</artifactId>--> |
| | | <!-- <version>${es.version}</version>--> |
| | | <!-- </dependency>--> |
| | | |
| | | <!-- <!– 积木报表功能,需要使用打开注释即可,2023-08-24 –>--> |
| | | <!-- <dependency>--> |
| | | <!-- <groupId>com.iplatform</groupId>--> |
| | | <!-- <artifactId>iplatform-report</artifactId>--> |
| | | <!-- </dependency>--> |
| | | <!-- 配置文件加密 --> |
| | | <dependency> |
| | | <groupId>com.github.ulisesbocchio</groupId> |
| | |
| | | <dependency> |
| | | <groupId>org.springframework.security</groupId> |
| | | <artifactId>spring-security-core</artifactId> |
| | | <version>5.7.12</version> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | |
| | | dataBaseName: low_consum_manage_test24041101 |
| | | username: root |
| | | # Bjjmy_2020 |
| | | password: ENC(V7lFKlYcHfEzTbXsbBQhSUswgxLsbS5z) |
| | | url: jdbc:mysql://116.198.40.76:3306/${spring.datasource.dataBaseName}?useUnicode=true&characterEncoding=UTF-8&useSSL=false |
| | | password: Bjjmy_2020 |
| | | url: jdbc:mysql://116.198.40.76:3306/low_consum_manage_test24041101?useUnicode=true&characterEncoding=UTF-8&useSSL=false |
| | | # Druid连接池 |
| | | type: com.walker.jdbc.ds.MyDruidDataSource |
| | | druid: |
| | |
| | | max-open-prepared-statements: 100 |
| | | use-global-data-source-stat: true |
| | | # Redis |
| | | redis: |
| | | host: 116.198.40.76 |
| | | port: 6379 |
| | | database: 11 |
| | | password: ENC(C40h1dp9Q1oLqdU+JUGSBOWUfOmj/ZO4) #Jmy2019. |
| | | |
| | | mvc: |
| | | pathmatch: |
| | | # 加该配置是因为 swagger3 启动报错,2023-02-23 |
| | |
| | | multipart: |
| | | max-file-size: 100MB |
| | | max-request-size: 300MB |
| | | data: |
| | | redis: |
| | | host: 116.198.40.76 |
| | | port: 6379 |
| | | database: 11 |
| | | password: Jmy2019. |
| | | |
| | | server: |
| | | port: 8083 |
| | |
| | | # - /api/** |
| | | |
| | | # 超级管理员密码,加密后的秘文 |
| | | supervisor-password: ENC(cDkgI4dm/vDXFDsDm5KJW23i5zAAUxIUW448ReA27tmgQ83ZLgO3k/YMK5+wIiuGDKPDIXUH9/irgKTLMKl7n7mP6XRgBnOf) |
| | | supervisor-password: $2a$10$9lSwwUFMULR6/KhPsUbTj.0PTZfTnq0fB3OtS6PWoKAibpa8hL1cy |
| | | # supervisor-password: $2a$10$9lSwwUFMULR6/KhPsUbTj.0PTZfTnq0fB3OtS6PWoKAibpa8hL1cy |
| | | # 是否允许配置跨域响应头, true 启用, false 不启用。2022-12-28 |
| | | # 在Gateway模式中,需要关闭跨域配置,因为网关也会配置。 |
| | |
| | | ip: 116.198.40.76 |
| | | port: 22 |
| | | user-name: mysftp |
| | | password: ENC(kEQ43JzZv6yOOmbmKNLWmsU/wQKTwA9x) |
| | | password: 123456 |
| | | private-key: |
| | | # ftp服务上面的存储根路径,只能是linux路径 |
| | | file-root: /progress/ |
| | |
| | | # 邮件通知发送信息配置,2023-04-26 |
| | | mail-server: smtp.126.com |
| | | mail-from: hnzzzhsl@126.com |
| | | mail-password: ENC(hjRDRcQmmhpUICkAaJnXUQ==) |
| | | mail-password: 123456 |
| | |
| | | max-open-prepared-statements: 100 |
| | | use-global-data-source-stat: true |
| | | # Redis |
| | | redis: |
| | | host: 192.200.0.49 |
| | | port: 6379 |
| | | database: 11 |
| | | password: ENC(1IxlpqZ3ykMIWVknDjVydrCpK/6nccv/) #Jmy2019. |
| | | |
| | | mvc: |
| | | pathmatch: |
| | | # 加该配置是因为 swagger3 启动报错,2023-02-23 |
| | |
| | | multipart: |
| | | max-file-size: 100MB |
| | | max-request-size: 300MB |
| | | data: |
| | | redis: |
| | | host: 192.200.0.49 |
| | | port: 6379 |
| | | database: 11 |
| | | password: ENC(1IxlpqZ3ykMIWVknDjVydrCpK/6nccv/) |
| | | |
| | | server: |
| | | port: 9301 |
| | |
| | | max-open-prepared-statements: 100 |
| | | use-global-data-source-stat: true |
| | | # Redis |
| | | redis: |
| | | host: 116.198.40.76 |
| | | port: 6379 |
| | | database: 11 |
| | | password: ENC(C40h1dp9Q1oLqdU+JUGSBOWUfOmj/ZO4) #Jmy2019. |
| | | |
| | | mvc: |
| | | pathmatch: |
| | | # 加该配置是因为 swagger3 启动报错,2023-02-23 |
| | |
| | | multipart: |
| | | max-file-size: 100MB |
| | | max-request-size: 300MB |
| | | data: |
| | | redis: |
| | | host: 116.198.40.76 |
| | | port: 6379 |
| | | database: 11 |
| | | password: ENC(C40h1dp9Q1oLqdU+JUGSBOWUfOmj/ZO4) |
| | | |
| | | server: |
| | | port: 8083 |
| | |
| | | spring: |
| | | profiles: |
| | | active: prod |
| | | active: dev |
| | | |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | |
| | | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <parent> |
| | | <artifactId>low-consum-manage</artifactId> |
| | | <groupId>com.consum</groupId> |
| | | <version>1.0.0-SNAPSHOT</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <groupId>com.iplatform</groupId> |
| | | <artifactId>iplatform-base-admin</artifactId> |
| | | <name>iplatform-base-admin</name> |
| | | <packaging>jar</packaging> |
| | | <version>3.2.0</version> |
| | | |
| | | <properties> |
| | | </properties> |
| | | |
| | | <dependencies> |
| | | |
| | | <!-- 基础模块界面管理,只依赖基础模块,运行环境必须提供。2022/11/16 --> |
| | | <dependency> |
| | | <groupId>com.iplatform</groupId> |
| | | <artifactId>iplatform-base</artifactId> |
| | | <scope>provided</scope> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | | |
| | | </project> |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | public class IdUtil { |
| | | |
| | | private static IdUtil instance = new IdUtil(0); |
| | | |
| | | public static IdUtil getInstance() { |
| | | return instance; |
| | | } |
| | | |
| | | public static long generateId() { |
| | | return instance.nextId(); |
| | | } |
| | | |
| | | private final static long MACHINE_BIT = 5; // max 31 |
| | | private final static long SEQUENCE_BIT = 8; // 256/10ms |
| | | |
| | | /** |
| | | * mask/max value |
| | | */ |
| | | private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT); |
| | | private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT); |
| | | |
| | | private final static long MACHINE_LEFT = SEQUENCE_BIT; |
| | | private final static long TIMESTMP_LEFT = MACHINE_BIT + SEQUENCE_BIT; |
| | | |
| | | private long machineId; |
| | | private long sequence = 0L; |
| | | private long lastStmp = -1L; |
| | | |
| | | private IdUtil(long machineId) { |
| | | if (machineId > MAX_MACHINE_NUM || machineId < 0) { |
| | | throw new IllegalArgumentException( |
| | | "machineId can't be greater than " + MAX_MACHINE_NUM + " or less than 0"); |
| | | } |
| | | this.machineId = machineId; |
| | | } |
| | | |
| | | /** |
| | | * generate new ID |
| | | * |
| | | * @return |
| | | */ |
| | | public synchronized long nextId() { |
| | | long currStmp = getTimestamp(); |
| | | if (currStmp < lastStmp) { |
| | | throw new RuntimeException("Clock moved backwards. Refusing to generate id"); |
| | | } |
| | | |
| | | if (currStmp == lastStmp) { |
| | | sequence = (sequence + 1) & MAX_SEQUENCE; |
| | | if (sequence == 0L) { |
| | | currStmp = getNextTimestamp(); |
| | | } |
| | | } else { |
| | | sequence = 0L; |
| | | } |
| | | |
| | | lastStmp = currStmp; |
| | | |
| | | return currStmp << TIMESTMP_LEFT // |
| | | | machineId << MACHINE_LEFT // |
| | | | sequence; |
| | | } |
| | | |
| | | private long getNextTimestamp() { |
| | | long mill = getTimestamp(); |
| | | while (mill <= lastStmp) { |
| | | mill = getTimestamp(); |
| | | } |
| | | return mill; |
| | | } |
| | | |
| | | private long getTimestamp() { |
| | | // per 10ms |
| | | return System.currentTimeMillis() / 10;// 10ms |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.walker.web.UserType; |
| | | |
| | | public class Test1 { |
| | | private UserType userType = UserType.User; |
| | | } |
New file |
| | |
| | | //package com.iplatform.base.config; |
| | | // |
| | | //import com.walker.infrastructure.utils.StringUtils; |
| | | // |
| | | //import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | //import org.springframework.context.annotation.Bean; |
| | | //import org.springframework.context.annotation.Configuration; |
| | | //import org.springframework.context.annotation.Profile; |
| | | //import springfox.documentation.builders.ApiInfoBuilder; |
| | | //import springfox.documentation.builders.PathSelectors; |
| | | //import springfox.documentation.builders.RequestHandlerSelectors; |
| | | //import springfox.documentation.oas.annotations.EnableOpenApi; |
| | | //import springfox.documentation.service.ApiInfo; |
| | | //import springfox.documentation.service.Contact; |
| | | //import springfox.documentation.spi.DocumentationType; |
| | | //import springfox.documentation.spring.web.plugins.ApiSelectorBuilder; |
| | | //import springfox.documentation.spring.web.plugins.Docket; |
| | | // |
| | | //@Configuration |
| | | //@EnableOpenApi |
| | | //@Profile({"dev"}) |
| | | //@ConditionalOnProperty(name = "iplatform.security.swagger.enable", havingValue = "true") |
| | | ////@EnableSwaggerBootstrapUI//访问美化,方便查看调试 |
| | | //public class SwaggerConfig { |
| | | // |
| | | // @Bean |
| | | // public Docket createApi(SwaggerProperties properties) { |
| | | // ApiSelectorBuilder builder = new Docket(DocumentationType.OAS_30).apiInfo(apiInfo(properties)).select(); |
| | | // if(StringUtils.isNotEmpty(properties.getBasePackage())){ |
| | | // // 如果存在包路径,优先使用 |
| | | // builder.apis(RequestHandlerSelectors.basePackage(properties.getBasePackage())); |
| | | // } else { |
| | | // // 没有配置包路径,则查找注解API的文档 |
| | | // builder.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)); |
| | | // } |
| | | // |
| | | // Docket docket = builder.paths(PathSelectors.any()).build(); |
| | | //// docket.globalRequestParameters(getGlobalRequestParameters()); |
| | | //// docket.globalResponses(HttpMethod.POST, getGlobalResonseMessage()); |
| | | // return docket; |
| | | // |
| | | ///* return new Docket(DocumentationType.OAS_30) |
| | | // .apiInfo(apiInfo(properties)) |
| | | // .select() |
| | | // // 指定扫描的包,不指定会扫描出 spring 框架的接口,指定错误会导致接口扫描不出来 |
| | | //// .apis(RequestHandlerSelectors.basePackage(properties.getBasePackage())) |
| | | // .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) |
| | | // .paths(PathSelectors.any()) |
| | | // .build() |
| | | // //加入通用入参 |
| | | //// .globalRequestParameters(getGlobalRequestParameters()) |
| | | // //post方法加入通用响应头 |
| | | //// .globalResponses(HttpMethod.POST, getGlobalResonseMessage()) |
| | | // ;*/ |
| | | // } |
| | | // |
| | | // @Bean |
| | | // public SwaggerProperties swaggerProperties(){ |
| | | // return new SwaggerProperties(); |
| | | // } |
| | | // |
| | | // private ApiInfo apiInfo(SwaggerProperties swaggerProperties) { |
| | | // return new ApiInfoBuilder() |
| | | // .title(swaggerProperties.getTitle()) |
| | | // .description(swaggerProperties().getDescription()) |
| | | // .contact(new Contact("时克英", "https://www.baidu.com", "28914843@qq.com")) |
| | | // .version("2.0") |
| | | // .build(); |
| | | // } |
| | | //} |
New file |
| | |
| | | //package com.iplatform.base.config; |
| | | // |
| | | //import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | // |
| | | //@ConfigurationProperties(prefix = "iplatform.swagger") |
| | | //public class SwaggerProperties { |
| | | // |
| | | // public String getBasePackage() { |
| | | // return basePackage; |
| | | // } |
| | | // |
| | | // public void setBasePackage(String basePackage) { |
| | | // this.basePackage = basePackage; |
| | | // } |
| | | // |
| | | // public String getTitle() { |
| | | // return title; |
| | | // } |
| | | // |
| | | // public void setTitle(String title) { |
| | | // this.title = title; |
| | | // } |
| | | // |
| | | // public String getDescription() { |
| | | // return description; |
| | | // } |
| | | // |
| | | // public void setDescription(String description) { |
| | | // this.description = description; |
| | | // } |
| | | // |
| | | // private String basePackage; |
| | | // private String title; |
| | | // private String description; |
| | | //} |
New file |
| | |
| | | package com.iplatform.base.controller; |
| | | |
| | | import com.iplatform.base.SystemController; |
| | | import com.iplatform.base.service.ApiTimeServiceImpl; |
| | | import com.iplatform.model.vo.ApiTime; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.web.ResponseValue; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.List; |
| | | |
| | | @RestController |
| | | @RequestMapping("/test/api") |
| | | public class ApiTimeController extends SystemController { |
| | | |
| | | private ApiTimeServiceImpl apiTimeService; |
| | | |
| | | @Autowired |
| | | public ApiTimeController(ApiTimeServiceImpl apiTimeService){ |
| | | this.apiTimeService = apiTimeService; |
| | | } |
| | | |
| | | /** |
| | | * 查询接口调用时间记录 |
| | | * @param currentDate 当前日期,如:20240229(可选) |
| | | * @param maxSize 限制返回记录最大条数,如:200(可选) |
| | | * @param cost 条件:最小花费时间,毫秒,超过该时间的记录,如:200(可选) |
| | | * @return |
| | | */ |
| | | @RequestMapping("/time") |
| | | public ResponseValue getCostMostList(String currentDate, String cost, String maxSize){ |
| | | Integer dateValue = null; |
| | | Integer maxSizeValue = null; |
| | | Long costValue = null; |
| | | if(StringUtils.isNotEmpty(currentDate)){ |
| | | dateValue = Integer.parseInt(currentDate); |
| | | } |
| | | if(StringUtils.isNotEmpty(maxSize)){ |
| | | maxSizeValue = Integer.parseInt(maxSize); |
| | | } |
| | | if(StringUtils.isNotEmpty(cost)){ |
| | | costValue = Long.parseLong(cost); |
| | | } |
| | | List<ApiTime> data = this.apiTimeService.queryCostList(dateValue, maxSizeValue, costValue); |
| | | return ResponseValue.success(data); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.controller; |
| | | |
| | | import com.iplatform.base.SystemController; |
| | | import com.iplatform.base.VariableConstants; |
| | | import com.iplatform.base.config.CacheProperties; |
| | | import com.iplatform.base.util.cache.CacheInfo; |
| | | import com.walker.cache.CacheProvider; |
| | | import com.walker.cache.SimpleCacheManager; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.web.ResponseValue; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.data.redis.core.RedisCallback; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Collection; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Properties; |
| | | |
| | | @RestController |
| | | @RequestMapping("/monitor/cache") |
| | | @ConditionalOnProperty(prefix = "iplatform.cache", name = "redis-enabled", havingValue = "true", matchIfMissing = false) |
| | | public class CacheController extends SystemController { |
| | | |
| | | private RedisTemplate<String, Object> redisTemplate; |
| | | private CacheProperties cacheProperties; |
| | | |
| | | @Autowired(required = false) |
| | | public CacheController(RedisTemplate<String, Object> redisTemplate, CacheProperties cacheProperties){ |
| | | this.redisTemplate = redisTemplate; |
| | | this.cacheProperties = cacheProperties; |
| | | } |
| | | |
| | | @RequestMapping("/clearCacheName") |
| | | public ResponseValue clearCacheName(String name){ |
| | | if(StringUtils.isEmpty(name)){ |
| | | return ResponseValue.error("必须指定缓存名称"); |
| | | } |
| | | CacheProvider<?> cacheProvider = SimpleCacheManager.getCacheProvider(name); |
| | | if(cacheProvider == null){ |
| | | return ResponseValue.error("缓存对象不存在"); |
| | | } |
| | | try { |
| | | cacheProvider.reload(); |
| | | return ResponseValue.success("缓存重新加载成功"); |
| | | } catch (Exception e) { |
| | | logger.error("重新加载缓存失败:" + e.getMessage(), e); |
| | | return ResponseValue.error("重新加载缓存失败:" + name); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 清空 系统缓存,该功能主要对 Redis 缓存方式,通过手动触发重构缓存,在开发阶段使用。 |
| | | * @return |
| | | * @date 2023-08-26 |
| | | */ |
| | | @RequestMapping("/clearCacheAll") |
| | | public ResponseValue reloadAllCacheProvider(){ |
| | | if(!this.cacheProperties.isRedisRebuild()){ |
| | | return ResponseValue.error("未开启'重构缓存'选项"); |
| | | } |
| | | |
| | | // 2023-08-26 开启了重建redis缓存选项 |
| | | Collection<CacheProvider<?>> cacheList = SimpleCacheManager.getCacheProviders(); |
| | | if(cacheList != null && cacheList.size() > 0){ |
| | | String name = null; |
| | | try{ |
| | | for(CacheProvider<?> cacheProvider : cacheList){ |
| | | name = cacheProvider.getProviderName(); |
| | | cacheProvider.reload(); |
| | | } |
| | | } catch (Exception ex){ |
| | | logger.error("重新加载所有缓存,出现异常:" + ex.getMessage() + ", name=" + name, ex); |
| | | return ResponseValue.error("重新加载缓存,出现错误,name = " + name); |
| | | } |
| | | } |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @RequestMapping("/getInfo") |
| | | public ResponseValue getInfo(){ |
| | | if(this.redisTemplate == null){ |
| | | return ResponseValue.error("系统未开启Redis方式缓存"); |
| | | } |
| | | |
| | | Properties info = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info()); |
| | | // Properties commandStats = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info("commandstats")); |
| | | Object dbSize = redisTemplate.execute((RedisCallback<Object>) connection -> connection.dbSize()); |
| | | |
| | | Map<String, Object> result = new HashMap<>(3); |
| | | result.put("info", info); |
| | | result.put("dbSize", dbSize); |
| | | result.put("commandStats", new ArrayList<>()); |
| | | |
| | | return ResponseValue.success(result); |
| | | } |
| | | |
| | | /** |
| | | * 返回缓存对象名称列表,即:系统所有缓存定义名称集合 |
| | | * @return |
| | | * @date 2023-01-04 |
| | | */ |
| | | @GetMapping("/select/getNames") |
| | | public ResponseValue getCacheNames(){ |
| | | List<CacheInfo> cacheNames = new ArrayList<>(); |
| | | Collection<CacheProvider<?>> cacheList = SimpleCacheManager.getCacheProviders(); |
| | | if(cacheList != null && cacheList.size() > 0){ |
| | | for(CacheProvider<?> cacheProvider : cacheList){ |
| | | cacheNames.add(new CacheInfo(cacheProvider.getProviderName(), cacheProvider.getProviderType().getName())); |
| | | } |
| | | } |
| | | return ResponseValue.success(cacheNames); |
| | | } |
| | | |
| | | @GetMapping("/select/getKeys/{cacheName}") |
| | | public ResponseValue getCacheKeys(@PathVariable String cacheName){ |
| | | if(StringUtils.isEmpty(cacheName)){ |
| | | return ResponseValue.error("参数错误"); |
| | | } |
| | | List<String> keyList = new ArrayList<>((int) VariableConstants.MAX_CACHE_SHOW); |
| | | CacheProvider<?> cacheProvider = SimpleCacheManager.getCacheProvider(cacheName); |
| | | if(cacheProvider != null){ |
| | | if(cacheProvider.getCache().getPersistentSize() <= VariableConstants.MAX_CACHE_SHOW){ |
| | | // Cachable cachable = null; |
| | | // for(Iterator<Cachable> it = cacheProvider.getCache().getIterator(); it.hasNext();){ |
| | | // cachable = it.next(); |
| | | // keyList.add(cachable.getKey()); |
| | | // } |
| | | return ResponseValue.success(cacheProvider.getCache().getKeys()); |
| | | } else { |
| | | return ResponseValue.error("缓存数据量超过 " + VariableConstants.MAX_CACHE_SHOW + ", 暂无法显示"); |
| | | } |
| | | } |
| | | return ResponseValue.success(keyList); |
| | | } |
| | | |
| | | @GetMapping("/select/getValue/{cacheName}/{cacheKey}") |
| | | public ResponseValue getOneCacheValue(@PathVariable String cacheName, @PathVariable String cacheKey){ |
| | | CacheProvider<?> cacheProvider = SimpleCacheManager.getCacheProvider(cacheName); |
| | | if(cacheProvider != null){ |
| | | Object value = cacheProvider.getCacheData(cacheKey); |
| | | CacheInfo cacheInfo = new CacheInfo(cacheName, cacheKey, value.toString()); |
| | | return ResponseValue.success(cacheInfo); |
| | | } |
| | | return ResponseValue.success(); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.controller; |
| | | |
| | | import com.iplatform.base.CategoryCacheProvider; |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.PlatformAdapterController; |
| | | import com.iplatform.base.cache.FormCacheProvider; |
| | | import com.iplatform.base.service.CategoryServiceImpl; |
| | | import com.iplatform.model.po.S_category; |
| | | import com.iplatform.model.vo.CategoryTreeVo; |
| | | import com.walker.infrastructure.utils.DateUtils; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.web.ResponseValue; |
| | | import com.walker.web.WebRuntimeException; |
| | | // |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RequestMethod; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 平台端基础分类服务 |
| | | * @date 2023-05-15 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/system/category") |
| | | public class CategoryController extends PlatformAdapterController { |
| | | |
| | | private CategoryServiceImpl categoryService; |
| | | private CategoryCacheProvider categoryCacheProvider; |
| | | private FormCacheProvider formCacheProvider; |
| | | |
| | | @Autowired |
| | | public CategoryController(CategoryServiceImpl categoryService |
| | | , CategoryCacheProvider categoryCacheProvider, FormCacheProvider formCacheProvider){ |
| | | this.categoryService = categoryService; |
| | | this.categoryCacheProvider = categoryCacheProvider; |
| | | this.formCacheProvider = formCacheProvider; |
| | | } |
| | | |
| | | @RequestMapping("/list/tree") |
| | | public ResponseValue getListTree(@RequestParam(name = "type") Integer type, |
| | | @RequestParam(name = "status") Integer status, |
| | | @RequestParam(name = "name", required = false) String name) { |
| | | int owner = (int)this.getOwner(); |
| | | // return ResponseValue.success(this.categoryService.getListTree(type, status, name, owner)); |
| | | // 2023-05-18 表加上关联表单名称。 |
| | | List<CategoryTreeVo> data = this.categoryCacheProvider.getListTree(type, status, name, owner); |
| | | if(!StringUtils.isEmptyList(data)){ |
| | | data.stream().forEach(e -> { |
| | | if(e.getType().intValue() == Constants.CATEGORY_TYPE_CONFIG && StringUtils.isNotEmpty(e.getExtra())){ |
| | | // 平台配置分类,extra存储的是formId |
| | | e.setFormName(this.formCacheProvider.getCacheData(e.getExtra()).getName()); |
| | | if(!StringUtils.isEmptyList(e.getChild())){ |
| | | for(CategoryTreeVo child : e.getChild()){ |
| | | if(StringUtils.isNotEmpty(child.getExtra())){ |
| | | child.setFormName(this.formCacheProvider.getCacheData(child.getExtra()).getName()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | return ResponseValue.success(data); |
| | | } |
| | | |
| | | @RequestMapping(value = "/info/{id}", method = RequestMethod.GET) |
| | | public ResponseValue getInfo(@PathVariable(value = "id") Integer id){ |
| | | S_category category = this.categoryCacheProvider.get(id); |
| | | if(category == null){ |
| | | throw new WebRuntimeException("分类不存在"); |
| | | } |
| | | return ResponseValue.success(category); |
| | | } |
| | | |
| | | // // @ApiOperation(value = "新增基础分类") |
| | | @RequestMapping(value = "/save", method = RequestMethod.POST) |
| | | public ResponseValue save(@RequestBody S_category category){ |
| | | if(category == null){ |
| | | return ResponseValue.error("提交内容错误"); |
| | | } |
| | | logger.debug(category.toString()); |
| | | |
| | | if(this.categoryService.queryNameUnique(category.getName(), category.getType(), (int)this.getOwner(), 0) > 0){ |
| | | return ResponseValue.error("相同分类已经存在"); |
| | | } |
| | | |
| | | long dateTime = DateUtils.getDateTimeNumber(); |
| | | int id = this.categoryService.queryNextId(); |
| | | |
| | | category.setId(id); |
| | | category.setPath(this.getPathByPId(category.getPid())); |
| | | category.setOwner((int)this.getOwner()); |
| | | category.setExtra(this.clearCdnPrefix(category.getExtra())); // 这里额外保存的可能是文件路径信息,清除了前缀。 |
| | | category.setCreate_time(dateTime); |
| | | category.setUpdate_time(dateTime); |
| | | this.categoryService.insert(category); |
| | | this.categoryCacheProvider.save(category); |
| | | |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | // // @ApiOperation(value = "修改基础分类") |
| | | @RequestMapping(value = "/update", method = RequestMethod.POST) |
| | | public ResponseValue update(@RequestBody S_category category){ |
| | | if(category == null || category.getId() <= 0){ |
| | | throw new WebRuntimeException("分类参数错误"); |
| | | } |
| | | S_category exist = this.categoryCacheProvider.get(category.getId()); |
| | | if(exist == null){ |
| | | throw new WebRuntimeException("分类数据不存在,id=" + category.getId()); |
| | | } |
| | | if(exist.getId().intValue() == category.getPid()){ |
| | | throw new WebRuntimeException("分类父级不能是自己"); |
| | | } |
| | | if(!exist.getName().equals(category.getName())){ |
| | | if(this.categoryService.queryNameUnique(category.getName(), category.getType(), (int)this.getOwner(), exist.getId()) > 0){ |
| | | return ResponseValue.error("分类名称重复"); |
| | | } |
| | | } |
| | | |
| | | if(StringUtils.isNotEmpty(category.getExtra())){ |
| | | category.setExtra(this.clearCdnPrefix(category.getExtra())); |
| | | } |
| | | category.setPath(this.getPathByPId(category.getPid())); |
| | | category.setOwner((int)this.getOwner()); |
| | | category.setUpdate_time(DateUtils.getDateTimeNumber()); |
| | | this.categoryService.execUpdateCategory(category); |
| | | this.categoryCacheProvider.update(category); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @RequestMapping("/delete") |
| | | public ResponseValue delete(Integer id){ |
| | | // S_category category = this.categoryCacheProvider.get(id); |
| | | if(this.categoryService.queryChildCategorySize(id) > 0){ |
| | | return ResponseValue.error("当前分类下有子类,请先删除子类!"); |
| | | } |
| | | this.categoryService.delete(new S_category(id)); |
| | | this.categoryCacheProvider.remove(id); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | private String getPathByPId(Integer pid) { |
| | | S_category category = this.categoryCacheProvider.get(pid); |
| | | if (category != null) { |
| | | return category.getPath() + pid + StringUtils.FOLDER_SEPARATOR; |
| | | } |
| | | return "/0/"; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.controller; |
| | | |
| | | import com.iplatform.base.SystemController; |
| | | import com.iplatform.base.pojo.dict.DictParam; |
| | | import com.iplatform.base.service.CodeServiceImpl; |
| | | import com.iplatform.model.po.S_dict_data; |
| | | import com.iplatform.model.po.S_dict_type; |
| | | import com.iplatform.model.po.S_user_core; |
| | | import com.walker.db.page.GenericPager; |
| | | import com.walker.infrastructure.utils.DateUtils; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.web.DataStatus; |
| | | import com.walker.web.ResponseValue; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | @RestController |
| | | @RequestMapping("/system/dict") |
| | | public class CodeController extends SystemController { |
| | | |
| | | private CodeServiceImpl codeService; |
| | | |
| | | @Autowired |
| | | public CodeController(CodeServiceImpl codeService){ |
| | | this.codeService = codeService; |
| | | } |
| | | |
| | | /** 类型列表 */ |
| | | @RequestMapping("/type/list") |
| | | public ResponseValue listType(DictParam dictParam){ |
| | | logger.debug(dictParam.toString()); |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | // 需要添加拦截器,统一销毁线程变量对象,马上要补充,2022-11-19 |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | // this.preparePageSearch(); |
| | | |
| | | long beginTime = -1; |
| | | long endTime = -1; |
| | | if(dictParam.getParams().get("beginTime") != null){ |
| | | beginTime = this.getParamsDateTime(dictParam.getParams().get("beginTime").toString(), false); |
| | | } |
| | | if(dictParam.getParams().get("endTime") != null){ |
| | | endTime = this.getParamsDateTime(dictParam.getParams().get("endTime").toString(), false); |
| | | } |
| | | logger.debug("beginTime = " + beginTime + ", endTime = " + endTime); |
| | | |
| | | GenericPager<S_dict_type> pager = this.codeService.queryPageDictType(dictParam.getDictName() |
| | | , dictParam.getDictType(), dictParam.getStatus(), beginTime, endTime); |
| | | // return this.acquireTablePage(pager.getDatas(), pager.getTotalRows()); |
| | | return ResponseValue.success(pager); |
| | | } |
| | | |
| | | /** 新增类型 */ |
| | | @PostMapping("/type/add") |
| | | public ResponseValue<?> addType(@RequestBody DictParam dictParam){ |
| | | S_user_core currentUser = getCurrentUser(); |
| | | S_dict_type byDictType = codeService.getByDictType(dictParam.getDictType()); |
| | | if (byDictType != null) { |
| | | return ResponseValue.error("字典类型[" + byDictType.getDict_type() + "] 已存在!"); |
| | | } |
| | | S_dict_type dictType = new S_dict_type(); |
| | | dictType.setDict_type(dictParam.getDictType()); |
| | | dictType.setDict_name(dictParam.getDictName()); |
| | | if (dictParam.getStatus() == null) { |
| | | dictType.setStatus(DataStatus.CONST_NORMAL); |
| | | } else { |
| | | dictType.setStatus(dictParam.getStatus()); |
| | | } |
| | | if (currentUser != null) { |
| | | dictType.setCreate_by(currentUser.getUser_name()); |
| | | dictType.setCreate_time(DateUtils.getDateTimeNumber()); |
| | | } |
| | | dictType.setRemark(dictParam.getRemark()); |
| | | this.codeService.save(dictType); |
| | | return ResponseValue.success(null); |
| | | } |
| | | |
| | | /** 类型修改 */ |
| | | @PostMapping("/type/upd") |
| | | public ResponseValue<?> updType(@RequestBody DictParam dictParam){ |
| | | S_dict_type dictType = new S_dict_type(); |
| | | dictType.setDict_id(dictParam.getDict_id()); |
| | | dictType.setDict_name(dictParam.getDictName()); |
| | | dictType.setStatus(dictParam.getStatus()); |
| | | dictType.setRemark(dictParam.getRemark()); |
| | | this.codeService.update(dictType); |
| | | return ResponseValue.success(null); |
| | | } |
| | | |
| | | /** 类型删除 */ |
| | | @DeleteMapping("/type/del") |
| | | public ResponseValue<?> delType(@RequestBody DictParam dictParam) { |
| | | this.codeService.execDelType(dictParam.getDict_id()); |
| | | return ResponseValue.success(null); |
| | | } |
| | | |
| | | /** 类型详情 */ |
| | | @RequestMapping("/type/{dictId}") |
| | | public ResponseValue detailDictType(@PathVariable Long dictId){ |
| | | if(dictId == null || dictId.longValue() <= 0){ |
| | | return ResponseValue.error("字典id错误"); |
| | | } |
| | | return ResponseValue.success(this.codeService.queryOneDictType(dictId)); |
| | | } |
| | | |
| | | /** |
| | | * 在数据字典项管理界面,查询条件展示所有'字典类型'列表。<p></p> |
| | | * 因为权限配置的是: /system/dict/data/** 开放,因此该权限也配置到data,否则还需要再加上一个权限点。 |
| | | * @return |
| | | * @date 2022-11-19 |
| | | */ |
| | | // @GetMapping("/type/optionselect") |
| | | @GetMapping("/data/optionselect") |
| | | public ResponseValue showDictTypeListAll(){ |
| | | List<S_dict_type> list = this.codeService.selectAll(new S_dict_type()); |
| | | return ResponseValue.success(list); |
| | | } |
| | | |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~` |
| | | |
| | | /** |
| | | * 根据代码表名字,查询包含的代码项集合。 |
| | | * @param dictType |
| | | * @return |
| | | */ |
| | | @RequestMapping("/data/type/{dictType}") |
| | | public ResponseValue<List<S_dict_data>> dictTypeList(@PathVariable String dictType){ |
| | | logger.debug("dictType = " + dictType); |
| | | List<S_dict_data> list = this.codeService.queryDictDataByType(dictType); |
| | | if(StringUtils.isEmptyList(list)){ |
| | | list = new ArrayList<S_dict_data>(2); |
| | | } |
| | | return ResponseValue.success(list); |
| | | } |
| | | |
| | | /** 字典数据列表 */ |
| | | @RequestMapping("/data/list") |
| | | public ResponseValue listData(DictParam dictParam){ |
| | | // this.preparePageSearch(); |
| | | if(StringUtils.isEmpty(dictParam.getDictType())){ |
| | | return ResponseValue.error("必须提供字典类型参数"); |
| | | } |
| | | GenericPager<S_dict_data> pager = this.codeService.queryPageDictData(dictParam.getDictType(), dictParam.getDictLabel()); |
| | | // return this.acquireTablePage(pager.getDatas(), pager.getTotalRows()); |
| | | return ResponseValue.success(pager); |
| | | } |
| | | |
| | | /** 字典数据新增 */ |
| | | @PostMapping("/add") |
| | | public ResponseValue<?> addDictData(@RequestBody S_dict_data s_dict_data){ |
| | | logger.debug(s_dict_data.toString()); |
| | | // if(s_dict_data.getDict_code() == null){ |
| | | // return ResponseValue.error("字典id必须输入!"); |
| | | // } |
| | | if(s_dict_data.getParent_id() == null){ |
| | | return ResponseValue.error("父id必须输入!"); |
| | | } |
| | | S_dict_data dict_data = this.getDictCacheProvider().getCacheData(String.valueOf(s_dict_data.getDict_code())); |
| | | if(dict_data != null){ |
| | | return ResponseValue.error("字典id已存在!"); |
| | | } |
| | | String error = this.validateDictData(s_dict_data, true); |
| | | if(error != null){ |
| | | return ResponseValue.error(error); |
| | | } |
| | | s_dict_data.setIs_default("N"); |
| | | if(StringUtils.isEmpty(s_dict_data.getDict_value())){ |
| | | // 字典值如果不填,必须和id一致 |
| | | s_dict_data.setDict_value(String.valueOf(s_dict_data.getDict_code())); |
| | | } |
| | | // s_dict_data.setDict_code(NumberGenerator.getSequenceNumber()); |
| | | s_dict_data.setCreate_time(DateUtils.getDateTimeNumber(System.currentTimeMillis())); |
| | | |
| | | this.codeService.save(s_dict_data); |
| | | this.getDictCacheProvider().putCacheData(String.valueOf(s_dict_data.getDict_code()), s_dict_data); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | |
| | | /** 字典数据详情 */ |
| | | @RequestMapping("/data/{dictCode}") |
| | | public ResponseValue getDictDataInfo(@PathVariable Long dictCode){ |
| | | S_dict_data e = this.codeService.queryOneDictData(dictCode); |
| | | return ResponseValue.success(e); |
| | | } |
| | | |
| | | /** 字典数据修改 */ |
| | | @RequestMapping("/edit") |
| | | public ResponseValue updateDictData(@RequestBody S_dict_data s_dict_data){ |
| | | String error = this.validateDictData(s_dict_data, false); |
| | | if(error != null){ |
| | | return ResponseValue.error(error); |
| | | } |
| | | this.codeService.save(s_dict_data); |
| | | this.getDictCacheProvider().updateCacheData(String.valueOf(s_dict_data.getDict_code()), s_dict_data); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | /** 字典数据删除 */ |
| | | @RequestMapping("/data/remove/{dictCodes}") |
| | | public ResponseValue removeDictData(@PathVariable Long[] dictCodes){ |
| | | this.codeService.execDeleteDictData(dictCodes); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | /** |
| | | * 校验 |
| | | * @param s_dict_data 数据 |
| | | * @param checkExist 是否检查存在 |
| | | * @return 错误信息 |
| | | */ |
| | | private String validateDictData(S_dict_data s_dict_data, boolean checkExist){ |
| | | if(s_dict_data == null){ |
| | | return "提交字典内容为空"; |
| | | } |
| | | if(StringUtils.isEmpty(s_dict_data.getDict_type())){ |
| | | return "请选择字典类型"; |
| | | } |
| | | if(StringUtils.isEmpty(s_dict_data.getDict_label())){ |
| | | return "请输入字典标签"; |
| | | } |
| | | // if(StringUtils.isEmpty(s_dict_data.getDict_value())){ |
| | | // return "请输入字典值"; |
| | | // } |
| | | |
| | | if(checkExist){ |
| | | S_dict_data exist = this.codeService.queryOneDictData(s_dict_data.getDict_type(), s_dict_data.getDict_value()); |
| | | if(exist != null){ |
| | | return "已经存在该字典值,请重新输入"; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.controller; |
| | | |
| | | import com.iplatform.base.SystemController; |
| | | import com.iplatform.base.cache.FormCacheProvider; |
| | | import com.iplatform.base.pojo.ConfigParam; |
| | | import com.iplatform.base.pojo.form.FormData; |
| | | import com.iplatform.base.pojo.form.FormDataItem; |
| | | import com.iplatform.base.service.ConfigArgumentServiceImpl; |
| | | import com.iplatform.model.po.S_config; |
| | | import com.walker.db.page.GenericPager; |
| | | import com.walker.infrastructure.arguments.ArgumentsManager; |
| | | import com.walker.infrastructure.arguments.Variable; |
| | | import com.walker.infrastructure.utils.DateUtils; |
| | | import com.walker.infrastructure.utils.NumberGenerator; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.web.ResponseValue; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RequestMethod; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | |
| | | @RestController |
| | | @RequestMapping("/system/config") |
| | | public class ConfigController extends SystemController { |
| | | |
| | | private ConfigArgumentServiceImpl configArgumentService; |
| | | |
| | | private ArgumentsManager argumentsManager = null; |
| | | private FormCacheProvider formCacheProvider; |
| | | |
| | | @Autowired |
| | | public ConfigController(ConfigArgumentServiceImpl configArgumentService |
| | | , ArgumentsManager argumentsManager, FormCacheProvider formCacheProvider){ |
| | | this.configArgumentService = configArgumentService; |
| | | this.argumentsManager = argumentsManager; |
| | | this.formCacheProvider = formCacheProvider; |
| | | } |
| | | |
| | | @RequestMapping("/list") |
| | | public ResponseValue list(ConfigParam configParam){ |
| | | // this.preparePageSearch(); |
| | | GenericPager<S_config> pager = this.configArgumentService.queryPageConfigList(configParam.getConfigName() |
| | | , configParam.getConfigKey(), configParam.getConfigType()); |
| | | // return this.acquireTablePage(pager.getDatas(), pager.getTotalRows()); |
| | | // 缓存前端封装的table组件,可以直接返回分页对象。2023-04-11 |
| | | return ResponseValue.success(pager); |
| | | } |
| | | |
| | | @RequestMapping("/view/{configId}") |
| | | public ResponseValue view(@PathVariable Long configId){ |
| | | if(configId == null || configId.longValue() <= 0){ |
| | | return ResponseValue.error("config id required!"); |
| | | } |
| | | S_config s_config = this.configArgumentService.get(new S_config(configId)); |
| | | return ResponseValue.success(s_config); |
| | | } |
| | | |
| | | @RequestMapping("/edit") |
| | | public ResponseValue saveEdit(@RequestBody S_config s_config){ |
| | | S_config exist = this.configArgumentService.get(new S_config(s_config.getConfig_id())); |
| | | if(exist == null){ |
| | | return ResponseValue.error("配置项不存在: " + s_config.getConfig_id()); |
| | | } |
| | | this.configArgumentService.save(s_config); |
| | | this.argumentsManager.persist(s_config.getConfig_key(), s_config.getConfig_value()); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | /** |
| | | * 添加保存新配置项。 |
| | | * @param s_config |
| | | * @return |
| | | */ |
| | | @RequestMapping("/add") |
| | | public ResponseValue saveAdd(@RequestBody S_config s_config){ |
| | | if(s_config == null || StringUtils.isEmpty(s_config.getConfig_key())){ |
| | | return ResponseValue.error("提交配置数据错误"); |
| | | } |
| | | S_config exist = this.configArgumentService.queryConfigByKey(s_config.getConfig_key()); |
| | | if(exist != null){ |
| | | return ResponseValue.error("配置项已经存在: " + s_config.getConfig_key()); |
| | | } |
| | | s_config.setConfig_id(NumberGenerator.getSequenceNumber()); |
| | | s_config.setCreate_time(DateUtils.getDateTimeNumber(System.currentTimeMillis())); |
| | | this.configArgumentService.insert(s_config); |
| | | this.argumentsManager.persist(s_config.getConfig_key(), s_config.getConfig_value()); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | //~ 2023-05-16 新界面使用,电商系统。 |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | /** |
| | | * 获得一个唯一配置项的值。 |
| | | * @param key |
| | | * @return |
| | | * @date 2023-05-15 |
| | | */ |
| | | @RequestMapping(value = "/getuniq", method = RequestMethod.GET) |
| | | public ResponseValue getConfigValue(@RequestParam String key){ |
| | | String configValue = this.getArgumentVariable(key).getStringValue(); |
| | | return ResponseValue.success("success", configValue); |
| | | } |
| | | |
| | | /** |
| | | * 根据formId(分组)获得包含的所有配置项集合,包括:key,value |
| | | * @param formId |
| | | * @return |
| | | * @date 2023-05-16 |
| | | */ |
| | | @RequestMapping(value = "/info", method = RequestMethod.GET) |
| | | public ResponseValue info(@RequestParam(value = "formId") Integer formId){ |
| | | if(formId == null){ |
| | | return ResponseValue.error("参数错误"); |
| | | } |
| | | List<Variable> list = this.argumentsManager.getVariableList(String.valueOf(formId)); |
| | | if(StringUtils.isEmptyList(list)){ |
| | | return ResponseValue.success(new HashMap<>(1)); |
| | | } |
| | | |
| | | HashMap<String, String> map = new HashMap<>(8); |
| | | for (Variable systemConfig : list) { |
| | | map.put(systemConfig.getId(), systemConfig.getStringValue()); |
| | | } |
| | | map.put("id", formId.toString()); |
| | | |
| | | if(this.logger.isDebugEnabled()){ |
| | | this.logger.debug(map.toString()); |
| | | } |
| | | return ResponseValue.success(map); |
| | | } |
| | | |
| | | @RequestMapping(value = "/save/form", method = RequestMethod.POST) |
| | | public ResponseValue saveFormConfig(@RequestBody FormData formData){ |
| | | if(formData == null || formData.getId() == null || StringUtils.isEmptyList(formData.getFields())){ |
| | | return ResponseValue.error("参数错误"); |
| | | } |
| | | try{ |
| | | this.formCacheProvider.validateForm(formData); |
| | | } catch (Exception ex){ |
| | | return ResponseValue.error("表单配置数据格式错误:" + ex.getMessage()); |
| | | } |
| | | |
| | | List<Object[]> savedConfigList = new ArrayList<>(8); |
| | | Object[] config = null; |
| | | String value = null; |
| | | for(FormDataItem formDataItem : formData.getFields()){ |
| | | value = this.clearCdnPrefix(formDataItem.getValue()); |
| | | if(StringUtils.isEmpty(value)){ |
| | | // 去掉图片域名之后没有数据则说明当前数据就是图片域名 |
| | | logger.debug("配置的值是:图片域名," + formDataItem.getValue()); |
| | | value = formDataItem.getValue(); |
| | | } |
| | | config = new Object[2]; |
| | | config[0] = value; |
| | | config[1] = formDataItem.getName(); |
| | | savedConfigList.add(config); |
| | | } |
| | | |
| | | // 多个配置项同时更新 |
| | | this.configArgumentService.execUpdateFormConfig(savedConfigList); |
| | | for(Object[] one : savedConfigList){ |
| | | this.argumentsManager.persist(one[1].toString(), one[0]); |
| | | } |
| | | return ResponseValue.success(); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.controller; |
| | | |
| | | import com.iplatform.base.PlatformAdapterController; |
| | | import com.iplatform.base.PlatformRuntimeException; |
| | | import com.iplatform.base.cache.FormCacheProvider; |
| | | import com.iplatform.base.pojo.KeywordsParam; |
| | | import com.iplatform.base.pojo.form.RequestForm; |
| | | import com.iplatform.base.service.ConfigFormServiceImpl; |
| | | import com.iplatform.model.po.S_config_form; |
| | | import com.iplatform.model.vo.ConfigFormVo; |
| | | import com.walker.db.page.GenericPager; |
| | | import com.walker.infrastructure.utils.DateUtils; |
| | | import com.walker.infrastructure.utils.JsonUtils; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.infrastructure.utils.UrlUtils; |
| | | import com.walker.web.ResponseValue; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RequestMethod; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | /** |
| | | * 配置表单管理功能。 |
| | | * @author 时克英 |
| | | * @date 2023-05-16 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/system/form") |
| | | public class ConfigFormController extends PlatformAdapterController { |
| | | |
| | | private ConfigFormServiceImpl configFormService; |
| | | private FormCacheProvider formCacheProvider; |
| | | |
| | | @Autowired |
| | | public ConfigFormController(ConfigFormServiceImpl configFormService, FormCacheProvider formCacheProvider){ |
| | | this.configFormService = configFormService; |
| | | this.formCacheProvider = formCacheProvider; |
| | | } |
| | | |
| | | @RequestMapping(value = "/update", method = RequestMethod.POST) |
| | | public ResponseValue edit(@RequestParam Integer id, @RequestBody RequestForm requestForm){ |
| | | if(requestForm == null || StringUtils.isEmpty(requestForm.getContent()) || id == null){ |
| | | return ResponseValue.error("参数错误"); |
| | | } |
| | | |
| | | try { |
| | | JsonUtils.jsonStringToObject(requestForm.getContent(), ConfigFormVo.class); |
| | | S_config_form form = this.acquireConfigForm(requestForm, id); |
| | | this.configFormService.save(form); |
| | | this.formCacheProvider.updateCacheData(String.valueOf(form.getId()), form); |
| | | logger.info("编辑表单模板成功:" + requestForm.getName()); |
| | | |
| | | } catch (Exception e) { |
| | | logger.error(requestForm.getContent()); |
| | | throw new PlatformRuntimeException("更新表单模板格式不正确:" + e.getMessage(), e); |
| | | } |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | /** |
| | | * 保存新创建表单模板。 |
| | | * @param requestForm |
| | | * @return |
| | | * @date 2023-05-23 |
| | | */ |
| | | @RequestMapping(value = "/save", method = RequestMethod.POST) |
| | | public ResponseValue add(@RequestBody RequestForm requestForm){ |
| | | if(requestForm == null || StringUtils.isEmpty(requestForm.getContent())){ |
| | | return ResponseValue.error("参数错误"); |
| | | } |
| | | try { |
| | | JsonUtils.jsonStringToObject(requestForm.getContent(), ConfigFormVo.class); |
| | | // S_config_form form = new S_config_form(); |
| | | // form.setName(requestForm.getName()); |
| | | // form.setInfo(requestForm.getInfo()); |
| | | // form.setContent(requestForm.getContent()); |
| | | // form.setCreate_time(DateUtils.getDateTimeNumber()); |
| | | // form.setUpdate_time(form.getCreate_time()); |
| | | // form.setId(this.configFormService.queryNextId()); |
| | | S_config_form form = this.acquireConfigForm(requestForm, this.configFormService.queryNextId()); |
| | | this.configFormService.insert(form); |
| | | this.formCacheProvider.putCacheData(String.valueOf(form.getId()), form); |
| | | logger.info("创建表单模板成功:" + requestForm.getName()); |
| | | |
| | | } catch (Exception e) { |
| | | logger.error(requestForm.getContent()); |
| | | throw new PlatformRuntimeException("创建的表单模板格式不正确:" + e.getMessage(), e); |
| | | } |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | private S_config_form acquireConfigForm(RequestForm requestForm, int id){ |
| | | S_config_form form = new S_config_form(); |
| | | form.setName(requestForm.getName()); |
| | | form.setInfo(requestForm.getInfo()); |
| | | form.setContent(requestForm.getContent()); |
| | | form.setCreate_time(DateUtils.getDateTimeNumber()); |
| | | form.setUpdate_time(form.getCreate_time()); |
| | | form.setId(id); |
| | | return form; |
| | | } |
| | | |
| | | @RequestMapping(value = "/info", method = RequestMethod.GET) |
| | | public ResponseValue info(@RequestParam(value = "id") Integer id){ |
| | | // S_config_form form = this.configFormService.get(new S_config_form(id)); |
| | | if(id == null || id.intValue() <= 0){ |
| | | return ResponseValue.error(); |
| | | } |
| | | S_config_form form = this.formCacheProvider.getCacheData(id.toString()); |
| | | if(form == null){ |
| | | return ResponseValue.error("表单不存在, id=" + id); |
| | | } |
| | | return ResponseValue.success(form); |
| | | } |
| | | |
| | | @RequestMapping(value = "/list", method = RequestMethod.GET) |
| | | public ResponseValue list(KeywordsParam keywordsParam){ |
| | | String keywords = null; |
| | | if(keywordsParam != null && StringUtils.isNotEmpty(keywordsParam.getKeywords())){ |
| | | keywords = UrlUtils.decode(keywordsParam.getKeywords()); |
| | | } |
| | | GenericPager<S_config_form> pager = this.configFormService.queryPageFormList(keywords); |
| | | return ResponseValue.success(pager); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.controller; |
| | | |
| | | import com.iplatform.base.SystemController; |
| | | import com.iplatform.base.pojo.DeptParam; |
| | | import com.iplatform.base.service.DeptServiceImpl; |
| | | import com.iplatform.base.util.DeptUtils; |
| | | import com.iplatform.model.po.S_dept; |
| | | import com.iplatform.model.po.S_user_core; |
| | | import com.walker.infrastructure.tree.TreeNode; |
| | | import com.walker.infrastructure.utils.DateUtils; |
| | | import com.walker.infrastructure.utils.NumberGenerator; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.web.DataStatus; |
| | | import com.walker.web.OrgType; |
| | | import com.walker.web.ResponseValue; |
| | | import com.walker.web.UserType; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | @RestController |
| | | @RequestMapping("/system/dept") |
| | | public class DeptController extends SystemController { |
| | | |
| | | private DeptServiceImpl deptService; |
| | | |
| | | @Autowired |
| | | public DeptController(DeptServiceImpl deptService){ |
| | | this.deptService = deptService; |
| | | } |
| | | |
| | | /** |
| | | * 前端展示所有顶级单位列表,超级管理员可以选择所有机构,普通用户只能显示自己单位的。 |
| | | * @return |
| | | * @date 2022-12-15 |
| | | */ |
| | | @GetMapping("/select/list_root_org") |
| | | public ResponseValue listOrgRoot(){ |
| | | List<S_dept> rootList = this.getOrgListScope(); |
| | | return ResponseValue.success(rootList); |
| | | } |
| | | |
| | | /** |
| | | * 前端展示部门机构树(单个组织机构),在添加用户选部门使用。 |
| | | * @param deptId 提供一个部门ID(界面选择),该参数在超级管理员时使用。 |
| | | * @return |
| | | * @date 2022-12-12 |
| | | */ |
| | | @GetMapping("/select/tree_dept/{deptId}") |
| | | public ResponseValue listSelectDeptTree(@PathVariable Long deptId){ |
| | | long orgId = 0; |
| | | if(this.isSupervisor()){ |
| | | if(deptId == null || deptId.longValue() <= 0){ |
| | | return ResponseValue.error("查询一个机构树,必须传入机构ID"); |
| | | } |
| | | orgId = this.getRootOrgIdByDept(deptId); |
| | | } else { |
| | | orgId = this.getCurrentUser().getOrg_id(); |
| | | } |
| | | List<S_dept> orgList = this.deptService.queryOrgListForTree(orgId); |
| | | List<TreeNode> treeNodeList = DeptUtils.getOrgDeptTree(orgList); |
| | | if(StringUtils.isEmptyList(treeNodeList)){ |
| | | // 2023-05-31 树组件不能数据为空 |
| | | treeNodeList = new ArrayList<>(1); |
| | | } |
| | | return ResponseValue.success(treeNodeList); |
| | | } |
| | | |
| | | /** |
| | | * 选择整个组织机构树,区分是否管理员。<p></p> |
| | | * <pre> |
| | | * 1)该功能是公共权限,system:dept:select:** |
| | | * 2)展示所有机构树节点,如果是超级管理员则会显示所有根单位(集团)。 |
| | | * 3)普通用户只能看到本单位机构树。 |
| | | * </pre> |
| | | * @return |
| | | * @date 2022-12-08 |
| | | */ |
| | | @GetMapping("/select/tree_org") |
| | | public ResponseValue listOrgRootTree(){ |
| | | List<S_dept> orgList = null; |
| | | if(this.isSupervisor()){ |
| | | orgList = this.deptService.queryOrgListForTree(-1); |
| | | } else { |
| | | long orgId = this.getCurrentUser().getOrg_id(); |
| | | orgList = this.deptService.queryOrgListForTree(orgId); |
| | | } |
| | | // DeptTreeGenerator deptTreeGenerator = new DeptTreeGenerator(null); |
| | | // deptTreeGenerator.setEntityList(orgList); |
| | | // List<TreeNode> treeNodeList = deptTreeGenerator.getTreeRootList(); |
| | | List<TreeNode> treeNodeList = DeptUtils.getOrgDeptTree(orgList); |
| | | if(StringUtils.isEmptyList(treeNodeList)){ |
| | | logger.error("未找到任何顶级机构树列表: treeNodeList = null"); |
| | | } else { |
| | | // logger.debug(treeNodeList.toString()); |
| | | } |
| | | return ResponseValue.success(treeNodeList); |
| | | } |
| | | |
| | | @GetMapping("/list") |
| | | public ResponseValue listOrgList(DeptParam deptParam){ |
| | | |
| | | String deptDataScope = this.getCurrentDataScope("103"); |
| | | logger.info("部门管理(数据权限) = " + deptDataScope); |
| | | |
| | | Map<String, Object> data = new HashMap<>(4); |
| | | |
| | | if(deptParam.getLoadSelect() == 1){ |
| | | // 来自下拉机构选择框请求 |
| | | List<S_dept> selectParentList = this.deptService.queryRootOrgChildrenList(deptParam.getOrgId(), null); |
| | | data.put("deptList", DeptUtils.toSystemDeptList(selectParentList)); |
| | | return ResponseValue.success(data); |
| | | } |
| | | |
| | | List<S_dept> rootList = this.getOrgListScope(); |
| | | S_user_core currentUser = this.getCurrentUser(); |
| | | List<S_dept> deptSrcList = null; |
| | | |
| | | long selectedOrgRoot = 0; |
| | | if(currentUser.getUser_type().intValue() == UserType.TYPE_SUPER){ |
| | | // 超级管理员,可以看到所有根单位列表 |
| | | if(deptParam != null && deptParam.getOrgId() > 0){ |
| | | // 管理员选择了一个根机构 |
| | | selectedOrgRoot = deptParam.getOrgId(); |
| | | } else if(!StringUtils.isEmptyList(rootList)){ |
| | | // 没有选择,则默认查询第一个根机构下面的 |
| | | selectedOrgRoot = rootList.get(0).getId(); |
| | | } |
| | | deptSrcList = this.deptService.queryRootOrgChildrenList(selectedOrgRoot, deptParam.getDeptName()); |
| | | data.put("deptList", DeptUtils.toSystemDeptList(deptSrcList)); |
| | | } else { |
| | | // 其他用户只能看到自己所在根机构下的所有机构 |
| | | deptSrcList = this.deptService.queryRootOrgChildrenList(currentUser.getOrg_id(), deptParam.getDeptName()); |
| | | data.put("deptList", DeptUtils.toSystemDeptList(deptSrcList)); |
| | | } |
| | | |
| | | // 记录超级管理员选择的顶级机构,返回前端。2022-12-03 |
| | | if(deptParam.getOrgId() > 0){ |
| | | data.put("selectedRootOrgId", deptParam.getOrgId()); |
| | | } else { |
| | | data.put("selectedRootOrgId", rootList.get(0).getId()); |
| | | } |
| | | |
| | | data.put("rootOrgList", rootList); |
| | | return ResponseValue.success(data); |
| | | } |
| | | |
| | | @PostMapping("/add") |
| | | public ResponseValue saveAddDept(@RequestBody S_dept s_dept){ |
| | | if(s_dept == null || StringUtils.isEmpty(s_dept.getDept_name())){ |
| | | return ResponseValue.error("提交保存机构为空"); |
| | | } |
| | | logger.info(s_dept.toString()); |
| | | |
| | | s_dept.setId(NumberGenerator.getSequenceNumber()); |
| | | s_dept.setCreate_time(DateUtils.getDateTimeNumber(System.currentTimeMillis())); |
| | | s_dept.setCreate_by(this.getCurrentUser().getUser_name()); |
| | | |
| | | Long parentId = s_dept.getParent_id(); |
| | | if(parentId == null || parentId.longValue() == 0){ |
| | | // 说明是根机构,根机构: id = org_id |
| | | s_dept.setOrg_id(s_dept.getId()); |
| | | s_dept.setParent_id(0L); |
| | | s_dept.setAncestors("0"); |
| | | if(s_dept.getOrg_type().intValue() != OrgType.TYPE_ORG){ |
| | | return ResponseValue.error("顶级机构只能选择第一项"); |
| | | } |
| | | |
| | | } else { |
| | | // 普通机构 |
| | | S_dept parentDept = this.deptService.queryOneDept(parentId); |
| | | if(parentDept == null){ |
| | | return ResponseValue.error("上级单位不存在"); |
| | | } |
| | | if(parentDept.getStatus().intValue() != DataStatus.CONST_NORMAL){ |
| | | return ResponseValue.error("该机构已停用,无法创建子机构"); |
| | | } |
| | | s_dept.setOrg_id(parentDept.getOrg_id()); |
| | | s_dept.setAncestors(parentDept.getAncestors() + "," + s_dept.getParent_id()); |
| | | |
| | | String error = this.checkOrgType(parentDept.getOrg_type(), s_dept.getOrg_type()); |
| | | if(error != null){ |
| | | return ResponseValue.error(error); |
| | | } |
| | | } |
| | | this.deptService.insert(s_dept); |
| | | // this.deptCacheProvider.putDept(s_dept); |
| | | this.getDeptCacheProvider().putDept(s_dept); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @RequestMapping("/remove/{deptId}") |
| | | public ResponseValue removeDept(@PathVariable Long deptId){ |
| | | if(deptId == null || deptId <= 0){ |
| | | return ResponseValue.error("机构参数错误"); |
| | | } |
| | | int subDeptSize = this.deptService.querySubDeptSizeInCurrent(deptId); |
| | | if(subDeptSize > 0){ |
| | | return ResponseValue.error("该机构下存在子机构,无法删除"); |
| | | } |
| | | long userSize = this.deptService.queryUserSizeInCurrent(deptId); |
| | | if(userSize > 0){ |
| | | return ResponseValue.error("该机构下存在用户,无法删除"); |
| | | } |
| | | this.deptService.delete(new S_dept(deptId)); |
| | | // this.deptCacheProvider.removeDept(deptId); |
| | | this.getDeptCacheProvider().removeDept(deptId); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @PostMapping("/edit") |
| | | public ResponseValue saveEdit(@RequestBody S_dept s_dept){ |
| | | if(s_dept == null){ |
| | | return ResponseValue.error("编辑的机构不存在"); |
| | | } |
| | | Long deptId = s_dept.getId(); |
| | | if(deptId == null || deptId.longValue() <= 0){ |
| | | return ResponseValue.error("编辑的机构ID不存在"); |
| | | } |
| | | Long parentId = s_dept.getParent_id(); |
| | | if(parentId == null || parentId.longValue() == 0){ |
| | | // 说明编辑的是顶级机构,根机构: id = org_id |
| | | if(s_dept.getOrg_type().intValue() != OrgType.TYPE_ORG){ |
| | | return ResponseValue.error("顶级机构只能选择一级机构"); |
| | | } |
| | | } else { |
| | | // 普通机构 |
| | | S_dept parentDept = this.deptService.queryOneDept(parentId); |
| | | if(parentDept == null){ |
| | | return ResponseValue.error("上级单位不存在"); |
| | | } |
| | | String error = this.checkOrgType(parentDept.getOrg_type(), s_dept.getOrg_type()); |
| | | if(error != null){ |
| | | return ResponseValue.error(error); |
| | | } |
| | | } |
| | | s_dept.setCreate_time(DateUtils.getDateTimeNumber(System.currentTimeMillis())); |
| | | this.deptService.save(s_dept); |
| | | // this.deptCacheProvider.updateDept(s_dept); |
| | | this.getDeptCacheProvider().updateDept(s_dept); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @GetMapping("/view/{deptId}") |
| | | public ResponseValue viewDept(@PathVariable Long deptId){ |
| | | if(deptId == null || deptId.longValue() <= 0){ |
| | | return ResponseValue.error("参数错误"); |
| | | } |
| | | S_dept s_dept = this.deptService.queryOneDept(deptId); |
| | | if(s_dept == null){ |
| | | return ResponseValue.error("机构不存在"); |
| | | } |
| | | return ResponseValue.success(s_dept); |
| | | } |
| | | |
| | | private String checkOrgType(int parentOrgTypeValue, int currentOrgTypeValue){ |
| | | OrgType parentOrgType = OrgType.getType(parentOrgTypeValue); |
| | | OrgType currentOrtType = OrgType.getType(currentOrgTypeValue); |
| | | if(currentOrtType == OrgType.OrgSub){ |
| | | if(parentOrgType != OrgType.Org){ |
| | | return "二级单位只能在顶级单位下面"; |
| | | } |
| | | } else if (currentOrtType == OrgType.OrgFactory) { |
| | | if(parentOrgType != OrgType.OrgSub){ |
| | | return "三级单位只能在二级单位下面"; |
| | | } |
| | | } else if (currentOrtType == OrgType.OrgSubFactory) { |
| | | if(parentOrgType != OrgType.OrgFactory){ |
| | | return "四级单位只能在三级级单位下面"; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.controller; |
| | | |
| | | import com.iplatform.base.PlatformAdapterController; |
| | | import com.iplatform.base.PlatformRuntimeException; |
| | | import com.iplatform.base.cache.FormCacheProvider; |
| | | import com.iplatform.base.pojo.GroupDataParam; |
| | | import com.iplatform.base.pojo.KeywordsParam; |
| | | import com.iplatform.base.pojo.form.FormData; |
| | | import com.iplatform.base.pojo.group.GroupData; |
| | | import com.iplatform.base.service.GroupServiceImpl; |
| | | import com.iplatform.model.po.S_group; |
| | | import com.iplatform.model.po.S_group_data; |
| | | import com.walker.db.page.GenericPager; |
| | | import com.walker.infrastructure.utils.DateUtils; |
| | | import com.walker.infrastructure.utils.JsonUtils; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.infrastructure.utils.UrlUtils; |
| | | import com.walker.web.ResponseValue; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 平台分组数据管理。 |
| | | * <p>实现配置功能块能包含哪些内容项,如:手机首页导航栏可配置等。</p> |
| | | * @author 时克英 |
| | | * @date 2023-05-20 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/system/group") |
| | | public class GroupController extends PlatformAdapterController { |
| | | |
| | | @Autowired |
| | | public GroupController(GroupServiceImpl groupService, FormCacheProvider formCacheProvider){ |
| | | this.groupService = groupService; |
| | | this.formCacheProvider = formCacheProvider; |
| | | } |
| | | |
| | | @RequestMapping(value = "/update", method = RequestMethod.POST) |
| | | public ResponseValue updateGroup( |
| | | // @RequestParam Integer id, |
| | | @RequestBody S_group group){ |
| | | if(group == null || StringUtils.isEmpty(group.getName()) || group.getId() == null){ |
| | | return ResponseValue.error("参数错误"); |
| | | } |
| | | // group.setId(id); |
| | | group.setUpdate_time(DateUtils.getDateTimeNumber()); |
| | | this.groupService.save(group); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @RequestMapping(value = "/delete", method = RequestMethod.GET) |
| | | public ResponseValue deleteGroup(Integer id){ |
| | | if(id == null){throw new IllegalArgumentException("缺少参数");} |
| | | S_group_data groupData = new S_group_data(); |
| | | groupData.setGid(id); |
| | | List<S_group_data> groupDataList = this.groupService.select(groupData); |
| | | if(!StringUtils.isEmptyList(groupDataList)){ |
| | | return ResponseValue.error("分组下存在数据项,无法删除!"); |
| | | } |
| | | this.groupService.delete(new S_group(id)); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @RequestMapping(value = "/save", method = RequestMethod.POST) |
| | | public ResponseValue saveGroup(@RequestBody S_group group){ |
| | | if(group == null){ |
| | | return ResponseValue.error("参数错误"); |
| | | } |
| | | group.setCreate_time(DateUtils.getDateTimeNumber()); |
| | | group.setUpdate_time(group.getCreate_time()); |
| | | group.setId(this.groupService.queryGroupNextId()); |
| | | this.groupService.insert(group); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @RequestMapping(value = "/data/delete", method = RequestMethod.GET) |
| | | public ResponseValue deleteData(@RequestParam(value = "id") Integer id){ |
| | | this.groupService.delete(new S_group_data(id)); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @RequestMapping(value = "/data/update", method = RequestMethod.POST) |
| | | public ResponseValue updateData(@RequestParam Integer id, @RequestBody GroupData groupData){ |
| | | if(groupData == null || id == null){ |
| | | return ResponseValue.error("参数错误"); |
| | | } |
| | | |
| | | String value = this.acquireFormValue(groupData.getForm()); |
| | | |
| | | S_group_data group_data = new S_group_data(); |
| | | group_data.setGid(groupData.getGid()); |
| | | group_data.setValue(this.clearCdnPrefix(value)); |
| | | group_data.setSort(groupData.getForm().getSort()); |
| | | group_data.setStatus(groupData.getForm().getStatus()); |
| | | group_data.setUpdate_time(group_data.getCreate_time()); |
| | | group_data.setId(id); |
| | | this.groupService.save(group_data); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | // // @ApiOperation(value = "新增:分组列表项") |
| | | @RequestMapping(value = "/data/save", method = RequestMethod.POST) |
| | | public ResponseValue saveData(@RequestBody GroupData groupData){ |
| | | if(groupData == null){ |
| | | return ResponseValue.error("参数错误"); |
| | | } |
| | | String value = this.acquireFormValue(groupData.getForm()); |
| | | int nextId = this.groupService.queryGroupDataNextId(); |
| | | |
| | | S_group_data group_data = new S_group_data(); |
| | | group_data.setGid(groupData.getGid()); |
| | | group_data.setValue(this.clearCdnPrefix(value)); |
| | | group_data.setSort(groupData.getForm().getSort()); |
| | | group_data.setStatus(groupData.getForm().getStatus()); |
| | | group_data.setCreate_time(DateUtils.getDateTimeNumber()); |
| | | group_data.setUpdate_time(group_data.getCreate_time()); |
| | | group_data.setId(nextId); |
| | | this.groupService.insert(group_data); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | private String acquireFormValue(FormData formData){ |
| | | this.formCacheProvider.validateForm(formData); |
| | | try { |
| | | return JsonUtils.objectToJsonString(formData); |
| | | } catch (Exception e) { |
| | | throw new PlatformRuntimeException("转换Json字符串失败:" + formData.getId(), e); |
| | | } |
| | | } |
| | | |
| | | @RequestMapping(value = "/data/list", method = RequestMethod.GET) |
| | | public ResponseValue listData(GroupDataParam groupDataParam){ |
| | | if(groupDataParam == null || groupDataParam.getGid() == null){ |
| | | throw new IllegalArgumentException("参数错误:groupDataParam"); |
| | | } |
| | | GenericPager<S_group_data> pager = this.groupService.queryPageGroupDataList(groupDataParam.getGid(), groupDataParam.getStatus()); |
| | | pager.getDatas().stream().forEach(data -> { |
| | | try { |
| | | // 把value转成Json,重新格式化一遍,返回前端。 |
| | | FormData formData = JsonUtils.jsonStringToObject(data.getValue(), FormData.class); |
| | | data.setValue(JsonUtils.objectToJsonString(formData)); |
| | | logger.info(data.getValue()); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | }); |
| | | return ResponseValue.success(pager); |
| | | } |
| | | |
| | | @RequestMapping(value = "/list", method = RequestMethod.GET) |
| | | public ResponseValue list(KeywordsParam keywordsParam){ |
| | | String keywords = null; |
| | | if(keywordsParam != null && StringUtils.isNotEmpty(keywordsParam.getKeywords())){ |
| | | keywords = UrlUtils.decode(keywordsParam.getKeywords()); |
| | | } |
| | | GenericPager<S_group> pager = this.groupService.queryPageGroupList(keywords); |
| | | return ResponseValue.success(pager); |
| | | } |
| | | |
| | | private GroupServiceImpl groupService; |
| | | private FormCacheProvider formCacheProvider; |
| | | } |
New file |
| | |
| | | package com.iplatform.base.controller; |
| | | |
| | | import com.iplatform.base.SystemController; |
| | | import com.iplatform.base.pojo.log.LoginLogParam; |
| | | import com.iplatform.base.service.LogServiceImpl; |
| | | import com.iplatform.model.po.S_login_info; |
| | | import com.walker.db.page.GenericPager; |
| | | import com.walker.web.ResponseValue; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | /** |
| | | * 登录日志查询。 |
| | | * @date 2023-01-04 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/monitor/login_info") |
| | | public class LoginInfoController extends SystemController { |
| | | |
| | | private LogServiceImpl logService; |
| | | |
| | | @Autowired |
| | | public LoginInfoController(LogServiceImpl logService){ |
| | | this.logService = logService; |
| | | } |
| | | |
| | | @RequestMapping("/select/clean") |
| | | public ResponseValue clear(){ |
| | | this.logService.execClearLoginLog(); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @RequestMapping("/list") |
| | | public ResponseValue list(LoginLogParam loginLogParam){ |
| | | // this.preparePageSearch(); |
| | | GenericPager<S_login_info> pager = null; |
| | | if(loginLogParam == null){ |
| | | pager = this.logService.queryPageLoginLogList(null, null, null); |
| | | } else { |
| | | pager = this.logService.queryPageLoginLogList(loginLogParam.getIpaddr() |
| | | , loginLogParam.getUserName(), loginLogParam.getStatus()); |
| | | } |
| | | // return this.acquireTablePage(pager.getDatas(), pager.getTotalRows()); |
| | | return ResponseValue.success(pager); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.controller; |
| | | |
| | | import com.iplatform.base.SystemController; |
| | | import com.iplatform.base.cache.MenuCacheProvider; |
| | | import com.iplatform.base.service.MenuServiceImpl; |
| | | import com.iplatform.base.service.RoleServiceImpl; |
| | | import com.iplatform.base.util.MenuUtils; |
| | | import com.iplatform.base.util.menu.SystemMenu; |
| | | import com.iplatform.model.po.S_menu; |
| | | import com.iplatform.model.po.S_user_core; |
| | | import com.walker.infrastructure.utils.DateUtils; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.web.DataStatus; |
| | | import com.walker.web.ResponseValue; |
| | | import com.walker.web.UserPrincipal; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | @RestController |
| | | @RequestMapping("/system/menu") |
| | | public class MenuController extends SystemController { |
| | | |
| | | private MenuCacheProvider menuCacheProvider; |
| | | private RoleServiceImpl roleService; |
| | | private MenuServiceImpl menuService; |
| | | |
| | | @Autowired |
| | | public MenuController(MenuCacheProvider menuCacheProvider |
| | | , RoleServiceImpl roleService, MenuServiceImpl menuService){ |
| | | this.menuCacheProvider = menuCacheProvider; |
| | | this.roleService = roleService; |
| | | this.menuService = menuService; |
| | | } |
| | | |
| | | @RequestMapping("/remove/{menuId}") |
| | | public ResponseValue remove(@PathVariable String menuId){ |
| | | boolean existChildren = this.menuCacheProvider.isHasChildren(menuId); |
| | | if(existChildren){ |
| | | return ResponseValue.error("该菜单存在子菜单,无法删除"); |
| | | } |
| | | int roleMenuSize = this.menuService.queryRoleMenuSize(menuId); |
| | | if(roleMenuSize > 0){ |
| | | return ResponseValue.error("菜单已分配,无法删除"); |
| | | } |
| | | this.menuService.delete(new S_menu(menuId)); |
| | | this.menuCacheProvider.removeCacheData(menuId); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @RequestMapping("/view/{menuId}") |
| | | public ResponseValue view(@PathVariable String menuId){ |
| | | S_menu s_menu = this.menuService.get(new S_menu(menuId)); |
| | | if(s_menu == null){ |
| | | return ResponseValue.error("菜单不存在:" + menuId); |
| | | } |
| | | return ResponseValue.success(new SystemMenu(s_menu)); |
| | | } |
| | | |
| | | @RequestMapping("/edit") |
| | | public ResponseValue saveEdit(@RequestBody S_menu s_menu){ |
| | | if(s_menu == null || StringUtils.isEmpty(s_menu.getParent_id()) || StringUtils.isEmpty(s_menu.getMenu_name())){ |
| | | return ResponseValue.error("参数错误"); |
| | | } |
| | | S_menu exist = this.menuService.queryExistMenuInParent(s_menu.getParent_id(), s_menu.getMenu_name()); |
| | | if(exist != null && !exist.getMenu_id().equals(s_menu.getMenu_id())){ |
| | | return ResponseValue.error("父菜单下已有相同名称菜单存在:" + s_menu.getMenu_name()); |
| | | } |
| | | if(s_menu.getIs_frame().intValue() == MenuUtils.MENU_FRAME_YES && !StringUtils.isHttpLink(s_menu.getPath())){ |
| | | return ResponseValue.error("地址必须以http(s)://开头"); |
| | | } |
| | | if(s_menu.getMenu_type().equals(MenuUtils.MENU_TYPE_ITEM) && StringUtils.isEmpty(s_menu.getComponent())){ |
| | | return ResponseValue.error("菜单项必须填写:组件路径(component)"); |
| | | } |
| | | this.menuService.save(s_menu); |
| | | this.menuCacheProvider.updateCacheData(s_menu.getMenu_id(), s_menu); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @RequestMapping("/add") |
| | | public ResponseValue saveAddMenu(@RequestBody S_menu s_menu){ |
| | | if(s_menu == null || StringUtils.isEmpty(s_menu.getParent_id()) || StringUtils.isEmpty(s_menu.getMenu_name())){ |
| | | return ResponseValue.error("参数错误"); |
| | | } |
| | | S_menu exist = this.menuService.queryExistMenuInParent(s_menu.getParent_id(), s_menu.getMenu_name()); |
| | | if(exist != null){ |
| | | return ResponseValue.error("父菜单下已有相同名称菜单存在:" + s_menu.getMenu_name()); |
| | | } |
| | | if(s_menu.getIs_frame().intValue() == MenuUtils.MENU_FRAME_YES && !StringUtils.isHttpLink(s_menu.getPath())){ |
| | | return ResponseValue.error("地址必须以http(s)://开头"); |
| | | } |
| | | if(s_menu.getMenu_type().equals(MenuUtils.MENU_TYPE_ITEM) && StringUtils.isEmpty(s_menu.getComponent())){ |
| | | return ResponseValue.error("菜单项必须填写:组件路径(component)"); |
| | | } |
| | | s_menu.setMenu_id(DateUtils.getDateTimeSecondForShow()); |
| | | this.menuService.insert(s_menu); |
| | | S_menu saved = this.menuService.get(new S_menu(s_menu.getMenu_id())); |
| | | this.menuCacheProvider.putCacheData(s_menu.getMenu_id(), saved); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | /** |
| | | * 角色编辑时,显示已经设置的功能树结构目录。 |
| | | * @param roleId |
| | | * @return |
| | | * @date 2022-12-19 |
| | | */ |
| | | @RequestMapping("/select/roleMenuTree/{roleId}") |
| | | public ResponseValue selectRoleMenuTree(@PathVariable Long roleId){ |
| | | if(roleId == null || roleId.longValue() <= 0){ |
| | | throw new IllegalArgumentException("角色参数不存在"); |
| | | } |
| | | Map<String, Object> data = new HashMap<>(4); |
| | | List<String> roleMenuIds = this.roleService.queryRoleMenuIdList(roleId); |
| | | int menuScope = this.getCurrentOrgMenuScope(); |
| | | List<SystemMenu> menuTreeList = this.menuCacheProvider.getMenuTreeAll(null, true, menuScope); |
| | | data.put("checkedKeys", roleMenuIds); |
| | | data.put("menus", menuTreeList); |
| | | return ResponseValue.success(data); |
| | | } |
| | | |
| | | /** |
| | | * 返回整个系统菜单树结构数据,目前前端角色设置中使用选择关联功能权限。 |
| | | * @return |
| | | * @date 2022-12-18 |
| | | */ |
| | | @RequestMapping("/select/tree") |
| | | public ResponseValue selectMenuTree(){ |
| | | int menuScope = this.getCurrentOrgMenuScope(); |
| | | List<SystemMenu> menuTreeList = this.menuCacheProvider.getMenuTreeAll(null, true, menuScope); |
| | | return ResponseValue.success(menuTreeList); |
| | | } |
| | | |
| | | @GetMapping("/list") |
| | | public ResponseValue listMenuWithoutTree(){ |
| | | List<SystemMenu> menuList = null; |
| | | UserPrincipal<S_user_core> userPrincipal = this.getCurrentUserPrincipal(); |
| | | if(this.isSupervisor()){ |
| | | menuList = this.menuCacheProvider.getMenuList(null, MenuUtils.MENU_SCOPE_ALL); |
| | | } else { |
| | | int menuScope = this.getCurrentOrgMenuScope(); |
| | | menuList = this.menuCacheProvider.getMenuList(userPrincipal.getRoleIdList(), menuScope); |
| | | } |
| | | return ResponseValue.success(menuList); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.iplatform.base.controller; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.NotifyConstants; |
| | | import com.iplatform.base.SystemController; |
| | | import com.iplatform.base.pojo.notify.InfoParam; |
| | | import com.iplatform.base.pojo.notify.NotificationParam; |
| | | import com.iplatform.base.service.NotificationServiceImpl; |
| | | import com.iplatform.base.util.NotificationUtils; |
| | | import com.iplatform.model.po.SfNotification; |
| | | import com.iplatform.model.po.SfTemplateMessage; |
| | | import com.iplatform.model.vo.NotificationConfigVo; |
| | | import com.walker.web.ResponseValue; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RequestMethod; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 消息通知管理,该通知仅是针对业务通知分类管理,同时能实现同步微信消息模板。 |
| | | * <pre> |
| | | * 1)目前微信公众号消息,依赖该功能中的同步模板记录 |
| | | * 2)平台推送消息列表,请在"消息推送记录" 中查询。 |
| | | * </pre> |
| | | * @author 时克英 |
| | | * @date 2023-08-24 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/platform/system/notification") |
| | | public class NotificationController extends SystemController { |
| | | |
| | | private NotificationServiceImpl notificationService; |
| | | |
| | | @Autowired |
| | | public NotificationController(NotificationServiceImpl notificationService){ |
| | | this.notificationService = notificationService; |
| | | } |
| | | |
| | | @RequestMapping(value = "/sms/switch", method = RequestMethod.POST) |
| | | public ResponseValue smsSwitch(Long id){ |
| | | SfNotification notification = this.notificationService.get(new SfNotification(id)); |
| | | if (notification.getIsSms().intValue() == NotifyConstants.SWITCH_NOT_EXIST) { |
| | | return ResponseValue.error("通知没有配置短信"); |
| | | } |
| | | if(notification.getIsSms().intValue() == NotifyConstants.SWITCH_OPEN){ |
| | | notification.setIsSms(NotifyConstants.SWITCH_COLSE); |
| | | } else { |
| | | notification.setIsSms(NotifyConstants.SWITCH_OPEN); |
| | | } |
| | | this.notificationService.update(notification); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @RequestMapping(value = "/routine/switch", method = RequestMethod.POST) |
| | | public ResponseValue routineSwitch(Long id){ |
| | | SfNotification notification = this.notificationService.get(new SfNotification(id)); |
| | | if (notification.getIsRoutine().intValue() == NotifyConstants.SWITCH_NOT_EXIST) { |
| | | return ResponseValue.error("通知没有配置小程序订阅模板"); |
| | | } |
| | | if(notification.getIsRoutine().intValue() == NotifyConstants.SWITCH_OPEN){ |
| | | notification.setIsRoutine(NotifyConstants.SWITCH_COLSE); |
| | | } else { |
| | | notification.setIsRoutine(NotifyConstants.SWITCH_OPEN); |
| | | } |
| | | this.notificationService.update(notification); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @RequestMapping(value = "/wechat/switch", method = RequestMethod.POST) |
| | | public ResponseValue wechatSwitch(Long id){ |
| | | SfNotification notification = this.notificationService.get(new SfNotification(id)); |
| | | if (notification.getIsWechat().intValue() == NotifyConstants.SWITCH_NOT_EXIST) { |
| | | return ResponseValue.error("通知没有配置公众号模板"); |
| | | } |
| | | if(notification.getIsWechat().intValue() == NotifyConstants.SWITCH_OPEN){ |
| | | notification.setIsWechat(NotifyConstants.SWITCH_COLSE); |
| | | } else { |
| | | notification.setIsWechat(NotifyConstants.SWITCH_OPEN); |
| | | } |
| | | this.notificationService.update(notification); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @RequestMapping(value = "/detail", method = RequestMethod.GET) |
| | | public ResponseValue detail(InfoParam request){ |
| | | if(request == null || request.getId() == null){ |
| | | return ResponseValue.error(Constants.ERROR_ARGUMENT); |
| | | } |
| | | long id = request.getId(); |
| | | SfNotification notification = this.notificationService.get(new SfNotification(id)); |
| | | NotificationConfigVo vo = new NotificationConfigVo(); |
| | | SfTemplateMessage templateMessage = null; |
| | | |
| | | if (request.getDetailType().equals(NotifyConstants.DETAIL_TYPE_WECHAT)) { |
| | | if (notification.getIsWechat().intValue() == NotifyConstants.SWITCH_NOT_EXIST) { |
| | | return ResponseValue.error("请先配置公众号模板消息"); |
| | | } |
| | | templateMessage = this.notificationService.get(new SfTemplateMessage(notification.getWechatId().longValue())); |
| | | vo = NotificationUtils.acquireNotificationConfigVo(templateMessage); |
| | | vo.setStatus(notification.getIsWechat()); |
| | | |
| | | } else if(request.getDetailType().equals(NotifyConstants.DETAIL_TYPE_ROUTINE)){ |
| | | if (notification.getIsRoutine().intValue() == NotifyConstants.SWITCH_NOT_EXIST) { |
| | | return ResponseValue.error("请先配置小程序订阅消息"); |
| | | } |
| | | templateMessage = this.notificationService.get(new SfTemplateMessage(notification.getRoutineId().longValue())); |
| | | vo = NotificationUtils.acquireNotificationConfigVo(templateMessage); |
| | | vo.setStatus(notification.getIsRoutine()); |
| | | |
| | | } else if(request.getDetailType().equals(NotifyConstants.DETAIL_TYPE_SMS)){ |
| | | if (notification.getIsSms().intValue() == NotifyConstants.SWITCH_NOT_EXIST) { |
| | | return ResponseValue.error("请先配置短信模板"); |
| | | } |
| | | templateMessage = this.notificationService.get(new SfTemplateMessage(notification.getSmsId().longValue())); |
| | | vo = NotificationUtils.acquireNotificationConfigVo(templateMessage); |
| | | vo.setStatus(notification.getIsSms()); |
| | | } |
| | | return ResponseValue.success(vo); |
| | | } |
| | | |
| | | @RequestMapping(value = "/list", method = RequestMethod.GET) |
| | | public ResponseValue list(NotificationParam param){ |
| | | List<SfNotification> data = null; |
| | | if(param == null){ |
| | | data = this.notificationService.queryList(null); |
| | | } else { |
| | | data = this.notificationService.queryList(param.getSendType()); |
| | | } |
| | | return ResponseValue.success(data); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.controller; |
| | | |
| | | import com.iplatform.base.SystemController; |
| | | import com.iplatform.base.util.UserUtils; |
| | | import com.walker.cache.AbstractCacheProvider; |
| | | import com.walker.web.ResponseValue; |
| | | import com.walker.web.UserOnlineProvider; |
| | | import com.walker.web.UserPrincipal; |
| | | import com.walker.web.WebRuntimeException; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | @RestController |
| | | @RequestMapping("/monitor/online") |
| | | public class OnlineUserController extends SystemController { |
| | | |
| | | private static final int MAX_DATA_SIZE = 64; |
| | | |
| | | private UserOnlineProvider userOnlineProvider; |
| | | |
| | | @Autowired |
| | | public OnlineUserController(UserOnlineProvider userOnlineProvider){ |
| | | this.userOnlineProvider = userOnlineProvider; |
| | | } |
| | | |
| | | @RequestMapping("/list") |
| | | public ResponseValue list(){ |
| | | AbstractCacheProvider cacheProvider = (AbstractCacheProvider)this.userOnlineProvider; |
| | | Collection<Object> list = cacheProvider.queryListLimit(MAX_DATA_SIZE); |
| | | List<UserPrincipal> data = new ArrayList<>(); |
| | | if(list != null && list.size() > 0){ |
| | | try { |
| | | for(Object up : list){ |
| | | // logger.debug(up.toString()); |
| | | data.add(UserUtils.toUserPrincipal(up.toString())); |
| | | } |
| | | } catch (Exception ex){ |
| | | throw new WebRuntimeException("在线用户缓存对象转换错误:"); |
| | | } |
| | | } |
| | | return this.acquireTablePage(data, data.size()); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.controller; |
| | | |
| | | import com.iplatform.base.SystemController; |
| | | import com.iplatform.base.pojo.log.OperateLogParam; |
| | | import com.iplatform.base.service.LogServiceImpl; |
| | | import com.iplatform.model.po.S_oper_log; |
| | | import com.walker.db.page.GenericPager; |
| | | import com.walker.infrastructure.utils.KeyValue; |
| | | import com.walker.web.ResponseValue; |
| | | import com.walker.web.log.BusinessType; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | @RestController |
| | | @RequestMapping("/monitor/operate_log") |
| | | public class OperateLogController extends SystemController { |
| | | |
| | | private LogServiceImpl logService; |
| | | |
| | | @Autowired |
| | | public OperateLogController(LogServiceImpl logService){ |
| | | this.logService = logService; |
| | | } |
| | | |
| | | @RequestMapping("/select/get_business_type") |
| | | public ResponseValue getBusinessTypeList(){ |
| | | List<KeyValue<Integer, String>> data = new ArrayList<>(); |
| | | for(BusinessType businessType : BusinessType.values()){ |
| | | data.add(new KeyValue<>(businessType.getIndex(), businessType.getName())); |
| | | } |
| | | return ResponseValue.success(data); |
| | | } |
| | | |
| | | @RequestMapping("/select/clean") |
| | | public ResponseValue clear(){ |
| | | this.logService.execClearOperateLog(); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @RequestMapping("/list") |
| | | public ResponseValue list(OperateLogParam operateLogParam){ |
| | | // this.preparePageSearch(); |
| | | GenericPager<S_oper_log> pager = null; |
| | | if(operateLogParam == null){ |
| | | pager = this.logService.queryPageOperateLogList(null, null, null, null); |
| | | } else { |
| | | pager = this.logService.queryPageOperateLogList(operateLogParam.getOperName() |
| | | , operateLogParam.getBusinessType(), operateLogParam.getStatus(), operateLogParam.getTitile()); |
| | | } |
| | | // return this.acquireTablePage(pager.getDatas(), pager.getTotalRows()); |
| | | return ResponseValue.success(pager); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.controller; |
| | | |
| | | import com.iplatform.base.ArgumentsConstants; |
| | | import com.iplatform.base.SystemController; |
| | | import com.iplatform.base.service.CodeServiceImpl; |
| | | import com.iplatform.base.support.DictTreeGenerator; |
| | | import com.iplatform.model.po.S_dict_data; |
| | | import com.walker.file.FileInfo; |
| | | import com.walker.infrastructure.tree.TreeNode; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.web.ResponseValue; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Comparator; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 公共权限操作方法。<p></p> |
| | | * 在该对象里面的方法,都无需配置菜单权限,只要登录用户都有权使用。 |
| | | * <pre> |
| | | * 1)比如:获取字典树等 |
| | | * </pre> |
| | | * @author 时克英 |
| | | * @date 2023-03-13 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/permit") |
| | | public class PermitController extends SystemController { |
| | | |
| | | // @RequestMapping("/copyright/get/info") |
| | | // public ResponseValue getCopyRight(){ |
| | | // CopyRightVo copyRightVo = new CopyRightVo(); |
| | | // copyRightVo.setCompanyName(this.getArgumentVariable(ArgumentsConstants.CONFIG_COPYRIGHT_COMPANY_INFO).getStringValue()); |
| | | // copyRightVo.setCompanyImage(this.getArgumentVariable(ArgumentsConstants.CONFIG_COPYRIGHT_COMPANY_IMAGE).getStringValue()); |
| | | // return ResponseValue.success(copyRightVo); |
| | | // } |
| | | |
| | | /** |
| | | * 获取移动端访问站点域名(地址),如:localhost:8080 |
| | | * @return |
| | | * @date 2023-05-12 |
| | | */ |
| | | @RequestMapping("/config/front/domain") |
| | | public ResponseValue getConfigFrontDomain(){ |
| | | String data = this.getArgumentVariable(ArgumentsConstants.CONFIG_KEY_SITE_URL).getStringValue(); |
| | | return ResponseValue.success("success", data); |
| | | } |
| | | |
| | | /** |
| | | * 根据文件id下载本地文件 |
| | | * @param id 文件id(系统存储的唯一编号) |
| | | * @throws Exception |
| | | * @date 2023-03-13 |
| | | */ |
| | | @RequestMapping("/file/{id}") |
| | | public void downloadLocalFile(@PathVariable String id) throws Exception{ |
| | | FileInfo fileInfo = this.getFileInfo(id); |
| | | if(fileInfo == null){ |
| | | throw new IllegalArgumentException("文件未找到,id=" + id); |
| | | } |
| | | logger.info("开始下载本地文件:{}", fileInfo); |
| | | this.downloadSimpleFile(this.getLocalFileData(fileInfo), fileInfo.getFileName()); |
| | | } |
| | | |
| | | /** |
| | | * 根据代码表名字,查询包含的代码项集合。 |
| | | * @param dictType |
| | | * @return |
| | | * @date 2023-03-22 该接口在字典管理中存在,这里需要放在公共权限里面一份,方便所有用户查询某个字典类型下的所有项目集合。 |
| | | * @date 2023-04-15 使用缓存,这里只能返回一级的情况,如果存在树结构则需要调用方法,参考 API:{@linkplain PermitController#selectDictTreeList(String)} |
| | | */ |
| | | @RequestMapping("/dict/data/type/{dictType}") |
| | | public ResponseValue<List<S_dict_data>> dictTypeList(@PathVariable String dictType){ |
| | | logger.debug("dictType = " + dictType); |
| | | String id = this.getDictCacheProvider().getDictTypeId(dictType); |
| | | List<S_dict_data> list = this.getDictCacheProvider().getRootChildrenOneLevelList(id); |
| | | // List<S_dict_data> list = this.codeService.queryDictDataByType(dictType); |
| | | if(StringUtils.isEmptyList(list)){ |
| | | list = new ArrayList<S_dict_data>(2); |
| | | } |
| | | list.sort(new Comparator<S_dict_data>() { |
| | | @Override |
| | | public int compare(S_dict_data stu1, S_dict_data stu2) { |
| | | return stu1.getDict_sort() - stu2.getDict_sort(); |
| | | } |
| | | }); |
| | | return ResponseValue.success(list); |
| | | } |
| | | |
| | | /** |
| | | * 返回代码树结构(列表集合),由前端展示组装。 |
| | | * @param dictType 数据字典类型 |
| | | * @return |
| | | * @auth 时克英 |
| | | * @date 2023-03-13 |
| | | */ |
| | | @RequestMapping("/dict/list_tree/{dictType}") |
| | | public ResponseValue selectDictTreeList(@PathVariable String dictType){ |
| | | if(StringUtils.isEmpty(dictType)){ |
| | | return ResponseValue.error("请提供字典类型!"); |
| | | } |
| | | List<TreeNode> treeNodeList = new ArrayList<>(8); |
| | | // this.getDictCacheProvider().getCodeChildrenList() |
| | | List<S_dict_data> dictDataList = this.codeService.queryDictTreeList(dictType); |
| | | if(StringUtils.isEmptyList(dictDataList)){ |
| | | return ResponseValue.success(treeNodeList); |
| | | } |
| | | |
| | | // s_dict_data表:第一个根节点的'parent_id' |
| | | // TreeGenerator组件使用的默认父id=0,所以对于字典来说,父id不是0可能是其他数值,所以这里需要先设置。 |
| | | long defaultParentId = dictDataList.get(0).getParent_id(); |
| | | DictTreeGenerator generator = new DictTreeGenerator(null); |
| | | generator.setDefaultParentId(defaultParentId); |
| | | generator.setEntityList(dictDataList); |
| | | return ResponseValue.success(generator.getTreeRootList()); |
| | | } |
| | | |
| | | @Autowired |
| | | public PermitController(CodeServiceImpl codeService){ |
| | | this.codeService = codeService; |
| | | } |
| | | |
| | | private CodeServiceImpl codeService; |
| | | } |
New file |
| | |
| | | package com.iplatform.base.controller; |
| | | |
| | | import com.iplatform.base.SystemController; |
| | | import com.iplatform.base.event.RoleSecurityChangeEvent; |
| | | import com.iplatform.base.pojo.role.RoleAuthParam; |
| | | import com.iplatform.base.pojo.role.RoleParam; |
| | | import com.iplatform.base.pojo.role.RoleUserParam; |
| | | import com.iplatform.base.service.RoleServiceImpl; |
| | | import com.iplatform.base.util.role.SystemRole; |
| | | import com.iplatform.core.BeanContextAware; |
| | | import com.iplatform.model.po.S_role; |
| | | import com.iplatform.model.po.S_user_core; |
| | | import com.walker.db.page.GenericPager; |
| | | import com.walker.infrastructure.utils.NumberGenerator; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.web.ResponseValue; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | @RestController |
| | | @RequestMapping("/system/role") |
| | | public class RoleController extends SystemController { |
| | | |
| | | private RoleServiceImpl roleService; |
| | | |
| | | @Autowired |
| | | public RoleController(RoleServiceImpl roleService){ |
| | | this.roleService = roleService; |
| | | } |
| | | |
| | | /** |
| | | * 批量添加授权用户。 |
| | | * @param roleId 角色ID |
| | | * @param userIds 用户ID集合 |
| | | * @return |
| | | * @date 2022-12-21 |
| | | */ |
| | | @RequestMapping("/select/authUser/all") |
| | | public ResponseValue batchAuthUserList(Long roleId, Long[] userIds){ |
| | | if(userIds == null || userIds.length == 0 || roleId == null){ |
| | | return ResponseValue.error("参数错误"); |
| | | } |
| | | logger.debug(roleId + ", " + userIds); |
| | | this.roleService.execInsertRoleUserList(roleId, userIds); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | /** |
| | | * 取消已授权用户,从角色里移除。 |
| | | * @param roleUserParam |
| | | * @return |
| | | * @date 2022-12-21 |
| | | */ |
| | | @RequestMapping("/select/authUser/cancel") |
| | | public ResponseValue cancelAuthUser(@RequestBody RoleUserParam roleUserParam){ |
| | | if(roleUserParam == null || roleUserParam.getRoleId() == null || roleUserParam.getUserId() == null){ |
| | | return ResponseValue.error("参数错误"); |
| | | } |
| | | this.roleService.execDeleteRoleUser(roleUserParam.getRoleId(), roleUserParam.getUserId()); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @RequestMapping("/select/authUser/unallocatedList") |
| | | public ResponseValue unallocatedList(RoleAuthParam roleAuthParam){ |
| | | if(roleAuthParam == null || roleAuthParam.getRoleId() == null){ |
| | | return ResponseValue.error(); |
| | | } |
| | | // 2023-01-28 这个由于url地址设置不合理,没能匹配: /list 所以暂时不能删除 |
| | | this.preparePageSearch(); |
| | | |
| | | S_role s_role = this.roleService.get(new S_role(roleAuthParam.getRoleId())); |
| | | GenericPager<S_user_core> pager = this.roleService.queryUnAllocatedUserList(roleAuthParam.getRoleId(), s_role.getOrg_id(), roleAuthParam.getUserName()); |
| | | // return this.acquireTablePage(pager.getDatas(), pager.getTotalRows()); |
| | | return ResponseValue.success(pager); |
| | | } |
| | | |
| | | /** |
| | | * 展示给定角色,已关联用户列表。 |
| | | * @param roleAuthParam |
| | | * @return |
| | | * @date 2022-12-21 |
| | | */ |
| | | @RequestMapping("/select/authUser/allocatedList") |
| | | public ResponseValue allocatedList(RoleAuthParam roleAuthParam){ |
| | | if(roleAuthParam == null || roleAuthParam.getRoleId() == null){ |
| | | return ResponseValue.error(); |
| | | } |
| | | // 2023-01-28 这个由于url地址设置不合理,没能匹配: /list 所以暂时不能删除 |
| | | this.preparePageSearch(); |
| | | |
| | | GenericPager<S_user_core> pager = this.roleService.queryAllocatedUserList(roleAuthParam.getRoleId(), roleAuthParam.getUserName()); |
| | | // return this.acquireTablePage(pager.getDatas(), pager.getTotalRows()); |
| | | return ResponseValue.success(pager); |
| | | } |
| | | |
| | | @RequestMapping("/edit") |
| | | public ResponseValue saveEdit(@RequestBody SystemRole systemRole){ |
| | | if(systemRole == null || StringUtils.isEmpty(systemRole.getRole_name()) || systemRole.getOrg_id() == null |
| | | || systemRole.getRole_id() == null){ |
| | | return ResponseValue.error("角色参数错误"); |
| | | } |
| | | long orgId = systemRole.getOrg_id(); |
| | | S_role existRole = this.roleService.queryRoleByName(orgId, systemRole.getRole_name()); |
| | | if(existRole != null && existRole.getRole_id().longValue() != systemRole.getRole_id().longValue()){ |
| | | return ResponseValue.error("角色名称已经存在"); |
| | | } |
| | | |
| | | this.roleService.execUpdateRole(systemRole.$clone(), systemRole.getMenuIds()); |
| | | |
| | | // 发送事件通知,让security重新加载权限数据 |
| | | BeanContextAware.publishEvent(new RoleSecurityChangeEvent(systemRole.getRole_id())); |
| | | |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @RequestMapping("/view/{roleId}") |
| | | public ResponseValue view(@PathVariable Long roleId){ |
| | | S_role s_role = this.roleService.get(new S_role(roleId)); |
| | | if(s_role == null){ |
| | | return ResponseValue.error("角色不存在"); |
| | | } |
| | | return ResponseValue.success(s_role); |
| | | } |
| | | |
| | | @RequestMapping("/remove/{roleId}") |
| | | public ResponseValue removeRole(@PathVariable Long roleId){ |
| | | if(roleId == null || roleId.longValue() <= 0){ |
| | | return ResponseValue.error("参数错误"); |
| | | } |
| | | int roleUserCount = this.roleService.queryRoleUserSize(roleId); |
| | | if(roleUserCount > 0){ |
| | | return ResponseValue.error("角色已分配用户,无法删除"); |
| | | } |
| | | this.roleService.execDeleteRole(roleId); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @RequestMapping("/add") |
| | | public ResponseValue saveAdd(@RequestBody SystemRole systemRole){ |
| | | if(systemRole == null || StringUtils.isEmpty(systemRole.getRole_name()) || systemRole.getOrg_id() == null){ |
| | | return ResponseValue.error("角色参数错误"); |
| | | } |
| | | long orgId = systemRole.getOrg_id(); |
| | | if(orgId <= 0){ |
| | | return ResponseValue.error("角色所属机构必须提供"); |
| | | } |
| | | S_role existRole = this.roleService.queryRoleByName(orgId, systemRole.getRole_name()); |
| | | if(existRole != null){ |
| | | return ResponseValue.error("角色名称已经存在"); |
| | | } |
| | | systemRole.setRole_id(NumberGenerator.getSequenceNumber()); |
| | | this.roleService.execInsertRole(systemRole.$clone(), systemRole.getMenuIds()); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @PostMapping("/select/changeStatus") |
| | | public ResponseValue changeStatus(@RequestBody S_role s_role){ |
| | | if(s_role == null || s_role.getRole_id() == null){ |
| | | return ResponseValue.error("参数错误"); |
| | | } |
| | | this.roleService.execUpdateStatus(s_role.getRole_id(), s_role.getStatus()); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @GetMapping("/list") |
| | | public ResponseValue pageList(RoleParam roleParam){ |
| | | if(roleParam == null || roleParam.getOrgId() <= 0){ |
| | | return ResponseValue.error("无法查询角色:没有条件"); |
| | | } |
| | | // this.preparePageSearch(); |
| | | |
| | | long orgId = 0; |
| | | if(!this.isSupervisor()){ |
| | | // 普通用户,只能看到自己顶级机构用户 |
| | | orgId = this.getCurrentUser().getOrg_id(); |
| | | } else { |
| | | orgId = roleParam.getOrgId(); |
| | | } |
| | | GenericPager<S_role> pager = this.roleService.queryPageRoleList(orgId, roleParam.getStatus(), roleParam.getRoleName()); |
| | | // return this.acquireTablePage(pager.getDatas(), pager.getTotalRows()); |
| | | return ResponseValue.success(pager); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | //package com.iplatform.base.controller; |
| | | // |
| | | //import com.iplatform.base.SystemController; |
| | | //import com.iplatform.model.po.S_scheduler; |
| | | //import com.iplatform.scheduler.PlatformSchedulerManager; |
| | | //import com.iplatform.scheduler.pojo.SchedulerParam; |
| | | //import com.iplatform.scheduler.service.SchedulerServiceImpl; |
| | | //import com.walker.db.page.GenericPager; |
| | | //import com.walker.scheduler.Scheduler; |
| | | //import com.walker.web.ResponseValue; |
| | | //import org.springframework.beans.factory.annotation.Autowired; |
| | | //import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | //import org.springframework.web.bind.annotation.GetMapping; |
| | | //import org.springframework.web.bind.annotation.RequestBody; |
| | | //import org.springframework.web.bind.annotation.RequestMapping; |
| | | //import org.springframework.web.bind.annotation.RestController; |
| | | // |
| | | //@RestController |
| | | //@RequestMapping("/monitor/job") |
| | | //@ConditionalOnProperty(prefix = "iplatform.scheduler", name = "enabled", havingValue = "true", matchIfMissing = true) |
| | | //public class SchedulerController extends SystemController { |
| | | // |
| | | // private SchedulerServiceImpl schedulerService; |
| | | // private PlatformSchedulerManager platformSchedulerManager; |
| | | // |
| | | // @Autowired |
| | | // public SchedulerController(SchedulerServiceImpl schedulerService, PlatformSchedulerManager platformSchedulerManager){ |
| | | // this.schedulerService = schedulerService; |
| | | // this.platformSchedulerManager = platformSchedulerManager; |
| | | // } |
| | | // |
| | | // @RequestMapping("/select/run") |
| | | // public ResponseValue run(@RequestBody S_scheduler s_scheduler){ |
| | | // if(this.platformSchedulerManager == null){ |
| | | // return ResponseValue.error("调度模块未开启配置"); |
| | | // } |
| | | // if(s_scheduler == null){ |
| | | // return ResponseValue.error("调度任务不存在"); |
| | | // } |
| | | // Scheduler scheduler = this.platformSchedulerManager.getOneGatherScheduler(s_scheduler.getId()); |
| | | // if(scheduler == null){ |
| | | // return ResponseValue.error("调度器不存在: " + s_scheduler.getId()); |
| | | // } |
| | | // if(scheduler.isStarted() && !scheduler.isPause()){ |
| | | // return ResponseValue.error("调度器已运行,无需重复启动"); |
| | | // } |
| | | // if(scheduler.isPause()){ |
| | | // this.platformSchedulerManager.restartScheduler(s_scheduler.getId()); |
| | | // logger.info("调度任务被暂停后重启,id = " + s_scheduler.getId()); |
| | | // } else { |
| | | // logger.warn("调度任务已经在运行中,无需重复启动,id = " + s_scheduler.getId()); |
| | | // } |
| | | // return ResponseValue.success(); |
| | | // } |
| | | // |
| | | // @GetMapping("/list") |
| | | // public ResponseValue list(SchedulerParam schedulerParam){ |
| | | // if(schedulerParam == null || schedulerParam.getOrgId() <= 0){ |
| | | // return ResponseValue.error("无法查询调度任务"); |
| | | // } |
| | | //// this.preparePageSearch(); |
| | | // |
| | | // long orgId = 0; |
| | | // if(!this.isSupervisor()){ |
| | | // // 普通用户,只能看到自己顶级机构用户 |
| | | // orgId = this.getCurrentUser().getOrg_id(); |
| | | // } else { |
| | | // orgId = schedulerParam.getOrgId(); |
| | | // } |
| | | // |
| | | // GenericPager<S_scheduler> pager = this.schedulerService.queryPageSchedulerList(orgId); |
| | | // return this.acquireTablePage(pager.getDatas(), pager.getTotalRows()); |
| | | // } |
| | | //} |
New file |
| | |
| | | package com.iplatform.base.controller; |
| | | |
| | | import com.iplatform.base.*; |
| | | import com.iplatform.base.excel.UserDataImportor; |
| | | import com.iplatform.base.pojo.UserParam; |
| | | import com.iplatform.base.service.LoginServiceImpl; |
| | | import com.iplatform.base.service.RoleServiceImpl; |
| | | import com.iplatform.base.service.UserServiceImpl; |
| | | import com.iplatform.base.util.UserUtils; |
| | | import com.iplatform.base.util.role.SystemRole; |
| | | import com.iplatform.base.util.user.SystemUser; |
| | | import com.iplatform.model.po.S_role; |
| | | import com.iplatform.model.po.S_user_core; |
| | | import com.walker.db.page.GenericPager; |
| | | import com.walker.di.DataImportException; |
| | | import com.walker.file.FileInfo; |
| | | import com.walker.infrastructure.utils.DateUtils; |
| | | import com.walker.infrastructure.utils.NumberGenerator; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.web.ResponseValue; |
| | | import com.walker.web.UserOnlineProvider; |
| | | import com.walker.web.log.BusinessType; |
| | | import com.walker.web.log.Log; |
| | | import com.walker.web.log.OperateUser; |
| | | // |
| | | // |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | //@Api(tags = "用户管理模块") |
| | | @RestController |
| | | @RequestMapping("/system/user") |
| | | public class UserController extends SystemController { |
| | | |
| | | // private DeptCacheProvider deptCacheProvider; |
| | | private UserServiceImpl userService; |
| | | private RoleServiceImpl roleService; |
| | | |
| | | // 2023-03-22 |
| | | private LoginServiceImpl loginService; |
| | | private UserOnlineProvider userOnlineProvider; |
| | | |
| | | @Autowired |
| | | public UserController(UserServiceImpl userService, RoleServiceImpl roleService |
| | | // , UserCacheProvider userCacheProvider, DeptCacheProvider deptCacheProvider |
| | | , LoginServiceImpl loginService, UserOnlineProvider userOnlineProvider){ |
| | | // this.setDeptCacheProvider(deptCacheProvider); |
| | | // this.setUserCacheProvider(userCacheProvider); |
| | | this.userService = userService; |
| | | this.roleService = roleService; |
| | | this.loginService = loginService; |
| | | this.userOnlineProvider = userOnlineProvider; |
| | | } |
| | | |
| | | @PostMapping("/import") |
| | | public ResponseValue importExcel(MultipartFile file, boolean updateSupport){ |
| | | try { |
| | | UserDataImportor dataImportor = new UserDataImportor(file.getInputStream()); |
| | | dataImportor.setId("user_import"); |
| | | this.getDataImportEngine().executeImport(dataImportor, this.getCurrentUserPrincipal().getUserName()); |
| | | logger.info("成功导入记录:{}", dataImportor.getSuccessSize()); |
| | | logger.info("错误结果文件:{}", dataImportor.getErrorFile()); |
| | | |
| | | // FileInfo errorFileInfo = this.uploadFileToRemote(dataImportor.getErrorFile()); |
| | | FileInfo errorFileInfo = this.uploadFileToRemote(dataImportor.getErrorFile(), null, String.valueOf(this.getOwner())); |
| | | if(errorFileInfo != null){ |
| | | logger.debug("用户导入存在'不符合数据': ,", errorFileInfo.toString()); |
| | | logger.debug("这里可以返回给前端,让前端点击链接下载!"); |
| | | } |
| | | |
| | | return ResponseValue.success(); |
| | | |
| | | } catch (Exception e) { |
| | | if(e instanceof DataImportException){ |
| | | return ResponseValue.error("导入出现异常:" + e.getMessage()); |
| | | } |
| | | logger.error("io异常:" + e.getMessage(), e); |
| | | return ResponseValue.error("上传文件异常:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 下载导入模板,该方法可做成统一接口,适合动态生成的模板。<p></p> |
| | | * 对于特定自定义的模板,业务自己提供下载地址。 |
| | | * @author 时克英 |
| | | * @date 2023-02-08 |
| | | */ |
| | | @PostMapping("/select/downloadTemplate") |
| | | public void downloadTemplate(){ |
| | | // 要保存的模板临时路径,仅仅提供一个本地路径地址,供导入引擎自动生成并保存! |
| | | // String templatePath = "d:/tmp/template_user.xlsx"; |
| | | // TemplateInfo templateInfo = new TemplateInfo(); |
| | | // templateInfo.setTemplatePath(templatePath); |
| | | // templateInfo.setTableName("s_user_core"); |
| | | // |
| | | // File templateFile = this.getDataImportEngine().generateTemplate(templateInfo); |
| | | // |
| | | // try { |
| | | // this.downloadSimpleFile(FileCopyUtils.copyToByteArray(templateFile), "系统用户导入"); |
| | | // } catch (IOException e) { |
| | | // logger.error("下载'导出用户'模板错误:" + e.getMessage(), e); |
| | | // ServletUtils.renderString(getResponse(), "下载'导出用户'模板错误:" + e.getMessage()); |
| | | // } |
| | | this.downloadLocalImportTemplate("s_user_core"); |
| | | } |
| | | |
| | | /** |
| | | * 更新用户归属角色,用户管理 --> 设置角色 |
| | | * @param userId |
| | | * @param roleIds |
| | | * @return |
| | | * @date 2022-12-15 |
| | | */ |
| | | @PostMapping("/select/saveAuthRole") |
| | | public ResponseValue updateAuthRole(Long userId, Long[] roleIds){ |
| | | if(userId == null || userId.longValue() <= 0){ |
| | | return ResponseValue.error("参数错误"); |
| | | } |
| | | |
| | | this.userService.execUpdateAuthRole(userId, roleIds); |
| | | logger.error("更新用户归属角色后,需要更新用户登录缓存中角色列表,记住修改代码!"); |
| | | // 处理缓存的登录信息中角色更新,2023-03-22 |
| | | String uuid = this.loginService.queryLoginUUID(userId); |
| | | if(StringUtils.isNotEmpty(uuid)){ |
| | | List<String> roleIdList = new ArrayList<>(4); |
| | | for(long roleId : roleIds){ |
| | | roleIdList.add(String.valueOf(roleId)); |
| | | } |
| | | DefaultUserPrincipal userPrincipal = new DefaultUserPrincipal(this.getUser(userId)); |
| | | userPrincipal.setRoleIdList(roleIdList); |
| | | // 缓存登录信息 |
| | | this.userOnlineProvider.cacheUserPrincipal(uuid, userPrincipal); |
| | | |
| | | } else { |
| | | logger.debug("用户从未登录过,不更新登录uuid信息,userId={}", userId); |
| | | } |
| | | |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | /** |
| | | * 前端,选定用户后,获取授权角色信息。 |
| | | * @param userId |
| | | * @return |
| | | * @date 2022-12-13 |
| | | */ |
| | | @GetMapping("/select/authRole/{userId}") |
| | | public ResponseValue authRole(@PathVariable Long userId){ |
| | | // List<S_role> roleList = this.userService.queryUserRoleList(userId); |
| | | List<SystemRole> userAuthRoleList = this.userService.queryAuthRoleList(this.getUserRootOrgId(userId), userId); |
| | | Map<String, Object> data = new HashMap<>(4); |
| | | // 本单位所有角色 |
| | | data.put("roles", userAuthRoleList); |
| | | // 用户信息 |
| | | data.put("user", this.getUserCacheProvider().getUser(userId)); |
| | | return ResponseValue.success(data); |
| | | } |
| | | |
| | | // // @ApiOperation(value = "重置用户密码") |
| | | @PostMapping("/resetPwd") |
| | | public ResponseValue resetPassword(@RequestBody SystemUser systemUser){ |
| | | if(systemUser == null || systemUser.getId() == null){ |
| | | return ResponseValue.error("参数错误"); |
| | | } |
| | | String initPassword = this.getArgumentVariable(ArgumentsConstants.KEY_SECURITY_PASSWORD_INIT).getStringValue(); |
| | | this.userService.execResetPassword(systemUser.getId(), initPassword); |
| | | S_user_core user_core = this.userService.get(new S_user_core(systemUser.getId())); |
| | | this.getUserCacheProvider().updateUser(user_core); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @GetMapping("/remove/{userId}") |
| | | @Log(title = "用户管理", businessType = BusinessType.Delete, isSaveRequestData = true, isSaveResponseData = true) |
| | | public ResponseValue deleteUser(@PathVariable Long userId){ |
| | | if(userId == null || userId.longValue() <= 0){ |
| | | return ResponseValue.error("参数错误"); |
| | | } |
| | | this.userService.execDeleteUser(userId, this.getPlatformCallback(PlatformUserCallback.class)); |
| | | this.getUserCacheProvider().removeUser(userId); |
| | | logger.info("删除一个用户,缓存已更新:" + userId); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @PostMapping("/edit") |
| | | public ResponseValue editUser(@RequestBody SystemUser user_core){ |
| | | if(user_core == null){ |
| | | return ResponseValue.error("参数不存在"); |
| | | } |
| | | if(StringUtils.isEmpty(user_core.getUser_name()) || StringUtils.isEmpty(user_core.getNick_name())){ |
| | | return ResponseValue.error("缺少: 登录ID或用户昵称"); |
| | | } |
| | | if(user_core.getUser_name().equals(Constants.SUPERVISOR_NAME_DEFAULT)){ |
| | | return ResponseValue.error("无法使用该用户名"); |
| | | } |
| | | S_user_core existUser = null; |
| | | String phoneNumber = user_core.getPhonenumber(); |
| | | if(StringUtils.isNotEmpty(phoneNumber)){ |
| | | existUser = this.userService.queryUserByPhone(phoneNumber); |
| | | if(existUser != null && existUser.getId().longValue() != user_core.getId().longValue()){ |
| | | return ResponseValue.error("该手机号已被现有用户使用"); |
| | | } |
| | | } |
| | | String email = user_core.getEmail(); |
| | | if(StringUtils.isNotEmpty(email)){ |
| | | existUser = this.userService.queryUserByEmail(email); |
| | | if(existUser != null && existUser.getId().longValue() != user_core.getId().longValue()){ |
| | | return ResponseValue.error("该邮箱地址已被现有用户使用"); |
| | | } |
| | | } |
| | | this.userService.execUpdateUser(user_core.$clone(), user_core.getRoleIds(), this.getPlatformCallback(PlatformUserCallback.class)); |
| | | this.getUserCacheProvider().updateUser(user_core); |
| | | logger.info("编辑用户成功,并更新缓存: " + user_core.getUser_name()); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @PostMapping("/select/changeStatus") |
| | | public ResponseValue changeStatus(@RequestBody SystemUser systemUser){ |
| | | if(systemUser == null || systemUser.getId() == null || systemUser.getStatus() == null){ |
| | | return ResponseValue.error("缺少参数"); |
| | | } |
| | | this.userService.execUpdateUserStatus(systemUser.getId(), systemUser.getStatus()); |
| | | S_user_core user_core = this.userService.get(new S_user_core(systemUser.getId())); |
| | | this.getUserCacheProvider().updateUser(user_core); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @PostMapping("/add") |
| | | @Log(title = "用户管理", businessType = BusinessType.Insert, operatorType = OperateUser.Manage) |
| | | public ResponseValue saveUser(@RequestBody SystemUser user_core){ |
| | | if(user_core == null){ |
| | | return ResponseValue.error("参数不存在"); |
| | | } |
| | | if(StringUtils.isEmpty(user_core.getUser_name()) || StringUtils.isEmpty(user_core.getNick_name())){ |
| | | return ResponseValue.error("缺少: 登录ID或用户昵称"); |
| | | } |
| | | if(user_core.getUser_name().equals(Constants.SUPERVISOR_NAME_DEFAULT)){ |
| | | return ResponseValue.error("无法使用该用户名"); |
| | | } |
| | | S_user_core existUser = this.userService.queryUserByLoginId(user_core.getUser_name()); |
| | | if(existUser != null){ |
| | | return ResponseValue.error("登录名已存在"); |
| | | } |
| | | |
| | | // 检查并设置密码 |
| | | String encryptInitPass = null; |
| | | if(StringUtils.isEmpty(user_core.getPassword())){ |
| | | // 用户没有录入特定密码,用平台配置的默认密码 |
| | | encryptInitPass = this.getArgumentVariable(ArgumentsConstants.KEY_SECURITY_PASSWORD_INIT).getStringValue(); |
| | | } else { |
| | | // 用户输入了明文密码 |
| | | encryptInitPass = this.encryptPassword(user_core.getPassword()); |
| | | } |
| | | user_core.setPassword(encryptInitPass); |
| | | |
| | | String phoneNumber = user_core.getPhonenumber(); |
| | | if(StringUtils.isNotEmpty(phoneNumber)){ |
| | | if(this.userService.queryUserByPhone(phoneNumber) != null){ |
| | | return ResponseValue.error("该手机号已被现有用户使用"); |
| | | } |
| | | } |
| | | String email = user_core.getEmail(); |
| | | if(StringUtils.isNotEmpty(email)){ |
| | | if(this.userService.queryUserByEmail(email) != null){ |
| | | return ResponseValue.error("该邮箱地址已被现有用户使用"); |
| | | } |
| | | } |
| | | user_core.setCreate_time(DateUtils.getDateTimeNumber(System.currentTimeMillis())); |
| | | user_core.setCreate_by(this.getCurrentUser().getUser_name()); |
| | | user_core.setOrg_id(this.getRootOrgIdByDept(user_core.getDept_id())); |
| | | user_core.setId(IdUtil.generateId()); |
| | | // 注意:这里保存必须用生成的 S_user_core 对象,所以通过 SystemUser克隆一个即可。 |
| | | // 否则报错, 2022-12-13 |
| | | this.userService.execSaveUser(user_core.$clone(), user_core.getRoleIds(), this.getPlatformCallback(PlatformUserCallback.class)); |
| | | // 更新缓存 |
| | | this.getUserCacheProvider().putUser(user_core); |
| | | logger.info("添加一个用户成功,缓存已加入: " + user_core.getUser_name()); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | /** |
| | | * 创建新用户时,选择角色列表。 |
| | | * @param deptId |
| | | * @return |
| | | * @date 2022-12-12 |
| | | */ |
| | | @GetMapping("/select/role/{deptId}") |
| | | public ResponseValue getNewUserRoles(@PathVariable Long deptId){ |
| | | long orgId = 0; |
| | | if(deptId == null || deptId.longValue() == 0){ |
| | | //普通用户 |
| | | orgId = this.getCurrentUser().getOrg_id(); |
| | | } else { |
| | | // 超级管理员选了特定机构 |
| | | orgId = this.getRootOrgIdByDept(deptId); |
| | | } |
| | | List<S_role> roleList = this.roleService.queryRoleList(orgId); |
| | | Map<String, Object> data = new HashMap<>(4); |
| | | data.put("roles", roleList); |
| | | // data.put("init_password", this.getArgumentVariable(ArgumentsConstants.KEY_SECURITY_PASSWORD_INIT).getStringValue()); |
| | | return ResponseValue.success(data); |
| | | } |
| | | |
| | | /** |
| | | * 编辑用户时,获得用户信息。 |
| | | * @param userId |
| | | * @return |
| | | * @date 2022-12-13 |
| | | */ |
| | | // @GetMapping(value = { "/view", "/view/{userId}" }) |
| | | @GetMapping("/view/{userId}") |
| | | public ResponseValue getUserInfo(@PathVariable Long userId){ |
| | | if(userId == null || userId <= 0){ |
| | | return ResponseValue.error("参数错误"); |
| | | } |
| | | long orgId = this.getUserCacheProvider().getUser(userId).getOrg_id(); |
| | | List<S_role> roleList = this.roleService.queryRoleList(orgId); |
| | | List<String> roleIds = this.userService.queryUserRoleIdList(userId); |
| | | Map<String, Object> data = new HashMap<>(4); |
| | | // 本单位所有角色 |
| | | data.put("roles", roleList); |
| | | // 用户所属角色 |
| | | data.put("roleIds", UserUtils.toRoleIdLongList(roleIds)); |
| | | // 用户信息 |
| | | data.put("data", this.getUserCacheProvider().getUser(userId)); |
| | | return ResponseValue.success(data); |
| | | } |
| | | |
| | | @GetMapping("/list") |
| | | public ResponseValue list(UserParam userParam){ |
| | | if(userParam == null){ |
| | | return ResponseValue.error("无法查询用户:没有条件"); |
| | | } |
| | | // this.preparePageSearch(); |
| | | |
| | | long orgId = 0; |
| | | long deptId = userParam.getDeptId(); |
| | | |
| | | if(!this.isSupervisor()){ |
| | | // 普通用户,只能看到自己顶级机构用户 |
| | | orgId = this.getCurrentUser().getOrg_id(); |
| | | } else { |
| | | // 超级管理员 |
| | | if(deptId <= 0){ |
| | | // 没有选择机构树,无法查询用户 |
| | | return ResponseValue.error("请选择一个机构查询"); |
| | | } |
| | | orgId = this.getRootOrgIdByDept(deptId); |
| | | } |
| | | if(orgId == deptId){ |
| | | // 点击的顶级机构 |
| | | deptId = 0; |
| | | } |
| | | return ResponseValue.error("您没有权限查询!"); |
| | | // GenericPager<S_user_core> pager = this.userService.queryPageUserList(orgId |
| | | // , deptId, userParam.getUserName(), userParam.getPhonenumber(), userParam.getStatus()); |
| | | // // 补充所在'部门名字'属性,2023-03-23 |
| | | // List<S_user_core> data = pager.getDatas(); |
| | | // if(!StringUtils.isEmptyList(data)){ |
| | | // data.stream().forEach(p -> { |
| | | // p.setParameterString("dept_name", this.getDeptName(p.getDept_id())); |
| | | // }); |
| | | // } |
| | | |
| | | // return this.acquireTablePage(pager.getDatas(), pager.getTotalRows()); |
| | | // return ResponseValue.error("您没有权限查询!"); |
| | | } |
| | | |
| | | // private long getRootOrgIdByDept(long deptId){ |
| | | // S_dept dept = this.deptCacheProvider.getDept(deptId); |
| | | // if(dept == null){ |
| | | // throw new IllegalStateException("缓存中未找到机构: " + dept); |
| | | // } |
| | | // return dept.getOrg_id(); |
| | | // } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.controller; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.SystemController; |
| | | import com.iplatform.base.callback.UserProfileCallback; |
| | | import com.iplatform.base.config.SecurityUserProperties; |
| | | import com.iplatform.base.pojo.UserInfoRequest; |
| | | import com.iplatform.base.service.UserServiceImpl; |
| | | import com.iplatform.base.util.PlatformRSAUtils; |
| | | import com.iplatform.core.BeanContextAware; |
| | | import com.iplatform.core.TokenAwareContext; |
| | | import com.iplatform.core.TokenEntity; |
| | | import com.iplatform.model.po.S_user_core; |
| | | import com.iplatform.model.po.S_user_login; |
| | | import com.walker.file.FileInfo; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.web.ResponseValue; |
| | | import com.walker.web.UserOnlineProvider; |
| | | import com.walker.web.UserPrincipal; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | //@Api(tags = "用户档案") |
| | | @RestController |
| | | @RequestMapping("/system/user/profile") |
| | | public class UserProfileController extends SystemController { |
| | | |
| | | private UserServiceImpl userService; |
| | | private SecurityUserProperties securityUserProperties; |
| | | |
| | | @Autowired |
| | | public UserProfileController(UserServiceImpl userService, SecurityUserProperties securityUserProperties){ |
| | | this.userService = userService; |
| | | this.securityUserProperties = securityUserProperties; |
| | | } |
| | | |
| | | /** |
| | | * 返回登录用户基本信息。 |
| | | * @return |
| | | * @date 2023-02-15 |
| | | */ |
| | | @GetMapping |
| | | public ResponseValue index(){ |
| | | List<String> roleIdList = this.getCurrentUserPrincipal().getRoleIdList(); |
| | | Map<String, Object> data = new HashMap<>(4); |
| | | data.put("user", this.getCurrentUser()); |
| | | if(!StringUtils.isEmptyList(roleIdList)){ |
| | | data.put("roleGroup", StringUtils.collectionToCommaDelimitedString(roleIdList)); |
| | | } else { |
| | | data.put("roleGroup", StringUtils.EMPTY_STRING); |
| | | } |
| | | return ResponseValue.success(data); |
| | | } |
| | | |
| | | // // @ApiOperation(value = "上传头像") |
| | | @PostMapping("/avatar") |
| | | public ResponseValue avatar(MultipartFile file){ |
| | | if(file == null){ |
| | | return ResponseValue.error("上传头像为空"); |
| | | } |
| | | long userId = this.getCurrentUserId(); |
| | | try { |
| | | FileInfo fileInfo = this.uploadFileToRemote(file.getInputStream(), "avatar.jpg", String.valueOf(userId), file.getSize(), null, String.valueOf(Constants.OWNER_PLATFORM)); |
| | | S_user_core s_user_core = new S_user_core(userId); |
| | | s_user_core.setAvatar(fileInfo.getId()); |
| | | // 更新数据库用户记录 |
| | | this.userService.save(s_user_core); |
| | | // 更新缓存 |
| | | S_user_core cacheUser = this.getUserCacheProvider().getUser(userId); |
| | | cacheUser.setAvatar(fileInfo.getId()); |
| | | this.getUserCacheProvider().updateUser(cacheUser); |
| | | return ResponseValue.success("success","imageUrl"); |
| | | |
| | | } catch (Exception e) { |
| | | logger.error("上传头像错误:" + e.getMessage(), e); |
| | | return ResponseValue.error("头像处理异常!"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 后台用户修改资料:姓名和密码,后续扩展。 |
| | | * @param request |
| | | * @return |
| | | * @date 2023-08-02 |
| | | */ |
| | | @RequestMapping(value = "/updateInfo", method = RequestMethod.POST) |
| | | public ResponseValue updateNameAndPassword(@RequestBody UserInfoRequest request){ |
| | | if(request == null){ |
| | | return ResponseValue.error("请填写更新资料"); |
| | | } |
| | | if(StringUtils.isEmpty(request.getRealName()) && StringUtils.isEmpty(request.getPassword())){ |
| | | return ResponseValue.error("未填写任何资料"); |
| | | } |
| | | |
| | | S_user_core currentUser = this.getCurrentUser(); |
| | | |
| | | if(StringUtils.isNotEmpty(request.getPassword())){ |
| | | String originPassword = PlatformRSAUtils.getRsaDecryptValue(request.getPassword(), PlatformRSAUtils.PRIK); |
| | | // String error = PasswordUtils.filterText(originPassword); |
| | | // if(error != null){ |
| | | // return ResponseValue.error(error); |
| | | // } |
| | | // int passLevelConfig = this.securityUserProperties.getPassLevel(); |
| | | // if(!PasswordUtils.validateComplex(originPassword, passLevelConfig)){ |
| | | // return ResponseValue.error("密码级别过低,请输入:大小写字母、数字以及至少一种特殊符号"); |
| | | // } |
| | | String error = this.validatePasswordRule(originPassword); |
| | | if(error != null){ |
| | | return ResponseValue.error(error); |
| | | } |
| | | |
| | | // 设置加密后的密码,直接保存更新 |
| | | request.setPassword(this.encryptPassword(originPassword)); |
| | | currentUser.setPassword(request.getPassword()); |
| | | currentUser.setModify_pwd(1); |
| | | } |
| | | |
| | | if(StringUtils.isNotEmpty(request.getRealName())){ |
| | | currentUser.setNick_name(request.getRealName()); |
| | | } |
| | | |
| | | UserProfileCallback callback = this.getPlatformCallback(UserProfileCallback.class); |
| | | this.getUserService().execUpdateUserInfo(request, currentUser.getId(), callback); |
| | | this.getUserCacheProvider().updateUser(currentUser); |
| | | logger.debug(TokenAwareContext.getCurrentToken().toString()); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | // /** |
| | | // * 验证密码是否符合平台政策。 |
| | | //// * @param encryptPassword 前端修改的密码(密文),RSA加密,后台要解密的 |
| | | // * @param originPassword 原始明文密码 |
| | | // * @return 返回错误提示,返回空表示成功 |
| | | // * @date 2023-08-05 |
| | | // */ |
| | | // protected String validatePasswordRule(String originPassword){ |
| | | //// String originPassword = PlatformRSAUtils.getRsaDecryptValue(encryptPassword, PlatformRSAUtils.PRIK); |
| | | // String error = PasswordUtils.filterText(originPassword); |
| | | // if(error != null){ |
| | | // return error; |
| | | // } |
| | | // int passLevelConfig = this.securityUserProperties.getPassLevel(); |
| | | // if(!PasswordUtils.validateComplex(originPassword, passLevelConfig)){ |
| | | // return "密码级别过低,请输入:大小写字母、数字以及至少一种特殊符号"; |
| | | // } |
| | | // return null; |
| | | // } |
| | | |
| | | /** |
| | | * 强制当前用户修改密码 |
| | | * @param encryptPassword |
| | | * @return |
| | | * @date 2023-08-05 |
| | | */ |
| | | @RequestMapping(value = "/force_change_pass", method = RequestMethod.POST) |
| | | public ResponseValue forceChangePassword(String encryptPassword){ |
| | | if(StringUtils.isEmpty(encryptPassword)){ |
| | | return ResponseValue.error("必须填写修改密码内容"); |
| | | } |
| | | String originPassword = PlatformRSAUtils.getRsaDecryptValue(encryptPassword, PlatformRSAUtils.PRIK); |
| | | String error = this.validatePasswordRule(originPassword); |
| | | if(error != null){ |
| | | return ResponseValue.error(error); |
| | | } |
| | | |
| | | long userId = this.getCurrentUserId(); |
| | | this.getUserService().execForceChangePassword(userId, this.encryptPassword(originPassword)); |
| | | // 更新缓存 |
| | | S_user_core userCore = this.getUserService().get(new S_user_core(userId)); |
| | | this.getUserCacheProvider().updateUser(userCore); |
| | | |
| | | // 更新登录用户缓存 |
| | | String uuid = null; |
| | | UserPrincipal<S_user_core> userPrincipal = null; |
| | | UserOnlineProvider userOnlineProvider = BeanContextAware.getBeanByType(UserOnlineProvider.class); |
| | | TokenEntity tokenEntity = TokenAwareContext.getCurrentToken(); |
| | | if(tokenEntity != null){ |
| | | uuid = tokenEntity.getUuid(); |
| | | userPrincipal = (UserPrincipal<S_user_core>)userOnlineProvider.getUserPrincipal(uuid); |
| | | } else { |
| | | logger.debug("TokenAwareContext 未获取到token信息,需要从登录缓存中查询,userId={}", userId); |
| | | S_user_login user_login = this.getLoginStrategyManager().getUserLogin(userCore.getUser_name()); |
| | | if(user_login == null){ |
| | | logger.warn("用户已(强制)修改密码,但未找到登录缓存(user_login),需要重新登录,user = {}", userCore.getUser_name()); |
| | | throw new IllegalStateException(""); |
| | | } |
| | | uuid = user_login.getUuid(); |
| | | userPrincipal = (UserPrincipal<S_user_core>)userOnlineProvider.getUserPrincipal(uuid); |
| | | } |
| | | userPrincipal.getUserInfo().setModify_pwd(1); |
| | | userOnlineProvider.cacheUserPrincipal(uuid, userPrincipal); |
| | | logger.debug("密码已修改,userId={}", userId); |
| | | |
| | | return ResponseValue.success(); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.excel; |
| | | |
| | | import com.iplatform.base.di.JdbcExcelDataImportor; |
| | | import com.iplatform.base.util.DataImportUtils; |
| | | import com.walker.di.ErrorRecord; |
| | | import com.walker.di.UpdateResult; |
| | | import com.walker.di.UpdateType; |
| | | import com.walker.infrastructure.utils.PhoneNumberUtils; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; |
| | | |
| | | import java.io.InputStream; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 系统用户导入器实现。 |
| | | * @author 时克英 |
| | | * @date 2023-02-07 |
| | | */ |
| | | public class UserDataImportor extends JdbcExcelDataImportor { |
| | | |
| | | // public UserDataImportor(File file){ |
| | | // this.setBatchEnabled(); |
| | | // this.setBatchSleepMills(200); |
| | | // this.setUpdateType(UpdateType.Override); // 设置更新策略为:覆盖记录 |
| | | // try { |
| | | // this.setSource(new BufferedInputStream(new FileInputStream(file))); |
| | | // } catch (FileNotFoundException e) { |
| | | // throw new RuntimeException(e); |
| | | // } |
| | | // } |
| | | public UserDataImportor(InputStream inputStream){ |
| | | this.setBatchEnabled(); |
| | | this.setBatchSleepMills(200); |
| | | this.setUpdateType(UpdateType.Override); // 设置更新策略为:覆盖记录 |
| | | this.setSource(inputStream); |
| | | } |
| | | |
| | | @Override |
| | | protected String acquireTableName() { |
| | | return "s_user_core"; |
| | | } |
| | | |
| | | @Override |
| | | protected boolean isCheckDataExist() { |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | protected UpdateResult checkDataExist(String tableName, List<Map<String, Object>> mapList) { |
| | | // 1 - 根据导入原始数据查询是否在表中存在这些记录 |
| | | MapSqlParameterSource sqlParameterSource = new MapSqlParameterSource(); |
| | | List<String> paramUserName = DataImportUtils.acquireWhereInStringValues("user_name", mapList); |
| | | sqlParameterSource.addValue("userName", paramUserName); |
| | | List<Map<String, Object>> existList = this.getDataImportService().queryListObjectWhereIn(SQL_QUERY, sqlParameterSource); |
| | | |
| | | if(!StringUtils.isEmptyList(existList)){ |
| | | if(this.logger.isDebugEnabled()){ |
| | | for(Map<String, Object> existOne : existList){ |
| | | logger.debug("存在一条数据 = " + existOne); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 创建更新结果对象 |
| | | UpdateResult updateResult = new UpdateResult(); |
| | | |
| | | // 2 - 设置准备更新的'条件字段集合',可支持多个 |
| | | List<String> whereColumnNames = Arrays.asList("user_name"); |
| | | |
| | | // 3 - 找到新写入和需要更新的数据集合 |
| | | Object[] result = DataImportUtils.calculateInsertAndUpdateList(mapList, existList, whereColumnNames); |
| | | List<Map<String, Object>> insertList = (List<Map<String, Object>>)result[0]; |
| | | List<Map<String, Object>> updateList = (List<Map<String, Object>>)result[1]; |
| | | |
| | | // 4 - 设置要写入集合 |
| | | updateResult.setInsertList(insertList); |
| | | |
| | | // 5 - 如果更新策略为覆盖,则设置要更新集合 |
| | | if(this.getUpdateType() == UpdateType.Override){ |
| | | // 如果更新数据策略为: 覆盖模式,需要批量更新数据,这里获得更新集合给平台。 |
| | | updateResult.setUpdateColumnNames(Arrays.asList("dept_id", "org_id", "nick_name", "user_type", "email", "phonenumber", "sex")); |
| | | updateResult.setWhereColumnNames(whereColumnNames); |
| | | updateResult.setUpdateList(updateList); |
| | | } |
| | | |
| | | return updateResult; |
| | | } |
| | | |
| | | private static final String SQL_QUERY = "select * from s_user_core where user_name in (:userName)"; |
| | | |
| | | @Override |
| | | protected void finish(long currentDataRowCount, int readRowIndex) { |
| | | |
| | | } |
| | | |
| | | @Override |
| | | protected void emptyDataAfterValidate() { |
| | | |
| | | } |
| | | |
| | | @Override |
| | | protected void onValidateError(List<ErrorRecord> errorRecordList) { |
| | | |
| | | } |
| | | |
| | | @Override |
| | | protected String validateData(Map<String, String> data, int rowIndex) { |
| | | if(data.get("user_name") == null){ |
| | | return "登录名不存在"; |
| | | } |
| | | if(data.get("nick_name") == null){ |
| | | return "昵称不存在"; |
| | | } |
| | | if(data.get("user_type") == null){ |
| | | return "用户类型不存在"; |
| | | } |
| | | String phoneNumber = data.get("phonenumber"); |
| | | if(StringUtils.isNotEmpty(phoneNumber) && !PhoneNumberUtils.isCellPhoneNumber(phoneNumber)){ |
| | | return "手机号格式错误"; |
| | | } |
| | | return null; |
| | | } |
| | | } |
| | |
| | | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <parent> |
| | | <artifactId>iplatform</artifactId> |
| | | <groupId>com.iplatform</groupId> |
| | | <version>2.3.0-SNAPSHOT</version> |
| | | <artifactId>low-consum-manage</artifactId> |
| | | <groupId>com.consum</groupId> |
| | | <version>1.0.0-SNAPSHOT</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>iplatform-base-security-consum</artifactId> |
| | | <packaging>jar</packaging> |
| | | <version>1.0.0-SNAPSHOT</version> |
| | | <version>3.2.0</version> |
| | | |
| | | <properties> |
| | | </properties> |
| | |
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | --> |
| | | <dependencies> |
| | | |
| | | <dependency> |
| | | <groupId>junit</groupId> |
| | | <artifactId>junit</artifactId> |
| | | <scope>test</scope> |
| | | </dependency> |
| | | |
| | | <!-- 通过基础库引入: spring-security, 2022/10/31 --> |
| | | <dependency> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-web-security</artifactId> |
| | | <exclusions> |
| | | <exclusion> |
| | | <artifactId>spring-security-core</artifactId> |
| | | <groupId>org.springframework.security</groupId> |
| | | </exclusion> |
| | | <exclusion> |
| | | <artifactId>snakeyaml</artifactId> |
| | | <groupId>org.yaml</groupId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.springframework.security</groupId> |
| | | <artifactId>spring-security-core</artifactId> |
| | | <version>5.7.12</version> |
| | | </dependency> |
| | | |
| | | <!-- 平台基础模块必须存在, 2022/10/31 --> |
| | | <dependency> |
| | | <groupId>com.iplatform</groupId> |
| | |
| | | <scope>provided</scope> |
| | | <exclusions> |
| | | <exclusion> |
| | | <artifactId>snakeyaml</artifactId> |
| | | <groupId>org.yaml</groupId> |
| | | <artifactId>walker-web</artifactId> |
| | | <groupId>com.walkersoft</groupId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.yaml</groupId> |
| | | <artifactId>snakeyaml</artifactId> |
| | | <version>2.0</version> |
| | | <groupId>io.jsonwebtoken</groupId> |
| | | <artifactId>jjwt-api</artifactId> |
| | | <version>0.11.5</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>io.jsonwebtoken</groupId> |
| | | <artifactId>jjwt-impl</artifactId> |
| | | <version>0.11.5</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>io.jsonwebtoken</groupId> |
| | | <artifactId>jjwt-jackson</artifactId> |
| | | <version>0.11.5</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-web</artifactId> |
| | | <version>3.2.0</version> |
| | | <scope>system</scope> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/walker-web-3.2.0.jar</systemPath> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | </project> |
| | |
| | | import com.walker.web.ResponseCode; |
| | | import com.walker.web.ResponseValue; |
| | | import com.walker.web.util.ServletUtils; |
| | | import jakarta.servlet.ServletException; |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.security.authentication.AccountExpiredException; |
| | |
| | | import org.springframework.security.core.AuthenticationException; |
| | | import org.springframework.security.web.authentication.AuthenticationFailureHandler; |
| | | |
| | | import javax.servlet.ServletException; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | |
| | | public class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandler { |
| | |
| | | package com.iplatform.security; |
| | | |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import org.springframework.security.authentication.AuthenticationServiceException; |
| | | import org.springframework.security.core.Authentication; |
| | | import org.springframework.security.core.AuthenticationException; |
| | | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | |
| | | /** |
| | | * DefaultAuthenticationToken 重写后,登录总是报错: 用户名或密码错误,尝试重写该过滤器。 |
| | |
| | | |
| | | import com.walker.web.TokenGenerator; |
| | | import com.walker.web.UserPrincipal; |
| | | import jakarta.servlet.ServletException; |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.security.core.Authentication; |
| | | import org.springframework.security.web.authentication.AuthenticationSuccessHandler; |
| | | |
| | | import javax.servlet.ServletException; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | |
| | | @Deprecated |
| | |
| | | import com.walker.web.TokenGenerator; |
| | | import com.walker.web.UserOnlineProvider; |
| | | import com.walker.web.util.ServletUtils; |
| | | import jakarta.servlet.ServletException; |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.security.core.Authentication; |
| | | import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; |
| | | |
| | | import javax.servlet.ServletException; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | |
| | | public class DefaultLogoutSuccessHandler implements LogoutSuccessHandler { |
| | |
| | | import com.walker.web.WebUserAgent; |
| | | import com.walker.web.util.IdUtils; |
| | | import com.walker.web.util.ServletUtils; |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.security.authentication.AuthenticationManager; |
| | |
| | | import org.springframework.security.core.userdetails.UsernameNotFoundException; |
| | | import org.springframework.security.crypto.password.PasswordEncoder; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | |
| | | import com.walker.web.ResponseCode; |
| | | import com.walker.web.ResponseValue; |
| | | import com.walker.web.util.ServletUtils; |
| | | import jakarta.servlet.ServletException; |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.security.core.AuthenticationException; |
| | | import org.springframework.security.web.AuthenticationEntryPoint; |
| | | |
| | | import javax.servlet.ServletException; |
| | | import java.io.IOException; |
| | | |
| | | /** |
| | |
| | | protected final transient Logger logger = LoggerFactory.getLogger(getClass()); |
| | | |
| | | @Override |
| | | public void commence(javax.servlet.http.HttpServletRequest request |
| | | , javax.servlet.http.HttpServletResponse response |
| | | public void commence(HttpServletRequest request |
| | | , HttpServletResponse response |
| | | , AuthenticationException authException) throws IOException, ServletException { |
| | | |
| | | String msg = "认证失败,无权限访问系统资源" + request.getRequestURI(); |
| | |
| | | import com.walker.web.UserOnlineProvider; |
| | | import com.walker.web.UserPrincipal; |
| | | import com.walker.web.util.ServletUtils; |
| | | import jakarta.servlet.FilterChain; |
| | | import jakarta.servlet.ServletException; |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; |
| | |
| | | import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; |
| | | import org.springframework.web.filter.OncePerRequestFilter; |
| | | |
| | | import javax.servlet.FilterChain; |
| | | import javax.servlet.ServletException; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | import java.util.List; |
| | | |
| | |
| | | import com.walker.web.security.DefaultSecurityMetadataSource; |
| | | import com.walker.web.security.ResourceLoadProvider; |
| | | import com.walker.web.token.JwtTokenGenerator; |
| | | import org.apache.commons.collections4.CollectionUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.boot.web.servlet.FilterRegistrationBean; |
| | | import org.springframework.context.annotation.Bean; |
| | |
| | | import org.springframework.security.access.AccessDecisionManager; |
| | | import org.springframework.security.authentication.AuthenticationManager; |
| | | import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; |
| | | import org.springframework.security.config.annotation.web.ExceptionHandlingDsl; |
| | | import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
| | | import org.springframework.security.config.http.SessionCreationPolicy; |
| | | import org.springframework.security.core.userdetails.UserDetailsService; |
| | |
| | | } |
| | | |
| | | /** |
| | | * HttpSecurity:忽略 antMatchers 中使用的端点的身份验证,其他安全功能将生效。<br></br> |
| | | * WebSecurity:直接忽略也不会进行 CSRF xss等攻击保护。 |
| | | * @param http |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | /** |
| | | * HttpSecurity:忽略 antMatchers 中使用的端点的身份验证,其他安全功能将生效。<br></br> |
| | | * WebSecurity:直接忽略也不会进行 CSRF xss等攻击保护。 |
| | | * @param http |
| | |
| | | */ |
| | | @Bean |
| | | public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { |
| | | // 缓存 securityProperties 的结果,避免重复调用 |
| | | SecurityProperties securityProperties = this.securityProperties(); |
| | | |
| | | DefaultUserDetailsService userDetailsService = userDetailsService(this.securityProperties(), this.userCacheProvider); |
| | | DefaultUserDetailsService userDetailsService = userDetailsService(securityProperties, this.userCacheProvider); |
| | | http.userDetailsService(userDetailsService); |
| | | |
| | | // CSRF禁用,因为不使用session |
| | | http.csrf().disable(); |
| | | // ??? |
| | | http.headers().frameOptions().disable(); |
| | | // 注意:禁用CSRF需确保所有接口已通过其他方式保护 |
| | | http.csrf(csrf -> csrf.disable()); |
| | | |
| | | // 登录行为由自己实现,参考 AuthController#login |
| | | http.formLogin().disable().httpBasic().disable(); |
| | | // 禁用frameOptions以支持iframe嵌套 |
| | | // 替换弃用的 headers() 方法 |
| | | http.headers(headers -> headers.frameOptions(frameOptions -> frameOptions.disable())); |
| | | |
| | | // 匿名资源访问权限,返回无权限提示接口 |
| | | http.exceptionHandling().authenticationEntryPoint(failedAuthenticationEntryPoint()) |
| | | // 已认证用户无权限访问配置 |
| | | .accessDeniedHandler(this.accessDeniedHandler()) |
| | | .and() |
| | | // 基于token,所以不需要session |
| | | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); |
| | | // 禁用默认登录和HTTP Basic认证 |
| | | http.formLogin(formLogin -> formLogin.disable()); |
| | | |
| | | // http.formLogin().loginProcessingUrl("/login") |
| | | // .failureHandler(this.authenticationFailureHandler()); |
| | | // 注意:这里不能配置上面的登录,否则就不会执行自己实现的/login方法。2022-11-11 |
| | | http.logout().logoutUrl("/logout").logoutSuccessHandler(this.logoutSuccessHandler()).permitAll(); |
| | | // 异常处理配置 |
| | | http.exceptionHandling(exceptionHandling -> exceptionHandling |
| | | .authenticationEntryPoint(failedAuthenticationEntryPoint()) |
| | | .accessDeniedHandler(this.accessDeniedHandler())); |
| | | |
| | | // 匿名访问集合,2022-11-07 |
| | | List<String> anonymousList = this.securityProperties().getAnonymousList(); |
| | | if(!StringUtils.isEmptyList(anonymousList)){ |
| | | http.authorizeHttpRequests().antMatchers(anonymousList.toArray(new String[]{})).permitAll(); |
| | | } |
| | | // http.authorizeHttpRequests().antMatchers("/login", "/register", "/captchaImage", "/test/**").permitAll(); |
| | | // http.authorizeHttpRequests().antMatchers("/static/**", "/test/**").permitAll(); |
| | | // http.authorizeHttpRequests().antMatchers("/security/**").hasAuthority("query_user"); |
| | | // 基于token,所以不需要session |
| | | http.sessionManagement(sessionManagement -> sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); |
| | | |
| | | // 2023-03-21 注释掉,调试activiti7时发现和下面重复, |
| | | // http.addFilterBefore(securityInterceptor(), FilterSecurityInterceptor.class); |
| | | /*http.authorizeHttpRequests().withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>(){ |
| | | @Override |
| | | public <O extends FilterSecurityInterceptor> O postProcess(O object) { |
| | | object.setAccessDecisionManager(accessDecisionManager());//决策管理器 |
| | | object.setSecurityMetadataSource(securityMetadataSource());//安全元数据源 |
| | | return object; |
| | | } |
| | | });*/ |
| | | // 登出配置 |
| | | http.logout(logout -> logout |
| | | .logoutUrl("/logout") |
| | | .logoutSuccessHandler(this.logoutSuccessHandler()) |
| | | .permitAll()); |
| | | |
| | | // 2023-01-28 配置自定义认证提供者(密码验证用) |
| | | http.authenticationProvider(this.authenticationProvider(userDetailsService, securityProperties())); |
| | | // 配置匿名访问权限 |
| | | configureAnonymousAccess(http, securityProperties); |
| | | |
| | | // 配置自定义认证提供者 |
| | | http.authenticationProvider(this.authenticationProvider(userDetailsService, securityProperties)); |
| | | |
| | | // 所有请求都需要认证 |
| | | http.authorizeHttpRequests().anyRequest().authenticated(); |
| | | // 使用自定义动态拦截器,拦截所有权限请求,2022-11-02 |
| | | http.authorizeHttpRequests(authorizeHttpRequests -> authorizeHttpRequests.anyRequest().authenticated()); |
| | | |
| | | // 添加自定义动态拦截器 |
| | | http.addFilterBefore(securityInterceptor(), FilterSecurityInterceptor.class); |
| | | |
| | | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | // token拦截过滤器,2022-11-02 |
| | | // 必须在这里添加拦截,不能放在'FilterSecurityInterceptor'之后,因为如果放在之后,那么就无法获得用户信息,从而无法 |
| | | // 获得用户所具有的权限角色集合:roleIdList。2022-11-14(2) |
| | | // 添加JWT认证过滤器 |
| | | http.addFilterBefore(jwtAuthenticationTokenFilter(userDetailsService), UsernamePasswordAuthenticationFilter.class); |
| | | // http.addFilterBefore(jwtAuthenticationTokenFilter(), DefaultAuthenticationFilter.class); |
| | | // 尝试让jwt在URL权限之后才拦截, 2022-11-14(1) |
| | | // 注意:以上 UsernamePasswordAuthenticationFilter 需要去掉才能生效 |
| | | // http.addFilterAfter(jwtAuthenticationTokenFilter(), FilterSecurityInterceptor.class); |
| | | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | if(this.securityProperties().isCorsEnabled()){ |
| | | // 解决跨域过滤器,2022-11-06 |
| | | http.addFilterBefore(this.corsFilter().getFilter(), JwtAuthenticationTokenFilter.class); |
| | | // 未知?2022-11-11 |
| | | http.addFilterBefore(this.corsFilter().getFilter(), LogoutFilter.class); |
| | | } else { |
| | | System.out.println("不添加跨域过滤器: "); |
| | | } |
| | | // 配置跨域过滤器 |
| | | configureCorsFilter(http, securityProperties); |
| | | |
| | | return http.build(); |
| | | } |
| | | |
| | | /** |
| | | * 配置匿名访问权限 |
| | | */ |
| | | private void configureAnonymousAccess(HttpSecurity http, SecurityProperties securityProperties) throws Exception { |
| | | List<String> anonymousList = securityProperties.getAnonymousList(); |
| | | if (!CollectionUtils.isEmpty(anonymousList)) { |
| | | http.authorizeHttpRequests(authorizeHttpRequests -> authorizeHttpRequests |
| | | .requestMatchers(anonymousList.toArray(new String[0])).permitAll()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 配置跨域过滤器 |
| | | */ |
| | | private void configureCorsFilter(HttpSecurity http, SecurityProperties securityProperties) throws Exception { |
| | | if (securityProperties.isCorsEnabled()) { |
| | | CorsFilter corsFilter = this.corsFilter().getFilter(); |
| | | if (corsFilter != null) { |
| | | http.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class) |
| | | .addFilterBefore(corsFilter, LogoutFilter.class); |
| | | logger.info("跨域过滤器已启用"); |
| | | } else { |
| | | logger.warn("跨域过滤器未正确初始化"); |
| | | } |
| | | } else { |
| | | logger.info("跨域过滤器未启用"); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取AuthenticationManager(认证管理器),登录时认证使用 |
| | | * @param authenticationConfiguration |
| | | * @return |
| | |
| | | } else { |
| | | // 2023-10-13 |
| | | logger.debug("存在业务自定义权限回调:{}", securityCallback.getClass().getName()); |
| | | Set<String> userPermission = securityCallback.loadUserPermission(userPrincipal.getUserInfo(), menuIdList); |
| | | Set<String> userPermission = securityCallback.loadUserPermission(userPrincipal.getUserInfo(), menuIdList, null); |
| | | if(userPermission != null){ |
| | | perms.addAll(userPermission); |
| | | } |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | |
| | | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <parent> |
| | | <artifactId>low-consum-manage</artifactId> |
| | | <groupId>com.consum</groupId> |
| | | <version>1.0.0-SNAPSHOT</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <groupId>com.iplatform</groupId> |
| | | <artifactId>iplatform-base-tcp</artifactId> |
| | | <name>iplatform-base-tcp</name> |
| | | <packaging>jar</packaging> |
| | | <version>3.2.0</version> |
| | | |
| | | <dependencies> |
| | | |
| | | <!-- 依赖底层通信模块,2024-01-23 --> |
| | | <dependency> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-tcp</artifactId> |
| | | <version>${walker-web-security.version}</version> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/walker-tcp-3.2.0.jar</systemPath> |
| | | <scope>system</scope> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.postgresql</groupId> |
| | | <artifactId>postgresql</artifactId> |
| | | <version>4.2</version> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/tdsql-pg-connector-java8-1.0.5.jar</systemPath> |
| | | <scope>system</scope> |
| | | </dependency> |
| | | |
| | | <!-- 提供平台基础环境,2023-04-16 --> |
| | | <dependency> |
| | | <groupId>com.iplatform</groupId> |
| | | <artifactId>iplatform-base</artifactId> |
| | | <exclusions> |
| | | <exclusion> |
| | | <artifactId>walker-web</artifactId> |
| | | <groupId>com.walkersoft</groupId> |
| | | </exclusion> |
| | | <exclusion> |
| | | <artifactId>jjwt</artifactId> |
| | | <groupId>io.jsonwebtoken</groupId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.consum</groupId> |
| | | <artifactId>iplatform-base-security-consum</artifactId> |
| | | <version>3.2.0</version> |
| | | <exclusions> |
| | | <exclusion> |
| | | <artifactId>walker-web</artifactId> |
| | | <groupId>com.walkersoft</groupId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.iplatform</groupId> |
| | | <artifactId>iplatform-file-server</artifactId> |
| | | </dependency> |
| | | <!-- 阿里druid数据库连接池,如果使用直接引入到业务发布模块中,2023-03-15 --> |
| | | <dependency> |
| | | <groupId>com.alibaba</groupId> |
| | | <artifactId>druid</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>io.netty</groupId> |
| | | <artifactId>netty-transport</artifactId> |
| | | <version>${netty.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>io.netty</groupId> |
| | | <artifactId>netty-codec</artifactId> |
| | | <version>${netty.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>io.netty</groupId> |
| | | <artifactId>netty-handler</artifactId> |
| | | <version>${netty.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>io.netty</groupId> |
| | | <artifactId>netty-codec-http</artifactId> |
| | | <version>${netty.version}</version> |
| | | </dependency> |
| | | <!-- 扫码包下面的 TcpRequest 注解使用,2023-04-16 --> |
| | | <dependency> |
| | | <groupId>org.reflections</groupId> |
| | | <artifactId>reflections</artifactId> |
| | | <version>0.9.9</version> |
| | | </dependency> |
| | | |
| | | <!-- RocketMQ Spring 框架依赖。2023-09-18 --> |
| | | <dependency> |
| | | <groupId>org.apache.rocketmq</groupId> |
| | | <artifactId>rocketmq-spring-boot-starter</artifactId> |
| | | <version>2.1.0</version> |
| | | <exclusions> |
| | | <exclusion> |
| | | <groupId>org.slf4j</groupId> |
| | | <artifactId>slf4j-api</artifactId> |
| | | </exclusion> |
| | | <exclusion> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot</artifactId> |
| | | </exclusion> |
| | | <exclusion> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-autoconfigure</artifactId> |
| | | </exclusion> |
| | | <exclusion> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-autoconfigure-processor</artifactId> |
| | | </exclusion> |
| | | <exclusion> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-configuration-processor</artifactId> |
| | | </exclusion> |
| | | <exclusion> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-test</artifactId> |
| | | </exclusion> |
| | | <exclusion> |
| | | <groupId>org.springframework</groupId> |
| | | <artifactId>spring-messaging</artifactId> |
| | | </exclusion> |
| | | <exclusion> |
| | | <groupId>org.springframework</groupId> |
| | | <artifactId>spring-core</artifactId> |
| | | </exclusion> |
| | | <exclusion> |
| | | <groupId>org.springframework</groupId> |
| | | <artifactId>spring-context</artifactId> |
| | | </exclusion> |
| | | <exclusion> |
| | | <groupId>org.springframework</groupId> |
| | | <artifactId>spring-aop</artifactId> |
| | | </exclusion> |
| | | <exclusion> |
| | | <groupId>com.fasterxml.jackson.core</groupId> |
| | | <artifactId>jackson-databind</artifactId> |
| | | </exclusion> |
| | | <exclusion> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter</artifactId> |
| | | </exclusion> |
| | | <exclusion> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-validation</artifactId> |
| | | </exclusion> |
| | | </exclusions> |
| | | |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springframework</groupId> |
| | | <artifactId>spring-messaging</artifactId> |
| | | </dependency> |
| | | |
| | | <!--websocket作为客户端--> |
| | | <dependency> |
| | | <groupId>org.java-websocket</groupId> |
| | | <artifactId>Java-WebSocket</artifactId> |
| | | <version>1.5.4</version> |
| | | <scope>test</scope> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | | |
| | | <build> |
| | | <finalName>ctoms-websocket</finalName> |
| | | <plugins> |
| | | <plugin> |
| | | <!--能够自动寻找springboot引导类,或者手动指定--> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-maven-plugin</artifactId> |
| | | <version>${spring-boot.version}</version> |
| | | <executions> |
| | | <execution> |
| | | <goals> |
| | | <goal>repackage</goal> |
| | | </goals> |
| | | </execution> |
| | | </executions> |
| | | <configuration> |
| | | <!-- 2023-11-06 该参数指定了依赖的本地类库,不引入则报错:不能指向本地jar文件 --> |
| | | <arguments> |
| | | <argument>${project.basedir}/src/main/resources/lib</argument> |
| | | </arguments> |
| | | <!-- 2023-11-06 该参数指定,打包忽略 Main 函数。--> |
| | | <!-- <skip>true</skip>--> |
| | | <!--本地包导入配置--> |
| | | <includeSystemScope>true</includeSystemScope> |
| | | <!--自定义分类器配置,防止父子项目打包失败--> |
| | | <!-- <classifier>exec</classifier>--> |
| | | </configuration> |
| | | </plugin> |
| | | <plugin> |
| | | <groupId>org.apache.maven.plugins</groupId> |
| | | <artifactId>maven-deploy-plugin</artifactId> |
| | | <version>${maven-deploy-plugin.version}</version> |
| | | <executions> |
| | | <execution> |
| | | <id>default-deploy</id> |
| | | <phase>deploy</phase> |
| | | <goals> |
| | | <goal>deploy</goal> |
| | | </goals> |
| | | <!-- skip默认deploy插件的执行 --> |
| | | <configuration> |
| | | <skip>true</skip> |
| | | </configuration> |
| | | </execution> |
| | | </executions> |
| | | </plugin> |
| | | </plugins> |
| | | </build> |
| | | |
| | | </project> |
New file |
| | |
| | | package com.iplatform; |
| | | |
| | | import org.springframework.boot.SpringApplication; |
| | | import org.springframework.boot.autoconfigure.SpringBootApplication; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; |
| | | import org.springframework.scheduling.annotation.EnableAsync; |
| | | |
| | | @SpringBootApplication(scanBasePackages = {"com.walker","com.iplatform"}) |
| | | @EnableAsync |
| | | public class CtomsTcpApplication { |
| | | |
| | | public static void main(String[] args) throws Exception{ |
| | | SpringApplication.run(CtomsTcpApplication.class, args); |
| | | } |
| | | |
| | | // @Bean |
| | | // public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() { |
| | | // PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer(); |
| | | // propertySourcesPlaceholderConfigurer.setIgnoreUnresolvablePlaceholders(true); |
| | | // return propertySourcesPlaceholderConfigurer; |
| | | // } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp; |
| | | |
| | | public class Constants { |
| | | |
| | | public static final String CACHE_NAME_EQUIPMENT = "cache.tcp.equip"; |
| | | public static final String CACHE_NAME_EQUIPMENT_STATUS = "cache.tcp.equip_status"; |
| | | |
| | | /** |
| | | * TCP模块缓存:长连接对象缓存。 |
| | | * @date 2023-09-23 |
| | | */ |
| | | public static final String CACHE_NAME_CONNECTION = "cache.tcp.connect"; |
| | | |
| | | // public static final String QUEUE_TYPE_MEMORY = "memory"; |
| | | |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp; |
| | | |
| | | /** |
| | | * TCP通信引擎类型定义。 |
| | | * @author 时克英 |
| | | * @date 2023-04-17 |
| | | */ |
| | | public enum EngineType { |
| | | |
| | | TcpEngine{ |
| | | public int getIndex(){ |
| | | return INDEX_TCP_ENGINE; |
| | | } |
| | | }, |
| | | WebsocketEngine{ |
| | | public int getIndex(){ |
| | | return INDEX_TCP_WEBSOCKET; |
| | | } |
| | | }; |
| | | |
| | | public int getIndex(){ |
| | | throw new AbstractMethodError(); |
| | | } |
| | | |
| | | public EngineType getType(int index){ |
| | | if(index == INDEX_TCP_ENGINE){ |
| | | return TcpEngine; |
| | | } else if(index == INDEX_TCP_WEBSOCKET){ |
| | | return WebsocketEngine; |
| | | } else { |
| | | throw new UnsupportedOperationException("不支持的通信引擎:" + index); |
| | | } |
| | | } |
| | | |
| | | public static final int INDEX_TCP_ENGINE = 1; |
| | | public static final int INDEX_TCP_WEBSOCKET = 2; |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp; |
| | | |
| | | import com.iplatform.model.po.TcpEquip; |
| | | |
| | | /** |
| | | * TCP设备缓存定义。<p>设备编号唯一,在所有机构中也是唯一的</p> |
| | | * @author 时克英 |
| | | * @date 2023-04-16 |
| | | */ |
| | | public interface EquipmentCacheProvider { |
| | | |
| | | void putEquipment(String key, TcpEquip tcpEquip); |
| | | |
| | | TcpEquip getEquipment(String key); |
| | | |
| | | void removeEquipment(String key); |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp; |
| | | |
| | | import com.iplatform.model.po.TcpEquipStatus; |
| | | |
| | | /** |
| | | * 设备状态缓存,一个设备对应一条记录。 |
| | | * @author 时克英 |
| | | * @date 2023-04-16 |
| | | */ |
| | | public interface EquipmentStatusCacheProvider { |
| | | |
| | | void putEquipmentStatus(String key, TcpEquipStatus tcpEquip); |
| | | |
| | | TcpEquipStatus getEquipmentStatus(String key); |
| | | |
| | | void removeEquipmentStatus(String key); |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp; |
| | | |
| | | /** |
| | | * 通讯连接状态枚举类型定义 |
| | | * @author 时克英 |
| | | * @date 2018-11-29 |
| | | * |
| | | */ |
| | | public enum LiveStatus { |
| | | |
| | | /** |
| | | * 未连接:0 |
| | | */ |
| | | NotConnect { |
| | | public int getTypeValue(){ |
| | | return CONST_NOT_CONNECT; |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 已连接:1 |
| | | */ |
| | | Connected { |
| | | public int getTypeValue(){ |
| | | return CONST_CONNECTED; |
| | | } |
| | | }; |
| | | |
| | | public static final int CONST_CONNECTED = 1; |
| | | public static final int CONST_NOT_CONNECT = 0; |
| | | |
| | | public int getTypeValue(){ |
| | | throw new AbstractMethodError(); |
| | | } |
| | | |
| | | public static LiveStatus getType(int index){ |
| | | if(index == CONST_CONNECTED){ |
| | | return Connected; |
| | | } else if(index == CONST_NOT_CONNECT){ |
| | | return NotConnect; |
| | | } else |
| | | throw new IllegalArgumentException("unsupported LiveStatus: " + index); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp; |
| | | |
| | | import com.iplatform.base.SystemController; |
| | | |
| | | public abstract class TcpBaseController extends SystemController { |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.cache; |
| | | |
| | | import com.iplatform.model.po.TcpEquipStatus; |
| | | import com.iplatform.tcp.Constants; |
| | | import com.iplatform.tcp.EquipmentStatusCacheProvider; |
| | | import com.iplatform.tcp.service.TcpEquipStatusServiceImpl; |
| | | import com.walker.cache.AbstractCacheProvider; |
| | | import com.walker.cache.Cache; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | |
| | | import java.util.List; |
| | | |
| | | public class LocalEquipStatusCacheProvider extends AbstractCacheProvider<TcpEquipStatus> implements EquipmentStatusCacheProvider { |
| | | |
| | | @Override |
| | | public void putEquipmentStatus(String key, TcpEquipStatus tcpEquipStatus) { |
| | | this.putCacheData(key, tcpEquipStatus); |
| | | } |
| | | |
| | | @Override |
| | | public TcpEquipStatus getEquipmentStatus(String key) { |
| | | return this.getCacheData(key); |
| | | } |
| | | |
| | | @Override |
| | | public void removeEquipmentStatus(String key) { |
| | | this.removeCacheData(key); |
| | | } |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | List<TcpEquipStatus> hosts = this.tcpEquipStatusService.selectAll(new TcpEquipStatus()); |
| | | if(!StringUtils.isEmptyList(hosts)){ |
| | | for(TcpEquipStatus h : hosts){ |
| | | cache.put(h.getEquipNum(), h); |
| | | } |
| | | return hosts.size(); |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_EQUIPMENT_STATUS; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return TcpEquipStatus.class; |
| | | } |
| | | |
| | | public void setTcpEquipStatusService(TcpEquipStatusServiceImpl tcpEquipStatusService) { |
| | | this.tcpEquipStatusService = tcpEquipStatusService; |
| | | } |
| | | |
| | | private TcpEquipStatusServiceImpl tcpEquipStatusService; |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.cache; |
| | | |
| | | import com.iplatform.model.po.TcpEquip; |
| | | import com.iplatform.tcp.Constants; |
| | | import com.iplatform.tcp.EquipmentCacheProvider; |
| | | import com.iplatform.tcp.service.TcpEquipServiceImpl; |
| | | import com.walker.cache.AbstractCacheProvider; |
| | | import com.walker.cache.Cache; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | |
| | | import java.util.List; |
| | | |
| | | public class LocalEquipmentCacheProvider extends AbstractCacheProvider<TcpEquip> implements EquipmentCacheProvider { |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | List<TcpEquip> hosts = this.tcpEquipService.selectAll(new TcpEquip()); |
| | | if(!StringUtils.isEmptyList(hosts)){ |
| | | for(TcpEquip h : hosts){ |
| | | cache.put(h.getNum(), h); |
| | | } |
| | | return hosts.size(); |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_EQUIPMENT; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return TcpEquip.class; |
| | | } |
| | | |
| | | public void setTcpEquipService(TcpEquipServiceImpl tcpEquipService) { |
| | | this.tcpEquipService = tcpEquipService; |
| | | } |
| | | |
| | | private TcpEquipServiceImpl tcpEquipService; |
| | | |
| | | @Override |
| | | public void putEquipment(String key, TcpEquip tcpEquip) { |
| | | this.putCacheData(key, tcpEquip); |
| | | } |
| | | |
| | | @Override |
| | | public TcpEquip getEquipment(String key) { |
| | | return this.getCacheData(key); |
| | | } |
| | | |
| | | @Override |
| | | public void removeEquipment(String key) { |
| | | this.removeCacheData(key); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.cache; |
| | | |
| | | import com.iplatform.model.po.TcpEquipStatus; |
| | | import com.iplatform.tcp.Constants; |
| | | import com.iplatform.tcp.EquipmentStatusCacheProvider; |
| | | import com.iplatform.tcp.service.TcpEquipStatusServiceImpl; |
| | | import com.walker.cache.Cache; |
| | | import com.walker.support.redis.cache.RedisCacheProvider; |
| | | |
| | | public class RedisEquipStatusCacheProvider extends RedisCacheProvider<TcpEquipStatus> implements EquipmentStatusCacheProvider { |
| | | |
| | | public RedisEquipStatusCacheProvider(){ |
| | | this.setUseRedis(true); |
| | | this.setLoadPage(false); |
| | | } |
| | | |
| | | @Override |
| | | public void putEquipmentStatus(String key, TcpEquipStatus tcpEquipStatus) { |
| | | this.putCacheData(key, tcpEquipStatus); |
| | | } |
| | | |
| | | @Override |
| | | public TcpEquipStatus getEquipmentStatus(String key) { |
| | | return this.getCacheData(key); |
| | | } |
| | | |
| | | @Override |
| | | public void removeEquipmentStatus(String key) { |
| | | this.removeCacheData(key); |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_EQUIPMENT_STATUS; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return TcpEquipStatus.class; |
| | | } |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | // List<TcpEquipStatus> hosts = this.tcpEquipStatusService.selectAll(new TcpEquipStatus()); |
| | | // if(!StringUtils.isEmptyList(hosts)){ |
| | | // // ------------------------- 切换成普通缓存步骤:3 |
| | | // if(this.isUseRedis()){ |
| | | // // 如果redis中缓存数量和数据库中不一致(少),则清空redis缓存,重新加载数据库数据到缓存中。 |
| | | // long totalCache = cache.getPersistentSize(); |
| | | // if(totalCache != hosts.size()){ |
| | | // logger.info("redis缓存中用户数量小于实际用户,需要清空缓存重新加载! cache = " + totalCache + ", db = " + hosts.size()); |
| | | // cache.clear(); |
| | | // |
| | | // for(TcpEquipStatus h : hosts){ |
| | | // cache.put(h.getEquipNum(), h); |
| | | // } |
| | | // } |
| | | // }//------------------------------------------ |
| | | // return hosts.size(); |
| | | // } |
| | | return 0; |
| | | } |
| | | |
| | | public void setTcpEquipStatusService(TcpEquipStatusServiceImpl tcpEquipStatusService) { |
| | | this.tcpEquipStatusService = tcpEquipStatusService; |
| | | } |
| | | |
| | | private TcpEquipStatusServiceImpl tcpEquipStatusService; |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.cache; |
| | | |
| | | import com.iplatform.model.po.TcpEquip; |
| | | import com.iplatform.tcp.Constants; |
| | | import com.iplatform.tcp.EquipmentCacheProvider; |
| | | import com.iplatform.tcp.service.TcpEquipServiceImpl; |
| | | import com.walker.cache.Cache; |
| | | import com.walker.support.redis.cache.RedisCacheProvider; |
| | | |
| | | public class RedisEquipmentCacheProvider extends RedisCacheProvider<TcpEquip> implements EquipmentCacheProvider { |
| | | |
| | | public RedisEquipmentCacheProvider(){ |
| | | this.setUseRedis(true); |
| | | this.setLoadPage(false); |
| | | } |
| | | |
| | | @Override |
| | | public void putEquipment(String key, TcpEquip tcpEquip) { |
| | | this.putCacheData(key, tcpEquip); |
| | | } |
| | | |
| | | @Override |
| | | public TcpEquip getEquipment(String key) { |
| | | return this.getCacheData(key); |
| | | } |
| | | |
| | | @Override |
| | | public void removeEquipment(String key) { |
| | | this.removeCacheData(key); |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_EQUIPMENT; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return TcpEquip.class; |
| | | } |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | // List<TcpEquip> hosts = this.tcpEquipService.selectAll(new TcpEquip()); |
| | | // if(!StringUtils.isEmptyList(hosts)){ |
| | | // // ------------------------- 切换成普通缓存步骤:3 |
| | | // if(this.isUseRedis()){ |
| | | // // 如果redis中缓存数量和数据库中不一致(少),则清空redis缓存,重新加载数据库数据到缓存中。 |
| | | // long totalCache = cache.getPersistentSize(); |
| | | // if(totalCache != hosts.size()){ |
| | | // logger.info("redis缓存中用户数量小于实际用户,需要清空缓存重新加载! cache = " + totalCache + ", db = " + hosts.size()); |
| | | // cache.clear(); |
| | | // |
| | | // for(TcpEquip h : hosts){ |
| | | // cache.put(h.getNum(), h); |
| | | // } |
| | | // } |
| | | // }//------------------------------------------ |
| | | // return hosts.size(); |
| | | // } |
| | | return 0; |
| | | } |
| | | |
| | | public void setTcpEquipService(TcpEquipServiceImpl tcpEquipService) { |
| | | this.tcpEquipService = tcpEquipService; |
| | | } |
| | | |
| | | private TcpEquipServiceImpl tcpEquipService; |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.config; |
| | | |
| | | import com.iplatform.core.PlatformConfiguration; |
| | | import com.iplatform.tcp.lb.DefaultResponseWriter; |
| | | import com.walker.push.rocketmq.RocketMQEnhanceTemplate; |
| | | import com.walker.tcp.lb.ResponseWriter; |
| | | import org.apache.rocketmq.spring.core.RocketMQTemplate; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | |
| | | /** |
| | | * 长连接负载方式时,启用MQ模板以及相关配置。 |
| | | * @author 时克英 |
| | | * @date 2023-09-26 |
| | | */ |
| | | @Configuration |
| | | @ConditionalOnProperty(prefix = "iplatform.tcp", name = "load-balance-enabled", havingValue = "true", matchIfMissing = false) |
| | | @ConditionalOnClass({RocketMQTemplate.class}) |
| | | public class LoadBalanceMQConfig extends PlatformConfiguration { |
| | | |
| | | private RocketMQTemplate rocketMQTemplate; |
| | | |
| | | @Autowired |
| | | public LoadBalanceMQConfig(RocketMQTemplate rocketMQTemplate){ |
| | | this.rocketMQTemplate = rocketMQTemplate; |
| | | } |
| | | |
| | | /** |
| | | * 默认RocketMQ监听器配置,测试使用。正式需要删除 |
| | | * @param connectionManager |
| | | // * @param template |
| | | * @return |
| | | * @date 2023-09-27 |
| | | */ |
| | | // @Bean |
| | | // public DefaultMqListener defaultMqListener(ConnectionManager connectionManager, RocketMQEnhanceTemplate template){ |
| | | // DefaultMqListener listener = new DefaultMqListener(); |
| | | // listener.setConnectionManager(connectionManager); |
| | | // listener.setRocketMQEnhanceTemplate(template); |
| | | // return listener; |
| | | // } |
| | | |
| | | /** |
| | | * 监听对象放在业务中处理,平台注释该对象,业务通过MQ接收其他节点发送的聊天消息。<br> |
| | | * |
| | | * 1)如果要在平台测试负责聊天,请放开注释,启用:SimpleMqListener |
| | | * @date 2023-12-14 |
| | | */ |
| | | // @Bean |
| | | // public SimpleMqListener simpleMqListener(ConnectionManager connectionManager){ |
| | | // SimpleMqListener listener = new SimpleMqListener(); |
| | | // listener.setConnectionManager(connectionManager); |
| | | // return listener; |
| | | // } |
| | | |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | //~ 以下为正式配置,上面为测试内容。 |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | /** |
| | | * 长连接响应消息写入通道具体实现。 |
| | | * <p>目前在负载模式中,发送消息到MQ,因为<code>LongConnectionMeta</code>从Redis反序列化后,无法执行子类write,所以通过该对象完成写入。</p> |
| | | * @return |
| | | * @date 2023-09-27 |
| | | */ |
| | | @Bean |
| | | public ResponseWriter responseWriter(){ |
| | | return new DefaultResponseWriter(); |
| | | } |
| | | |
| | | @Bean |
| | | public RocketMQEnhanceTemplate rocketMQEnhanceTemplate(){ |
| | | RocketMQEnhanceTemplate template = new RocketMQEnhanceTemplate(); |
| | | template.setTemplate(this.rocketMQTemplate); |
| | | // template.setEnabledIsolation(); |
| | | // template.setEnvironmentName(); |
| | | return template; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.config; |
| | | |
| | | import com.iplatform.core.PlatformConfiguration; |
| | | import com.iplatform.tcp.EquipmentCacheProvider; |
| | | import com.iplatform.tcp.EquipmentStatusCacheProvider; |
| | | import com.iplatform.tcp.cache.LocalEquipStatusCacheProvider; |
| | | import com.iplatform.tcp.cache.LocalEquipmentCacheProvider; |
| | | import com.iplatform.tcp.service.TcpEquipServiceImpl; |
| | | import com.iplatform.tcp.service.TcpEquipStatusServiceImpl; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | |
| | | @Configuration |
| | | @ConditionalOnProperty(prefix = "iplatform.cache", name = "redis-enabled", havingValue = "false", matchIfMissing = true) |
| | | public class LocalTcpCacheConfig extends PlatformConfiguration { |
| | | |
| | | /** |
| | | * 配置TCP设备信息缓存 |
| | | * @param tcpEquipService |
| | | * @return |
| | | * @date 2023-04-16 |
| | | */ |
| | | @Bean |
| | | public EquipmentCacheProvider equipmentCacheProvider(TcpEquipServiceImpl tcpEquipService){ |
| | | LocalEquipmentCacheProvider localEquipmentCacheProvider = new LocalEquipmentCacheProvider(); |
| | | localEquipmentCacheProvider.setTcpEquipService(tcpEquipService); |
| | | return localEquipmentCacheProvider; |
| | | } |
| | | |
| | | /** |
| | | * 配置设备状态缓存,一个设备一条记录。 |
| | | * @param tcpEquipStatusService |
| | | * @return |
| | | * @date 2023-04-16 |
| | | */ |
| | | @Bean |
| | | public EquipmentStatusCacheProvider equipmentStatusCacheProvider(TcpEquipStatusServiceImpl tcpEquipStatusService){ |
| | | LocalEquipStatusCacheProvider localEquipStatusCacheProvider = new LocalEquipStatusCacheProvider(); |
| | | localEquipStatusCacheProvider.setTcpEquipStatusService(tcpEquipStatusService); |
| | | return localEquipStatusCacheProvider; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.config; |
| | | |
| | | import com.iplatform.core.PlatformConfiguration; |
| | | import com.iplatform.tcp.EquipmentCacheProvider; |
| | | import com.iplatform.tcp.EquipmentStatusCacheProvider; |
| | | import com.iplatform.tcp.cache.RedisEquipStatusCacheProvider; |
| | | import com.iplatform.tcp.cache.RedisEquipmentCacheProvider; |
| | | import com.iplatform.tcp.service.TcpEquipServiceImpl; |
| | | import com.iplatform.tcp.service.TcpEquipStatusServiceImpl; |
| | | import com.walker.support.redis.RedisHelper; |
| | | import com.walker.support.redis.cache.RedisCacheProvider; |
| | | import com.walker.tcp.lb.RedisConnectionMetaCache; |
| | | import com.walker.tcp.lb.RedisConnectionNameCache; |
| | | import org.springframework.boot.autoconfigure.AutoConfigureAfter; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | |
| | | @Configuration |
| | | @ConditionalOnProperty(prefix = "iplatform.cache", name = "redis-enabled", havingValue = "true", matchIfMissing = false) |
| | | @ConditionalOnClass({RedisCacheProvider.class}) |
| | | @AutoConfigureAfter(RedisAutoConfiguration.class) |
| | | public class RedisTcpCacheConfig extends PlatformConfiguration { |
| | | |
| | | /** |
| | | * 长连接负载模式中,连接(注册)名称与通道ID关系缓存定义。 |
| | | * @param redisHelper |
| | | * @return |
| | | * @date 2023-09-26 |
| | | */ |
| | | @Bean |
| | | public RedisConnectionNameCache redisConnectionNameCache(RedisHelper redisHelper){ |
| | | RedisConnectionNameCache cache = new RedisConnectionNameCache(); |
| | | cache.setRedisHelper(redisHelper); |
| | | return cache; |
| | | } |
| | | |
| | | /** |
| | | * 长连接负载模式中,连接元数据缓存定义。 |
| | | * @param redisHelper |
| | | * @return |
| | | * @date 2023-09-26 |
| | | */ |
| | | @Bean |
| | | public RedisConnectionMetaCache redisConnectionMetaCache(RedisHelper redisHelper){ |
| | | RedisConnectionMetaCache cache = new RedisConnectionMetaCache(); |
| | | cache.setRedisHelper(redisHelper); |
| | | // cache.setExpiredSeconds(); |
| | | return cache; |
| | | } |
| | | |
| | | @Bean |
| | | public EquipmentCacheProvider equipmentCacheProvider(RedisHelper redisHelper, TcpEquipServiceImpl tcpEquipService){ |
| | | RedisEquipmentCacheProvider redisEquipmentCacheProvider = new RedisEquipmentCacheProvider(); |
| | | redisEquipmentCacheProvider.setRedisHelper(redisHelper); |
| | | redisEquipmentCacheProvider.setTcpEquipService(tcpEquipService); |
| | | return redisEquipmentCacheProvider; |
| | | } |
| | | |
| | | @Bean |
| | | public EquipmentStatusCacheProvider equipmentStatusCacheProvider(RedisHelper redisHelper, TcpEquipStatusServiceImpl tcpEquipStatusService){ |
| | | RedisEquipStatusCacheProvider redisEquipStatusCacheProvider = new RedisEquipStatusCacheProvider(); |
| | | redisEquipStatusCacheProvider.setRedisHelper(redisHelper); |
| | | redisEquipStatusCacheProvider.setTcpEquipStatusService(tcpEquipStatusService); |
| | | return redisEquipStatusCacheProvider; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.config; |
| | | |
| | | import com.walker.tcp.ActionCallablePostProcessor; |
| | | import com.walker.tcp.ConnectionManager; |
| | | import com.walker.tcp.ProtocolResolverPostProcessor; |
| | | import com.walker.tcp.RequestPostProcessor; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | |
| | | @Configuration |
| | | public class TcpBeanPostProcessorConfig { |
| | | |
| | | // public static ConnectionManager connectionManager; |
| | | |
| | | @Bean |
| | | public ProtocolResolverPostProcessor protocolResolverPostProcessor(){ |
| | | return new ProtocolResolverPostProcessor(); |
| | | } |
| | | |
| | | @Bean |
| | | public ActionCallablePostProcessor actionCallablePostProcessor(){ |
| | | return new ActionCallablePostProcessor(); |
| | | } |
| | | |
| | | @Bean |
| | | public RequestPostProcessor requestPostProcessor(){ |
| | | return new RequestPostProcessor(); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.config; |
| | | |
| | | import com.iplatform.base.config.TcpProperties; |
| | | import com.iplatform.core.PlatformConfiguration; |
| | | import com.iplatform.core.config.LoadBalanceProperties; |
| | | import com.iplatform.tcp.EngineType; |
| | | import com.iplatform.tcp.EquipmentCacheProvider; |
| | | import com.iplatform.tcp.EquipmentStatusCacheProvider; |
| | | import com.iplatform.tcp.lb.DefaultLbConnectionManager; |
| | | import com.iplatform.tcp.service.TcpEquipStatusServiceImpl; |
| | | import com.iplatform.tcp.support.PersistentConnectionManager; |
| | | import com.iplatform.tcp.support.PlatformSharpProtocolResolver; |
| | | import com.walker.infrastructure.ApplicationRuntimeException; |
| | | import com.walker.push.rocketmq.RocketQueueManager; |
| | | import com.walker.queue.QueueManager; |
| | | import com.walker.tcp.ConnectionManager; |
| | | import com.walker.tcp.ProtocolResolver; |
| | | import com.walker.tcp.handler.LongHandler; |
| | | import com.walker.tcp.lb.RedisConnectionMetaCache; |
| | | import com.walker.tcp.lb.RedisConnectionNameCache; |
| | | import com.walker.tcp.lb.ResponseWriter; |
| | | import com.walker.tcp.netty.DefaultLongEngine; |
| | | import com.walker.tcp.netty.DefaultLongHandler; |
| | | import com.walker.tcp.netty.DefaultServerInitializer; |
| | | import com.walker.tcp.protocol.LineProtocolResolver; |
| | | import com.walker.tcp.support.MemoryQueueManager; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | import org.springframework.lang.Nullable; |
| | | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | @Configuration |
| | | @ConditionalOnProperty(prefix = "iplatform.tcp", name = "enabled", havingValue = "true", matchIfMissing = false) |
| | | public class TcpConfig extends PlatformConfiguration { |
| | | |
| | | // 迁移到base中 |
| | | // @Bean |
| | | // public TcpProperties tcpProperties(){ |
| | | // return new TcpProperties(); |
| | | // } |
| | | |
| | | /** |
| | | * 配置设备连接管理器。 |
| | | * @param equipmentCacheProvider |
| | | * @param equipmentStatusCacheProvider |
| | | * @param tcpEquipStatusService |
| | | * @return |
| | | * @date 2023-04-16 |
| | | * @date 2023-07-19 添加条件限制,如果设置自定义连接管理器,则平台不再创建,由业务自己配置。 |
| | | * @date 2023-09-26 添加长连接元数据缓存配置,仅在集群模式可用。 |
| | | */ |
| | | @ConditionalOnProperty(prefix = "iplatform.tcp", name = "custom-connection-manager", havingValue = "false", matchIfMissing = false) |
| | | @Bean |
| | | public ConnectionManager connectionManager(EquipmentCacheProvider equipmentCacheProvider |
| | | , EquipmentStatusCacheProvider equipmentStatusCacheProvider, TcpEquipStatusServiceImpl tcpEquipStatusService |
| | | , TcpProperties tcpProperties |
| | | , @Nullable RedisConnectionMetaCache connectionMetaCache, @Nullable RedisConnectionNameCache connectionNameCache |
| | | , @Nullable ResponseWriter responseWriter){ |
| | | Map<Integer, String> connectionTypeMap = new HashMap<>(4); |
| | | connectionTypeMap.put(EngineType.INDEX_TCP_ENGINE, "TCP长连接"); |
| | | connectionTypeMap.put(EngineType.INDEX_TCP_WEBSOCKET, "WebSocket连接"); |
| | | |
| | | if(tcpProperties.isLoadBalanceEnabled()){ |
| | | DefaultLbConnectionManager connectionManager = new DefaultLbConnectionManager(); |
| | | connectionManager.setMultipleEngine(true); |
| | | connectionManager.setConnectionTypeMap(connectionTypeMap); |
| | | // 下面这两个缓存参数,只有在Redis启用时才存在,单机模式可为空。2023-09-26 |
| | | connectionManager.setConnectionMetaCache(connectionMetaCache); |
| | | connectionManager.setConnectionNameCache(connectionNameCache); |
| | | connectionManager.setConnectionHost(tcpProperties.getConnectionHost()); |
| | | connectionManager.setResponseWriter(responseWriter); |
| | | // connectionManager.setEquipCache(equipmentCacheProvider); |
| | | // connectionManager.setStatusCache(equipmentStatusCacheProvider); |
| | | // connectionManager.setTcpEquipStatusService(tcpEquipStatusService); |
| | | logger.debug("getConnectionHost = {}", tcpProperties.getConnectionHost()); |
| | | logger.info("connectionMetaCache = {}", connectionMetaCache.getClass().getName()); |
| | | return connectionManager; |
| | | |
| | | } else { |
| | | PersistentConnectionManager connectionManager = new PersistentConnectionManager(); |
| | | connectionManager.setMultipleEngine(true); |
| | | connectionManager.setConnectionTypeMap(connectionTypeMap); |
| | | connectionManager.setEquipCache(equipmentCacheProvider); |
| | | connectionManager.setStatusCache(equipmentStatusCacheProvider); |
| | | connectionManager.setTcpEquipStatusService(tcpEquipStatusService); |
| | | return connectionManager; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 配置协议解析器:最基本的文本换行,一行是一个消息体。 |
| | | * @return |
| | | * @date 2023-04-16 |
| | | */ |
| | | @Bean |
| | | public LineProtocolResolver lineProtocolResolver(){ |
| | | return new LineProtocolResolver(); |
| | | } |
| | | |
| | | @Bean |
| | | public PlatformSharpProtocolResolver platformSharpProtocolResolver(){ |
| | | PlatformSharpProtocolResolver resolver = new PlatformSharpProtocolResolver(); |
| | | return resolver; |
| | | } |
| | | |
| | | /** |
| | | * 配置消息队列管理器实现。 |
| | | * @param connectionManager |
| | | * @return |
| | | */ |
| | | @Bean |
| | | public QueueManager queueManager(ConnectionManager connectionManager |
| | | , TcpProperties tcpProperties, ThreadPoolTaskExecutor executor){ |
| | | if(tcpProperties.isLoadBalanceEnabled()){ |
| | | RocketQueueManager queueManager = new RocketQueueManager(); |
| | | queueManager.setConnectionManager(connectionManager); |
| | | queueManager.setId(1); |
| | | queueManager.setName("报文消息队列管理器【集群】"); |
| | | queueManager.setExecutor(executor); |
| | | queueManager.startup(); |
| | | return queueManager; |
| | | } else { |
| | | MemoryQueueManager queueManager = new MemoryQueueManager(); |
| | | queueManager.setConnectionManager(connectionManager); |
| | | queueManager.setId(1); |
| | | queueManager.setName("报文消息队列管理器【内置】"); |
| | | queueManager.setMaxWorkerThread(1); |
| | | queueManager.startup(); // 必须启动 |
| | | return queueManager; |
| | | } |
| | | } |
| | | |
| | | private List<ProtocolResolver<?>> acquireProtocolResolverList(){ |
| | | List<ProtocolResolver<?>> protocolResolverList = new ArrayList<>(4); |
| | | protocolResolverList.add(lineProtocolResolver()); |
| | | protocolResolverList.add(platformSharpProtocolResolver()); |
| | | return protocolResolverList; |
| | | } |
| | | |
| | | @Bean |
| | | public LongHandler tcpServerHandler(QueueManager queueManager |
| | | , ConnectionManager connectionManager, TcpProperties tcpProperties){ |
| | | logger.debug("...... tcp_scan_packages = {}", tcpProperties.getScanPackagesTcp()); |
| | | LongHandler longHandler = new LongHandler(); |
| | | longHandler.setEmptyMsgDisconnect(false); |
| | | longHandler.setEngineId(EngineType.INDEX_TCP_ENGINE); |
| | | // longHandler.setScanPackages("com.walker.tcp,com.iplatform.tcp"); |
| | | longHandler.setScanPackages(tcpProperties.getScanPackagesTcp()); |
| | | longHandler.setQueueManager(queueManager); |
| | | longHandler.setConnectionManager(connectionManager); |
| | | longHandler.setProtocolResolverList(this.acquireProtocolResolverList()); |
| | | longHandler.setConnectionHost(tcpProperties.getConnectionHost()); |
| | | return longHandler; |
| | | } |
| | | |
| | | @Bean |
| | | public DefaultLongHandler nettyLongHandler(ConnectionManager connectionManager, LongHandler tcpServerHandler){ |
| | | DefaultLongHandler longHandler = new DefaultLongHandler(); |
| | | longHandler.setConnectionManager(connectionManager); |
| | | longHandler.setTcpServerHandler(tcpServerHandler); |
| | | return longHandler; |
| | | } |
| | | |
| | | /** |
| | | * 配置:TCP 服务初始化器。 |
| | | * @param nettyLongHandler |
| | | * @return |
| | | * @date 2023-04-16 |
| | | */ |
| | | @Bean |
| | | public DefaultServerInitializer nettyServerInitializer(DefaultLongHandler nettyLongHandler, TcpProperties tcpProperties){ |
| | | DefaultServerInitializer initializer = new DefaultServerInitializer(); |
| | | initializer.setHandler(nettyLongHandler); |
| | | initializer.setProtocolResolverList(this.acquireProtocolResolverList()); |
| | | initializer.setShowLog(tcpProperties.isShowLog()); |
| | | // initializer.setTimeOutAll(); |
| | | return initializer; |
| | | } |
| | | |
| | | /** |
| | | * 配置TCP引擎。 |
| | | * @param nettyServerInitializer |
| | | * @param connectionManager |
| | | * @return |
| | | */ |
| | | @Bean |
| | | public DefaultLongEngine tcpLongEngine(DefaultServerInitializer nettyServerInitializer |
| | | , ConnectionManager connectionManager, TcpProperties tcpProperties |
| | | , LoadBalanceProperties loadBalanceProperties){ |
| | | DefaultLongEngine longEngine = new DefaultLongEngine(); |
| | | longEngine.setId(EngineType.INDEX_TCP_ENGINE); |
| | | longEngine.setName("测试TCP长连接引擎"); |
| | | longEngine.setServerInitializer(nettyServerInitializer); |
| | | longEngine.setConnectionManager(connectionManager); |
| | | longEngine.setPort(tcpProperties.getPortTcp()); |
| | | longEngine.setBossThreadNum(tcpProperties.getBossThreadNum()); |
| | | longEngine.setWorkerThreadNum(tcpProperties.getWorkerThreadNum()); |
| | | longEngine.setOpenHeartBeat(tcpProperties.isOpenHeartBeat()); |
| | | try { |
| | | longEngine.start(); |
| | | } catch (Exception e) { |
| | | throw new ApplicationRuntimeException("启动'DefaultLongEngine'失败:" + e.getMessage(), e); |
| | | } |
| | | return longEngine; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.config; |
| | | |
| | | import com.iplatform.base.config.TcpProperties; |
| | | import com.iplatform.core.config.LoadBalanceProperties; |
| | | import com.iplatform.tcp.EngineType; |
| | | import com.iplatform.tcp.support.TestConnectionCallback; |
| | | import com.iplatform.tcp.support.WebSocketPush; |
| | | import com.iplatform.tcp.util.ws.LoginAction; |
| | | import com.walker.infrastructure.ApplicationRuntimeException; |
| | | import com.walker.push.PushManager; |
| | | import com.walker.push.Pushable; |
| | | import com.walker.queue.QueueManager; |
| | | import com.walker.tcp.ConnectionCallback; |
| | | import com.walker.tcp.ConnectionManager; |
| | | import com.walker.tcp.ProtocolResolver; |
| | | import com.walker.tcp.netty.WebSocketEngine; |
| | | import com.walker.tcp.netty.WebSocketNettyHandler; |
| | | import com.walker.tcp.netty.WebSocketServerInitializer; |
| | | import com.walker.tcp.websocket.WebsocketHandler; |
| | | import com.walker.tcp.websocket.WebsocketProtocolResolver; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | import org.springframework.lang.Nullable; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | @Configuration |
| | | @ConditionalOnProperty(prefix = "iplatform.tcp", name = "enabled", havingValue = "true", matchIfMissing = false) |
| | | public class WebsocketConfig { |
| | | |
| | | @Bean |
| | | public WebsocketProtocolResolver websocketProtocolResolver(){ |
| | | WebsocketProtocolResolver websocketProtocolResolver = new WebsocketProtocolResolver(); |
| | | websocketProtocolResolver.setPermitNotRegisterConnect(false); |
| | | return websocketProtocolResolver; |
| | | } |
| | | |
| | | private List<ProtocolResolver<?>> acquireProtocolResolverList(){ |
| | | List<ProtocolResolver<?>> protocolResolverList = new ArrayList<>(2); |
| | | protocolResolverList.add(websocketProtocolResolver()); |
| | | return protocolResolverList; |
| | | } |
| | | |
| | | /** |
| | | * 配置业务定义的处理方法实现。 |
| | | * @param connectionManager |
| | | * @param queueManager |
| | | * @return |
| | | * @date 2023-04-17 |
| | | */ |
| | | @Bean |
| | | public WebsocketHandler wsServerHandler(ConnectionManager connectionManager |
| | | , QueueManager queueManager, TcpProperties tcpProperties){ |
| | | WebsocketHandler websocketHandler = new WebsocketHandler(); |
| | | websocketHandler.setEmptyMsgDisconnect(false); |
| | | websocketHandler.setEngineId(EngineType.INDEX_TCP_WEBSOCKET); |
| | | websocketHandler.setConnectionManager(connectionManager); |
| | | websocketHandler.setQueueManager(queueManager); |
| | | websocketHandler.setProtocolResolverList(this.acquireProtocolResolverList()); |
| | | // websocketHandler.setScanPackages("com.iplatform.tcp.util.ws"); |
| | | websocketHandler.setScanPackages(tcpProperties.getScanPackagesWs()); |
| | | // 2023-09-27 |
| | | websocketHandler.setConnectionHost(tcpProperties.getConnectionHost()); |
| | | return websocketHandler; |
| | | } |
| | | |
| | | @Bean |
| | | public WebSocketNettyHandler wsNettyLongHandler(ConnectionManager connectionManager |
| | | , WebsocketHandler wsServerHandler, TcpProperties tcpProperties){ |
| | | WebSocketNettyHandler webSocketNettyHandler = new WebSocketNettyHandler(); |
| | | webSocketNettyHandler.setConnectionManager(connectionManager); |
| | | webSocketNettyHandler.setTcpServerHandler(wsServerHandler); |
| | | webSocketNettyHandler.setUri(tcpProperties.getWebsocketUri()); |
| | | return webSocketNettyHandler; |
| | | } |
| | | |
| | | @Bean |
| | | public WebSocketServerInitializer wsServerInitializer(WebSocketNettyHandler wsNettyLongHandler, TcpProperties tcpProperties){ |
| | | WebSocketServerInitializer webSocketServerInitializer = new WebSocketServerInitializer(); |
| | | webSocketServerInitializer.setHandler(wsNettyLongHandler); |
| | | webSocketServerInitializer.setProtocolResolverList(this.acquireProtocolResolverList()); |
| | | webSocketServerInitializer.setShowLog(tcpProperties.isShowLog()); |
| | | return webSocketServerInitializer; |
| | | } |
| | | |
| | | @Bean |
| | | public WebSocketEngine webSocketEngine(ConnectionManager connectionManager |
| | | , WebSocketServerInitializer webSocketServerInitializer |
| | | , TcpProperties tcpProperties, @Nullable ConnectionCallback connectionCallback |
| | | , LoadBalanceProperties loadBalanceProperties){ |
| | | WebSocketEngine webSocketEngine = new WebSocketEngine(); |
| | | webSocketEngine.setId(EngineType.INDEX_TCP_WEBSOCKET); |
| | | webSocketEngine.setName("websocket测试引擎"); |
| | | webSocketEngine.setConnectionManager(connectionManager); |
| | | webSocketEngine.setServerInitializer(webSocketServerInitializer); |
| | | webSocketEngine.setOpenHeartBeat(tcpProperties.isOpenHeartBeat()); |
| | | webSocketEngine.setBossThreadNum(tcpProperties.getBossThreadNum()); |
| | | webSocketEngine.setWorkerThreadNum(tcpProperties.getWorkerThreadNum()); |
| | | // webSocketEngine.setHeartBeatTimeInterval(180000); |
| | | webSocketEngine.setHeartBeatTimeInterval(tcpProperties.getHeartBeatSeconds() * 1000); |
| | | webSocketEngine.setPort(tcpProperties.getPortWs()); |
| | | // 2023-08-25 |
| | | if(connectionCallback != null){ |
| | | webSocketEngine.setConnectionCallback(connectionCallback); |
| | | } else { |
| | | webSocketEngine.setConnectionCallback(new TestConnectionCallback()); |
| | | } |
| | | // 延时启动,测试用。正式注释掉。2023-09-27 |
| | | webSocketEngine.setEngineStartDelaySeconds(30); |
| | | try { |
| | | webSocketEngine.start(); |
| | | } catch (Exception e) { |
| | | throw new ApplicationRuntimeException("启动'WebSocketEngine'失败:" + e.getMessage(), e); |
| | | } |
| | | return webSocketEngine; |
| | | } |
| | | |
| | | /** |
| | | * Websocket登录认证动作配置 |
| | | * @return |
| | | * @date 2023-04-17 |
| | | */ |
| | | @Bean |
| | | public LoginAction wsLoginAction(){ |
| | | LoginAction loginAction = new LoginAction(); |
| | | return loginAction; |
| | | } |
| | | |
| | | /** |
| | | * 配置'WebSocketPush'推送实现,同时注册到管理器中。 |
| | | * @param webSocketEngine |
| | | * @param pushManager |
| | | * @return |
| | | * @date 2023-04-21 |
| | | */ |
| | | @Bean |
| | | public Pushable websocketPush(WebSocketEngine webSocketEngine, PushManager pushManager){ |
| | | WebSocketPush webSocketPush = new WebSocketPush(); |
| | | webSocketPush.setWebSocketEngine(webSocketEngine); |
| | | webSocketPush.startup(); |
| | | pushManager.register(webSocketPush); |
| | | return webSocketPush; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.controller; |
| | | |
| | | import com.iplatform.tcp.TcpBaseController; |
| | | import com.walker.db.page.GenericPager; |
| | | import com.walker.db.page.ListPageContext; |
| | | import com.walker.tcp.Connection; |
| | | import com.walker.tcp.ConnectionManager; |
| | | import com.walker.web.ResponseValue; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.List; |
| | | |
| | | @RestController |
| | | @RequestMapping("/tcp/connection") |
| | | public class ConnectionManagerController extends TcpBaseController { |
| | | |
| | | private ConnectionManager connectionManager; |
| | | |
| | | @Autowired |
| | | public ConnectionManagerController(ConnectionManager connectionManager){ |
| | | this.connectionManager = connectionManager; |
| | | } |
| | | |
| | | @RequestMapping("/list") |
| | | public ResponseValue list(){ |
| | | List<Connection> list = this.connectionManager.queryAllConnectionList(); |
| | | if(list != null && list.size() > 256){ |
| | | logger.warn("TCP连接过多,仅展示前256个"); |
| | | } |
| | | ListPageContext.setCurrentPageSize(256); |
| | | GenericPager<Connection> pager = ListPageContext.createGenericPager(list, 1, list.size()); |
| | | return ResponseValue.success(pager); |
| | | } |
| | | |
| | | @RequestMapping("/select/send_test") |
| | | public ResponseValue sendTestCommand(){ |
| | | |
| | | return ResponseValue.success(); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.controller; |
| | | |
| | | import com.iplatform.model.po.TcpEquip; |
| | | import com.iplatform.tcp.TcpBaseController; |
| | | import com.iplatform.tcp.pojo.EquipParam; |
| | | import com.iplatform.tcp.service.TcpEquipServiceImpl; |
| | | import com.walker.db.page.GenericPager; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.tcp.ProtocolResolverPostProcessor; |
| | | import com.walker.web.ResponseValue; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.List; |
| | | |
| | | @RestController |
| | | @RequestMapping("/tcp/equip") |
| | | public class EquipController extends TcpBaseController { |
| | | |
| | | private TcpEquipServiceImpl tcpEquipService; |
| | | // private ProtocolResolverPostProcessor protocolResolverPostProcessor; |
| | | |
| | | @Autowired |
| | | public EquipController(TcpEquipServiceImpl tcpEquipService){ |
| | | this.tcpEquipService = tcpEquipService; |
| | | } |
| | | |
| | | @RequestMapping("/list") |
| | | public ResponseValue list(EquipParam equipParam){ |
| | | // PageSearch pageSearch = ListPageContext.getPageSearch(); |
| | | // GenericPager<TcpEquip> pager = this.tcpEquipService.selectSplit(new TcpEquip(), pageSearch.getPageIndex(), pageSearch.getPageSize()); |
| | | GenericPager<TcpEquip> pager = this.tcpEquipService.selectSplit(new TcpEquip()); |
| | | List<TcpEquip> data = pager.getDatas(); |
| | | if(!StringUtils.isEmptyList(data)){ |
| | | for(TcpEquip e : data){ |
| | | e.setParameterString("deptName", this.getDeptName(e.getDept())); |
| | | e.setParameterString("protocolResolverName", ProtocolResolverPostProcessor.getProtocolResolver(e.getProtocolResolver()).getName()); |
| | | } |
| | | } |
| | | return ResponseValue.success(pager); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.controller; |
| | | |
| | | import com.iplatform.base.SystemController; |
| | | import com.iplatform.tcp.util.ws.WebBroadCastResponse; |
| | | import com.iplatform.tcp.util.ws.WebDataResponse; |
| | | import com.walker.infrastructure.utils.DateUtils; |
| | | import com.walker.infrastructure.utils.NumberGenerator; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.push.Notification; |
| | | import com.walker.push.NotificationChannel; |
| | | import com.walker.push.PushManager; |
| | | import com.walker.push.PushResult; |
| | | import com.walker.tcp.Connection; |
| | | import com.walker.tcp.ConnectionManager; |
| | | import com.walker.tcp.connect.LongConnection; |
| | | import com.walker.tcp.lb.LongConnectionMeta; |
| | | import com.walker.tcp.lb.RedisConnectionMetaCache; |
| | | import com.walker.tcp.lb.RedisConnectionNameCache; |
| | | import com.walker.tcp.netty.WebSocketEngine; |
| | | import com.walker.web.ResponseValue; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.lang.Nullable; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.util.*; |
| | | |
| | | @RestController |
| | | @RequestMapping("/test/tcp") |
| | | public class TestTcpController extends SystemController { |
| | | |
| | | private WebSocketEngine webSocketEngine; |
| | | private PushManager pushManager; |
| | | private RedisConnectionMetaCache connectionMetaCache; |
| | | private RedisConnectionNameCache connectionNameCache; |
| | | |
| | | @Autowired |
| | | public TestTcpController(WebSocketEngine webSocketEngine, PushManager pushManager |
| | | , @Nullable RedisConnectionMetaCache connectionMetaCache |
| | | , @Nullable RedisConnectionNameCache connectionNameCache){ |
| | | this.webSocketEngine = webSocketEngine; |
| | | this.pushManager = pushManager; |
| | | this.connectionMetaCache = connectionMetaCache; |
| | | this.connectionNameCache = connectionNameCache; |
| | | } |
| | | |
| | | /** |
| | | * 获取websocket基本情况。 |
| | | * @return |
| | | * @date 2023-12-14 |
| | | */ |
| | | @RequestMapping("/ws/info") |
| | | public ResponseValue getWebsocketLinkInfo(){ |
| | | Map<String, Object> infoMap = new HashMap<>(8); |
| | | if(this.connectionNameCache != null){ |
| | | long totalWebsocketSize = this.connectionNameCache.getCache().getPersistentSize(); |
| | | infoMap.put("total_websocket", totalWebsocketSize); |
| | | infoMap.put("create_time", connectionNameCache.getCreateTime()); |
| | | infoMap.put("cache_name", this.connectionNameCache.getProviderName()); |
| | | } |
| | | if(this.connectionMetaCache != null){ |
| | | infoMap.put("connection_meta_size", this.connectionMetaCache.getCache().getPersistentSize()); |
| | | } |
| | | return ResponseValue.success(infoMap); |
| | | } |
| | | |
| | | /** |
| | | * 获取一个链接信息。 |
| | | * @param userId 连接绑定的用户名称(name),一般为用户ID。 |
| | | * @return |
| | | * @date 2023-12-14 |
| | | */ |
| | | @RequestMapping("/ws/connection") |
| | | public ResponseValue getWebsocketConnection(String userId){ |
| | | if(StringUtils.isEmpty(userId)){ |
| | | return ResponseValue.error("userId is required!"); |
| | | } |
| | | Map<String, Object> infoMap = new HashMap<>(8); |
| | | |
| | | ConnectionManager connectionManager = this.webSocketEngine.getConnectionManager(); |
| | | if(connectionManager != null){ |
| | | LongConnection connection = (LongConnection) connectionManager.getConnectionByName(userId); |
| | | if(connection == null){ |
| | | return ResponseValue.success("连接不存在:" + userId); |
| | | } |
| | | |
| | | if(connection instanceof LongConnectionMeta){ |
| | | infoMap.put("type", "集群连接对象(LongConnectionMeta),不是当前主机物理连接"); |
| | | } |
| | | infoMap.put("id", connection.getId()); |
| | | infoMap.put("host", connection.getConnectionHost()); |
| | | infoMap.put("name", connection.getName()); |
| | | infoMap.put("alreadyLogin", connection.getAlreadyLogin()); |
| | | infoMap.put("engineId", connection.getEngineId()); |
| | | infoMap.put("lastTime", connection.getLastTime()); |
| | | } else { |
| | | infoMap.put("error", "connectionManager 为空"); |
| | | } |
| | | return ResponseValue.success(infoMap); |
| | | } |
| | | |
| | | /** |
| | | * 向所有链接广播消息。 |
| | | * @param name |
| | | * @param uid |
| | | * @return |
| | | */ |
| | | @RequestMapping("/ws/send_broadcast") |
| | | public ResponseValue sendTestCommand(String name, String uid){ |
| | | WebBroadCastResponse msg = new WebBroadCastResponse(); |
| | | msg.setMessageId(String.valueOf(NumberGenerator.getSequenceNumber())); |
| | | msg.setName(uid); |
| | | msg.setData(name + ": " + msg.getMessageId()); |
| | | webSocketEngine.sendBroadcast(msg); |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | /** |
| | | * 向浏览器(用户)推送一个websocket实时消息。 |
| | | * @param userIds |
| | | * @return |
| | | * @date 2024-01-23 |
| | | */ |
| | | @RequestMapping("/ws/send") |
| | | public ResponseValue sendToUser(String userIds){ |
| | | if (StringUtils.isNotEmpty(userIds)){ |
| | | String[] split = userIds.split(","); |
| | | List<String> ids = Arrays.asList(split); |
| | | for (String id : ids) { |
| | | Connection connection = this.webSocketEngine.getConnectionManager().getConnectionByName(id); |
| | | if (connection!=null){ |
| | | WebDataResponse msg = new WebDataResponse(); |
| | | msg.setMessageId(NumberGenerator.getLongSequenceId()); |
| | | msg.setName(id); // 指定用户发送,该id与浏览器端注册的id保持一致。 |
| | | msg.setData("有新消息,速度刷新"); |
| | | webSocketEngine.sendResponse(msg); |
| | | } |
| | | } |
| | | } |
| | | return ResponseValue.success(); |
| | | } |
| | | |
| | | @RequestMapping("/push") |
| | | public ResponseValue pushOne(String type, String userId){ |
| | | PushResult pushResult = null; |
| | | if(type.equals("1")){ |
| | | logger.info("推送短信测试,user = 0"); |
| | | pushResult = this.pushManager.push(this.acquireNotification(NotificationChannel.Sms, "13838277463"), null); |
| | | } else if(type.equals("2")){ |
| | | if(StringUtils.isEmpty(userId)){ |
| | | userId = "0"; |
| | | } |
| | | pushResult = this.pushManager.push(this.acquireNotification(NotificationChannel.WebSocket, userId), null); |
| | | } else { |
| | | throw new UnsupportedOperationException("暂不支持其他推送方式:" + type); |
| | | } |
| | | return ResponseValue.success(pushResult); |
| | | } |
| | | |
| | | private Notification acquireNotification(NotificationChannel channel, String user){ |
| | | Notification n = new Notification(); |
| | | n.setId(NumberGenerator.generatorHexUUID()); |
| | | n.setCreateTime(DateUtils.getDateTimeNumber()); |
| | | n.setCreator("creator"); |
| | | n.setFrom("shikeying"); |
| | | n.setContent("这是一个测试"); |
| | | |
| | | List<NotificationChannel> channels = new ArrayList<>(2); |
| | | channels.add(channel); |
| | | n.setChannelList(channels); |
| | | n.setPersistent(true); |
| | | n.setTitle("title"); |
| | | |
| | | List<String> userList = new ArrayList<>(2); |
| | | userList.add(user); |
| | | n.setReceiverList(userList); |
| | | return n; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.lb; |
| | | |
| | | import com.walker.tcp.Connection; |
| | | import com.walker.tcp.lb.LoadBalanceConnectionManager; |
| | | import com.walker.tcp.lb.LongConnectionMeta; |
| | | |
| | | /** |
| | | * 支持集群的长连接管理器。 |
| | | * @author 时克英 |
| | | * @date 2023-09-26 |
| | | */ |
| | | public class DefaultLbConnectionManager extends LoadBalanceConnectionManager { |
| | | |
| | | // private ResponseWriter responseWriter = new DefaultResponseWriter(); |
| | | |
| | | @Override |
| | | protected LongConnectionMeta acquireConnectionMeta(Connection connection) { |
| | | MqConnectionMeta meta = new MqConnectionMeta(connection.getId()); |
| | | meta.setEngineId(connection.getEngineId()); |
| | | meta.setName(connection.getName()); |
| | | meta.setConnectionHost(connection.getConnectionHost()); |
| | | meta.setLastTime(connection.getLastTime()); |
| | | meta.setAlreadyLogin(connection.getAlreadyLogin()); |
| | | meta.setLongConnection(true); |
| | | // meta.setProtocolResolver(connection.getProtocolResolver()); |
| | | meta.setResponseWriter(this.getResponseWriter()); |
| | | logger.debug("准备更新(保存或更新)一个链接:{}", meta); |
| | | return meta; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.lb; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.tcp.util.ws.LoginResponse; |
| | | import com.iplatform.tcp.util.ws.WebDataResponse; |
| | | import com.walker.infrastructure.utils.JsonUtils; |
| | | import com.walker.push.rocketmq.EnhanceMessageHandler; |
| | | import com.walker.push.rocketmq.tcp.MqResponse; |
| | | import com.walker.tcp.Connection; |
| | | import com.walker.tcp.ConnectionManager; |
| | | import com.walker.tcp.Response; |
| | | import com.walker.tcp.lb.LongConnectionMeta; |
| | | import org.apache.rocketmq.spring.core.RocketMQListener; |
| | | |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 平台默认的MQ队列监听器,业务需要根据情况继承该对象,实现自己的业务。 |
| | | * <p>需要重写方法:{@linkplain DefaultMqListener#handleMessage(MqResponse)}</p> |
| | | * @author 时克英 |
| | | * @date 2023-09-26 |
| | | * @date 2024-01-23 无需使用集群模式,单机即可,MQ不用开启监听。 |
| | | */ |
| | | //@RocketMQMessageListener(topic = "${iplatform.tcp.connection-host}", consumerGroup = "consumer-group") |
| | | //public class DefaultMqListener extends EnhanceMessageHandler<MqResponse> implements RocketMQListener<MqResponse> { |
| | | public class DefaultMqListener extends EnhanceMessageHandler<MqResponse> implements RocketMQListener<MqResponse> { |
| | | |
| | | // protected final transient Logger logger = LoggerFactory.getLogger(this.getClass()); |
| | | |
| | | @Override |
| | | public void onMessage(MqResponse mqResponse) { |
| | | this.dispatchMessage(mqResponse); |
| | | } |
| | | |
| | | @Override |
| | | protected void handleMessage(MqResponse message) throws Exception { |
| | | // 具体执行业务消息方法。 |
| | | // 这里聊天业务中,需要推送到本机连接的客户端(或浏览器) |
| | | // Response<?> response = message.getResponse(); |
| | | Response<?> response = this.translateResponse(message.getResponse()); |
| | | Connection conn = connectionManager.getConnectionByName(response.getName()); |
| | | if(conn == null || !conn.isConnected()){ |
| | | logger.debug("mq消息已接收,但长连接不存在无法推送,response = {}", response); |
| | | return; |
| | | } |
| | | |
| | | if(conn instanceof LongConnectionMeta){ |
| | | throw new IllegalStateException("这个应该是本地物理连接,但找到的是:LongConnectionMeta,name=" + response.getName()); |
| | | } |
| | | conn.write(response); |
| | | } |
| | | |
| | | /** |
| | | * 转换成实际发送的业务数据,业务可以继承该类,并重写方法。 |
| | | * @param json |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | protected Response<?> translateResponse(String json) throws Exception{ |
| | | Map<String, Object> responseMap = JsonUtils.jsonStringToObject(json, Map.class); |
| | | if(!responseMap.containsKey(KEY_PROTOCOL_NUM)){ |
| | | throw new IllegalArgumentException("responseMap中必须包含协议号字段:" + KEY_PROTOCOL_NUM); |
| | | } |
| | | String protocolNum = responseMap.get(KEY_PROTOCOL_NUM).toString(); |
| | | if(protocolNum.equals("login")){ |
| | | return JsonUtils.jsonStringToObject(json, LoginResponse.class); |
| | | } else if(protocolNum.equals(Constants.PUSH_SCOPE_DATA)){ |
| | | return JsonUtils.jsonStringToObject(json, WebDataResponse.class); |
| | | } else { |
| | | throw new UnsupportedOperationException("未实现的 websocket.response对象转换:" + json); |
| | | } |
| | | } |
| | | |
| | | private final String KEY_PROTOCOL_NUM = "protocolNum"; |
| | | |
| | | @Override |
| | | protected void handleMaxRetriesExceeded(MqResponse message) { |
| | | |
| | | } |
| | | |
| | | @Override |
| | | protected boolean isRetry() { |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | protected boolean throwException() { |
| | | return true; |
| | | } |
| | | |
| | | public void setConnectionManager(ConnectionManager connectionManager) { |
| | | this.connectionManager = connectionManager; |
| | | } |
| | | |
| | | private ConnectionManager connectionManager; |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.lb; |
| | | |
| | | import com.iplatform.base.PlatformRuntimeException; |
| | | import com.iplatform.core.BeanContextAware; |
| | | import com.walker.infrastructure.utils.DateUtils; |
| | | import com.walker.infrastructure.utils.JsonUtils; |
| | | import com.walker.push.rocketmq.RocketMQEnhanceTemplate; |
| | | import com.walker.push.rocketmq.tcp.MqResponse; |
| | | import com.walker.tcp.Response; |
| | | import com.walker.tcp.lb.ResponseWriter; |
| | | import com.walker.web.util.IdUtils; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | public class DefaultResponseWriter implements ResponseWriter { |
| | | |
| | | private final transient SendStatusCallback callback = new SendStatusCallback(); |
| | | |
| | | protected final transient Logger logger = LoggerFactory.getLogger(this.getClass()); |
| | | |
| | | @Override |
| | | public Object write(String type, Response<?> response, String connectionHost, String channelId) { |
| | | if(type.equals(TYPE_MQ)){ |
| | | logger.debug("+++++++++++++++++++++++++"); |
| | | BeanContextAware.getBeanByType(RocketMQEnhanceTemplate.class) |
| | | .sendAsync(connectionHost, this.acquireMqResponse(response), callback); |
| | | if(this.logger.isDebugEnabled()){ |
| | | logger.debug("MqConnectionMeta 发送一个消息:{}", response); |
| | | } |
| | | } else { |
| | | throw new UnsupportedOperationException("不支持的 ResponseWriter.type = " + type); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | private MqResponse acquireMqResponse(Response<?> response){ |
| | | MqResponse data = new MqResponse(); |
| | | // data.setResponse(response); |
| | | try { |
| | | data.setResponse(JsonUtils.objectToJsonString(response)); |
| | | } catch (Exception e) { |
| | | throw new PlatformRuntimeException("Response<?> --> String 失败:" + e.getMessage(), e); |
| | | } |
| | | data.setKey(IdUtils.fastSimpleUUID()); |
| | | data.setRetryTimes(1); |
| | | data.setSource(response.getProtocolNum()); |
| | | data.setSendTime(DateUtils.getDateTimeNumber()); |
| | | data.setTopic(response.getTopic()); |
| | | return data; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.lb; |
| | | |
| | | import com.walker.tcp.lb.LongConnectionMeta; |
| | | |
| | | /** |
| | | * 平台实现的长连接元数据对象。 |
| | | * <pre> |
| | | * 1) 该对象表示一个物理连接的映射,会缓存到Redis中。 |
| | | * 2) 本机节点只能获取自己的链路连接,并通过连接直接发送消息。 |
| | | * 3) 连接元数据作用是,在其他节点中通过Redis中记录的连接映射以MQ消息形式发送出去。 |
| | | * </pre> |
| | | * @author 时克英 |
| | | * @date 2023-09-26 |
| | | */ |
| | | public class MqConnectionMeta extends LongConnectionMeta { |
| | | |
| | | // private final transient SendStatusCallback callback = new SendStatusCallback(); |
| | | |
| | | public MqConnectionMeta(){} |
| | | |
| | | public MqConnectionMeta(String id) { |
| | | super(id); |
| | | } |
| | | |
| | | // @JsonIgnore |
| | | // @Override |
| | | // public void write(Response<?> response) { |
| | | // // 通过MQ发送消息到目标主机,该目标就是当前连接绑定的主机标识。 |
| | | // // 暂时使用异步任务发送,2023-09-26 |
| | | // // 这里发送的主题就是全局连接对应的主机信息: |
| | | //// BeanContextAware.getBeanByType(RocketMQEnhanceTemplate.class) |
| | | //// .sendAsync(response.getTopic(), this.acquireMqResponse(response), callback); |
| | | // logger.info("+++++++++++++++++++++++++"); |
| | | // BeanContextAware.getBeanByType(RocketMQEnhanceTemplate.class) |
| | | // .sendAsync(this.getConnectionHost(), this.acquireMqResponse(response), callback); |
| | | // if(this.logger.isDebugEnabled()){ |
| | | // logger.debug("MqConnectionMeta 发送一个消息:{}", response); |
| | | // } |
| | | // } |
| | | |
| | | // @Override |
| | | // protected void onWrite(Response<?> response){ |
| | | // logger.info("+++++++++++++++++++++++++"); |
| | | // BeanContextAware.getBeanByType(RocketMQEnhanceTemplate.class) |
| | | // .sendAsync(this.getConnectionHost(), this.acquireMqResponse(response), callback); |
| | | // if(this.logger.isDebugEnabled()){ |
| | | // logger.debug("MqConnectionMeta 发送一个消息:{}", response); |
| | | // } |
| | | // } |
| | | |
| | | // private MqResponse acquireMqResponse(Response<?> response){ |
| | | // MqResponse data = new MqResponse(); |
| | | // data.setResponse(response); |
| | | // data.setKey(IdUtils.fastSimpleUUID()); |
| | | // data.setRetryTimes(1); |
| | | // data.setSource(response.getProtocolNum()); |
| | | // data.setSendTime(DateUtils.getDateTimeNumber()); |
| | | // data.setTopic(response.getTopic()); |
| | | // return data; |
| | | // } |
| | | |
| | | @Override |
| | | public void disconnect() { |
| | | // nothing; |
| | | } |
| | | |
| | | @Override |
| | | public boolean isConnected() { |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public String toString(){ |
| | | return new StringBuilder("MqConnectionMeta{id=").append(this.getId()) |
| | | .append(", alreadyLogin=").append(this.getAlreadyLogin()) |
| | | .append(", host=").append(this.getConnectionHost()) |
| | | .append(", name=").append(this.getName()) |
| | | .append(", lastTime=").append(this.getLastTime()) |
| | | .append("}").toString(); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.lb; |
| | | |
| | | import com.walker.push.rocketmq.tcp.MqResponse; |
| | | |
| | | import java.util.Map; |
| | | |
| | | public class MqResponseUtils { |
| | | |
| | | public static final MqResponse acquireMqResponse(Map<String, Object> map){ |
| | | int retryTimes = Integer.parseInt(map.get("retryTimes").toString()); |
| | | MqResponse mqResponse = new MqResponse(); |
| | | mqResponse.setRetryTimes(retryTimes); |
| | | mqResponse.setKey(map.get("key").toString()); |
| | | mqResponse.setSource(map.get("source").toString()); |
| | | mqResponse.setTopic(map.get("topic") != null? map.get("topic").toString() : ""); |
| | | return mqResponse; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.lb; |
| | | |
| | | import org.apache.rocketmq.client.producer.SendCallback; |
| | | import org.apache.rocketmq.client.producer.SendResult; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | /** |
| | | * 消息发送回调定义。 |
| | | * <p>暂时还不知道如何使用(在哪个地方使用)</p> |
| | | * @date 2023-09-26 |
| | | */ |
| | | public class SendStatusCallback implements SendCallback { |
| | | |
| | | protected final transient Logger logger = LoggerFactory.getLogger(this.getClass()); |
| | | |
| | | @Override |
| | | public void onSuccess(SendResult sendResult) { |
| | | logger.debug("消息发送成功:{}", sendResult.getMsgId()); |
| | | } |
| | | |
| | | @Override |
| | | public void onException(Throwable throwable) { |
| | | logger.error("消息发送失败:", throwable); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.lb; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.PlatformRuntimeException; |
| | | import com.iplatform.tcp.util.ws.LoginResponse; |
| | | import com.iplatform.tcp.util.ws.WebDataResponse; |
| | | import com.walker.infrastructure.utils.JsonUtils; |
| | | import com.walker.push.rocketmq.tcp.MqResponse; |
| | | import com.walker.tcp.Connection; |
| | | import com.walker.tcp.ConnectionManager; |
| | | import com.walker.tcp.Response; |
| | | import com.walker.tcp.lb.LongConnectionMeta; |
| | | import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; |
| | | import org.apache.rocketmq.spring.core.RocketMQListener; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * MQ消息监听接收处理。 |
| | | * <pre> |
| | | * 1) consumerGroup:消费者组,这个是针对同一个主题和Tag。 |
| | | * 资料介绍: |
| | | * A.一个消费者组,代表着一群topic相同,tag相同(即逻辑相同)的Consumer。通过一个消费者组,则可容易的进行负载均衡以及容错 |
| | | * B.使用时,一个节点下,一个topic加一个tag可以对应一个consumer。一个消费者组就是横向上多个节点的相同consumer为一个消费组。 |
| | | * </pre> |
| | | * @date 2023-10-07 修改消费者组,尝试解决多个队列消息无法接收问题。 |
| | | * @date 2023-12-14 监听对象放在业务中处理,平台注释该对象,业务通过MQ接收其他节点发送的聊天消息。如果要测试,请打开注解。(标注废弃是为了引起注意!) |
| | | */ |
| | | //@RocketMQMessageListener(topic = "${iplatform.tcp.connection-host}", selectorExpression = "*", consumerGroup = "${iplatform.tcp.connection-host}-consumer-group") |
| | | @Deprecated |
| | | public class SimpleMqListener implements RocketMQListener<String> { |
| | | |
| | | protected final transient Logger logger = LoggerFactory.getLogger(this.getClass()); |
| | | |
| | | @Override |
| | | public void onMessage(String s) { |
| | | logger.debug("mq = {}", s); |
| | | // MqResponse mqResponse = null; |
| | | Map<String, Object> mqResponse = null; |
| | | try { |
| | | // mqResponse = JsonUtils.jsonStringToObject(s, MqResponse.class); |
| | | mqResponse = JsonUtils.jsonStringToObject(s, Map.class); |
| | | } catch (Exception e) { |
| | | throw new PlatformRuntimeException("mq消息转换json对象失败:" + e.getMessage(), e); |
| | | } |
| | | |
| | | MqResponse message = MqResponseUtils.acquireMqResponse(mqResponse); |
| | | |
| | | // 超过最大重试次数时调用子类方法处理 |
| | | if (message.getRetryTimes() > getMaxRetryTimes()) { |
| | | handleMaxRetriesExceeded(message); |
| | | return; |
| | | } |
| | | |
| | | Response<?> response = null; |
| | | try { |
| | | response = this.translateResponse(mqResponse.get("response").toString()); |
| | | } catch (Exception e) { |
| | | throw new PlatformRuntimeException("转换成'Response'失败:" + e.getMessage(), e); |
| | | } |
| | | |
| | | try { |
| | | long now = System.currentTimeMillis(); |
| | | // handleMessage(message); |
| | | Connection conn = connectionManager.getConnectionByName(response.getName()); |
| | | if(conn == null || !conn.isConnected()){ |
| | | logger.debug("mq消息已接收,但长连接不存在无法推送,response = {}", response); |
| | | return; |
| | | } |
| | | |
| | | if(conn instanceof LongConnectionMeta){ |
| | | throw new IllegalStateException("这个应该是本地物理连接,但找到的是:LongConnectionMeta,name=" + response.getName()); |
| | | } |
| | | conn.write(response); |
| | | |
| | | long costTime = System.currentTimeMillis() - now; |
| | | logger.debug("消息{}消费成功,耗时[{}ms]", message.getKey(), costTime); |
| | | |
| | | } catch (Exception e) { |
| | | logger.error("消息{}消费异常", message.getKey(),e); |
| | | // 是捕获异常还是抛出,由子类决定 |
| | | if (throwException()) { |
| | | //抛出异常,由DefaultMessageListenerConcurrently类处理 |
| | | throw new RuntimeException(e); |
| | | } |
| | | //此时如果不开启重试机制,则默认ACK了 |
| | | // if (isRetry()) { |
| | | // handleRetry(message); |
| | | // } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 转换成实际发送的业务数据,业务可以继承该类,并重写方法。 |
| | | * @param json |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | protected Response<?> translateResponse(String json) throws Exception{ |
| | | Map<String, Object> responseMap = JsonUtils.jsonStringToObject(json, Map.class); |
| | | if(!responseMap.containsKey(KEY_PROTOCOL_NUM)){ |
| | | throw new IllegalArgumentException("responseMap中必须包含协议号字段:" + KEY_PROTOCOL_NUM); |
| | | } |
| | | String protocolNum = responseMap.get(KEY_PROTOCOL_NUM).toString(); |
| | | if(protocolNum.equals("login")){ |
| | | return JsonUtils.jsonStringToObject(json, LoginResponse.class); |
| | | } else if(protocolNum.equals(Constants.PUSH_SCOPE_DATA)){ |
| | | return JsonUtils.jsonStringToObject(json, WebDataResponse.class); |
| | | } else { |
| | | throw new UnsupportedOperationException("未实现的 websocket.response对象转换:" + json); |
| | | } |
| | | } |
| | | |
| | | protected void handleMaxRetriesExceeded(MqResponse message) { |
| | | |
| | | } |
| | | |
| | | protected boolean throwException() { |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * 最大重试次数 |
| | | * |
| | | * @return 最大重试次数,默认5次 |
| | | */ |
| | | protected int getMaxRetryTimes() { |
| | | return MAX_RETRY_TIMES; |
| | | } |
| | | |
| | | /** |
| | | * 默认重试次数 |
| | | */ |
| | | private static final int MAX_RETRY_TIMES = 3; |
| | | |
| | | public void setConnectionManager(ConnectionManager connectionManager) { |
| | | this.connectionManager = connectionManager; |
| | | } |
| | | |
| | | private ConnectionManager connectionManager; |
| | | private final String KEY_PROTOCOL_NUM = "protocolNum"; |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.pojo; |
| | | |
| | | import com.walker.web.param.ParamRequest; |
| | | |
| | | public class EquipParam extends ParamRequest { |
| | | |
| | | public String getName() { |
| | | return name; |
| | | } |
| | | |
| | | public void setName(String name) { |
| | | this.name = name; |
| | | } |
| | | |
| | | private String name; |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.service; |
| | | |
| | | import com.walker.jdbc.service.BaseServiceImpl; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | @Service |
| | | public class TcpEquipServiceImpl extends BaseServiceImpl { |
| | | |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.service; |
| | | |
| | | import com.walker.jdbc.service.BaseServiceImpl; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | @Service |
| | | public class TcpEquipStatusServiceImpl extends BaseServiceImpl { |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.support; |
| | | |
| | | import com.iplatform.model.po.TcpEquip; |
| | | import com.iplatform.model.po.TcpEquipStatus; |
| | | import com.iplatform.tcp.EngineType; |
| | | import com.iplatform.tcp.EquipmentCacheProvider; |
| | | import com.iplatform.tcp.EquipmentStatusCacheProvider; |
| | | import com.iplatform.tcp.LiveStatus; |
| | | import com.iplatform.tcp.service.TcpEquipStatusServiceImpl; |
| | | import com.walker.infrastructure.utils.DateUtils; |
| | | import com.walker.infrastructure.utils.NumberGenerator; |
| | | import com.walker.tcp.Connection; |
| | | import com.walker.tcp.support.SimpleEngineConnectionManager; |
| | | |
| | | /** |
| | | * 可持久化存储连接状态的连接管理器实现。 |
| | | * @author 时克英 |
| | | * @date 2018-11-29 |
| | | * |
| | | */ |
| | | public class PersistentConnectionManager extends SimpleEngineConnectionManager { |
| | | |
| | | public void setWebsocketPersistent(boolean websocketPersistent) { |
| | | this.websocketPersistent = websocketPersistent; |
| | | } |
| | | |
| | | private boolean websocketPersistent = false; |
| | | |
| | | @Override |
| | | protected void onSaveConnection(Connection connection) throws Exception { |
| | | if(connection.getEngineId() == EngineType.INDEX_TCP_WEBSOCKET && !this.websocketPersistent){ |
| | | // websocket连接不需要持久化 |
| | | return; |
| | | } |
| | | logger.debug("保存了一个连接:" + connection.getName()); |
| | | String num = connection.getName(); |
| | | TcpEquipStatus cacheStatus = statusCache.getEquipmentStatus(num); |
| | | if(cacheStatus == null){ |
| | | // 数据库还没有状态记录 |
| | | TcpEquipStatus newStatus = this.createStatus(connection, num); |
| | | this.tcpEquipStatusService.insert(newStatus); |
| | | statusCache.putEquipmentStatus(num, newStatus); |
| | | |
| | | } else { |
| | | // 已经存在记录(更新缓存数据,并也更新status表) |
| | | cacheStatus.setStartTime(Long.parseLong(DateUtils.getDateTimeSecondForShow(System.currentTimeMillis()))); |
| | | cacheStatus.setLiveStatus(LiveStatus.CONST_CONNECTED); |
| | | this.tcpEquipStatusService.save(cacheStatus); |
| | | // statusCache.updateCacheData(num, cacheStatus); |
| | | } |
| | | |
| | | this.afterSaveConnection(cacheStatus); |
| | | } |
| | | |
| | | private TcpEquipStatus createStatus(Connection connection, String num){ |
| | | TcpEquip equip = this.getEquipmentFromCache(num); |
| | | TcpEquipStatus entity = new TcpEquipStatus(); |
| | | entity.setCreateTime(NumberGenerator.getSequenceNumber()); |
| | | entity.setEquipNum(num); |
| | | entity.setId(NumberGenerator.getLongSequenceNumber()); |
| | | entity.setLiveStatus(LiveStatus.CONST_CONNECTED); |
| | | entity.setStartTime(Long.parseLong(DateUtils.getDateTimeSecondForShow(connection.getCreateTimeMills()))); |
| | | if(equip == null){ |
| | | // 没有注册设备,但仍允许上报数据 |
| | | entity.setEquipId(0L); |
| | | entity.setDept(0L); |
| | | } else { |
| | | entity.setEquipId(equip.getId()); |
| | | entity.setDept(equip.getDept()); |
| | | } |
| | | return entity; |
| | | } |
| | | |
| | | private TcpEquip getEquipmentFromCache(String num){ |
| | | return equipCache.getEquipment(num); |
| | | } |
| | | |
| | | @Override |
| | | protected void onDeleteConnection(int engineId, String name) throws Exception { |
| | | if(engineId == EngineType.INDEX_TCP_WEBSOCKET && !this.websocketPersistent){ |
| | | // websocket连接不需要持久化 |
| | | return; |
| | | } |
| | | logger.debug("删除了一个连接:" + name); |
| | | TcpEquipStatus cacheStatus = statusCache.getEquipmentStatus(name); |
| | | cacheStatus.setEndTime(Long.parseLong(DateUtils.getDateTimeSecondForShow(System.currentTimeMillis()))); |
| | | cacheStatus.setLiveStatus(LiveStatus.CONST_NOT_CONNECT); |
| | | this.tcpEquipStatusService.save(cacheStatus); |
| | | |
| | | this.afterDeleteConnection(cacheStatus); |
| | | } |
| | | |
| | | @Override |
| | | protected void onUpdateLastTime(int engineId, String name, long lastTime) throws Exception { |
| | | logger.debug("更新了一个连接:" + name); |
| | | } |
| | | |
| | | /** |
| | | * 保存连接之后动作,由子类实现。目前为websocket推送做准备 |
| | | * @param cacheStatus |
| | | */ |
| | | protected void afterSaveConnection(TcpEquipStatus cacheStatus){ |
| | | // OnlineResponse response = new OnlineResponse(); |
| | | // response.setName(cacheStatus.getEquipNum()); |
| | | // this.webSocketEngine.sendBroadcast(response); |
| | | } |
| | | |
| | | /** |
| | | * 设备断开连接之后动作,由子类实现。目前为websocket推送做准备 |
| | | * @param cacheStatus |
| | | */ |
| | | protected void afterDeleteConnection(TcpEquipStatus cacheStatus){ |
| | | // OfflineResponse response = new OfflineResponse(); |
| | | // response.setName(cacheStatus.getEquipNum()); |
| | | // this.webSocketEngine.sendBroadcast(response); |
| | | } |
| | | |
| | | public void setStatusCache(EquipmentStatusCacheProvider statusCache) { |
| | | this.statusCache = statusCache; |
| | | } |
| | | |
| | | public void setEquipCache(EquipmentCacheProvider equipCache) { |
| | | this.equipCache = equipCache; |
| | | } |
| | | |
| | | public void setTcpEquipStatusService(TcpEquipStatusServiceImpl tcpEquipStatusService) { |
| | | this.tcpEquipStatusService = tcpEquipStatusService; |
| | | } |
| | | |
| | | private EquipmentStatusCacheProvider statusCache; |
| | | private EquipmentCacheProvider equipCache; |
| | | private TcpEquipStatusServiceImpl tcpEquipStatusService; |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.support; |
| | | |
| | | import com.walker.tcp.littleD.Constants; |
| | | import com.walker.tcp.littleD.LittleDProtocolResolver; |
| | | |
| | | /** |
| | | * 平台TCP通信协议解析器实现。 |
| | | * <p>沿用小D智能终端协议规范,#为结束标志,前缀可修改(2位),协议编号4位</p> |
| | | * @author 时克英 |
| | | * @date 2023-04-17 |
| | | */ |
| | | public class PlatformSharpProtocolResolver extends LittleDProtocolResolver { |
| | | |
| | | public PlatformSharpProtocolResolver(){ |
| | | this.setDelimiter(Constants.DATA_END_FLAG); |
| | | this.setProtocolFeature(Constants.BODY_ID); |
| | | this.setName("平台通信解析器"); |
| | | this.setOrder(1); |
| | | } |
| | | |
| | | // @Override |
| | | // protected String onResolve(String data, int size) throws ProtocolException { |
| | | // if(size < 6){ |
| | | // throw new ProtocolException(ERR_PROTOCOL_SIZE); |
| | | // } |
| | | // |
| | | // if(!source.startsWith(this.getProtocolFeature().toString())){ |
| | | // throw new ProtocolException(ERR_PROTOCOL_FEATURE); |
| | | // } |
| | | // return source.substring(2, 6); |
| | | // } |
| | | // @Override |
| | | // protected Response<?> doCreateOneResponse() { |
| | | // // 返回心跳响应 |
| | | // return new HeartBeatResponse(); |
| | | // } |
| | | // @Override |
| | | // public String getAuthenticateInfo(Request<?> request) throws AuthenticateException { |
| | | // if(request instanceof LoginRequest){ |
| | | // String clientId = request.getName(); |
| | | // if(StringUtils.isEmpty(clientId)){ |
| | | // throw new AuthenticateException("请求信息中不存在设备ID号,无法认证"); |
| | | // } |
| | | // |
| | | // if(!isPermitNotRegisterConnect() && !this.isRegistered(clientId)){ |
| | | // throw new AuthenticateException("设备未在列表中注册,无法认证。clientId = " + clientId); |
| | | // } |
| | | // return clientId; |
| | | // |
| | | // } else { |
| | | // throw new AuthenticateException("connection通道认证失败,请求不是登录"); |
| | | // } |
| | | // } |
| | | |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.support; |
| | | |
| | | import com.walker.tcp.Connection; |
| | | import com.walker.tcp.ConnectionCallback; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | /** |
| | | * 测试 Tcp 或 Websocket 连接回调实现。 |
| | | * @author 时克英 |
| | | * @date 2023-08-26 |
| | | */ |
| | | public class TestConnectionCallback implements ConnectionCallback { |
| | | |
| | | private final transient Logger logger = LoggerFactory.getLogger(getClass()); |
| | | |
| | | @Override |
| | | public void onIdle(Connection connection) { |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public void onAfterLogin(Connection connection) { |
| | | logger.info("连接认证成功,已发送登录响应,这里可以直接再次发送业务消息。"); |
| | | // String userId = connection.getName(); |
| | | // // 用户是否,门户前端用户? |
| | | // boolean isFrontUser = false; |
| | | // if(isFrontUser){ |
| | | // connection.write(Response); |
| | | // } |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.support; |
| | | |
| | | import com.iplatform.tcp.util.ws.WebBroadCastResponse; |
| | | import com.iplatform.tcp.util.ws.WebDataResponse; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.push.AbstractPushObject; |
| | | import com.walker.push.Notification; |
| | | import com.walker.push.NotificationChannel; |
| | | import com.walker.push.PushException; |
| | | import com.walker.push.PushResult; |
| | | import com.walker.push.util.PushUtils; |
| | | import com.walker.tcp.netty.WebSocketEngine; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * WebSocket方式实现的推送对象。 |
| | | * @author 时克英 |
| | | * @date 2023-04-21 |
| | | */ |
| | | public class WebSocketPush extends AbstractPushObject<WebBroadCastResponse> { |
| | | |
| | | public WebSocketPush(){ |
| | | this.setId(NotificationChannel.WebSocket.getIndex()); |
| | | this.setName(NotificationChannel.WebSocket.getName() + "推送"); |
| | | } |
| | | |
| | | @Override |
| | | protected PushResult doPushContent(Notification notification, List<WebBroadCastResponse> data) throws PushException { |
| | | PushResult pushResult = PushUtils.acquireSuccessPushResult(); |
| | | String error = null; |
| | | for(WebBroadCastResponse response : data){ |
| | | if(notification.getBroadcast()){ |
| | | webSocketEngine.sendBroadcast(response); |
| | | logger.debug("websocket广播直接发送,没有状态"); |
| | | return pushResult; |
| | | } |
| | | |
| | | error = this.webSocketEngine.sendResponse(response); |
| | | |
| | | if(StringUtils.isNotEmpty(error)){ |
| | | if(pushResult.getCode() == 0){ |
| | | pushResult.setCode(-1); |
| | | } |
| | | // 这里无需转换用户信息,因为使用的就是userId,一致的! |
| | | pushResult.addOneFailed(response.getName()); |
| | | } |
| | | } |
| | | return pushResult; |
| | | } |
| | | |
| | | // @Override |
| | | // protected PushResult doPushContent(Notification notification) throws PushException { |
| | | // if(notification.getBroadcast()){ |
| | | // logger.debug("websocket推送广播"); |
| | | // |
| | | // WebBroadCastResponse msg = new WebBroadCastResponse(); |
| | | // msg.setMessageId(String.valueOf(NumberGenerator.getSequenceNumber())); |
| | | // msg.setData(notification.getContent()); |
| | | // webSocketEngine.sendBroadcast(msg); |
| | | // return PushUtils.acquireSuccessPushResult(); |
| | | // } |
| | | // |
| | | // // 普通推送消息 |
| | | // PushResult pushResult = new PushResult(); |
| | | // WebDataResponse response = null; |
| | | // String error = null; |
| | | // |
| | | // List<String> receiverList = notification.getReceiverList(); |
| | | // for(String user : receiverList){ |
| | | // response = new WebDataResponse(); |
| | | // response.setMessageId(String.valueOf(NumberGenerator.getSequenceNumber())); |
| | | // response.setData(notification.getContent()); |
| | | // response.setName(user); // websocket用户标识为:userId |
| | | // error = this.webSocketEngine.sendResponse(response); |
| | | // |
| | | // if(StringUtils.isNotEmpty(error)){ |
| | | // if(pushResult.getCode() == 0){ |
| | | // pushResult.setCode(-1); |
| | | // } |
| | | // pushResult.addOneFailed(user); |
| | | // } |
| | | // } |
| | | // return pushResult; |
| | | // } |
| | | |
| | | @Override |
| | | public NotificationChannel getNotificationChannel() { |
| | | return NotificationChannel.WebSocket; |
| | | } |
| | | |
| | | @Override |
| | | public List<WebBroadCastResponse> translateToTarget(Notification notification) { |
| | | |
| | | List<WebBroadCastResponse> data = new ArrayList<>(2); |
| | | WebBroadCastResponse webBroadCastResponse = null; |
| | | |
| | | if(notification.getBroadcast()){ |
| | | logger.debug("websocket推送广播"); |
| | | webBroadCastResponse = new WebBroadCastResponse(); |
| | | webBroadCastResponse.setMessageId(notification.getId()); |
| | | webBroadCastResponse.setData(notification.getContent()); |
| | | data.add(webBroadCastResponse); |
| | | return data; |
| | | } |
| | | |
| | | // 非广播,则需要把所有接收人集合返回 |
| | | int i = 1; |
| | | for(String user: notification.getReceiverList()){ |
| | | webBroadCastResponse = new WebDataResponse(); |
| | | webBroadCastResponse.setMessageId(notification.getId() + i); |
| | | webBroadCastResponse.setData(notification.getContent()); |
| | | webBroadCastResponse.setName(user); // websocket用户标识为:userId |
| | | data.add(webBroadCastResponse); |
| | | i++; |
| | | } |
| | | return data; |
| | | } |
| | | |
| | | @Override |
| | | public void startup() { |
| | | |
| | | } |
| | | |
| | | public void setWebSocketEngine(WebSocketEngine webSocketEngine) { |
| | | this.webSocketEngine = webSocketEngine; |
| | | } |
| | | |
| | | private WebSocketEngine webSocketEngine; |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.util; |
| | | |
| | | import com.walker.tcp.Request; |
| | | import com.walker.tcp.Response; |
| | | import com.walker.tcp.support.AbstractActionCall; |
| | | |
| | | /** |
| | | * 指令下发请求处理器,终端接到指令后,会发起确认请求,系统会调用该接口。</p> |
| | | * 该处理器对应功能:立即定位指令 |
| | | * @author 时克英 |
| | | * @date 2018-08-22 |
| | | * @date 2023-04-17 移植过来,用于演示用法。 |
| | | */ |
| | | //@Component |
| | | public class LocationNowAction extends AbstractActionCall { |
| | | |
| | | @Override |
| | | public Response<?> action(Request<?> request) { |
| | | logger.info("接收到指令下发后的,确认请求,不需要响应。请求信息 = " + request); |
| | | // 可以再次更新业务状态,或者处理自己的商业过程 |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public String getRequestProtocol() { |
| | | return "AP16"; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.util.ws; |
| | | |
| | | import com.walker.tcp.Request; |
| | | import com.walker.tcp.Response; |
| | | import com.walker.tcp.support.AbstractActionCall; |
| | | |
| | | /** |
| | | * websocket登录认证请求处理器 |
| | | * @author 时克英 |
| | | * @date 2019-01-10 |
| | | * |
| | | */ |
| | | public class LoginAction extends AbstractActionCall { |
| | | |
| | | @Override |
| | | public Response<?> action(Request<?> request) { |
| | | logger.debug("接收到用户websocket登录请求:" + request.getName()); |
| | | LoginResponse response = new LoginResponse(); |
| | | response.setName(request.getName()); |
| | | response.setStatus(0); |
| | | logger.debug(response.toString()); |
| | | return response; |
| | | } |
| | | |
| | | @Override |
| | | public String getRequestProtocol() { |
| | | return "login"; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.util.ws; |
| | | |
| | | import com.fasterxml.jackson.databind.node.ObjectNode; |
| | | import com.walker.infrastructure.utils.JsonUtils; |
| | | import com.walker.tcp.TcpRequest; |
| | | import com.walker.tcp.data.AbstractStringRequest; |
| | | import com.walker.tcp.util.WebSocketUtils; |
| | | |
| | | @TcpRequest("login") |
| | | public class LoginRequest extends AbstractStringRequest { |
| | | |
| | | /** |
| | | * |
| | | */ |
| | | private static final long serialVersionUID = 8346500913809847710L; |
| | | |
| | | @Override |
| | | protected void translateData(String source) { |
| | | // JSONObject json = JSONObject.parseObject(source); |
| | | // this.setName(json.getString(WebSocketUtils.WEB_SOCKET_KEY_UID)); |
| | | ObjectNode json = null; |
| | | try { |
| | | json = JsonUtils.jsonStringToObjectNode(source); |
| | | this.setName(json.get(WebSocketUtils.WEB_SOCKET_KEY_UID).asText()); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public String getProtocolNum() { |
| | | return "login"; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.util.ws; |
| | | |
| | | import com.walker.tcp.websocket.JsonResponse; |
| | | |
| | | import java.util.Map; |
| | | |
| | | public class LoginResponse extends JsonResponse { |
| | | |
| | | /** |
| | | * |
| | | */ |
| | | private static final long serialVersionUID = 1167352207355638142L; |
| | | |
| | | private int status = 0; |
| | | |
| | | public void setStatus(int status) { |
| | | this.status = status; |
| | | } |
| | | |
| | | // @Override |
| | | // protected void translateProperties(JSONObject result) { |
| | | // result.put("status", status); |
| | | // } |
| | | |
| | | @Override |
| | | public String getProtocolNum() { |
| | | return "login"; |
| | | } |
| | | |
| | | @Override |
| | | protected void translateProperties(Map<String, Object> result) { |
| | | result.put("status", status); |
| | | } |
| | | |
| | | @Override |
| | | public String toString(){ |
| | | return new StringBuilder("[protocol=").append(this.getProtocolNum()) |
| | | .append(", name=").append(this.getName()) |
| | | .append(", messageId=").append(this.getMessageId()) |
| | | .append(", status=").append(this.status) |
| | | .append("]").toString(); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.util.ws; |
| | | |
| | | import com.walker.tcp.websocket.JsonResponse; |
| | | |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 设备离线后,推送给websocket的响应对象定义 |
| | | * @author 时克英 |
| | | * @date 2019-01-10 |
| | | * |
| | | */ |
| | | public class OfflineResponse extends JsonResponse { |
| | | |
| | | /** |
| | | * |
| | | */ |
| | | private static final long serialVersionUID = -4170534196705654880L; |
| | | |
| | | @Override |
| | | protected void translateProperties(Map<String, Object> result) { |
| | | result.put("name", this.getName()); |
| | | } |
| | | |
| | | @Override |
| | | public String getProtocolNum() { |
| | | return "equip_offline"; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.util.ws; |
| | | |
| | | import com.walker.tcp.websocket.JsonResponse; |
| | | |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 设备离线后,推送给websocket的响应对象定义 |
| | | * @author 时克英 |
| | | * @date 2019-01-10 |
| | | * |
| | | */ |
| | | public class OnlineResponse extends JsonResponse { |
| | | |
| | | /** |
| | | * |
| | | */ |
| | | private static final long serialVersionUID = -4170534196705654880L; |
| | | |
| | | @Override |
| | | protected void translateProperties(Map<String, Object> result) { |
| | | result.put("name", this.getName()); |
| | | } |
| | | |
| | | @Override |
| | | public String getProtocolNum() { |
| | | return "equip_online"; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.util.ws; |
| | | |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | import com.walker.tcp.Context; |
| | | import com.walker.tcp.filter.DefaultFilter; |
| | | |
| | | /** |
| | | * 让接收数据有规律间隔的,过滤器实现 |
| | | * @author Administrator |
| | | * |
| | | */ |
| | | public class StepTimeFilter extends DefaultFilter { |
| | | |
| | | @Override |
| | | public boolean doFilter(Context context) throws Exception { |
| | | // long spanTime = context.getPreviousTimeSpan(); |
| | | // if(context.getPreviousData() != null && spanTime != 0){ |
| | | // long span = Math.abs(spanTime - 600); |
| | | // TimeUnit.MILLISECONDS.sleep(span); |
| | | // logger.debug("~~~~~~~~~~~~~~过滤器执行一次,间隔:" + span + ", spanTime = " + spanTime); |
| | | // logger.debug(context.getPreviousData()); |
| | | // } else { |
| | | // TimeUnit.MILLISECONDS.sleep(600); |
| | | // logger.debug("~~~~~~~~~~~~~~过滤器执行一次,间隔:600 mills" ); |
| | | // } |
| | | |
| | | TimeUnit.MILLISECONDS.sleep(500); |
| | | return true; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.util.ws; |
| | | |
| | | import com.walker.tcp.Request; |
| | | import com.walker.tcp.Response; |
| | | import com.walker.tcp.support.AbstractActionCall; |
| | | import com.walker.tcp.websocket.HelloResponse; |
| | | |
| | | public class TestHelloAction extends AbstractActionCall { |
| | | |
| | | @Override |
| | | public Response<?> action(Request<?> request) { |
| | | return new HelloResponse(); |
| | | } |
| | | |
| | | @Override |
| | | public String getRequestProtocol() { |
| | | return "hello"; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.util.ws; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.walker.tcp.websocket.JsonResponse; |
| | | |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * websocket广播消息响应对象 |
| | | * @author 时克英 |
| | | * @date 2018-10-25 |
| | | * |
| | | */ |
| | | public class WebBroadCastResponse extends JsonResponse { |
| | | |
| | | /** |
| | | * |
| | | */ |
| | | private static final long serialVersionUID = -7104409587873056275L; |
| | | |
| | | private String data; |
| | | |
| | | public String getData() { |
| | | return data; |
| | | } |
| | | |
| | | public WebBroadCastResponse(){ |
| | | this.setProtocolNum(Constants.PUSH_SCOPE_BROAD_CAST); |
| | | } |
| | | |
| | | public void setData(String say) { |
| | | this.data = say; |
| | | } |
| | | |
| | | // @Override |
| | | // protected void translateProperties(JSONObject json) { |
| | | // json.put("data", data); |
| | | // } |
| | | |
| | | // 在构造方法中设置初始化,2023-09-28 |
| | | // @Override |
| | | // public String getProtocolNum() { |
| | | // return Constants.PUSH_SCOPE_BROAD_CAST; |
| | | // } |
| | | |
| | | @Override |
| | | protected void translateProperties(Map<String, Object> result) { |
| | | result.put("data", data); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.tcp.util.ws; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | |
| | | /** |
| | | * 推送普通的网页消息,响应定义。 |
| | | * @author 时克英 |
| | | * @date 2023-04-21 |
| | | */ |
| | | public class WebDataResponse extends WebBroadCastResponse{ |
| | | |
| | | public WebDataResponse(){ |
| | | this.setProtocolNum(Constants.PUSH_SCOPE_DATA); |
| | | } |
| | | |
| | | // @Override |
| | | // public String getProtocolNum() { |
| | | // return Constants.PUSH_SCOPE_DATA; |
| | | // } |
| | | } |
New file |
| | |
| | | spring: |
| | | application: |
| | | name: deploy |
| | | datasource: |
| | | # 是否显示dao中打印的SQL语句 |
| | | show-sql: true |
| | | |
| | | ## driver-class-name: sunje.goldilocks.jdbc.GoldilocksDriver |
| | | # 注意:MySQL服务端,需要调整两个参数,否则服务端会主动断开连接 |
| | | # wait_timeout: 超过改时间(秒)服务端主动断开 |
| | | # interactive_timeout: 客户端工具交互超过这个时间(秒)会端口,表现为navicat |
| | | driver-class-name: org.postgresql.Driver |
| | | username: tbase |
| | | password: ENC(SDQnluhnbTXI2XBdvnpBMw==) |
| | | # url: jdbc:postgresql://116.198.40.76:30004/ctoms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&stringtype=unspecified |
| | | url: jdbc:postgresql://116.198.40.76:30004/ctoms?targetServerType=master&useUnicode=true&characterEncoding=UTF-8&useSSL=false&stringtype=unspecified |
| | | |
| | | # username: root |
| | | # url: jdbc:mysql://116.198.40.76:3306/iplatform?useUnicode=true&characterEncoding=UTF-8&useSSL=false |
| | | |
| | | # 达梦数据库 |
| | | # driver-class-name: dm.jdbc.driver.DmDriver |
| | | # username: iplatform |
| | | # url: jdbc:dm://116.198.39.83:5236?schema=iplatform |
| | | |
| | | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # 使用 Hikari 连接池 |
| | | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # type: com.walker.jdbc.ds.DefaultDataSource |
| | | # hikari: |
| | | # minimum-idle: 5 |
| | | # idle-timeout: 600000 |
| | | # pool-name: databasePool_walker |
| | | # # 连接最大超时时间 |
| | | # connection-timeout: 30000 |
| | | # # 连接池最大数量 |
| | | # maximum-pool-size: 10 |
| | | # # 控制池中连接最大生存期 |
| | | # # max-lifetime: 70000 |
| | | # # 此属性控制测试连接是否活跃的最长时间。此值必须小于 connectionTimeout |
| | | # validation-timeout: 10000 |
| | | # # |
| | | # connection-test-query: select 1 |
| | | |
| | | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # 使用 Druid 连接池 |
| | | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | type: com.walker.jdbc.ds.MyDruidDataSource |
| | | # type: com.ctoms.base.support.PostgresqlDataSource |
| | | # type: com.ctoms.base.support.PostgresqlClusterDataSource |
| | | druid: |
| | | initial-size: 5 |
| | | min-idle: 10 |
| | | max-active: 20 |
| | | # 配置获取连接等待超时的时间 |
| | | max-wait: 60000 |
| | | # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 |
| | | time-between-eviction-runs-millis: 60000 |
| | | # 配置一个连接在池中最小生存的时间,单位是毫秒 超过这个时间每次会回收默认3个连接 |
| | | min-evictable-idle-time-millis: 30000 |
| | | # 线上配置的mysql断开闲置连接时间为1小时,数据源配置回收时间为3分钟,以最后一次活跃时间开始算 |
| | | max-evictable-idle-time-millis: 180000 |
| | | validation-query: select 1 |
| | | test-while-idle: true |
| | | test-on-borrow: false |
| | | test-on-return: false |
| | | pool-prepared-statements: true |
| | | max-open-prepared-statements: 100 |
| | | use-global-data-source-stat: true |
| | | webStatFilter: |
| | | enabled: false |
| | | statViewServlet: |
| | | enabled: false |
| | | # 设置白名单,不填则允许所有访问 |
| | | # allow: |
| | | # url-pattern: /druid/* |
| | | # # 控制台管理用户名和密码 |
| | | # login-username: ruoyi |
| | | filter: |
| | | stat: |
| | | enabled: false |
| | | # 慢SQL记录 |
| | | log-slow-sql: true |
| | | slow-sql-millis: 1000 |
| | | merge-sql: true |
| | | wall: |
| | | config: |
| | | multi-statement-allow: false |
| | | |
| | | redis: |
| | | host: 116.198.40.76 |
| | | port: 6379 |
| | | password: ENC(VQ9j5YF08eKywBGZzMFq4g==) |
| | | # 内网环境不认该参数,2023-11-10 |
| | | # database: 2 |
| | | |
| | | mvc: |
| | | pathmatch: |
| | | # 加该配置是因为 swagger3 启动报错,2023-02-23 |
| | | matching-strategy: ant_path_matcher |
| | | |
| | | hiddenmethod: |
| | | filter: |
| | | enabled: true # 加上该配置可以接收: application/x-www-form-urlencoded请求参数为对象。支付通知中使用。2023-02-26 |
| | | |
| | | servlet: |
| | | multipart: |
| | | # maxFileSize 是单个文件大小 |
| | | # maxRequestSize是设置总上传的数据大小 |
| | | enabled: true |
| | | max-file-size: 5MB |
| | | max-request-size: 10MB |
| | | |
| | | server: |
| | | port: 8083 |
| | | servlet: |
| | | context-path: /tcp |
| | | session: |
| | | timeout: 30m |
| | | |
| | | logging: |
| | | level: |
| | | root: info |
| | | org: |
| | | springframework: info |
| | | io.swagger: error |
| | | com: |
| | | walker: debug |
| | | iplatform: debug |
| | | ctoms: debug |
| | | RocketmqRemoting: error # MQ打印该日志,目前没有找到解决资料。2023-09-27 |
| | | charset: |
| | | # 控制台编码 |
| | | console: UTF-8 |
| | | # 输出文件编码 |
| | | file: UTF-8 |
| | | |
| | | # file: # logging.file.path 和 logging.file.name,只会有一个生效,配了path不要配name,配了name不要配path,只配path时name默认为spring.log,想路径和文件名同时生效可配置logging.file.name=d:/logs/mylog.log |
| | | # name: ${spring.application.name}.log #日志文件名 |
| | | # path: logs #日志存储路径 |
| | | # max-history: 30 #保留多少天的日志 |
| | | # max-size: 10MB |
| | | # pattern: |
| | | # rolling-file-name: ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz |
| | | logback: |
| | | rollingpolicy: |
| | | # 单个文件最大为30MB,超过之后会打包成一个日志文件 |
| | | max-file-size: 10MB |
| | | # 文件保存7天 |
| | | max-history: 1 |
| | | # 打包文件格式,默认: ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz,书写格式为:文件路径/文件名.%i.文件后缀,其中%i不可省去,否则无日志显示 |
| | | # 例如: 日期为:2023/07/13 ,则打包文件之后为: log/ota.2023-07-13.0.gz,0表示日志的第一部分,后续就是,1,2,3... |
| | | # 如果是压缩包,里面会多一个名log/ota.2023-07-13.0的日志文件 |
| | | # 如下面的例子,打包之后为: log/2023-07/ota.2020-07-13.0.log,这是一个日志文件 |
| | | file-name-pattern: ${logging.file.path}%d{yyyy-MM}/iplatform-tcp.%d{yyyy-MM-dd}.%i.log |
| | | |
| | | file: |
| | | name: ${logging.file.path}iplatform-tcp.log |
| | | path: D:/log/ |
| | | |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # 平台配置支持功能 |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | iplatform: |
| | | |
| | | # 平台缓存,是否启用redis缓存,默认使用基于内存缓存. |
| | | # 注意:如果开启redis缓存,业务工程必须依赖(walker-support-redis) |
| | | cache: |
| | | redis-enabled: true |
| | | # redis 缓存是否要重建,如果设置 true,则系统启动后会删除缓存,并执行默认重新加载方法。2023-08-26 |
| | | # 注意:该参数一般在测试阶段使用,正式环境不要使用! |
| | | redis-rebuild: true |
| | | # 机构用户是否很庞大,如果是则缓存中会关闭初始化加载,同时机构树也不会放入缓存,2023-07-17 |
| | | org-user-big: false |
| | | # 单独加载机构 |
| | | org-alone-big: false |
| | | # 相似度分析模块使用(已废弃) |
| | | # similarity: |
| | | # # 是否启用相似度模块,如果禁用则要确保注入时支持为空 |
| | | # enabled: false |
| | | # milvus-host: 172.16.60.65 |
| | | # milvus-port: 19530 |
| | | # word-file: d:/dev_tools/ai/w2v_sogou_dim300_vocab.txt |
| | | # embedding-file: d:/dev_tools/ai/w2v_sogou_dim300.npy |
| | | |
| | | # 调度器模块,是否启用 |
| | | scheduler: |
| | | enabled: false |
| | | # 是否支持数据库存储任务(废弃该配置) |
| | | database-enabled: false |
| | | |
| | | # 数据采集模块 |
| | | gather: |
| | | enabled: false |
| | | |
| | | # 权限控制相关 |
| | | security: |
| | | # 匿名可访问地址(开放地址) |
| | | anonymous-list: |
| | | - /login |
| | | - /register |
| | | - /captcha/* # 验证码统一放开 |
| | | - /test/** # 开发测试,仅开发板可用 |
| | | - /template/ctoms/** |
| | | - /swagger-resources/** # swagger |
| | | - /swagger-ui/** # swagger |
| | | - /v3/** # swagger |
| | | - /pay/notify/** # 支付通知 |
| | | - /jmreport/** # 积木报表 |
| | | - /file/** # 登录用户可访问系统文件,2023-06-09 |
| | | - /third_party/unified/** # 系统第三方登录地址,前端获取网院token后,调用后台地址实现隐式登录,2023-10-23 |
| | | - /door/** |
| | | - /oss/** # 测试使用,正式应配置到permit下,2023-12-13 |
| | | # 允许所有认证用户都可访问地址,请慎重否则权限都过大,一般API都应该设置在这里 |
| | | permit-list: |
| | | # - /permit # 公用权限,2023-03-13,平台代码已经添加过了,这里不需要配置 |
| | | - /getInfo |
| | | - /getRouters |
| | | - /getMenus # 新界面菜单,2023-05-12 |
| | | - /logout |
| | | - /api/** |
| | | - /dqyy/** #档期预约 |
| | | - /pxjd/** #培训资源 |
| | | - /tr/** #教师 |
| | | - /base/** #基地 |
| | | - /bjgl/class/** #班级管理 |
| | | - /app/** #app |
| | | - /system/** #平台系统 |
| | | - /report/** #费用汇总 |
| | | - /settlement/** #费用汇总记录 |
| | | - /resource/** #资源 |
| | | - /evaluation/** #教学评估 |
| | | - /stat/workload/** #校内师资工作量 |
| | | - /bjgl/bus/** #接送站 |
| | | - /base/statistics/report/** #基地统计 |
| | | - /all/base/statistics/** #全网统计 |
| | | |
| | | # 超级管理员密码,加密后的秘文 |
| | | supervisor-password: ENC(i2QGr3kEu49MbMrW7dR+Q7jiPn1WpeuIbCfemGkhy+aMTamfXxrmKyS6j4GqG2TDm/7MTF8Q/+xqQB5pvy6rqA==) |
| | | |
| | | # 是否允许配置跨域响应头, true 启用, false 不启用。2022-12-28 |
| | | # 在Gateway模式中,需要关闭跨域配置,因为网关也会配置。 |
| | | cors-enabled: true |
| | | |
| | | # 用户名密码方式登录,配置的验证码类型:code/sms/slide/jigsaw,2023-03-14 |
| | | login-captcha-user-pass: code |
| | | # 手机验证码方式登录,配置的验证码类型:code/sms/slide/jigsaw,2023-03-14 |
| | | login-captcha-sms-code: sms |
| | | |
| | | # 是否允许后台用户(非App)登录手机端?2023-03-20 |
| | | allow-pc-user-access-app: true |
| | | |
| | | # 是否支持手机登录时(不存在手机号)直接注册?目前电商系统支持! 2023-06-26 |
| | | allow-mobile-login-reg: true |
| | | |
| | | # PC端token失效分钟,默认:120分钟,2023-03-28 |
| | | token-expire-web: 120 |
| | | # 移动端token失效分钟,2023-03-28 |
| | | token-expire-mobile: 120 |
| | | |
| | | # 用户体系(用户名)都是手机号,2023-06-28 |
| | | # 一般系统PC端通常都不是手机号作为用户名,只有在互联网相关系统中会存在手机号作为登录账号 |
| | | user-name-is-phone: false |
| | | |
| | | # 2023-07-11 登录策略配置,列表中存在的策略都表示启用(不启用的删掉) |
| | | login-strategy-list: |
| | | # - com.iplatform.base.support.strategy.WebOnceLoginStrategy ##同一账号只能登录一个ip |
| | | # - com.iplatform.base.support.strategy.MobileOnceLoginStrategy |
| | | |
| | | # 用户相关安全配置,2023-08-03 |
| | | user: |
| | | # 用户修改密码等级,分四级:1-2-3-4,常量:PasswordUtils# |
| | | pass-level: 1 |
| | | # 是否强制用户修改默认密码? |
| | | pass-default-modify: false |
| | | |
| | | # 代码生成,2022-11-26 |
| | | gen: |
| | | # 作者 |
| | | author: Mike |
| | | # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool |
| | | package-name: com.iplatform.model.po |
| | | # 自动去除表前缀,默认是false |
| | | auto-remove-pre: false |
| | | # 表前缀(生成类名不会包含表前缀,多个用逗号分隔) |
| | | table-prefix: s_ |
| | | |
| | | log: |
| | | # 是否打开登录日志,2023-01-05 |
| | | # 如果不打开,则设备登录的uuid更新操作也无法获得,用于记录每个登录用户的uuid(用户登录角色更新),2023-03-23 |
| | | login-enabled: false |
| | | # 是否打开操作日志,2023-01-05 |
| | | operate-enabled: false |
| | | |
| | | # 验证码相关配置,2023-01-27 |
| | | captcha: |
| | | # 图形验证码实现类, TextCaptchaProvider | DefaultCaptchaProvider |
| | | image-captcha-class: com.iplatform.base.captcha.TextCaptchaProvider |
| | | # 短信验证码实现类(配置废弃,2023-04-25) |
| | | sms-captcha-class: com.iplatform.base.captcha.MockSmsCaptchaProvider |
| | | |
| | | # 平台文件存储配置,2023-02-15 |
| | | file: |
| | | # FileStoreType = FileSystem 本地磁盘存储根路径 |
| | | file-root: d:/tmp/ |
| | | # 调用远程上传文件,是否按照本地文件处理,2023-07-03 |
| | | # 在测试过程中如果没有FTP等服务,可以设置为true临时存储本地 |
| | | remote-as-local: false |
| | | |
| | | # oss实现类型:aws_s3(亚马逊) | tx(腾讯) | ali(阿里) | qn(七牛),2023-12-13 |
| | | oss-type: aws_s3 |
| | | # oss访问前缀,如:http://localhost:8082/admin/oss/,2023-12-13 |
| | | oss-prefix: http://localhost:8082/admin/oss/ |
| | | oss-access-key: ENC(BTHETNjs5ddRjYrdMF9ltmw8DMIEYTuyXIgDOeLIHy0=) |
| | | oss-secret-key: ENC(jROCWGpiPULZrU1wBZAsXvQQovvqnhoJKWpmYD/3nbkNGDikxfEvCXW5jn3QsYnG) |
| | | # oss服务地址 |
| | | oss-endpoint: https://eos-beijing-1.cmecloud.cn |
| | | # oss默认的桶名称 |
| | | oss-bucket-name: ctoms-file |
| | | protocol: https |
| | | |
| | | # # oss实现类型:aws_s3(亚马逊) | tx(腾讯) | ali(阿里) | qn(七牛),2023-12-13 |
| | | # oss-type: aws_s3 |
| | | # # oss访问前缀,如:http://localhost:8082/admin/oss/,2023-12-13 |
| | | # oss-prefix: http://localhost:8082/admin/oss/ |
| | | # # oss服务地址 |
| | | # oss-endpoint: http://10.10.5.191:8080 |
| | | # # oss默认的桶名称 |
| | | # oss-bucket-name: ctoms-file |
| | | |
| | | ftp: |
| | | ip: 116.198.40.76 |
| | | port: 22 |
| | | user-name: mysftp |
| | | password: |
| | | private-key: |
| | | # ftp服务上面的存储根路径,只能是linux路径 |
| | | # file-root: /files/ |
| | | file-root: /train/ |
| | | |
| | | # 接口文档生成,swagger3,2023-02-23 |
| | | swagger: |
| | | enable: false |
| | | # 包路径,暂时不用 |
| | | base-package: com.iplatform.base.controller |
| | | title: 云原生微服务平台 |
| | | description: 一个快速web开发框架 |
| | | |
| | | # TCP通信配置,2024-01-23 |
| | | tcp: |
| | | # 是否开启引擎 |
| | | enabled: true |
| | | # 是否打开心跳 |
| | | open-heart-beat: true |
| | | # 心跳时间(秒),2023-08-28 |
| | | heart-beat-seconds: 60 |
| | | # 是否显示详细日志 |
| | | show-log: false |
| | | # 请求队列类型:memory 基于内存 |
| | | queue-type: memory |
| | | # tcp方式要扫描的请求对象的包空间 |
| | | scan-packages-tcp: com.walker.tcp,com.iplatform.tcp |
| | | # websocket方式要扫描的请求对象的包空间 |
| | | scan-packages-ws: com.iplatform.tcp.util.ws |
| | | # tcp长连接的端口 |
| | | port-tcp: 7878 |
| | | # websocket连接端口 |
| | | port-ws: 60001 |
| | | # websocket连接uri |
| | | # websocket-uri: ws://jmy.jinmingyuan.com:60001/websocket |
| | | websocket-uri: ws://www.shikeying.com:60000/websocket |
| | | # 通信线程数量 |
| | | boss-thread-num: 2 |
| | | # 业务处理线程数量 |
| | | worker-thread-num: 4 |
| | | # 启用自定义连接管理器,如果true则业务需要提供自定义实现(配置),2023-07-18 |
| | | custom-connection-manager: false |
| | | # 是否开启集群模式,连接管理器会默认加载负载支持,2023-09-26 |
| | | load-balance-enabled: false |
| | | # 长连接主机(标记)信息,可以是任意字符串,只要集群中每个服务配置不同即可。 |
| | | # 在集群模式中,每个连接要加上主机标识,以便别人推送消息时,知道在哪个主机上推送。2023-09-19 |
| | | connection-host: topic_master |
| | | |
| | | # 推送模块配置,2023-04-25 |
| | | push: |
| | | # 短信推送者名称:mock_sms_push(模拟短信),alidy_sms_push(阿里大鱼短信) |
| | | sms-push-name: alidy_sms_push |
| | | # 短信验证码模板ID,根据实际情况(每个平台可能不同) |
| | | sms-template-code: SMS_285145505 |
| | | |
| | | # 对于一般业务提醒(不包括:邮件、短信),推送的方式。推送者ID组合 |
| | | # && 表示并列,|| 表示或(只要一个成功就OK) |
| | | # 2023-04-26,可用的 id = 'tcp', 'web_socket', 'wx', 'system' |
| | | # message-type: tcp && web_socket && wx && system |
| | | # 如果是或者方式,需要把最可靠的放前面,因为系统会找到第一个发送成功即可。 |
| | | message-type: system || tcp || web_socket || wx |
| | | |
| | | # 邮件通知发送信息配置,2023-04-26 |
| | | mail-server: smtp.126.com |
| | | mail-from: hnzzzhsl@126.com |
| | | mail-password: 123456 |
| | | |
| | | # RestTemplate连接池配置,2023-08-18 |
| | | rest: |
| | | # 连接保持活动时间,默认:600秒 |
| | | keep-alive-duration-seconds: 600 |
| | | # 空闲连接数量,默认:200个 |
| | | max-idle-connections: 200 |
| | | # 连接超时,默认:2秒 |
| | | connect-timeout-seconds: 2 |
| | | # 读超时,默认3秒 |
| | | read-timeout-seconds: 3 |
| | | # 写超时,默认3秒 |
| | | write-timeout-seconds: 3 |
| | | |
| | | # 集群支持相关配置,2023-09-29 |
| | | lb: |
| | | # 本机服务节点ID,每个主机一个唯一数字编号,从1开始 |
| | | server-id: 8 |
| | | |
| | | # 2024-02-29 api监控相关 |
| | | api: |
| | | # 2024-02-29 是否打开接口时间统计记录,如果:true 则会记录接口调用时间,写入表:s_api_time |
| | | time-enabled: false |
| | | |
| | | # 网院统一认证配置选项,2023-10-23 |
| | | unified: |
| | | # 是否开启测试模式,测试模式用于本地测试,无法连接网院认证接口 |
| | | test-mode: true |
| | | # 网院提供的认证地址,关闭测试模式后,该选项生效 |
| | | remote-url: http://10.30.2.86:8001/uaa/person/current |
| | | |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # RocketMQ队列配置,2023-09-26 |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | rocketmq: |
| | | # 服务地址,多个用逗号分开 |
| | | # name-server: 116.198.40.76:9876 |
| | | name-server: 116.198.39.83:9898 |
| | | producer: |
| | | # 发送消息超时时间,默认3000 |
| | | send-message-timeout: 3000 |
| | | # 生产者组 |
| | | group: producer_group |
| | | # 发送消息失败重试次数,默认2 |
| | | retryTimesWhenSendFailed: 2 |
| | | # 异步消息重试此处,默认2 |
| | | retryTimesWhenSendAsyncFailed: 2 |
| | | # 消息最大长度,默认1024 * 1024 * 4(默认4M) |
| | | # 1024 * 128 = 128K |
| | | maxMessageSize: 131072 |
| | | # 压缩消息阈值,默认4k(1024 * 4) |
| | | compressMessageBodyThreshold: 4096 |
| | | # 是否在内部发送失败时重试另一个broker,默认false |
| | | retryNextServer: false |
| | | |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # 集中培训业务器配置,2023-10-26 |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | ctoms: |
| | | # 调度器配置,2023-10-26 |
| | | scheduler: |
| | | # 是否允许集群模式启用, |
| | | # true:表示集群部署,则业务打包发布中不包含调度模块(ctoms-scheduler-server),调度模块需要独立打包; |
| | | # false:表示单机部署,调度模块会被自动打包(作为一个类库)发布; |
| | | cluster-enabled: false |
| | | # 发布类型, |
| | | # single:业务单应用打包,直接能运行调度任务 |
| | | # scheduler:调度任务包(独立打包支持集群) |
| | | deploy-type: single |
| | | # 消息推送请求地址 |
| | | push-url: "https://push.cpoc.cn/sendv2" #互联网 |
| | | link-app-url: "https://jmy.jinmingyuan.com/ctoms-h5/#/?" #移动跳转 |
| | | link-pc-url: "https://jmy.jinmingyuan.com" |
| | | # push-url: "http://10.5.6.99:9001/sendv2" #综合网 |
| | | # push-url: "http://push.cpoc.cn:9001/sendv2" #综合网 |
New file |
| | |
| | | # 对应邮政内网开发环境配置 |
| | | spring: |
| | | application: |
| | | name: deploy |
| | | datasource: |
| | | # 是否显示dao中打印的SQL语句 |
| | | show-sql: true |
| | | |
| | | ## driver-class-name: sunje.goldilocks.jdbc.GoldilocksDriver |
| | | # 注意:MySQL服务端,需要调整两个参数,否则服务端会主动断开连接 |
| | | # wait_timeout: 超过改时间(秒)服务端主动断开 |
| | | # interactive_timeout: 客户端工具交互超过这个时间(秒)会端口,表现为navicat |
| | | |
| | | username: cent_glyyb_ctoms_uat_user |
| | | password: ENC(QlpRYCjAXS8pElGluLTsCA==) |
| | | # url: jdbc:postgresql://10.1.149.211:11023/cent_uat_db?currentSchema=cent_glyyb_ctoms_uat_schema&useUnicode=true&characterEncoding=UTF-8&useSSL=false&stringtype=unspecified |
| | | url: jdbc:postgresql://10.3.80.15:11002/cent_uat_db?currentSchema=cent_glyyb_ctoms_uat_schema&useUnicode=true&characterEncoding=UTF-8&useSSL=false&stringtype=unspecified |
| | | |
| | | # username: root |
| | | # url: jdbc:mysql://116.198.40.76:3306/iplatform?useUnicode=true&characterEncoding=UTF-8&useSSL=false |
| | | |
| | | # 达梦数据库 |
| | | # driver-class-name: dm.jdbc.driver.DmDriver |
| | | # username: iplatform |
| | | # url: jdbc:dm://116.198.39.83:5236?schema=iplatform |
| | | |
| | | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # 使用 Hikari 连接池 |
| | | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # type: com.walker.jdbc.ds.DefaultDataSource |
| | | # hikari: |
| | | # minimum-idle: 5 |
| | | # idle-timeout: 600000 |
| | | # pool-name: databasePool_walker |
| | | # # 连接最大超时时间 |
| | | # connection-timeout: 30000 |
| | | # # 连接池最大数量 |
| | | # maximum-pool-size: 10 |
| | | # # 控制池中连接最大生存期 |
| | | # # max-lifetime: 70000 |
| | | # # 此属性控制测试连接是否活跃的最长时间。此值必须小于 connectionTimeout |
| | | # validation-timeout: 10000 |
| | | # # |
| | | # connection-test-query: select 1 |
| | | |
| | | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # 使用 Druid 连接池 |
| | | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | type: com.walker.jdbc.ds.MyDruidDataSource |
| | | druid: |
| | | initial-size: 5 |
| | | min-idle: 10 |
| | | max-active: 20 |
| | | # 配置获取连接等待超时的时间 |
| | | max-wait: 60000 |
| | | # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 |
| | | time-between-eviction-runs-millis: 60000 |
| | | # 配置一个连接在池中最小生存的时间,单位是毫秒 超过这个时间每次会回收默认3个连接 |
| | | min-evictable-idle-time-millis: 30000 |
| | | # 线上配置的mysql断开闲置连接时间为1小时,数据源配置回收时间为3分钟,以最后一次活跃时间开始算 |
| | | max-evictable-idle-time-millis: 180000 |
| | | validation-query: select 1 |
| | | test-while-idle: true |
| | | test-on-borrow: false |
| | | test-on-return: false |
| | | pool-prepared-statements: true |
| | | max-open-prepared-statements: 100 |
| | | use-global-data-source-stat: true |
| | | webStatFilter: |
| | | enabled: false |
| | | statViewServlet: |
| | | enabled: false |
| | | # 设置白名单,不填则允许所有访问 |
| | | # allow: |
| | | # url-pattern: /druid/* |
| | | # # 控制台管理用户名和密码 |
| | | # login-username: ruoyi |
| | | filter: |
| | | stat: |
| | | enabled: false |
| | | # 慢SQL记录 |
| | | log-slow-sql: true |
| | | slow-sql-millis: 1000 |
| | | merge-sql: true |
| | | wall: |
| | | config: |
| | | multi-statement-allow: false |
| | | |
| | | redis: |
| | | host: 10.2.38.137 |
| | | port: 31512 |
| | | password: ENC(JgSbHpKSmIUMVvqeEwbst9xY3WxyJmwcNQ70gz0aZM8=) |
| | | # 内网环境不认该参数,2023-11-10 |
| | | # database: 2 |
| | | |
| | | mvc: |
| | | pathmatch: |
| | | # 加该配置是因为 swagger3 启动报错,2023-02-23 |
| | | matching-strategy: ant_path_matcher |
| | | |
| | | hiddenmethod: |
| | | filter: |
| | | enabled: true # 加上该配置可以接收: application/x-www-form-urlencoded请求参数为对象。支付通知中使用。2023-02-26 |
| | | |
| | | servlet: |
| | | multipart: |
| | | # maxFileSize 是单个文件大小 |
| | | # maxRequestSize是设置总上传的数据大小 |
| | | enabled: true |
| | | max-file-size: 5MB |
| | | max-request-size: 10MB |
| | | |
| | | server: |
| | | port: 8083 |
| | | servlet: |
| | | context-path: /tcp |
| | | session: |
| | | timeout: 30m |
| | | |
| | | logging: |
| | | level: |
| | | root: info |
| | | org: |
| | | springframework: info |
| | | io.swagger: error |
| | | com: |
| | | walker: debug |
| | | iplatform: debug |
| | | ctoms: debug |
| | | RocketmqRemoting: error # MQ打印该日志,目前没有找到解决资料。2023-09-27 |
| | | charset: |
| | | # 控制台编码 |
| | | console: UTF-8 |
| | | # 输出文件编码 |
| | | file: UTF-8 |
| | | |
| | | # file: # logging.file.path 和 logging.file.name,只会有一个生效,配了path不要配name,配了name不要配path,只配path时name默认为spring.log,想路径和文件名同时生效可配置logging.file.name=d:/logs/mylog.log |
| | | # name: ${spring.application.name}.log #日志文件名 |
| | | # path: logs #日志存储路径 |
| | | # max-history: 30 #保留多少天的日志 |
| | | # max-size: 10MB |
| | | # pattern: |
| | | # rolling-file-name: ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz |
| | | logback: |
| | | rollingpolicy: |
| | | # 单个文件最大为30MB,超过之后会打包成一个日志文件 |
| | | max-file-size: 10MB |
| | | # 文件保存7天 |
| | | max-history: 1 |
| | | # 打包文件格式,默认: ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz,书写格式为:文件路径/文件名.%i.文件后缀,其中%i不可省去,否则无日志显示 |
| | | # 例如: 日期为:2023/07/13 ,则打包文件之后为: log/ota.2023-07-13.0.gz,0表示日志的第一部分,后续就是,1,2,3... |
| | | # 如果是压缩包,里面会多一个名log/ota.2023-07-13.0的日志文件 |
| | | # 如下面的例子,打包之后为: log/2023-07/ota.2020-07-13.0.log,这是一个日志文件 |
| | | file-name-pattern: ${logging.file.path}%d{yyyy-MM}/iplatform-tcp.%d{yyyy-MM-dd}.%i.log |
| | | |
| | | file: |
| | | name: ${logging.file.path}iplatform-tcp.log |
| | | path: D:/log/ |
| | | |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # 平台配置支持功能 |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | iplatform: |
| | | |
| | | # 平台缓存,是否启用redis缓存,默认使用基于内存缓存. |
| | | # 注意:如果开启redis缓存,业务工程必须依赖(walker-support-redis) |
| | | cache: |
| | | redis-enabled: true |
| | | # redis 缓存是否要重建,如果设置 true,则系统启动后会删除缓存,并执行默认重新加载方法。2023-08-26 |
| | | # 注意:该参数一般在测试阶段使用,正式环境不要使用! |
| | | redis-rebuild: false |
| | | # 机构用户是否很庞大,如果是则缓存中会关闭初始化加载,同时机构树也不会放入缓存,2023-07-17 |
| | | org-user-big: true |
| | | # 单独加载机构 |
| | | org-alone-big: true |
| | | # 相似度分析模块使用(已废弃) |
| | | # similarity: |
| | | # # 是否启用相似度模块,如果禁用则要确保注入时支持为空 |
| | | # enabled: false |
| | | # milvus-host: 172.16.60.65 |
| | | # milvus-port: 19530 |
| | | # word-file: d:/dev_tools/ai/w2v_sogou_dim300_vocab.txt |
| | | # embedding-file: d:/dev_tools/ai/w2v_sogou_dim300.npy |
| | | |
| | | # 调度器模块,是否启用 |
| | | scheduler: |
| | | enabled: false |
| | | # 是否支持数据库存储任务(废弃该配置) |
| | | database-enabled: false |
| | | |
| | | # 数据采集模块 |
| | | gather: |
| | | enabled: false |
| | | |
| | | # 权限控制相关 |
| | | security: |
| | | # 匿名可访问地址(开放地址) |
| | | anonymous-list: |
| | | - /login |
| | | - /register |
| | | - /captcha/* # 验证码统一放开 |
| | | - /test/** # 开发测试,仅开发板可用 |
| | | - /template/ctoms/** |
| | | - /swagger-resources/** # swagger |
| | | - /swagger-ui/** # swagger |
| | | - /v3/** # swagger |
| | | - /pay/notify/** # 支付通知 |
| | | - /jmreport/** # 积木报表 |
| | | - /file/** # 登录用户可访问系统文件,2023-06-09 |
| | | - /third_party/unified/** # 系统第三方登录地址,前端获取网院token后,调用后台地址实现隐式登录,2023-10-23 |
| | | |
| | | |
| | | # 允许所有认证用户都可访问地址,请慎重否则权限都过大,一般API都应该设置在这里 |
| | | permit-list: |
| | | # - /permit # 公用权限,2023-03-13,平台代码已经添加过了,这里不需要配置 |
| | | - /getInfo |
| | | - /getRouters |
| | | - /getMenus # 新界面菜单,2023-05-12 |
| | | - /logout |
| | | - /api/** |
| | | - /dqyy/** #档期预约 |
| | | - /pxjd/** #培训资源 |
| | | - /tr/** #教师 |
| | | - /base/** #基地 |
| | | - /bjgl/class/** #班级管理 |
| | | - /app/** #app |
| | | - /system/** #平台系统 |
| | | - /report/** #费用汇总 |
| | | - /settlement/** #费用汇总记录 |
| | | - /door/** #门户 |
| | | |
| | | # 超级管理员密码,加密后的秘文 |
| | | supervisor-password: ENC(5hx5es5ySh5vySqCDFb61o1vhDVyOiA+gOBwkHjW1TbyUQwVWOVgKY+KUBOynTxOVDFFwGULPdCT8S4pJaSjGQ==) |
| | | |
| | | # 是否允许配置跨域响应头, true 启用, false 不启用。2022-12-28 |
| | | # 在Gateway模式中,需要关闭跨域配置,因为网关也会配置。 |
| | | cors-enabled: true |
| | | |
| | | # 用户名密码方式登录,配置的验证码类型:code/sms/slide/jigsaw,2023-03-14 |
| | | login-captcha-user-pass: code |
| | | # 手机验证码方式登录,配置的验证码类型:code/sms/slide/jigsaw,2023-03-14 |
| | | login-captcha-sms-code: sms |
| | | |
| | | # 是否允许后台用户(非App)登录手机端?2023-03-20 |
| | | allow-pc-user-access-app: true |
| | | |
| | | # 是否支持手机登录时(不存在手机号)直接注册?目前电商系统支持! 2023-06-26 |
| | | allow-mobile-login-reg: true |
| | | |
| | | # PC端token失效分钟,默认:120分钟,2023-03-28 |
| | | token-expire-web: 120 |
| | | # 移动端token失效分钟,2023-03-28 |
| | | token-expire-mobile: 120 |
| | | |
| | | # 用户体系(用户名)都是手机号,2023-06-28 |
| | | # 一般系统PC端通常都不是手机号作为用户名,只有在互联网相关系统中会存在手机号作为登录账号 |
| | | user-name-is-phone: false |
| | | |
| | | # 2023-07-11 登录策略配置,列表中存在的策略都表示启用(不启用的删掉) |
| | | login-strategy-list: |
| | | # - com.iplatform.base.support.strategy.WebOnceLoginStrategy ##同一账号只能登录一个ip |
| | | # - com.iplatform.base.support.strategy.MobileOnceLoginStrategy |
| | | |
| | | # 用户相关安全配置,2023-08-03 |
| | | user: |
| | | # 用户修改密码等级,分四级:1-2-3-4,常量:PasswordUtils# |
| | | pass-level: 1 |
| | | # 是否强制用户修改默认密码? |
| | | pass-default-modify: false |
| | | |
| | | # 代码生成,2022-11-26 |
| | | gen: |
| | | # 作者 |
| | | author: Mike |
| | | # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool |
| | | package-name: com.iplatform.model.po |
| | | # 自动去除表前缀,默认是false |
| | | auto-remove-pre: false |
| | | # 表前缀(生成类名不会包含表前缀,多个用逗号分隔) |
| | | table-prefix: s_ |
| | | |
| | | log: |
| | | # 是否打开登录日志,2023-01-05 |
| | | # 如果不打开,则设备登录的uuid更新操作也无法获得,用于记录每个登录用户的uuid(用户登录角色更新),2023-03-23 |
| | | login-enabled: true |
| | | # 是否打开操作日志,2023-01-05 |
| | | operate-enabled: false |
| | | |
| | | # 验证码相关配置,2023-01-27 |
| | | captcha: |
| | | # 图形验证码实现类, TextCaptchaProvider | DefaultCaptchaProvider |
| | | image-captcha-class: com.iplatform.base.captcha.TextCaptchaProvider |
| | | # 短信验证码实现类(配置废弃,2023-04-25) |
| | | sms-captcha-class: com.iplatform.base.captcha.MockSmsCaptchaProvider |
| | | |
| | | # 平台文件存储配置,2023-02-15 |
| | | file: |
| | | # FileStoreType = FileSystem 本地磁盘存储根路径 |
| | | file-root: d:/tmp/ |
| | | # 调用远程上传文件,是否按照本地文件处理,2023-07-03 |
| | | # 在测试过程中如果没有FTP等服务,可以设置为true临时存储本地 |
| | | remote-as-local: false |
| | | |
| | | # oss实现类型:aws_s3(亚马逊) | tx(腾讯) | ali(阿里) | qn(七牛),2023-12-13 |
| | | oss-type: aws_s3 |
| | | # oss访问前缀,如:http://localhost:8082/admin/oss/,2023-12-13 |
| | | oss-prefix: http://localhost:8082/admin/oss/ |
| | | oss-access-key: ENC(kLcOGmTADXxiDphSUZvMevg1Hw+mUhiX7w8Z7U1FQD8=) |
| | | oss-secret-key: ENC(w+UXEgJ4OhBqDdEP/ev6y4AisCUcUUAdDsUal24SvI1Ml8POKkIVlheaQn9qeo34) |
| | | # oss服务地址 |
| | | oss-endpoint: http://10.2.36.9:8080 |
| | | # oss默认的桶名称 |
| | | oss-bucket-name: ctoms-file |
| | | |
| | | ftp: |
| | | ip: 116.198.40.76 |
| | | port: 22 |
| | | user-name: mysftp |
| | | password: ENC(zHTagUyi1g+/syVY8gVOww==) |
| | | private-key: |
| | | # ftp服务上面的存储根路径,只能是linux路径 |
| | | # file-root: /files/ |
| | | file-root: /train/ |
| | | |
| | | # 接口文档生成,swagger3,2023-02-23 |
| | | swagger: |
| | | enable: false |
| | | # 包路径,暂时不用 |
| | | base-package: com.iplatform.base.controller |
| | | title: 云原生微服务平台 |
| | | description: 一个快速web开发框架 |
| | | |
| | | # TCP通信配置,2024-01-23 |
| | | tcp: |
| | | # 是否开启引擎 |
| | | enabled: true |
| | | # 是否打开心跳 |
| | | open-heart-beat: true |
| | | # 心跳时间(秒),2023-08-28 |
| | | heart-beat-seconds: 60 |
| | | # 是否显示详细日志 |
| | | show-log: false |
| | | # 请求队列类型:memory 基于内存 |
| | | queue-type: memory |
| | | # tcp方式要扫描的请求对象的包空间 |
| | | scan-packages-tcp: com.walker.tcp,com.iplatform.tcp |
| | | # websocket方式要扫描的请求对象的包空间 |
| | | scan-packages-ws: com.iplatform.tcp.util.ws |
| | | # tcp长连接的端口 |
| | | port-tcp: 7878 |
| | | # websocket连接端口 |
| | | port-ws: 60001 |
| | | # websocket连接uri |
| | | websocket-uri: wss://ctomsuat.chinapost.com.cn/ws |
| | | # 通信线程数量 |
| | | boss-thread-num: 2 |
| | | # 业务处理线程数量 |
| | | worker-thread-num: 4 |
| | | # 启用自定义连接管理器,如果true则业务需要提供自定义实现(配置),2023-07-18 |
| | | custom-connection-manager: false |
| | | # 是否开启集群模式,连接管理器会默认加载负载支持,2023-09-26 |
| | | load-balance-enabled: false |
| | | # 长连接主机(标记)信息,可以是任意字符串,只要集群中每个服务配置不同即可。 |
| | | # 在集群模式中,每个连接要加上主机标识,以便别人推送消息时,知道在哪个主机上推送。2023-09-19 |
| | | connection-host: topic_master |
| | | |
| | | # 推送模块配置,2023-04-25 |
| | | push: |
| | | # 短信推送者名称:mock_sms_push(模拟短信),alidy_sms_push(阿里大鱼短信) |
| | | sms-push-name: alidy_sms_push |
| | | # 短信验证码模板ID,根据实际情况(每个平台可能不同) |
| | | sms-template-code: SMS_285145505 |
| | | |
| | | # 对于一般业务提醒(不包括:邮件、短信),推送的方式。推送者ID组合 |
| | | # && 表示并列,|| 表示或(只要一个成功就OK) |
| | | # 2023-04-26,可用的 id = 'tcp', 'web_socket', 'wx', 'system' |
| | | # message-type: tcp && web_socket && wx && system |
| | | # 如果是或者方式,需要把最可靠的放前面,因为系统会找到第一个发送成功即可。 |
| | | message-type: system || tcp || web_socket || wx |
| | | |
| | | # 邮件通知发送信息配置,2023-04-26 |
| | | mail-server: smtp.126.com |
| | | mail-from: hnzzzhsl@126.com |
| | | mail-password: ENC(8Xr7W72lyjRVi0InopfITw==) |
| | | |
| | | # 聊天相关配置,2023-07-07 |
| | | # chat: |
| | | # # 是否启用机器人答复,2023-07-12 |
| | | # robot-enabled: true |
| | | # # 机器人具体实现对象,2023-07-12 |
| | | # robot-class: com.iplatform.chat.support.TestRobot |
| | | # # 是否开启mongo存储,如果false则默认使用数据库表 |
| | | # mongo-enabled: true |
| | | # mongo: |
| | | # ip: 116.198.40.76 |
| | | # port: 27017 |
| | | # # 聊天数据库名称,默认:chat |
| | | # database: czt_ops_test |
| | | # user-name: czt_ops_test |
| | | # password: czt_ops_test |
| | | # max-size: 10 |
| | | # min-size: 2 |
| | | # # 连接最大空闲时间,20分钟 |
| | | # max-idle-time-seconds: 1200 |
| | | # # 连接等待最大时间,10秒 |
| | | # max-wait-time-seconds: 10 |
| | | |
| | | # RestTemplate连接池配置,2023-08-18 |
| | | rest: |
| | | # 连接保持活动时间,默认:600秒 |
| | | keep-alive-duration-seconds: 600 |
| | | # 空闲连接数量,默认:200个 |
| | | max-idle-connections: 200 |
| | | # 连接超时,默认:2秒 |
| | | connect-timeout-seconds: 2 |
| | | # 读超时,默认3秒 |
| | | read-timeout-seconds: 3 |
| | | # 写超时,默认3秒 |
| | | write-timeout-seconds: 3 |
| | | |
| | | # 集群支持相关配置,2023-09-29 |
| | | lb: |
| | | # 本机服务节点ID,每个主机一个唯一数字编号,从1开始 |
| | | server-id: 8 |
| | | |
| | | # 2024-02-29 api监控相关 |
| | | api: |
| | | # 2024-02-29 是否打开接口时间统计记录,如果:true 则会记录接口调用时间,写入表:s_api_time |
| | | time-enabled: false |
| | | |
| | | # 网院统一认证配置选项,2023-10-23 |
| | | unified: |
| | | # 是否开启测试模式,测试模式用于本地测试,无法连接网院认证接口 |
| | | test-mode: false |
| | | # 网院提供的认证地址,关闭测试模式后,该选项生效 |
| | | remote-url: http://10.5.6.105:8001/uaa/person/current |
| | | |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # RocketMQ队列配置,2023-09-26 |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | rocketmq: |
| | | # 服务地址,多个用逗号分开 |
| | | # name-server: 116.198.40.76:9876 |
| | | name-server: 116.198.39.83:9898 |
| | | producer: |
| | | # 发送消息超时时间,默认3000 |
| | | send-message-timeout: 3000 |
| | | # 生产者组 |
| | | group: producer_group |
| | | # 发送消息失败重试次数,默认2 |
| | | retryTimesWhenSendFailed: 2 |
| | | # 异步消息重试此处,默认2 |
| | | retryTimesWhenSendAsyncFailed: 2 |
| | | # 消息最大长度,默认1024 * 1024 * 4(默认4M) |
| | | # 1024 * 128 = 128K |
| | | maxMessageSize: 131072 |
| | | # 压缩消息阈值,默认4k(1024 * 4) |
| | | compressMessageBodyThreshold: 4096 |
| | | # 是否在内部发送失败时重试另一个broker,默认false |
| | | retryNextServer: false |
| | | |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # 集中培训业务器配置,2023-10-26 |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | ctoms: |
| | | # 调度器配置,2023-10-26 |
| | | scheduler: |
| | | # 是否允许集群模式启用, |
| | | # true:表示集群部署,则业务打包发布中不包含调度模块(ctoms-scheduler-server),调度模块需要独立打包; |
| | | # false:表示单机部署,调度模块会被自动打包(作为一个类库)发布; |
| | | cluster-enabled: false |
| | | # 发布类型, |
| | | # single:业务单应用打包,直接能运行调度任务 |
| | | # scheduler:调度任务包(独立打包支持集群) |
| | | deploy-type: single |
| | | # push-url: "https://push.cpoc.cn/sendv2" #互联网 |
| | | push-url: "http://10.5.6.99:9001/sendv2" #综合网 |
| | | link-app-url: "https://ctomsuat.chinapost.com.cn/ctoms-h5/#/?" #移动跳转 |
| | | link-pc-url: "http://websocket:8083/tcp/" |
| | | # push-url: "http://push.cpoc.cn:9001/sendv2" #综合网 |
New file |
| | |
| | | # 对应邮政内网开发环境配置 |
| | | spring: |
| | | application: |
| | | name: deploy |
| | | datasource: |
| | | # 是否显示dao中打印的SQL语句 |
| | | show-sql: true |
| | | |
| | | ## driver-class-name: sunje.goldilocks.jdbc.GoldilocksDriver |
| | | # 注意:MySQL服务端,需要调整两个参数,否则服务端会主动断开连接 |
| | | # wait_timeout: 超过改时间(秒)服务端主动断开 |
| | | # interactive_timeout: 客户端工具交互超过这个时间(秒)会端口,表现为navicat |
| | | |
| | | username: cent_glyyb_ctoms_sc_user |
| | | password: ENC(Z/HgOaZnJvhO9EiwCu71jA==) |
| | | url: jdbc:postgresql://10.1.153.107:11004/cent_ctoms_sc_db?currentSchema=cent_glyyb_ctoms_sc_schema&targetServerType=primary&useUnicode=true&characterEncoding=UTF-8&useSSL=false&stringtype=unspecified |
| | | |
| | | # username: root |
| | | # url: jdbc:mysql://116.198.40.76:3306/iplatform?useUnicode=true&characterEncoding=UTF-8&useSSL=false |
| | | |
| | | # 达梦数据库 |
| | | # driver-class-name: dm.jdbc.driver.DmDriver |
| | | # username: iplatform |
| | | # url: jdbc:dm://116.198.39.83:5236?schema=iplatform |
| | | |
| | | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # 使用 Hikari 连接池 |
| | | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # type: com.walker.jdbc.ds.DefaultDataSource |
| | | # hikari: |
| | | # minimum-idle: 5 |
| | | # idle-timeout: 600000 |
| | | # pool-name: databasePool_walker |
| | | # # 连接最大超时时间 |
| | | # connection-timeout: 30000 |
| | | # # 连接池最大数量 |
| | | # maximum-pool-size: 10 |
| | | # # 控制池中连接最大生存期 |
| | | # # max-lifetime: 70000 |
| | | # # 此属性控制测试连接是否活跃的最长时间。此值必须小于 connectionTimeout |
| | | # validation-timeout: 10000 |
| | | # # |
| | | # connection-test-query: select 1 |
| | | |
| | | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # 使用 Druid 连接池 |
| | | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | type: com.walker.jdbc.ds.MyDruidDataSource |
| | | # type: com.ctoms.base.support.PostgresqlClusterDataSource |
| | | druid: |
| | | initial-size: 5 |
| | | min-idle: 10 |
| | | max-active: 20 |
| | | # 配置获取连接等待超时的时间 |
| | | max-wait: 60000 |
| | | # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 |
| | | time-between-eviction-runs-millis: 60000 |
| | | # 配置一个连接在池中最小生存的时间,单位是毫秒 超过这个时间每次会回收默认3个连接 |
| | | min-evictable-idle-time-millis: 30000 |
| | | # 线上配置的mysql断开闲置连接时间为1小时,数据源配置回收时间为3分钟,以最后一次活跃时间开始算 |
| | | max-evictable-idle-time-millis: 180000 |
| | | validation-query: select 1 |
| | | test-while-idle: true |
| | | test-on-borrow: false |
| | | test-on-return: false |
| | | pool-prepared-statements: true |
| | | max-open-prepared-statements: 100 |
| | | use-global-data-source-stat: true |
| | | webStatFilter: |
| | | enabled: false |
| | | statViewServlet: |
| | | enabled: false |
| | | # 设置白名单,不填则允许所有访问 |
| | | # allow: |
| | | # url-pattern: /druid/* |
| | | # # 控制台管理用户名和密码 |
| | | # login-username: ruoyi |
| | | filter: |
| | | stat: |
| | | enabled: false |
| | | # 慢SQL记录 |
| | | log-slow-sql: true |
| | | slow-sql-millis: 1000 |
| | | merge-sql: true |
| | | wall: |
| | | config: |
| | | multi-statement-allow: false |
| | | |
| | | redis: |
| | | host: 10.2.38.137 |
| | | port: 32157 |
| | | password: ENC(Kzn/kublbAelEFPfxxw8DZoNqudtoNUpUb/AOl1/s60=) |
| | | # 内网环境不认该参数,2023-11-10 |
| | | # database: 2 |
| | | |
| | | mvc: |
| | | pathmatch: |
| | | # 加该配置是因为 swagger3 启动报错,2023-02-23 |
| | | matching-strategy: ant_path_matcher |
| | | |
| | | hiddenmethod: |
| | | filter: |
| | | enabled: true # 加上该配置可以接收: application/x-www-form-urlencoded请求参数为对象。支付通知中使用。2023-02-26 |
| | | |
| | | servlet: |
| | | multipart: |
| | | # maxFileSize 是单个文件大小 |
| | | # maxRequestSize是设置总上传的数据大小 |
| | | enabled: true |
| | | max-file-size: 5MB |
| | | max-request-size: 10MB |
| | | |
| | | server: |
| | | port: 8083 |
| | | servlet: |
| | | context-path: /tcp |
| | | session: |
| | | timeout: 30m |
| | | |
| | | logging: |
| | | level: |
| | | root: info |
| | | org: |
| | | springframework: info |
| | | io.swagger: error |
| | | com: |
| | | walker: debug |
| | | iplatform: debug |
| | | ctoms: debug |
| | | RocketmqRemoting: error # MQ打印该日志,目前没有找到解决资料。2023-09-27 |
| | | charset: |
| | | # 控制台编码 |
| | | console: UTF-8 |
| | | # 输出文件编码 |
| | | file: UTF-8 |
| | | |
| | | # file: # logging.file.path 和 logging.file.name,只会有一个生效,配了path不要配name,配了name不要配path,只配path时name默认为spring.log,想路径和文件名同时生效可配置logging.file.name=d:/logs/mylog.log |
| | | # name: ${spring.application.name}.log #日志文件名 |
| | | # path: logs #日志存储路径 |
| | | # max-history: 30 #保留多少天的日志 |
| | | # max-size: 10MB |
| | | # pattern: |
| | | # rolling-file-name: ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz |
| | | logback: |
| | | rollingpolicy: |
| | | # 单个文件最大为30MB,超过之后会打包成一个日志文件 |
| | | max-file-size: 10MB |
| | | # 文件保存7天 |
| | | max-history: 1 |
| | | # 打包文件格式,默认: ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz,书写格式为:文件路径/文件名.%i.文件后缀,其中%i不可省去,否则无日志显示 |
| | | # 例如: 日期为:2023/07/13 ,则打包文件之后为: log/ota.2023-07-13.0.gz,0表示日志的第一部分,后续就是,1,2,3... |
| | | # 如果是压缩包,里面会多一个名log/ota.2023-07-13.0的日志文件 |
| | | # 如下面的例子,打包之后为: log/2023-07/ota.2020-07-13.0.log,这是一个日志文件 |
| | | file-name-pattern: ${logging.file.path}%d{yyyy-MM}/iplatform-tcp.%d{yyyy-MM-dd}.%i.log |
| | | |
| | | file: |
| | | name: ${logging.file.path}iplatform-tcp.log |
| | | path: D:/log/ |
| | | |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # 平台配置支持功能 |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | iplatform: |
| | | |
| | | # 平台缓存,是否启用redis缓存,默认使用基于内存缓存. |
| | | # 注意:如果开启redis缓存,业务工程必须依赖(walker-support-redis) |
| | | cache: |
| | | redis-enabled: true |
| | | # redis 缓存是否要重建,如果设置 true,则系统启动后会删除缓存,并执行默认重新加载方法。2023-08-26 |
| | | # 注意:该参数一般在测试阶段使用,正式环境不要使用! |
| | | redis-rebuild: false |
| | | # 机构用户是否很庞大,如果是则缓存中会关闭初始化加载,同时机构树也不会放入缓存,2023-07-17 |
| | | org-user-big: true |
| | | # 单独加载机构 |
| | | org-alone-big: true |
| | | # 相似度分析模块使用(已废弃) |
| | | # similarity: |
| | | # # 是否启用相似度模块,如果禁用则要确保注入时支持为空 |
| | | # enabled: false |
| | | # milvus-host: 172.16.60.65 |
| | | # milvus-port: 19530 |
| | | # word-file: d:/dev_tools/ai/w2v_sogou_dim300_vocab.txt |
| | | # embedding-file: d:/dev_tools/ai/w2v_sogou_dim300.npy |
| | | |
| | | # 调度器模块,是否启用 |
| | | scheduler: |
| | | enabled: false |
| | | # 是否支持数据库存储任务(废弃该配置) |
| | | database-enabled: false |
| | | |
| | | # 数据采集模块 |
| | | gather: |
| | | enabled: false |
| | | |
| | | # 权限控制相关 |
| | | security: |
| | | # 匿名可访问地址(开放地址) |
| | | anonymous-list: |
| | | - /login |
| | | - /register |
| | | - /captcha/* # 验证码统一放开 |
| | | - /test/** # 开发测试,仅开发板可用 |
| | | - /template/ctoms/** |
| | | - /swagger-resources/** # swagger |
| | | - /swagger-ui/** # swagger |
| | | - /v3/** # swagger |
| | | - /pay/notify/** # 支付通知 |
| | | - /jmreport/** # 积木报表 |
| | | - /file/** # 登录用户可访问系统文件,2023-06-09 |
| | | - /third_party/unified/** # 系统第三方登录地址,前端获取网院token后,调用后台地址实现隐式登录,2023-10-23 |
| | | |
| | | |
| | | # 允许所有认证用户都可访问地址,请慎重否则权限都过大,一般API都应该设置在这里 |
| | | permit-list: |
| | | # - /permit # 公用权限,2023-03-13,平台代码已经添加过了,这里不需要配置 |
| | | - /getInfo |
| | | - /getRouters |
| | | - /getMenus # 新界面菜单,2023-05-12 |
| | | - /logout |
| | | - /api/** |
| | | - /dqyy/** #档期预约 |
| | | - /pxjd/** #培训资源 |
| | | - /tr/** #教师 |
| | | - /base/** #基地 |
| | | - /bjgl/class/** #班级管理 |
| | | - /app/** #app |
| | | - /system/** #平台系统 |
| | | - /report/** #费用汇总 |
| | | - /settlement/** #费用汇总记录 |
| | | - /door/** #门户 |
| | | |
| | | # 超级管理员密码,加密后的秘文 |
| | | supervisor-password: ENC(5hx5es5ySh5vySqCDFb61o1vhDVyOiA+gOBwkHjW1TbyUQwVWOVgKY+KUBOynTxOVDFFwGULPdCT8S4pJaSjGQ==) |
| | | |
| | | # 是否允许配置跨域响应头, true 启用, false 不启用。2022-12-28 |
| | | # 在Gateway模式中,需要关闭跨域配置,因为网关也会配置。 |
| | | cors-enabled: true |
| | | |
| | | # 用户名密码方式登录,配置的验证码类型:code/sms/slide/jigsaw,2023-03-14 |
| | | login-captcha-user-pass: code |
| | | # 手机验证码方式登录,配置的验证码类型:code/sms/slide/jigsaw,2023-03-14 |
| | | login-captcha-sms-code: sms |
| | | |
| | | # 是否允许后台用户(非App)登录手机端?2023-03-20 |
| | | allow-pc-user-access-app: true |
| | | |
| | | # 是否支持手机登录时(不存在手机号)直接注册?目前电商系统支持! 2023-06-26 |
| | | allow-mobile-login-reg: true |
| | | |
| | | # PC端token失效分钟,默认:120分钟,2023-03-28 |
| | | token-expire-web: 120 |
| | | # 移动端token失效分钟,2023-03-28 |
| | | token-expire-mobile: 120 |
| | | |
| | | # 用户体系(用户名)都是手机号,2023-06-28 |
| | | # 一般系统PC端通常都不是手机号作为用户名,只有在互联网相关系统中会存在手机号作为登录账号 |
| | | user-name-is-phone: false |
| | | |
| | | # 2023-07-11 登录策略配置,列表中存在的策略都表示启用(不启用的删掉) |
| | | login-strategy-list: |
| | | # - com.iplatform.base.support.strategy.WebOnceLoginStrategy ##同一账号只能登录一个ip |
| | | # - com.iplatform.base.support.strategy.MobileOnceLoginStrategy |
| | | |
| | | # 用户相关安全配置,2023-08-03 |
| | | user: |
| | | # 用户修改密码等级,分四级:1-2-3-4,常量:PasswordUtils# |
| | | pass-level: 1 |
| | | # 是否强制用户修改默认密码? |
| | | pass-default-modify: false |
| | | |
| | | # 代码生成,2022-11-26 |
| | | gen: |
| | | # 作者 |
| | | author: Mike |
| | | # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool |
| | | package-name: com.iplatform.model.po |
| | | # 自动去除表前缀,默认是false |
| | | auto-remove-pre: false |
| | | # 表前缀(生成类名不会包含表前缀,多个用逗号分隔) |
| | | table-prefix: s_ |
| | | |
| | | log: |
| | | # 是否打开登录日志,2023-01-05 |
| | | # 如果不打开,则设备登录的uuid更新操作也无法获得,用于记录每个登录用户的uuid(用户登录角色更新),2023-03-23 |
| | | login-enabled: true |
| | | # 是否打开操作日志,2023-01-05 |
| | | operate-enabled: false |
| | | |
| | | # 验证码相关配置,2023-01-27 |
| | | captcha: |
| | | # 图形验证码实现类, TextCaptchaProvider | DefaultCaptchaProvider |
| | | image-captcha-class: com.iplatform.base.captcha.TextCaptchaProvider |
| | | # 短信验证码实现类(配置废弃,2023-04-25) |
| | | sms-captcha-class: com.iplatform.base.captcha.MockSmsCaptchaProvider |
| | | |
| | | # 平台文件存储配置,2023-02-15 |
| | | file: |
| | | # FileStoreType = FileSystem 本地磁盘存储根路径 |
| | | file-root: d:/tmp/ |
| | | # 调用远程上传文件,是否按照本地文件处理,2023-07-03 |
| | | # 在测试过程中如果没有FTP等服务,可以设置为true临时存储本地 |
| | | remote-as-local: false |
| | | |
| | | # oss实现类型:aws_s3(亚马逊) | tx(腾讯) | ali(阿里) | qn(七牛),2023-12-13 |
| | | oss-type: aws_s3 |
| | | # oss访问前缀,如:http://localhost:8082/admin/oss/,2023-12-13 |
| | | oss-prefix: http://localhost:8082/admin/oss/ |
| | | oss-access-key: 5YOZCZF4AFDGJBAFEFF9 |
| | | oss-secret-key: aE3EXCkMflK5VtOZeAI1ySX7acWoPB1KhOBOPGgf |
| | | # oss服务地址 |
| | | oss-endpoint: http://10.2.36.9:8080 |
| | | # oss默认的桶名称 |
| | | oss-bucket-name: ctoms-file |
| | | |
| | | ftp: |
| | | ip: 116.198.40.76 |
| | | port: 22 |
| | | user-name: mysftp |
| | | password: |
| | | private-key: |
| | | # ftp服务上面的存储根路径,只能是linux路径 |
| | | # file-root: /files/ |
| | | file-root: /train/ |
| | | |
| | | # 接口文档生成,swagger3,2023-02-23 |
| | | swagger: |
| | | enable: false |
| | | # 包路径,暂时不用 |
| | | base-package: com.iplatform.base.controller |
| | | title: 云原生微服务平台 |
| | | description: 一个快速web开发框架 |
| | | |
| | | # TCP通信配置,2024-01-23 |
| | | tcp: |
| | | # 是否开启引擎 |
| | | enabled: true |
| | | # 是否打开心跳 |
| | | open-heart-beat: true |
| | | # 心跳时间(秒),2023-08-28 |
| | | heart-beat-seconds: 60 |
| | | # 是否显示详细日志 |
| | | show-log: false |
| | | # 请求队列类型:memory 基于内存 |
| | | queue-type: memory |
| | | # tcp方式要扫描的请求对象的包空间 |
| | | scan-packages-tcp: com.walker.tcp,com.iplatform.tcp |
| | | # websocket方式要扫描的请求对象的包空间 |
| | | scan-packages-ws: com.iplatform.tcp.util.ws |
| | | # tcp长连接的端口 |
| | | port-tcp: 7878 |
| | | # websocket连接端口 |
| | | port-ws: 60001 |
| | | # websocket连接uri |
| | | websocket-uri: wss://ctoms.chinapost.com.cn/ws |
| | | # 通信线程数量 |
| | | boss-thread-num: 2 |
| | | # 业务处理线程数量 |
| | | worker-thread-num: 4 |
| | | # 启用自定义连接管理器,如果true则业务需要提供自定义实现(配置),2023-07-18 |
| | | custom-connection-manager: false |
| | | # 是否开启集群模式,连接管理器会默认加载负载支持,2023-09-26 |
| | | load-balance-enabled: false |
| | | # 长连接主机(标记)信息,可以是任意字符串,只要集群中每个服务配置不同即可。 |
| | | # 在集群模式中,每个连接要加上主机标识,以便别人推送消息时,知道在哪个主机上推送。2023-09-19 |
| | | connection-host: topic_master |
| | | |
| | | # 推送模块配置,2023-04-25 |
| | | push: |
| | | # 短信推送者名称:mock_sms_push(模拟短信),alidy_sms_push(阿里大鱼短信) |
| | | sms-push-name: alidy_sms_push |
| | | # 短信验证码模板ID,根据实际情况(每个平台可能不同) |
| | | sms-template-code: SMS_285145505 |
| | | |
| | | # 对于一般业务提醒(不包括:邮件、短信),推送的方式。推送者ID组合 |
| | | # && 表示并列,|| 表示或(只要一个成功就OK) |
| | | # 2023-04-26,可用的 id = 'tcp', 'web_socket', 'wx', 'system' |
| | | # message-type: tcp && web_socket && wx && system |
| | | # 如果是或者方式,需要把最可靠的放前面,因为系统会找到第一个发送成功即可。 |
| | | message-type: system || tcp || web_socket || wx |
| | | |
| | | # 邮件通知发送信息配置,2023-04-26 |
| | | mail-server: smtp.126.com |
| | | mail-from: hnzzzhsl@126.com |
| | | mail-password: |
| | | |
| | | # 聊天相关配置,2023-07-07 |
| | | # chat: |
| | | # # 是否启用机器人答复,2023-07-12 |
| | | # robot-enabled: true |
| | | # # 机器人具体实现对象,2023-07-12 |
| | | # robot-class: com.iplatform.chat.support.TestRobot |
| | | # # 是否开启mongo存储,如果false则默认使用数据库表 |
| | | # mongo-enabled: true |
| | | # mongo: |
| | | # ip: 116.198.40.76 |
| | | # port: 27017 |
| | | # # 聊天数据库名称,默认:chat |
| | | # database: czt_ops_test |
| | | # user-name: czt_ops_test |
| | | # password: czt_ops_test |
| | | # max-size: 10 |
| | | # min-size: 2 |
| | | # # 连接最大空闲时间,20分钟 |
| | | # max-idle-time-seconds: 1200 |
| | | # # 连接等待最大时间,10秒 |
| | | # max-wait-time-seconds: 10 |
| | | |
| | | # RestTemplate连接池配置,2023-08-18 |
| | | rest: |
| | | # 连接保持活动时间,默认:600秒 |
| | | keep-alive-duration-seconds: 600 |
| | | # 空闲连接数量,默认:200个 |
| | | max-idle-connections: 200 |
| | | # 连接超时,默认:2秒 |
| | | connect-timeout-seconds: 2 |
| | | # 读超时,默认3秒 |
| | | read-timeout-seconds: 3 |
| | | # 写超时,默认3秒 |
| | | write-timeout-seconds: 3 |
| | | |
| | | # 集群支持相关配置,2023-09-29 |
| | | lb: |
| | | # 本机服务节点ID,每个主机一个唯一数字编号,从1开始 |
| | | server-id: 8 |
| | | |
| | | # 2024-02-29 api监控相关 |
| | | api: |
| | | # 2024-02-29 是否打开接口时间统计记录,如果:true 则会记录接口调用时间,写入表:s_api_time |
| | | time-enabled: false |
| | | |
| | | # 网院统一认证配置选项,2023-10-23 |
| | | unified: |
| | | # 是否开启测试模式,测试模式用于本地测试,无法连接网院认证接口 |
| | | test-mode: false |
| | | # 网院提供的认证地址,关闭测试模式后,该选项生效 |
| | | remote-url: http://10.5.6.105:8001/uaa/person/current |
| | | |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # RocketMQ队列配置,2023-09-26 |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | rocketmq: |
| | | # 服务地址,多个用逗号分开 |
| | | # name-server: 116.198.40.76:9876 |
| | | name-server: 116.198.39.83:9898 |
| | | producer: |
| | | # 发送消息超时时间,默认3000 |
| | | send-message-timeout: 3000 |
| | | # 生产者组 |
| | | group: producer_group |
| | | # 发送消息失败重试次数,默认2 |
| | | retryTimesWhenSendFailed: 2 |
| | | # 异步消息重试此处,默认2 |
| | | retryTimesWhenSendAsyncFailed: 2 |
| | | # 消息最大长度,默认1024 * 1024 * 4(默认4M) |
| | | # 1024 * 128 = 128K |
| | | maxMessageSize: 131072 |
| | | # 压缩消息阈值,默认4k(1024 * 4) |
| | | compressMessageBodyThreshold: 4096 |
| | | # 是否在内部发送失败时重试另一个broker,默认false |
| | | retryNextServer: false |
| | | |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # 集中培训业务器配置,2023-10-26 |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | ctoms: |
| | | # 调度器配置,2023-10-26 |
| | | scheduler: |
| | | # 是否允许集群模式启用, |
| | | # true:表示集群部署,则业务打包发布中不包含调度模块(ctoms-scheduler-server),调度模块需要独立打包; |
| | | # false:表示单机部署,调度模块会被自动打包(作为一个类库)发布; |
| | | cluster-enabled: false |
| | | # 发布类型, |
| | | # single:业务单应用打包,直接能运行调度任务 |
| | | # scheduler:调度任务包(独立打包支持集群) |
| | | deploy-type: single |
| | | # push-url: "https://push.cpoc.cn/sendv2" #互联网 |
| | | push-url: "http://10.5.6.99:9001/sendv2" #综合网 |
| | | link-app-url: "https://ctoms.chinapost.com.cn/ctoms-h5/#/?" #移动跳转 |
| | | link-pc-url: "http://websocket:8083/tcp/" |
| | | # push-url: "http://push.cpoc.cn:9001/sendv2" #综合网 |
New file |
| | |
| | | spring: |
| | | application: |
| | | name: deploy |
| | | datasource: |
| | | # 是否显示dao中打印的SQL语句 |
| | | show-sql: true |
| | | |
| | | ## driver-class-name: sunje.goldilocks.jdbc.GoldilocksDriver |
| | | # 注意:MySQL服务端,需要调整两个参数,否则服务端会主动断开连接 |
| | | # wait_timeout: 超过改时间(秒)服务端主动断开 |
| | | # interactive_timeout: 客户端工具交互超过这个时间(秒)会端口,表现为navicat |
| | | |
| | | username: tbase |
| | | password: ENC(SDQnluhnbTXI2XBdvnpBMw==) |
| | | url: jdbc:postgresql://116.198.40.76:30004/ctoms-beifen?useUnicode=true&characterEncoding=UTF-8&useSSL=false&stringtype=unspecified |
| | | |
| | | # username: root |
| | | # password: Bjjmy_2020 |
| | | # url: jdbc:mysql://116.198.40.76:3306/iplatform?useUnicode=true&characterEncoding=UTF-8&useSSL=false |
| | | |
| | | # 达梦数据库 |
| | | # driver-class-name: dm.jdbc.driver.DmDriver |
| | | # username: iplatform |
| | | # password: iplatform |
| | | # url: jdbc:dm://116.198.39.83:5236?schema=iplatform |
| | | |
| | | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # 使用 Hikari 连接池 |
| | | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # type: com.walker.jdbc.ds.DefaultDataSource |
| | | # hikari: |
| | | # minimum-idle: 5 |
| | | # idle-timeout: 600000 |
| | | # pool-name: databasePool_walker |
| | | # # 连接最大超时时间 |
| | | # connection-timeout: 30000 |
| | | # # 连接池最大数量 |
| | | # maximum-pool-size: 10 |
| | | # # 控制池中连接最大生存期 |
| | | # # max-lifetime: 70000 |
| | | # # 此属性控制测试连接是否活跃的最长时间。此值必须小于 connectionTimeout |
| | | # validation-timeout: 10000 |
| | | # # |
| | | # connection-test-query: select 1 |
| | | |
| | | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # 使用 Druid 连接池 |
| | | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | type: com.walker.jdbc.ds.MyDruidDataSource |
| | | druid: |
| | | initial-size: 5 |
| | | min-idle: 10 |
| | | max-active: 20 |
| | | # 配置获取连接等待超时的时间 |
| | | max-wait: 60000 |
| | | # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 |
| | | time-between-eviction-runs-millis: 60000 |
| | | # 配置一个连接在池中最小生存的时间,单位是毫秒 超过这个时间每次会回收默认3个连接 |
| | | min-evictable-idle-time-millis: 30000 |
| | | # 线上配置的mysql断开闲置连接时间为1小时,数据源配置回收时间为3分钟,以最后一次活跃时间开始算 |
| | | max-evictable-idle-time-millis: 180000 |
| | | validation-query: select 1 |
| | | test-while-idle: true |
| | | test-on-borrow: false |
| | | test-on-return: false |
| | | pool-prepared-statements: true |
| | | max-open-prepared-statements: 100 |
| | | use-global-data-source-stat: true |
| | | webStatFilter: |
| | | enabled: false |
| | | statViewServlet: |
| | | enabled: false |
| | | # 设置白名单,不填则允许所有访问 |
| | | # allow: |
| | | # url-pattern: /druid/* |
| | | # # 控制台管理用户名和密码 |
| | | # login-username: ruoyi |
| | | filter: |
| | | stat: |
| | | enabled: false |
| | | # 慢SQL记录 |
| | | log-slow-sql: true |
| | | slow-sql-millis: 1000 |
| | | merge-sql: true |
| | | wall: |
| | | config: |
| | | multi-statement-allow: false |
| | | |
| | | redis: |
| | | host: 116.198.40.76 |
| | | port: 6379 |
| | | password: ENC(VQ9j5YF08eKywBGZzMFq4g==) |
| | | # 内网环境不认该参数,2023-11-10 |
| | | database: 2 |
| | | |
| | | mvc: |
| | | pathmatch: |
| | | # 加该配置是因为 swagger3 启动报错,2023-02-23 |
| | | matching-strategy: ant_path_matcher |
| | | |
| | | hiddenmethod: |
| | | filter: |
| | | enabled: true # 加上该配置可以接收: application/x-www-form-urlencoded请求参数为对象。支付通知中使用。2023-02-26 |
| | | |
| | | servlet: |
| | | multipart: |
| | | # maxFileSize 是单个文件大小 |
| | | # maxRequestSize是设置总上传的数据大小 |
| | | enabled: true |
| | | max-file-size: 5MB |
| | | max-request-size: 10MB |
| | | |
| | | server: |
| | | port: 8088 |
| | | servlet: |
| | | context-path: /tcp |
| | | session: |
| | | timeout: 30m |
| | | |
| | | logging: |
| | | level: |
| | | root: info |
| | | org: |
| | | springframework: info |
| | | io.swagger: error |
| | | com: |
| | | walker: debug |
| | | iplatform: debug |
| | | ctoms: debug |
| | | RocketmqRemoting: error # MQ打印该日志,目前没有找到解决资料。2023-09-27 |
| | | charset: |
| | | # 控制台编码 |
| | | console: UTF-8 |
| | | # 输出文件编码 |
| | | file: UTF-8 |
| | | |
| | | # file: # logging.file.path 和 logging.file.name,只会有一个生效,配了path不要配name,配了name不要配path,只配path时name默认为spring.log,想路径和文件名同时生效可配置logging.file.name=d:/logs/mylog.log |
| | | # name: ${spring.application.name}.log #日志文件名 |
| | | # path: logs #日志存储路径 |
| | | # max-history: 30 #保留多少天的日志 |
| | | # max-size: 10MB |
| | | # pattern: |
| | | # rolling-file-name: ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz |
| | | logback: |
| | | rollingpolicy: |
| | | # 单个文件最大为30MB,超过之后会打包成一个日志文件 |
| | | max-file-size: 10MB |
| | | # 文件保存7天 |
| | | max-history: 1 |
| | | # 打包文件格式,默认: ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz,书写格式为:文件路径/文件名.%i.文件后缀,其中%i不可省去,否则无日志显示 |
| | | # 例如: 日期为:2023/07/13 ,则打包文件之后为: log/ota.2023-07-13.0.gz,0表示日志的第一部分,后续就是,1,2,3... |
| | | # 如果是压缩包,里面会多一个名log/ota.2023-07-13.0的日志文件 |
| | | # 如下面的例子,打包之后为: log/2023-07/ota.2020-07-13.0.log,这是一个日志文件 |
| | | file-name-pattern: ${logging.file.path}%d{yyyy-MM}/iplatform-tcp.%d{yyyy-MM-dd}.%i.log |
| | | |
| | | file: |
| | | name: ${logging.file.path}iplatform-tcp.log |
| | | path: D:/log/ |
| | | |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # 平台配置支持功能 |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | iplatform: |
| | | |
| | | # 平台缓存,是否启用redis缓存,默认使用基于内存缓存. |
| | | # 注意:如果开启redis缓存,业务工程必须依赖(walker-support-redis) |
| | | cache: |
| | | redis-enabled: true |
| | | # redis 缓存是否要重建,如果设置 true,则系统启动后会删除缓存,并执行默认重新加载方法。2023-08-26 |
| | | # 注意:该参数一般在测试阶段使用,正式环境不要使用! |
| | | redis-rebuild: true |
| | | # 机构用户是否很庞大,如果是则缓存中会关闭初始化加载,同时机构树也不会放入缓存,2023-07-17 |
| | | org-user-big: true |
| | | # 单独加载机构 |
| | | org-alone-big: true |
| | | # 相似度分析模块使用(已废弃) |
| | | # similarity: |
| | | # # 是否启用相似度模块,如果禁用则要确保注入时支持为空 |
| | | # enabled: false |
| | | # milvus-host: 172.16.60.65 |
| | | # milvus-port: 19530 |
| | | # word-file: d:/dev_tools/ai/w2v_sogou_dim300_vocab.txt |
| | | # embedding-file: d:/dev_tools/ai/w2v_sogou_dim300.npy |
| | | |
| | | # 调度器模块,是否启用 |
| | | scheduler: |
| | | enabled: false |
| | | # 是否支持数据库存储任务(废弃该配置) |
| | | database-enabled: false |
| | | |
| | | # 数据采集模块 |
| | | gather: |
| | | enabled: false |
| | | |
| | | security: |
| | | # 匿名可访问地址(开放地址) |
| | | anonymous-list: |
| | | - /login |
| | | - /register |
| | | - /captcha/* # 验证码统一放开 |
| | | - /test/** # 开发测试,仅开发板可用 |
| | | - /template/ctoms/** |
| | | - /swagger-resources/** # swagger |
| | | - /swagger-ui/** # swagger |
| | | - /v3/** # swagger |
| | | - /pay/notify/** # 支付通知 |
| | | - /jmreport/** # 积木报表 |
| | | - /file/** # 登录用户可访问系统文件,2023-06-09 |
| | | - /third_party/unified/** # 系统第三方登录地址,前端获取网院token后,调用后台地址实现隐式登录,2023-10-23 |
| | | - /door/** |
| | | - /oss/** # 测试使用,正式应配置到permit下,2023-12-13 |
| | | # 允许所有认证用户都可访问地址,请慎重否则权限都过大,一般API都应该设置在这里 |
| | | permit-list: |
| | | # - /permit # 公用权限,2023-03-13,平台代码已经添加过了,这里不需要配置 |
| | | - /getInfo |
| | | - /getRouters |
| | | - /getMenus # 新界面菜单,2023-05-12 |
| | | - /logout |
| | | - /api/** |
| | | - /dqyy/** #档期预约 |
| | | - /pxjd/** #培训资源 |
| | | - /tr/** #教师 |
| | | - /base/** #基地 |
| | | - /bjgl/class/** #班级管理 |
| | | - /app/** #app |
| | | - /system/** #平台系统 |
| | | - /report/** #费用汇总 |
| | | - /settlement/** #费用汇总记录 |
| | | - /resource/** #资源 |
| | | - /evaluation/** #教学评估 |
| | | - /stat/workload/** #校内师资工作量 |
| | | - /bjgl/bus/** #接送站 |
| | | - /all/base/statistics/** #全网统计 |
| | | |
| | | # 超级管理员密码,加密后的秘文 |
| | | supervisor-password: ENC(i2QGr3kEu49MbMrW7dR+Q7jiPn1WpeuIbCfemGkhy+aMTamfXxrmKyS6j4GqG2TDm/7MTF8Q/+xqQB5pvy6rqA==) |
| | | |
| | | # 是否允许配置跨域响应头, true 启用, false 不启用。2022-12-28 |
| | | # 在Gateway模式中,需要关闭跨域配置,因为网关也会配置。 |
| | | cors-enabled: true |
| | | |
| | | # 用户名密码方式登录,配置的验证码类型:code/sms/slide/jigsaw,2023-03-14 |
| | | login-captcha-user-pass: code |
| | | # 手机验证码方式登录,配置的验证码类型:code/sms/slide/jigsaw,2023-03-14 |
| | | login-captcha-sms-code: sms |
| | | |
| | | # 是否允许后台用户(非App)登录手机端?2023-03-20 |
| | | allow-pc-user-access-app: true |
| | | |
| | | # 是否支持手机登录时(不存在手机号)直接注册?目前电商系统支持! 2023-06-26 |
| | | allow-mobile-login-reg: true |
| | | |
| | | # PC端token失效分钟,默认:120分钟,2023-03-28 |
| | | token-expire-web: 120 |
| | | # 移动端token失效分钟,2023-03-28 |
| | | token-expire-mobile: 120 |
| | | |
| | | # 用户体系(用户名)都是手机号,2023-06-28 |
| | | # 一般系统PC端通常都不是手机号作为用户名,只有在互联网相关系统中会存在手机号作为登录账号 |
| | | user-name-is-phone: false |
| | | |
| | | # 2023-07-11 登录策略配置,列表中存在的策略都表示启用(不启用的删掉) |
| | | login-strategy-list: |
| | | # - com.iplatform.base.support.strategy.WebOnceLoginStrategy ##同一账号只能登录一个ip |
| | | # - com.iplatform.base.support.strategy.MobileOnceLoginStrategy |
| | | |
| | | # 用户相关安全配置,2023-08-03 |
| | | user: |
| | | # 用户修改密码等级,分四级:1-2-3-4,常量:PasswordUtils# |
| | | pass-level: 1 |
| | | # 是否强制用户修改默认密码? |
| | | pass-default-modify: false |
| | | |
| | | # 代码生成,2022-11-26 |
| | | gen: |
| | | # 作者 |
| | | author: Mike |
| | | # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool |
| | | package-name: com.iplatform.model.po |
| | | # 自动去除表前缀,默认是false |
| | | auto-remove-pre: false |
| | | # 表前缀(生成类名不会包含表前缀,多个用逗号分隔) |
| | | table-prefix: s_ |
| | | |
| | | log: |
| | | # 是否打开登录日志,2023-01-05 |
| | | # 如果不打开,则设备登录的uuid更新操作也无法获得,用于记录每个登录用户的uuid(用户登录角色更新),2023-03-23 |
| | | login-enabled: true |
| | | # 是否打开操作日志,2023-01-05 |
| | | operate-enabled: false |
| | | |
| | | # 验证码相关配置,2023-01-27 |
| | | captcha: |
| | | # 图形验证码实现类, TextCaptchaProvider | DefaultCaptchaProvider |
| | | image-captcha-class: com.iplatform.base.captcha.TextCaptchaProvider |
| | | # 短信验证码实现类(配置废弃,2023-04-25) |
| | | sms-captcha-class: com.iplatform.base.captcha.MockSmsCaptchaProvider |
| | | |
| | | # 平台文件存储配置,2023-02-15 |
| | | file: |
| | | # FileStoreType = FileSystem 本地磁盘存储根路径 |
| | | file-root: d:/tmp/ |
| | | # 调用远程上传文件,是否按照本地文件处理,2023-07-03 |
| | | # 在测试过程中如果没有FTP等服务,可以设置为true临时存储本地 |
| | | remote-as-local: false |
| | | |
| | | # oss实现类型:aws_s3(亚马逊) | tx(腾讯) | ali(阿里) | qn(七牛),2023-12-13 |
| | | oss-type: aws_s3 |
| | | # oss访问前缀,如:http://localhost:8082/admin/oss/,2023-12-13 |
| | | oss-prefix: http://localhost:8082/admin/oss/ |
| | | oss-access-key: ENC(BTHETNjs5ddRjYrdMF9ltmw8DMIEYTuyXIgDOeLIHy0=) |
| | | oss-secret-key: ENC(jROCWGpiPULZrU1wBZAsXvQQovvqnhoJKWpmYD/3nbkNGDikxfEvCXW5jn3QsYnG) |
| | | # oss服务地址 |
| | | oss-endpoint: https://eos-beijing-1.cmecloud.cn |
| | | # oss默认的桶名称 |
| | | oss-bucket-name: ctoms-file |
| | | protocol: https |
| | | |
| | | ftp: |
| | | ip: 116.198.40.76 |
| | | port: 22 |
| | | user-name: mysftp |
| | | password: |
| | | private-key: |
| | | # ftp服务上面的存储根路径,只能是linux路径 |
| | | # file-root: /files/ |
| | | file-root: /train/ |
| | | |
| | | # 接口文档生成,swagger3,2023-02-23 |
| | | swagger: |
| | | enable: false |
| | | # 包路径,暂时不用 |
| | | base-package: com.iplatform.base.controller |
| | | title: 云原生微服务平台 |
| | | description: 一个快速web开发框架 |
| | | |
| | | # TCP通信配置,2024-01-23 |
| | | tcp: |
| | | # 是否开启引擎 |
| | | enabled: true |
| | | # 是否打开心跳 |
| | | open-heart-beat: true |
| | | # 心跳时间(秒),2023-08-28 |
| | | heart-beat-seconds: 60 |
| | | # 是否显示详细日志 |
| | | show-log: false |
| | | # 请求队列类型:memory 基于内存 |
| | | queue-type: memory |
| | | # tcp方式要扫描的请求对象的包空间 |
| | | scan-packages-tcp: com.walker.tcp,com.iplatform.tcp |
| | | # websocket方式要扫描的请求对象的包空间 |
| | | scan-packages-ws: com.iplatform.tcp.util.ws |
| | | # tcp长连接的端口 |
| | | port-tcp: 7878 |
| | | # websocket连接端口 |
| | | port-ws: 60001 |
| | | # websocket连接uri |
| | | websocket-uri: wss://jmy.jinmingyuan.com/wss |
| | | # 通信线程数量 |
| | | boss-thread-num: 2 |
| | | # 业务处理线程数量 |
| | | worker-thread-num: 4 |
| | | # 启用自定义连接管理器,如果true则业务需要提供自定义实现(配置),2023-07-18 |
| | | custom-connection-manager: false |
| | | # 是否开启集群模式,连接管理器会默认加载负载支持,2023-09-26 |
| | | load-balance-enabled: false |
| | | # 长连接主机(标记)信息,可以是任意字符串,只要集群中每个服务配置不同即可。 |
| | | # 在集群模式中,每个连接要加上主机标识,以便别人推送消息时,知道在哪个主机上推送。2023-09-19 |
| | | connection-host: topic_master |
| | | |
| | | # 推送模块配置,2023-04-25 |
| | | push: |
| | | # 短信推送者名称:mock_sms_push(模拟短信),alidy_sms_push(阿里大鱼短信) |
| | | sms-push-name: alidy_sms_push |
| | | # 短信验证码模板ID,根据实际情况(每个平台可能不同) |
| | | sms-template-code: SMS_285145505 |
| | | |
| | | # 对于一般业务提醒(不包括:邮件、短信),推送的方式。推送者ID组合 |
| | | # && 表示并列,|| 表示或(只要一个成功就OK) |
| | | # 2023-04-26,可用的 id = 'tcp', 'web_socket', 'wx', 'system' |
| | | # message-type: tcp && web_socket && wx && system |
| | | # 如果是或者方式,需要把最可靠的放前面,因为系统会找到第一个发送成功即可。 |
| | | message-type: system || tcp || web_socket || wx |
| | | |
| | | # 邮件通知发送信息配置,2023-04-26 |
| | | mail-server: smtp.126.com |
| | | mail-from: hnzzzhsl@126.com |
| | | mail-password: |
| | | |
| | | # 聊天相关配置,2023-07-07 |
| | | # chat: |
| | | # # 是否启用机器人答复,2023-07-12 |
| | | # robot-enabled: true |
| | | # # 机器人具体实现对象,2023-07-12 |
| | | # robot-class: com.iplatform.chat.support.TestRobot |
| | | # # 是否开启mongo存储,如果false则默认使用数据库表 |
| | | # mongo-enabled: true |
| | | # mongo: |
| | | # ip: 116.198.40.76 |
| | | # port: 27017 |
| | | # # 聊天数据库名称,默认:chat |
| | | # database: czt_ops_test |
| | | # user-name: czt_ops_test |
| | | # password: czt_ops_test |
| | | # max-size: 10 |
| | | # min-size: 2 |
| | | # # 连接最大空闲时间,20分钟 |
| | | # max-idle-time-seconds: 1200 |
| | | # # 连接等待最大时间,10秒 |
| | | # max-wait-time-seconds: 10 |
| | | |
| | | # RestTemplate连接池配置,2023-08-18 |
| | | rest: |
| | | # 连接保持活动时间,默认:600秒 |
| | | keep-alive-duration-seconds: 600 |
| | | # 空闲连接数量,默认:200个 |
| | | max-idle-connections: 200 |
| | | # 连接超时,默认:2秒 |
| | | connect-timeout-seconds: 2 |
| | | # 读超时,默认3秒 |
| | | read-timeout-seconds: 3 |
| | | # 写超时,默认3秒 |
| | | write-timeout-seconds: 3 |
| | | |
| | | # 集群支持相关配置,2023-09-29 |
| | | lb: |
| | | # 本机服务节点ID,每个主机一个唯一数字编号,从1开始 |
| | | server-id: 1 |
| | | |
| | | # 2024-02-29 api监控相关 |
| | | api: |
| | | # 2024-02-29 是否打开接口时间统计记录,如果:true 则会记录接口调用时间,写入表:s_api_time |
| | | time-enabled: false |
| | | |
| | | # 网院统一认证配置选项,2023-10-23 |
| | | unified: |
| | | # 是否开启测试模式,测试模式用于本地测试,无法连接网院认证接口 |
| | | test-mode: true |
| | | # 网院提供的认证地址,关闭测试模式后,该选项生效 |
| | | remote-url: https://wangyuan.com/api/unified |
| | | |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # RocketMQ队列配置,2023-09-26 |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | rocketmq: |
| | | # 服务地址,多个用逗号分开 |
| | | # name-server: 116.198.40.76:9876 |
| | | name-server: 116.198.39.83:9898 |
| | | producer: |
| | | # 发送消息超时时间,默认3000 |
| | | send-message-timeout: 3000 |
| | | # 生产者组 |
| | | group: producer_group |
| | | # 发送消息失败重试次数,默认2 |
| | | retryTimesWhenSendFailed: 2 |
| | | # 异步消息重试此处,默认2 |
| | | retryTimesWhenSendAsyncFailed: 2 |
| | | # 消息最大长度,默认1024 * 1024 * 4(默认4M) |
| | | # 1024 * 128 = 128K |
| | | maxMessageSize: 131072 |
| | | # 压缩消息阈值,默认4k(1024 * 4) |
| | | compressMessageBodyThreshold: 4096 |
| | | # 是否在内部发送失败时重试另一个broker,默认false |
| | | retryNextServer: false |
| | | |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | # 集中培训业务器配置,2023-10-26 |
| | | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | ctoms: |
| | | # 调度器配置,2023-10-26 |
| | | scheduler: |
| | | # 是否允许集群模式启用, |
| | | # true:表示集群部署,则业务打包发布中不包含调度模块(ctoms-scheduler-server),调度模块需要独立打包; |
| | | # false:表示单机部署,调度模块会被自动打包(作为一个类库)发布; |
| | | cluster-enabled: false |
| | | # 发布类型, |
| | | # single:业务单应用打包,直接能运行调度任务 |
| | | # scheduler:调度任务包(独立打包支持集群) |
| | | deploy-type: single |
| | | # 消息推送请求地址 |
| | | push-url: "https://push.cpoc.cn/sendv2" #互联网 |
| | | link-app-url: "https://jmy.jinmingyuan.com/ctoms-h5/#/?" #移动跳转 |
| | | link-pc-url: "https://jmy.jinmingyuan.com/tcp/" |
| | | # push-url: "http://10.5.6.99:9001/sendv2" #综合网 |
| | | # push-url: "http://push.cpoc.cn:9001/sendv2" #综合网 |
New file |
| | |
| | | spring: |
| | | profiles: |
| | | # active: oracle |
| | | active: dev |
| | | # active: test |
| | | # 默认基地超级管理员角色key |
| | | baseRole: ROLE-BASE-ADMIN |
New file |
| | |
| | | A/3öeº`DÇ^·»z¼ OÅZ¹ãyðÈͼ.4KU[ÒǾïÈæÎãY$qñZ_h½º^+EÎ* ¿æÁ>nu4GÑ-# |
| | | ö(¬ï|6ÐUqå¢gt0Æ b÷
Ï\Ô:?Sè}e_ -ÔÕEÀÀÐ |
New file |
| | |
| | | package com.ctoms; |
| | | |
| | | import com.ctoms.tcp.WebsocketClientTest; |
| | | |
| | | /** |
| | | * Unit test for simple App. |
| | | */ |
| | | public class AppTest |
| | | { |
| | | public static void main( String[] args ) |
| | | { |
| | | System.out.println( "Hello World!" ); |
| | | WebsocketClientTest test = new WebsocketClientTest(); |
| | | test.createBatch(); |
| | | } |
| | | } |
New file |
| | |
| | | package com.ctoms.tcp; |
| | | |
| | | public class DemoLoginResponse { |
| | | |
| | | /** |
| | | * |
| | | */ |
| | | private static final long serialVersionUID = 1167352207355638142L; |
| | | |
| | | // @Override |
| | | // protected void translateProperties(JSONObject result) { |
| | | // result.put("status", status); |
| | | // } |
| | | |
| | | @Override |
| | | public String toString(){ |
| | | return new StringBuilder("[protocol=").append(this.getProtocol()) |
| | | .append(", name=").append(this.getUid()) |
| | | .append(", status=").append(this.status) |
| | | .append("]").toString(); |
| | | } |
| | | |
| | | public String getUid() { |
| | | return uid; |
| | | } |
| | | |
| | | public void setUid(String uid) { |
| | | this.uid = uid; |
| | | } |
| | | |
| | | private String protocol; |
| | | |
| | | public String getProtocol() { |
| | | return protocol; |
| | | } |
| | | |
| | | public void setProtocol(String protocol) { |
| | | this.protocol = protocol; |
| | | } |
| | | |
| | | public int getStatus() { |
| | | return status; |
| | | } |
| | | |
| | | public void setStatus(int status) { |
| | | this.status = status; |
| | | } |
| | | |
| | | private int status = 0; |
| | | private String uid; |
| | | } |
New file |
| | |
| | | package com.ctoms.tcp; |
| | | |
| | | import com.walker.infrastructure.utils.JsonUtils; |
| | | import org.java_websocket.client.WebSocketClient; |
| | | import org.java_websocket.handshake.ServerHandshake; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import java.net.URI; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | public class DemoWebsocketClient extends WebSocketClient { |
| | | |
| | | protected final transient Logger logger = LoggerFactory.getLogger(this.getClass()); |
| | | |
| | | public DemoWebsocketClient(URI serverUri) { |
| | | super(serverUri); |
| | | } |
| | | |
| | | @Override |
| | | public void onOpen(ServerHandshake serverHandshake) { |
| | | // logger.info("ws 连接成功"); |
| | | String data = null; |
| | | Map<String, String> map = new HashMap<>(4); |
| | | map.put("protocol", "login"); |
| | | map.put("uid", this.uid); |
| | | try { |
| | | data = JsonUtils.objectToJsonString(map); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | this.send(data); |
| | | logger.info("客户端发送登录请求,name = {}", this.uid); |
| | | } |
| | | |
| | | @Override |
| | | public void onMessage(String s) { |
| | | if(s.indexOf("heartbeat") >= 0){ |
| | | return; |
| | | } |
| | | logger.info("ws 收到消息:{}", s); |
| | | try { |
| | | DemoLoginResponse response = JsonUtils.jsonStringToObject(s, DemoLoginResponse.class); |
| | | if(response.getProtocol().equals("login")){ |
| | | logger.info("websocket 登录成功:{}", response.getUid()); |
| | | } |
| | | } catch (Exception e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void onClose(int i, String s, boolean b) { |
| | | logger.warn("连接被关闭:code={}, reason={}, remote={}", i, s, b); |
| | | } |
| | | |
| | | @Override |
| | | public void onError(Exception e) { |
| | | logger.error("连接错误:" + e.getMessage(), e); |
| | | } |
| | | |
| | | public String getUid() { |
| | | return uid; |
| | | } |
| | | |
| | | public void setUid(String uid) { |
| | | this.uid = uid; |
| | | } |
| | | |
| | | public String getUserName() { |
| | | return userName; |
| | | } |
| | | |
| | | public void setUserName(String userName) { |
| | | this.userName = userName; |
| | | } |
| | | |
| | | private String uid; |
| | | private String userName; |
| | | } |
New file |
| | |
| | | package com.ctoms.tcp; |
| | | |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import java.net.URI; |
| | | import java.util.Map; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | import java.util.concurrent.ExecutorService; |
| | | import java.util.concurrent.Executors; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | public class WebsocketClientTest { |
| | | |
| | | protected final transient Logger logger = LoggerFactory.getLogger(this.getClass()); |
| | | |
| | | // private static final URI wsUri = URI.create("ws://127.0.0.1:60000/websocket"); |
| | | // private static final URI wsUri = URI.create("ws://116.198.40.76:60000/websocket"); |
| | | // private static final URI wsUri = URI.create("ws://10.8.4.35:60035/websocket"); |
| | | // private static final URI wsUri = URI.create("ws://www.shikeying.com:60001/websocket"); |
| | | // private static final URI wsUri = URI.create("ws://ctoms.chinapost.com.cn/ws/websocket"); |
| | | // private static final URI wsUri = URI.create("ws://localhost:60000"); |
| | | // private static final URI wsUri = URI.create("ws://116.198.40.76:60001"); |
| | | private static final URI wsUri = URI.create("wss://jmy.jinmingyuan.com/wss"); |
| | | |
| | | private static Map<String, DemoWebsocketClient> cacheClient = new ConcurrentHashMap<>(32770); |
| | | |
| | | private ExecutorService executorService = Executors.newFixedThreadPool(4); |
| | | // private static int currentSize = 20000; |
| | | private static int currentSize = 1; |
| | | private static final int TOTAL_LINES = 2; |
| | | // private static final int TOTAL_LINES = 16; |
| | | // private static final int BATCH_SIZE = 8; |
| | | private static final int BATCH_SIZE = 2; |
| | | |
| | | public void createBatch(){ |
| | | logger.info(".........开始测试通信连接.......... TOTAL_LINES = {}, url = {}", TOTAL_LINES, wsUri); |
| | | while(currentSize < TOTAL_LINES){ |
| | | try { |
| | | this.executorService.execute(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | int count = BATCH_SIZE; |
| | | for(int i=0; i<count; i++){ |
| | | String uri = "mike" + (currentSize); |
| | | DemoWebsocketClient client = createOneClient(wsUri, uri); |
| | | logger.info("创建了一个客户端: " + uri); |
| | | cacheClient.put(uri, client); |
| | | currentSize ++; |
| | | } |
| | | } |
| | | }); |
| | | } catch (Exception ex){ |
| | | ex.printStackTrace(); |
| | | } finally { |
| | | try { |
| | | logger.info("currentSize = {}", currentSize); |
| | | TimeUnit.SECONDS.sleep(3); |
| | | } catch (InterruptedException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | logger.info("已累计创建连接:{} 个", currentSize); |
| | | try { |
| | | TimeUnit.SECONDS.sleep(10); |
| | | } catch (InterruptedException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | |
| | | // logger.info("准备关闭所有链接对象..."); |
| | | // for(DemoWebsocketClient client : cacheClient.values()){ |
| | | // client.close(); |
| | | // } |
| | | // logger.info("执行了关闭操作,所有连接稍后会完全关闭"); |
| | | } |
| | | |
| | | private DemoWebsocketClient createOneClient(URI uri, String uid){ |
| | | DemoWebsocketClient client = new DemoWebsocketClient(uri); |
| | | client.setUid(uid); |
| | | client.setConnectionLostTimeout(0); |
| | | try { |
| | | client.connectBlocking(); |
| | | } catch (InterruptedException e) { |
| | | throw new RuntimeException("创建client错误, uid=" + uid + ", " + e.getMessage(), e); |
| | | } |
| | | return client; |
| | | } |
| | | |
| | | // public void createOneClient(){ |
| | | // DemoWebsocketClient client = new DemoWebsocketClient(wsUri); |
| | | // client.setUid("mike"); |
| | | // try { |
| | | // client.connectBlocking(); |
| | | // } catch (InterruptedException e) { |
| | | // throw new RuntimeException(e); |
| | | // } |
| | | // WaitConsoleInput.waitInput(); |
| | | // } |
| | | } |
New file |
| | |
| | | package com.ctoms.tcp; |
| | | |
| | | import com.iplatform.tcp.util.ws.WebDataResponse; |
| | | import com.walker.infrastructure.utils.JsonUtils; |
| | | import com.walker.infrastructure.utils.NumberGenerator; |
| | | import org.junit.Test; |
| | | |
| | | public class WebsocketDemo { |
| | | |
| | | @Test |
| | | public void sendDataFormat(){ |
| | | WebDataResponse msg = new WebDataResponse(); |
| | | msg.setMessageId(NumberGenerator.getLongSequenceId()); |
| | | msg.setName("shikeying"); // 指定用户发送,该id与浏览器端注册的id保持一致。 |
| | | msg.setData("你好,这是推送给浏览器的内容,一般是JSON格式。"); |
| | | try { |
| | | System.out.println(JsonUtils.objectToJsonString(msg)); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | -- |
| | | ALTER TABLE s_user_core |
| | | ADD UNIQUE INDEX inx_usr_login (user_name) USING BTREE ; |
| | | |
| | | ALTER TABLE s_role_user |
| | | ADD INDEX inx_ru_uid (user_id) USING BTREE ; |
| | | |
| | | ALTER TABLE s_config |
| | | ADD INDEX inx_sc_key (config_key) USING BTREE ; |
| | | |
| | | -- 用户核心表添加字段 2023-03-06 |
| | | ALTER TABLE s_user_core |
| | | ADD COLUMN wx_open_id varchar(64) NULL AFTER remark; |
| | | ALTER TABLE s_user_core |
| | | ADD COLUMN wx_union_id varchar(64) NULL AFTER wx_open_id; |
| | | ALTER TABLE s_user_core |
| | | ADD COLUMN ding_user_id varchar(64) NULL AFTER wx_union_id; |
| | | ALTER TABLE s_user_core |
| | | ADD COLUMN bind_client_id varchar(64) NULL AFTER ding_user_id; |
| | | ALTER TABLE s_user_core |
| | | ADD COLUMN bind_wechat int NOT NULL DEFAULT 0 COMMENT '是否绑定微信:1_是, 0_否。' AFTER bind_client_id; |
| | | ALTER TABLE s_user_core |
| | | ADD COLUMN modify_pwd int NOT NULL DEFAULT 0 COMMENT '是否修改密码:0_否,1_是' AFTER bind_wechat; |
| | | ALTER TABLE s_user_core |
| | | ADD COLUMN bind_mobile int NOT NULL DEFAULT 0 COMMENT '是否绑定手机:1_是, 0_否。' AFTER modify_pwd; |
| | | ALTER TABLE s_user_core |
| | | ADD COLUMN bind_mail int NOT NULL DEFAULT 0 COMMENT '是否绑定邮箱:1_是, 0_否。' AFTER bind_mobile; |
| | | ALTER TABLE s_user_core |
| | | ADD COLUMN profile_id bigint NOT NULL DEFAULT 0 COMMENT '关联的档案id,0表示未关联' AFTER bind_mail; |
| | | |
| | | -- 数据字典 |
| | | ALTER TABLE s_dict_data |
| | | ADD COLUMN parent_id bigint NOT NULL DEFAULT 0 COMMENT '父记录id' AFTER remark; |
| | | |
| | | -- |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | |
| | | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <parent> |
| | | <artifactId>low-consum-manage</artifactId> |
| | | <groupId>com.consum</groupId> |
| | | <version>1.0.0-SNAPSHOT</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <groupId>com.iplatform</groupId> |
| | | <artifactId>iplatform-base</artifactId> |
| | | <name>iplatform-base</name> |
| | | <packaging>jar</packaging> |
| | | <version>3.2.0</version> |
| | | |
| | | <properties> |
| | | </properties> |
| | | |
| | | <dependencies> |
| | | <!-- 平台实体接口对象, 2022/09/19 --> |
| | | <dependency> |
| | | <groupId>com.iplatform</groupId> |
| | | <artifactId>iplatform-model-pojo</artifactId> |
| | | <version>3.2.0</version> |
| | | </dependency> |
| | | |
| | | <!-- 核心模块:提供非常基础服务(不连接数据库), 2022/09/19 --> |
| | | <dependency> |
| | | <groupId>com.iplatform</groupId> |
| | | <artifactId>iplatform-core</artifactId> |
| | | <version>3.2.0</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-infrastructure</artifactId> |
| | | <version>${walker-infrastructure.version}</version> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/walker-infrastructure-3.2.0.jar</systemPath> |
| | | <scope>system</scope> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-web</artifactId> |
| | | <version>3.2.0</version> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/walker-web-3.2.0.jar</systemPath> |
| | | <scope>system</scope> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-licence</artifactId> |
| | | <version>3.2.0</version> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/walker-licence-3.2.0.jar</systemPath> |
| | | <scope>system</scope> |
| | | </dependency> |
| | | |
| | | |
| | | <!-- 提供数据库支持, 2022/09/19 --> |
| | | <dependency> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-jdbc</artifactId> |
| | | <version>${walker-jdbc.version}</version> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/walker-jdbc-3.2.0.jar</systemPath> |
| | | <scope>system</scope> |
| | | </dependency> |
| | | |
| | | <!-- 提供Redis支持,由业务子工程决定是否依赖, 2022/09/20 --> |
| | | <dependency> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-support-redis</artifactId> |
| | | <version>3.2.0</version> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/walker-support-redis-3.2.0.jar</systemPath> |
| | | <scope>system</scope> |
| | | <exclusions> |
| | | <exclusion> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-cache</artifactId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-connector</artifactId> |
| | | <version>${walker-connector.version}</version> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/walker-connector-3.2.0.jar</systemPath> |
| | | <scope>system</scope> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-db-meta</artifactId> |
| | | <version>${walker-db-meta.version}</version> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/walker-db-meta-3.2.0.jar</systemPath> |
| | | <scope>system</scope> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-web-security</artifactId> |
| | | <version>${walker-web-security.version}</version> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/walker-web-security-3.2.0.jar</systemPath> |
| | | <scope>system</scope> |
| | | </dependency> |
| | | |
| | | <!-- 基础模块提供web支持, 2022/10/31 --> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-web</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-aop</artifactId> |
| | | <exclusions> |
| | | <exclusion> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter</artifactId> |
| | | </exclusion> |
| | | <exclusion> |
| | | <groupId>org.springframework</groupId> |
| | | <artifactId>spring-beans</artifactId> |
| | | </exclusion> |
| | | <exclusion> |
| | | <groupId>org.springframework</groupId> |
| | | <artifactId>spring-core</artifactId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-data-redis</artifactId> |
| | | <exclusions> |
| | | <exclusion> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-logging</artifactId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | |
| | | <!-- 简单的验证码实现(若依), 2022/11/06 --> |
| | | <dependency> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-support-kaptcha</artifactId> |
| | | <version>3.2.0</version> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/walker-support-kaptcha-3.2.0.jar</systemPath> |
| | | <scope>system</scope> |
| | | </dependency> |
| | | |
| | | <!-- |
| | | csv数据导入支持: univocity实现, 2023/02/01 |
| | | excel导入,目前这两种先放一起,2023/02/06 |
| | | --> |
| | | <dependency> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-di-support-univocity</artifactId> |
| | | <version>3.2.0</version> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/walker-di-support-univocity-3.2.0.jar</systemPath> |
| | | <scope>system</scope> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-security</artifactId> |
| | | <version>3.2.0</version> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/walker-security-3.2.0.jar</systemPath> |
| | | <scope>system</scope> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.walkersoft</groupId> |
| | | <artifactId>walker-push-wx-public</artifactId> |
| | | <version>3.2.0</version> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/walker-push-wx-public-3.2.0.jar</systemPath> |
| | | <scope>system</scope> |
| | | </dependency> |
| | | |
| | | <!-- 亚马逊S3 OSS 服务配置,2023-12-12 --> |
| | | <dependency> |
| | | <groupId>com.amazonaws</groupId> |
| | | <artifactId>aws-java-sdk-s3</artifactId> |
| | | <version>1.11.126</version> |
| | | <scope>system</scope> |
| | | <systemPath>${project.basedir}/src/main/resources/lib/aws-java-sdk-s3-1.11.126-with-dependencies.jar</systemPath> |
| | | </dependency> |
| | | |
| | | <!-- 引入apache common-io, AbstractController 下载文件使用。2022-11-28 --> |
| | | <dependency> |
| | | <groupId>commons-io</groupId> |
| | | <artifactId>commons-io</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- easyExcel底层依赖poi --> |
| | | <dependency> |
| | | <groupId>org.apache.poi</groupId> |
| | | <artifactId>poi</artifactId> |
| | | <version>${poi.version}</version> |
| | | <exclusions> |
| | | <exclusion> |
| | | <groupId>org.slf4j</groupId> |
| | | <artifactId>slf4j-api</artifactId> |
| | | </exclusion> |
| | | <exclusion> |
| | | <groupId>org.projectlombok</groupId> |
| | | <artifactId>lombok</artifactId> |
| | | </exclusion> |
| | | <exclusion> |
| | | <groupId>commons-codec</groupId> |
| | | <artifactId>commons-codec</artifactId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.apache.poi</groupId> |
| | | <artifactId>poi-ooxml</artifactId> |
| | | <version>${poi.version}</version> |
| | | </dependency> |
| | | |
| | | <!-- jwt token: 2022/10/10 --> |
| | | <dependency> |
| | | <groupId>io.jsonwebtoken</groupId> |
| | | <artifactId>jjwt-api</artifactId> |
| | | <version>0.11.5</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>io.jsonwebtoken</groupId> |
| | | <artifactId>jjwt-impl</artifactId> |
| | | <version>0.11.5</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>io.jsonwebtoken</groupId> |
| | | <artifactId>jjwt-jackson</artifactId> |
| | | <version>0.11.5</version> |
| | | </dependency> |
| | | |
| | | <!-- 获取浏览器信息, WebAgent依赖该对象用于解析Excel: 2023/01/05 --> |
| | | <dependency> |
| | | <groupId>com.univocity</groupId> |
| | | <artifactId>univocity-parsers</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- RestTemplate使用: 2023/08/16 --> |
| | | <dependency> |
| | | <groupId>com.squareup.okhttp3</groupId> |
| | | <artifactId>okhttp</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.alibaba</groupId> |
| | | <artifactId>druid</artifactId> |
| | | <scope>provided</scope> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | | |
| | | <build> |
| | | <plugins> |
| | | <plugin> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-maven-plugin</artifactId> |
| | | <version>3.2.11</version> |
| | | <configuration> |
| | | <!-- 2023-11-06 该参数指定了依赖的本地类库,不引入则报错:不能指向本地jar文件 --> |
| | | <arguments> |
| | | <argument>${project.basedir}/src/main/resources/lib</argument> |
| | | </arguments> |
| | | <!-- 2023-11-06 该参数指定,打包忽略 Main 函数。--> |
| | | <skip>true</skip> |
| | | </configuration> |
| | | </plugin> |
| | | </plugins> |
| | | </build> |
| | | |
| | | </project> |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.iplatform.base.callback.PlatformCallbackPostProcessor; |
| | | import com.iplatform.core.BeanContextAware; |
| | | import com.walker.db.page.ListPageContext; |
| | | import com.walker.db.page.PageSearch; |
| | | import com.walker.infrastructure.ApplicationRuntimeException; |
| | | import com.walker.infrastructure.arguments.ArgumentsManager; |
| | | import com.walker.infrastructure.arguments.Variable; |
| | | import com.walker.infrastructure.utils.DateUtils; |
| | | import com.walker.infrastructure.utils.FileUtils; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.web.ResponseValue; |
| | | import com.walker.web.util.ServletUtils; |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import org.apache.commons.io.IOUtils; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.InitializingBean; |
| | | |
| | | import java.io.File; |
| | | import java.io.IOException; |
| | | import java.io.OutputStream; |
| | | import java.io.PrintWriter; |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.net.URLDecoder; |
| | | import java.net.URLEncoder; |
| | | import java.util.List; |
| | | |
| | | public abstract class AbstractController implements InitializingBean { |
| | | |
| | | protected final transient Logger logger = LoggerFactory.getLogger(this.getClass()); |
| | | |
| | | private static String contextPath; |
| | | private static final Object lock = new Object(); |
| | | |
| | | /** |
| | | * 返回第三方对接管理器对象。 |
| | | * @return |
| | | * @date 2023-07-03 |
| | | */ |
| | | protected ThirdPartyManager getThirdPartyManager(){ |
| | | return BeanContextAware.getBeanByType(ThirdPartyManager.class); |
| | | } |
| | | |
| | | /** |
| | | * 返回服务端调用地址前缀,如:<br> |
| | | * http://localhost:8080/demo |
| | | * @return |
| | | * @date 2023-01-06 |
| | | */ |
| | | protected String getServerDomain(){ |
| | | HttpServletRequest request = this.getRequest(); |
| | | return ServletUtils.getServerDomain(request); |
| | | } |
| | | |
| | | /** |
| | | * 返回给定的回调实现对象。 |
| | | * @param clazz 定义的回调接口,如: PlatformUserCallback.class |
| | | * @return |
| | | * @param <T> |
| | | * @date 2023-01-05 |
| | | * @date 2023-01-28 该方法只能获取单个类型Callback,对于存在多种实现的请使用方法: |
| | | * {@linkplain PlatformCallbackPostProcessor#getCallbackMultipleBean(Class)} |
| | | */ |
| | | protected <T> T getPlatformCallback(Class<T> clazz){ |
| | | return PlatformCallbackPostProcessor.getCallbackObject(clazz); |
| | | } |
| | | |
| | | /** |
| | | * 返回系统配置可变参数对象。 |
| | | * @param key 参数 key |
| | | * @return |
| | | * @date 2022-11-29 |
| | | */ |
| | | protected Variable getArgumentVariable(String key){ |
| | | Variable v = this.getArgumentManager().getVariable(key); |
| | | if(v == null){ |
| | | throw new IllegalArgumentException("可变配置参数不存在: " + key); |
| | | } |
| | | return v; |
| | | } |
| | | |
| | | protected ArgumentsManager getArgumentManager(){ |
| | | return BeanContextAware.getBeanByType(ArgumentsManager.class); |
| | | } |
| | | |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | //~ 新添加的方法,2022-11-16 |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | /** |
| | | * 下载简单的文件,通常文件不大。 |
| | | * @param data 文件字节码内容 |
| | | * @param fileName 文件名称,如: demo.zip |
| | | * @throws IOException |
| | | * @date 2022-11-28 |
| | | */ |
| | | protected void downloadSimpleFile(byte[] data, String fileName) throws IOException{ |
| | | HttpServletResponse response = this.getResponse(); |
| | | response.reset(); |
| | | response.addHeader("Access-Control-Allow-Origin", "*"); |
| | | response.addHeader("Access-Control-Expose-Headers", "Content-Disposition"); |
| | | response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(fileName) + "\""); |
| | | response.addHeader("Content-Length", "" + data.length); |
| | | response.setContentType("application/octet-stream; charset=UTF-8"); |
| | | IOUtils.write(data, response.getOutputStream()); |
| | | } |
| | | |
| | | /** |
| | | * 从前端获得分页查询条件,写入线程参数中。 |
| | | * @author 时克英 |
| | | * @date 2022-11-16 |
| | | * @date 2023-01-28 该方法废弃,由拦截器根据特征'/list'自动执行分页准备调用。 |
| | | */ |
| | | @Deprecated |
| | | protected PageSearch preparePageSearch(){ |
| | | PageSearch pageSearch = new PageSearch(); |
| | | Integer pn = this.getIntParameter(PageSearch.PAGE_NUM); |
| | | if(pn != null){ |
| | | pageSearch.setPageIndex(pn.intValue()); |
| | | } |
| | | Integer pageSize = this.getIntParameter(PageSearch.PAGE_SIZE); |
| | | if(pageSize != null){ |
| | | pageSearch.setPageSize(pageSize.intValue()); |
| | | } |
| | | pageSearch.setOrderByColumn(this.getParameter(PageSearch.ORDER_BY_COLUMN)); |
| | | pageSearch.setOrderAsc(this.getParameter(PageSearch.IS_ASC)); |
| | | // pageSearch.setReasonable(this.getParameter(PageSearch)); |
| | | ListPageContext.setPageSearch(pageSearch); |
| | | return pageSearch; |
| | | } |
| | | |
| | | /** |
| | | * 把一个日期或时间字符串,转换成数值。 |
| | | * <pre> |
| | | * 1.2022-11-16 --> 20221116000000 |
| | | * 2.2022-11-16 12:01:30 --> 20221116120130 |
| | | * </pre> |
| | | * @param dateTime 给定时间或日期字符串 |
| | | * @param isTime 是否时间,否表示只有日期 |
| | | * @return |
| | | */ |
| | | protected long getParamsDateTime(String dateTime, boolean isTime){ |
| | | if(StringUtils.isEmpty(dateTime)){ |
| | | return -1; |
| | | } |
| | | if(isTime){ |
| | | return DateUtils.getDateTimeNumber(dateTime); |
| | | } else { |
| | | return DateUtils.toLongDateTime(dateTime); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 包装返回带分页的表格集合,加上total属性(适配前端) |
| | | * @param data |
| | | * @param total |
| | | * @return |
| | | * @param <T> |
| | | * @date 2022-11-19 |
| | | * @date 2023-05-16 从2.3.0之后废弃,因为使用了新的完整前端界面,返回的业务数据是一个整体,不再随意增加:ResponseValue属性。 |
| | | */ |
| | | @Deprecated |
| | | protected <T> ResponseValue<List<?>> acquireTablePage(List<T> data, long total){ |
| | | ResponseValue<List<?>> rv = ResponseValue.success(data); |
| | | rv.setTotal(total); |
| | | return rv; |
| | | } |
| | | |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~ end ~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | protected HttpServletRequest getRequest(){ |
| | | // ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); |
| | | // HttpServletRequest request = servletRequestAttributes.getRequest(); |
| | | // return request; |
| | | return ServletUtils.getRequest(); |
| | | } |
| | | |
| | | protected HttpServletResponse getResponse(){ |
| | | // return ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse(); |
| | | return ServletUtils.getResponse(); |
| | | } |
| | | |
| | | /** |
| | | * 得到WEB应用上下文路径,如:/web |
| | | * @return |
| | | */ |
| | | protected String getContextPath(){ |
| | | if(contextPath == null){ |
| | | synchronized (lock) { |
| | | HttpServletRequest request = getRequest(); |
| | | if(request == null) { |
| | | throw new Error("request not found: getRequest()."); |
| | | } |
| | | contextPath = request.getContextPath(); |
| | | } |
| | | } |
| | | return contextPath; |
| | | } |
| | | |
| | | protected String getParameter(String name){ |
| | | return getRequest().getParameter(name); |
| | | } |
| | | |
| | | protected String getParameterUTF8(String name) throws UnsupportedEncodingException { |
| | | String value = this.getParameter(name); |
| | | return value == null ? null : URLDecoder.decode(value, "UTF-8"); |
| | | } |
| | | |
| | | protected String[] getParameterValues(String name) { |
| | | return this.getRequest().getParameterValues(name); |
| | | } |
| | | |
| | | protected Integer getIntParameter(String name) { |
| | | String value = this.getParameter(name); |
| | | return value == null ? null : Integer.valueOf(value); |
| | | } |
| | | |
| | | protected Long getLongParameter(String name) { |
| | | String value = this.getParameter(name); |
| | | return value == null ? null : Long.valueOf(value); |
| | | } |
| | | |
| | | protected Float getFloatParameter(String name) { |
| | | String value = this.getParameter(name); |
| | | return value == null ? null : Float.valueOf(value); |
| | | } |
| | | |
| | | protected Double getDoubleParameter(String name) { |
| | | String value = this.getParameter(name); |
| | | return value == null ? null : Double.valueOf(value); |
| | | } |
| | | |
| | | /** |
| | | * @param name |
| | | * @return Attribute value |
| | | */ |
| | | protected Object getAttribute(String name) { |
| | | return this.getRequest().getAttribute(name); |
| | | } |
| | | |
| | | /** |
| | | * @param name |
| | | * @param value |
| | | */ |
| | | protected void setAttribute(String name, Object value) { |
| | | this.getRequest().setAttribute(name, value); |
| | | } |
| | | |
| | | protected void setDefaultContentType() { |
| | | this.getResponse().setContentType("text/html; charset=utf-8"); |
| | | } |
| | | |
| | | private void ajaxOutPut(ResponseFormat format, Object outputString) throws IOException { |
| | | HttpServletResponse response = this.getResponse(); |
| | | response.setCharacterEncoding(StringUtils.DEFAULT_CHARSET_UTF8); |
| | | response.setContentType(format.getValue()); |
| | | this.print(response, outputString == null ? StringUtils.EMPTY_STRING : outputString.toString()); |
| | | } |
| | | |
| | | protected void print(HttpServletResponse response, String str) throws IOException { |
| | | // ServletOutputStream outputStream = this.getResponse().getOutputStream(); |
| | | PrintWriter pw = response.getWriter(); |
| | | pw.print(str); |
| | | } |
| | | |
| | | protected void ajaxOutPutText(Object outputString) throws IOException { |
| | | this.ajaxOutPut(ResponseFormat.TextPlain, outputString); |
| | | } |
| | | |
| | | protected void ajaxOutPutJson(Object outputString) throws IOException { |
| | | this.ajaxOutPut(ResponseFormat.ApplicationJson, outputString); |
| | | } |
| | | |
| | | protected void ajaxOutPutXml(Object outputString) throws IOException { |
| | | this.ajaxOutPut(ResponseFormat.TextXml, outputString); |
| | | } |
| | | |
| | | protected void ajaxOutPutHtml(Object outputString) throws IOException { |
| | | setDefaultContentType(); |
| | | this.print(this.getResponse(), outputString == null ? StringUtils.EMPTY_STRING : outputString.toString()); |
| | | } |
| | | |
| | | protected void ajaxOutputFileStream(String contentType, String filePath){ |
| | | ajaxOutputFileStream(contentType, new File(filePath)); |
| | | } |
| | | |
| | | protected void ajaxOutputFileStream(String contentType, File file){ |
| | | HttpServletResponse response = this.getResponse(); |
| | | response.setCharacterEncoding(StringUtils.DEFAULT_CHARSET_UTF8); |
| | | response.setContentType(contentType); |
| | | byte[] content = FileUtils.getFileBytes(file); |
| | | if(content == null) { |
| | | return; |
| | | } |
| | | OutputStream out = null; |
| | | try { |
| | | out = response.getOutputStream(); |
| | | out.write(content); |
| | | out.flush(); |
| | | } catch (IOException e) { |
| | | throw new ApplicationRuntimeException("输出服务器文件流出现异常!", e); |
| | | } finally { |
| | | if(out != null){ |
| | | try { |
| | | out.close(); |
| | | } catch (IOException e) {} |
| | | } |
| | | } |
| | | } |
| | | |
| | | public enum ResponseFormat{ |
| | | ApplicationJson{ |
| | | }, |
| | | ApplicationXml{ |
| | | |
| | | }, |
| | | TextXml{ |
| | | |
| | | }, |
| | | TextPlain{ |
| | | |
| | | }; |
| | | // ImagePng{ |
| | | // public String getValue(){ |
| | | // return Constants.IMAGE_PNG; |
| | | // } |
| | | // }, |
| | | // ImageJpeg{ |
| | | // public String getValue(){ |
| | | // return Constants.IMAGE_JPEG; |
| | | // } |
| | | // }, |
| | | // ImageGif{ |
| | | // public String getValue(){ |
| | | // return Constants.IMAGE_GIF; |
| | | // } |
| | | // }; |
| | | public String getValue(){ |
| | | throw new AbstractMethodError(); |
| | | } |
| | | } |
| | | |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | //~ 为老的freemarker界面预留的方法,2022-11-08 |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | /** |
| | | * 前端页面调用的JS方面名称 |
| | | */ |
| | | protected static final String DEFAULT_JS_NAME = "reload"; |
| | | |
| | | /** |
| | | * 前端使用的分页对象引用名称,默认值 |
| | | */ |
| | | protected static final String DEFAULT_PAGER_VIEW_NAME = "pagerView"; |
| | | |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.iplatform.core.BeanContextAware; |
| | | import com.walker.file.FileInfo; |
| | | import com.walker.file.FileStoreType; |
| | | import com.walker.infrastructure.utils.FileCopyUtils; |
| | | import com.walker.infrastructure.utils.FileUtils; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.io.BufferedInputStream; |
| | | import java.io.File; |
| | | import java.io.FileInputStream; |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | |
| | | public abstract class AbstractFileOperateSpiController extends AbstractSecurityController{ |
| | | |
| | | protected FileOperateSpi acquireFileOperateSpi(){ |
| | | return BeanContextAware.getBeanByType(FileOperateSpi.class); |
| | | } |
| | | |
| | | /** |
| | | * 清除给定文件地址的CDN前缀。如:https://qnyun.com/oss/12345678 |
| | | * <pre> |
| | | * 去掉前缀后,只剩下"12345678" |
| | | * </pre> |
| | | * @param path 给定的文件资源地址 |
| | | * @return |
| | | * @date 2023-05-17 |
| | | */ |
| | | protected String clearCdnPrefix(String path){ |
| | | return this.acquireFileOperateSpi().clearCdnPrefix(path); |
| | | } |
| | | |
| | | /** |
| | | * 返回存储文件的前缀,根据平台配置参数:本地、FTP或OSS远程存储不同而返回不同前缀。 |
| | | * @return |
| | | * @date 2023-06-10 |
| | | */ |
| | | protected String getCdnUrl(){ |
| | | return this.acquireFileOperateSpi().getCdnUrl(); |
| | | } |
| | | |
| | | /** |
| | | * 根据文件信息,加载文件二进制内容。 |
| | | * @param fileInfo |
| | | * @return |
| | | * @date 2023-03-17 |
| | | */ |
| | | protected byte[] getLocalFileData(FileInfo fileInfo){ |
| | | String localRoot = this.acquireFileOperateSpi().getFileRootConfig(); |
| | | String absolutePath = localRoot + fileInfo.getUrl(); |
| | | try { |
| | | return FileCopyUtils.copyToByteArray(new File(absolutePath)); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException("文件加载异常,可能不存在:" + absolutePath, e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 根据文件id编号,获取文件基本信息。 |
| | | * @param id |
| | | * @return |
| | | * @date 2023-03-17 |
| | | */ |
| | | protected FileInfo getFileInfo(String id){ |
| | | if(StringUtils.isEmpty(id)){ |
| | | logger.warn("id为空,无法获得文件信息"); |
| | | return null; |
| | | } |
| | | return this.acquireFileOperateSpi().getFileInfo(Long.parseLong(id)); |
| | | } |
| | | |
| | | protected List<FileInfo> getFileInfoList(List<String> ids){ |
| | | if(StringUtils.isEmptyList(ids)){ |
| | | throw new IllegalArgumentException("ids is required!"); |
| | | } |
| | | return this.acquireFileOperateSpi().getFileInfoList(ids); |
| | | } |
| | | |
| | | /** |
| | | * 下载oss文件 |
| | | * @param id 文件唯一编号 |
| | | * @return |
| | | * @date 2023-12-13 |
| | | */ |
| | | protected byte[] getOssFileData(String id){ |
| | | return this.acquireFileOperateSpi().downloadOssFile(id); |
| | | } |
| | | |
| | | protected FileInfo uploadFileToLocal(InputStream inputStream |
| | | , String fileName, String groupId, long fileSize, Integer businessType, String owner) throws Exception{ |
| | | return this.acquireFileOperateSpi().uploadFileToLocal(inputStream, fileName, groupId, fileSize, businessType, owner); |
| | | } |
| | | protected FileInfo[] uploadFileToLocal(InputStream[] inputStream |
| | | , String[] fileName, String groupId, long[] fileSize, Integer businessType, String owner) throws Exception{ |
| | | return this.acquireFileOperateSpi().uploadFileToLocal(inputStream, fileName, groupId, fileSize, businessType, owner); |
| | | } |
| | | |
| | | /** |
| | | * 上传文件到本地,业务控制器直接调用该方法。 |
| | | * @param multipartFile |
| | | * @param groupId 分组ID,可选 |
| | | * @param businessType 业务类型,可选,请参考电商模块(PID) |
| | | * @param owner 数据归属:平台为-1,其他为顶级机构ID(商户ID) |
| | | * @param fileContentType 前端传入的文件上传类型:uploadf 表示文件,其他为图片 |
| | | * @return |
| | | * @throws Exception 上传失败抛出异常 |
| | | * @date 2023-06-09 |
| | | */ |
| | | protected FileInfo uploadFileToLocal(MultipartFile multipartFile |
| | | , String groupId, Integer businessType, String owner, String fileContentType) throws Exception{ |
| | | this.checkMultipartFile(multipartFile); |
| | | long fileSize = multipartFile.getSize(); |
| | | String fileName = multipartFile.getOriginalFilename().toLowerCase(); |
| | | if(fileName.length() > 99){ |
| | | fileName = fileName.substring(fileName.length()-99); |
| | | } |
| | | String fileExt = this.checkFile(fileName, fileSize, fileContentType); |
| | | logger.debug("上传本地文件扩展名:" + fileExt); |
| | | return this.uploadFileToLocal(multipartFile.getInputStream(), fileName, groupId, fileSize, businessType, owner); |
| | | } |
| | | |
| | | /** |
| | | * 上传多个文件 |
| | | * @param multipartFile |
| | | * @param groupId |
| | | * @param businessType |
| | | * @param owner |
| | | * @param fileContentType |
| | | * @return |
| | | * @throws Exception |
| | | * @date 2023-08-01 |
| | | */ |
| | | protected FileInfo[] uploadFileToLocal(MultipartFile[] multipartFile |
| | | , String groupId, Integer businessType, String owner, String fileContentType) throws Exception{ |
| | | if(multipartFile == null || multipartFile.length == 0){ |
| | | throw new IllegalArgumentException("multipartFile数组为空"); |
| | | } |
| | | int size = multipartFile.length; |
| | | InputStream[] inputStream = new InputStream[size]; |
| | | String[] fileName = new String[size]; |
| | | long[] fileSize = new long[size]; |
| | | for(int i=0; i<size; i++){ |
| | | inputStream[i] = multipartFile[i].getInputStream(); |
| | | fileName[i] = multipartFile[i].getOriginalFilename().toLowerCase(); |
| | | fileSize[i] = multipartFile[i].getSize(); |
| | | } |
| | | return this.uploadFileToLocal(inputStream, fileName, groupId, fileSize, businessType, owner); |
| | | } |
| | | |
| | | protected FileInfo uploadFileToRemote(InputStream inputStream |
| | | , String fileName, String groupId, long fileSize, Integer businessType, String owner) throws Exception{ |
| | | // String remoteFileStoreType = this.getArgumentVariable(ArgumentsConstants.CONFIG_UPLOAD_TYPE).getStringValue(); |
| | | // if(StringUtils.isEmpty(remoteFileStoreType)){ |
| | | // throw new PlatformRuntimeException("平台未配置任何远程存储类别:" + ArgumentsConstants.CONFIG_UPLOAD_TYPE); |
| | | // } |
| | | // 2023-07-03,如果配置远程上传为本地 |
| | | if(this.acquireFileOperateSpi().isRemoteAsLocal()){ |
| | | return this.acquireFileOperateSpi().uploadFileToLocal(inputStream, fileName, groupId, fileSize, businessType, owner); |
| | | } |
| | | |
| | | // FileStoreType fileStoreType = FileStoreType.getType(remoteFileStoreType); |
| | | FileStoreType fileStoreType = FileStoreType.OssAws; |
| | | if(fileStoreType == FileStoreType.Ftp){ |
| | | return this.acquireFileOperateSpi().uploadFileToFtp(inputStream, fileName, groupId, fileSize, businessType, owner); |
| | | } else { |
| | | return this.acquireFileOperateSpi().uploadFileToOss(inputStream, fileName, groupId, fileSize, businessType, owner, fileStoreType); |
| | | } |
| | | } |
| | | |
| | | protected FileInfo[] uploadFileToRemote(InputStream[] inputStream |
| | | , String[] fileName, String groupId, long[] fileSize, Integer businessType, String owner) throws Exception{ |
| | | // String remoteFileStoreType = this.getArgumentVariable(ArgumentsConstants.CONFIG_UPLOAD_TYPE).getStringValue(); |
| | | // if(StringUtils.isEmpty(remoteFileStoreType)){ |
| | | // throw new PlatformRuntimeException("平台未配置任何远程存储类别:" + ArgumentsConstants.CONFIG_UPLOAD_TYPE); |
| | | // } |
| | | // 2023-07-03,如果配置远程上传为本地 |
| | | if(this.acquireFileOperateSpi().isRemoteAsLocal()){ |
| | | return this.acquireFileOperateSpi().uploadFileToLocal(inputStream, fileName, groupId, fileSize, businessType, owner); |
| | | } |
| | | |
| | | // FileStoreType fileStoreType = FileStoreType.getType(remoteFileStoreType); |
| | | FileStoreType fileStoreType = FileStoreType.OssAws; |
| | | if(fileStoreType == FileStoreType.Ftp){ |
| | | return this.acquireFileOperateSpi().uploadFileToFtp(inputStream, fileName, groupId, fileSize, businessType, owner); |
| | | } else { |
| | | return this.acquireFileOperateSpi().uploadFileToOss(inputStream, fileName, groupId, fileSize, businessType, owner, fileStoreType); |
| | | } |
| | | } |
| | | |
| | | protected FileInfo uploadFileToRemote(MultipartFile multipartFile |
| | | , String groupId, Integer businessType, String owner, String fileContentType) throws Exception{ |
| | | this.checkMultipartFile(multipartFile); |
| | | long fileSize = multipartFile.getSize(); |
| | | String fileName = multipartFile.getOriginalFilename().toLowerCase(); |
| | | String fileExt = this.checkFile(fileName, fileSize, fileContentType); |
| | | logger.debug("上传远程文件扩展名:" + fileExt); |
| | | return this.uploadFileToRemote(multipartFile.getInputStream(), fileName, groupId, fileSize, businessType, owner); |
| | | } |
| | | |
| | | protected FileInfo[] uploadFileToRemote(MultipartFile[] multipartFile |
| | | , String groupId, Integer businessType, String owner, String fileContentType) throws Exception{ |
| | | int size = multipartFile.length; |
| | | InputStream[] inputStream = new InputStream[size]; |
| | | String[] fileName = new String[size]; |
| | | long[] fileSize = new long[size]; |
| | | for(int i=0; i<size; i++){ |
| | | inputStream[i] = multipartFile[i].getInputStream(); |
| | | fileName[i] = multipartFile[i].getOriginalFilename().toLowerCase(); |
| | | fileSize[i] = multipartFile[i].getSize(); |
| | | } |
| | | return this.uploadFileToRemote(inputStream, fileName, groupId, fileSize, businessType, owner); |
| | | } |
| | | |
| | | private void checkMultipartFile(MultipartFile multipartFile){ |
| | | if(multipartFile == null){ |
| | | throw new PlatformRuntimeException("上传文件不存在"); |
| | | } |
| | | long fileSize = multipartFile.getSize(); |
| | | if(fileSize <= 0){ |
| | | throw new PlatformRuntimeException("上传文件大小错误:" + fileSize); |
| | | } |
| | | } |
| | | |
| | | private String checkFile(String fileName, long fileSize, String fileContentType){ |
| | | String fileExt = FileUtils.getFileExt(fileName); |
| | | if(StringUtils.isEmpty(fileExt)){ |
| | | logger.error("错误文件信息:{}" ,fileName); |
| | | throw new PlatformRuntimeException("不存在文件扩展名,无法上传"); |
| | | } |
| | | |
| | | // 平台配置可支持的文件后缀类型 |
| | | String extArrayConfig = null; |
| | | if(fileContentType.equals(Constants.UPLOAD_AFTER_FILE_KEYWORD)){ |
| | | extArrayConfig = this.getArgumentVariable(ArgumentsConstants.UPLOAD_FILE_EXT_STR_CONFIG_KEY).getStringValue(); |
| | | } else { |
| | | extArrayConfig = this.getArgumentVariable(ArgumentsConstants.UPLOAD_IMAGE_EXT_STR_CONFIG_KEY).getStringValue(); |
| | | } |
| | | |
| | | // 如果存在配置后缀限制,就要检查匹配 |
| | | if(StringUtils.isNotEmpty(extArrayConfig)){ |
| | | Set<String> extensionList = StringUtils.commaDelimitedListToSet(extArrayConfig); |
| | | if(extensionList == null || extensionList.size() == 0){ |
| | | throw new PlatformRuntimeException("上传文件类型,只能是:" + extArrayConfig); |
| | | } |
| | | if(!extensionList.contains(fileExt)){ |
| | | throw new PlatformRuntimeException("上传文件类型,只能是:" + extArrayConfig); |
| | | } |
| | | } |
| | | |
| | | // 文件大小限制 |
| | | long fileSizeConfig = 0; |
| | | if(fileContentType.equals(Constants.UPLOAD_AFTER_FILE_KEYWORD)){ |
| | | fileSizeConfig = this.getArgumentVariable(ArgumentsConstants.UPLOAD_FILE_MAX_SIZE_CONFIG_KEY).getLongValue(); |
| | | } else { |
| | | fileSizeConfig = this.getArgumentVariable(ArgumentsConstants.UPLOAD_IMAGE_MAX_SIZE_CONFIG_KEY).getLongValue(); |
| | | } |
| | | // 配置的大小单位:M,这里换成字节 |
| | | fileSizeConfig = fileSizeConfig * 1024 * 1024; |
| | | if(fileSize > fileSizeConfig){ |
| | | throw new PlatformRuntimeException("上传文件大小:" + fileSize + ",超出限制:" + fileSizeConfig); |
| | | } |
| | | return fileExt; |
| | | } |
| | | |
| | | /** |
| | | * 上传文件到服务器本地磁盘。 |
| | | * @param inputStream 文件流,系统使用完会自动关闭 |
| | | * @param fileName 文件名,如: demo.txt |
| | | * @param groupId 业务ID,可选 |
| | | * @return |
| | | * @throws Exception |
| | | * @date 2023-03-16 |
| | | */ |
| | | @Deprecated |
| | | protected FileInfo uploadFileToLocal(InputStream inputStream, String fileName, String groupId, long fileSize) throws Exception{ |
| | | return this.acquireFileOperateSpi().uploadFileToSystem(inputStream, fileName, groupId, fileSize); |
| | | } |
| | | |
| | | /** |
| | | * 上传文件到远程服务。 |
| | | * @param inputStream 文件流,系统使用完会自动关闭 |
| | | * @param fileName 文件名,如: demo.txt |
| | | * @param groupId 业务ID,可选 |
| | | * @return |
| | | * @throws Exception |
| | | * @date 2023-02-15 |
| | | */ |
| | | @Deprecated |
| | | protected FileInfo uploadFileToRemote(InputStream inputStream, String fileName, String groupId, long fileSize) throws Exception{ |
| | | if(inputStream == null){ |
| | | throw new IllegalArgumentException("上传ftp文件流为空!"); |
| | | } |
| | | return this.acquireFileOperateSpi().uploadFileToFtp(inputStream, fileName, groupId,fileSize); |
| | | } |
| | | |
| | | protected FileInfo uploadFileToRemote(String absoluteFilePath, Integer businessType, String owner) throws Exception{ |
| | | File uploadFile = this.checkAbsoluteFilePath(absoluteFilePath); |
| | | BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(uploadFile)); |
| | | return this.uploadFileToRemote(inputStream, uploadFile.getName(), null, uploadFile.getTotalSpace(), businessType, owner); |
| | | } |
| | | |
| | | /** |
| | | * 上传文件到远程服务目录中。 |
| | | * @param absoluteFilePath |
| | | * @return 返回上传文件基本信息 |
| | | * @throws Exception |
| | | * @date 2023-02-15 |
| | | */ |
| | | @Deprecated |
| | | protected FileInfo uploadFileToRemote(String absoluteFilePath) throws Exception{ |
| | | // if(StringUtils.isEmpty(absoluteFilePath)){ |
| | | // throw new IllegalArgumentException("上传文件全路径不存在!"); |
| | | // } |
| | | // File uploadFile = new File(absoluteFilePath); |
| | | // if(!uploadFile.exists()){ |
| | | // logger.warn("上传文件不存在,file=" + absoluteFilePath); |
| | | // return null; |
| | | // } |
| | | File uploadFile = this.checkAbsoluteFilePath(absoluteFilePath); |
| | | BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(uploadFile)); |
| | | return this.acquireFileOperateSpi().uploadFileToFtp(inputStream, FileUtils.getFileNameWithoutPath(absoluteFilePath), null, uploadFile.getTotalSpace()); |
| | | } |
| | | |
| | | private File checkAbsoluteFilePath(String absoluteFilePath) throws Exception{ |
| | | if(StringUtils.isEmpty(absoluteFilePath)){ |
| | | throw new IllegalArgumentException("上传文件全路径不存在!"); |
| | | } |
| | | File uploadFile = new File(absoluteFilePath.toLowerCase()); |
| | | if(!uploadFile.exists()){ |
| | | throw new IllegalArgumentException("上传文件不存在, file=" + absoluteFilePath); |
| | | } |
| | | return uploadFile; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.iplatform.base.config.SecurityUserProperties; |
| | | import com.iplatform.core.BeanContextAware; |
| | | import com.iplatform.model.po.S_user_core; |
| | | import com.walker.infrastructure.utils.PasswordUtils; |
| | | import com.walker.web.UserPrincipal; |
| | | import com.walker.web.UserType; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 获得当前登录用户认证信息。<p></p> |
| | | * <pre> |
| | | * 1.如果你的控制器必须在用户认证之后才能操作,就必须继承该对象,请参考: {@linkplain AbstractSecurityController} |
| | | * |
| | | * 2.如果你的控制器没有权限控制,则只需要集成<code>AbstractController</code>即可, |
| | | * 请参考: {@linkplain AbstractController} |
| | | * </pre> |
| | | * @author 时克英 |
| | | * @date 2022-11-11 |
| | | */ |
| | | public abstract class AbstractSecurityController extends AbstractController{ |
| | | |
| | | /** |
| | | * 验证密码是否符合平台政策。 |
| | | // * @param encryptPassword 前端修改的密码(密文),RSA加密,后台要解密的 |
| | | * @param originPassword 原始明文密码 |
| | | * @return 返回错误提示,返回空表示成功 |
| | | * @date 2023-08-05 |
| | | */ |
| | | protected String validatePasswordRule(String originPassword){ |
| | | // String originPassword = PlatformRSAUtils.getRsaDecryptValue(encryptPassword, PlatformRSAUtils.PRIK); |
| | | String error = PasswordUtils.filterText(originPassword); |
| | | if(error != null){ |
| | | return error; |
| | | } |
| | | int passLevelConfig = this.acquireSecurityUserProperties().getPassLevel(); |
| | | if(!PasswordUtils.validateComplex(originPassword, passLevelConfig)){ |
| | | return "密码级别过低,请输入:大小写字母、数字以及至少一种特殊符号"; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | protected SecurityUserProperties acquireSecurityUserProperties(){ |
| | | return BeanContextAware.getBeanByType(SecurityUserProperties.class); |
| | | } |
| | | |
| | | /** |
| | | * 以流程角色登录获取权限,activiti7专用,后续会废弃。 |
| | | * @date 2023-03-21 |
| | | */ |
| | | @Deprecated |
| | | protected void loginAsWorkflowRole(){ |
| | | this.acquireSecuritySpi().loginAsWorkflowRole(); |
| | | } |
| | | |
| | | /** |
| | | * 判断当前登录用户是否超级管理员。 |
| | | * @return |
| | | * @date 2022-11-27 |
| | | */ |
| | | protected boolean isSupervisor(){ |
| | | S_user_core user_core = this.getCurrentUser(); |
| | | if(user_core == null){ |
| | | throw new IllegalStateException("获取当前用户错误,未找到"); |
| | | } |
| | | return user_core.getUser_type() == UserType.TYPE_SUPER; |
| | | } |
| | | |
| | | /** |
| | | * 返回当前用户具有的角色集合,注意:这里面会有权限使用的特定角色,如: <p> ROLE_SUPERVISOR, ROLE_USER, ROLE_ADMIN 等。</p> |
| | | * <pre> |
| | | * 其他的是系统角色管理的ID,因此数据库通过角色集合查询菜单并不影响结果。 |
| | | * </pre> |
| | | * @return |
| | | * @date 2022-11-27 |
| | | */ |
| | | public List<String> getCurrentUserRoleIdList(){ |
| | | return this.acquireSecuritySpi().getCurrentUserRoleIdList(); |
| | | } |
| | | |
| | | public UserPrincipal<S_user_core> getCurrentUserPrincipal(){ |
| | | return this.acquireSecuritySpi().getCurrentUserPrincipal(); |
| | | } |
| | | |
| | | /** |
| | | * 返回用户指定菜单的权限标识(是否存在),如果不存在返回空。 |
| | | * @param menuId 对应功能菜单ID |
| | | * @return |
| | | * @date 2022-12-21 |
| | | */ |
| | | protected String getCurrentDataScope(String menuId){ |
| | | UserPrincipal<S_user_core> userPrincipal = this.getCurrentUserPrincipal(); |
| | | return userPrincipal.getDataScope(menuId); |
| | | } |
| | | |
| | | public S_user_core getCurrentUser(){ |
| | | return this.acquireSecuritySpi().getCurrentUser(); |
| | | } |
| | | |
| | | public long getCurrentUserId(){ |
| | | return this.acquireSecuritySpi().getCurrentUserId(); |
| | | } |
| | | |
| | | /** |
| | | * 返回加密后的密文 |
| | | * @param password 明文密码 |
| | | * @return |
| | | * @date 2022-12-13 |
| | | */ |
| | | public String encryptPassword(String password){ |
| | | return this.acquireSecuritySpi().encryptPassword(password); |
| | | } |
| | | |
| | | /** |
| | | * 比较提供的明文密码是否与加密的密码相同。 |
| | | * @param rawPassword 明文原始密码 |
| | | * @param encodedPassword 加密后的密码 |
| | | * @return |
| | | */ |
| | | public boolean matchesPassword(String rawPassword, String encodedPassword){ |
| | | return this.acquireSecuritySpi().matchesPassword(rawPassword, encodedPassword); |
| | | } |
| | | |
| | | private SecuritySpi acquireSecuritySpi(){ |
| | | return BeanContextAware.getBeanByType(SecuritySpi.class); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | /** |
| | | * 可变参数常量定义,变量的KEY常量对应数据库中的: config_key 字段。 |
| | | * @author 时克英 |
| | | * @date 2022-11-30 |
| | | */ |
| | | public class ArgumentsConstants { |
| | | |
| | | public static final String KEY_SECURITY_CAPTCHA_ENABLED = "security.captcha.enabled"; |
| | | |
| | | /** |
| | | * 用户初始密码参数,明文密码。 |
| | | * @date 2022-12-13 |
| | | */ |
| | | public static final String KEY_SECURITY_PASSWORD_INIT = "security.password.init"; |
| | | |
| | | /** |
| | | * 安全:是否开启用户注册 |
| | | * @date 2023-07-28 |
| | | */ |
| | | public static final String KEY_SECURITY_ACCOUNT_REGISTER = "security.account.register"; |
| | | |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | //~ 平台配置参数,以Tab分组方式展示的界面。2023-05-12 |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | /** 移动端域名 */ |
| | | public static final String CONFIG_KEY_SITE_URL = "site_url"; |
| | | |
| | | /** 图片上传类型 1本地 2七牛云 3OSS 4COS, 默认本地 |
| | | * <p>支持系统自己的定义常量,参考:{@linkplain com.walker.file.FileStoreType}</p> |
| | | * */ |
| | | public static final String CONFIG_UPLOAD_TYPE = "uploadType"; |
| | | |
| | | /** 全局本地图片域名 */ |
| | | public static final String CONFIG_LOCAL_UPLOAD_URL = "localUploadUrl"; |
| | | /** 七牛云上传URL */ |
| | | public static final String CONFIG_QN_UPLOAD_URL = "qnUploadUrl"; |
| | | /** 阿里云上传URL */ |
| | | public static final String CONFIG_AL_UPLOAD_URL = "alUploadUrl"; |
| | | /** 腾讯云上传URL */ |
| | | public static final String CONFIG_TX_UPLOAD_URL = "txUploadUrl"; |
| | | /** 亚马逊S3上传URL */ |
| | | public static final String CONFIG_S3_UPLOAD_URL = "s3UploadUrl"; |
| | | /** FTP上传URL */ |
| | | public static final String CONFIG_FTP_UPLOAD_URL = "ftpUploadUrl"; |
| | | |
| | | /** 版权-公司信息 */ |
| | | public static final String CONFIG_COPYRIGHT_COMPANY_INFO = "copyright_company_name"; |
| | | /** 版权-公司图片 */ |
| | | public static final String CONFIG_COPYRIGHT_COMPANY_IMAGE = "copyright_company_image"; |
| | | |
| | | /** 图片上传,拓展名 */ |
| | | public static final String UPLOAD_IMAGE_EXT_STR_CONFIG_KEY = "image_ext_str"; |
| | | /** 图片上传,最大尺寸 */ |
| | | public static final String UPLOAD_IMAGE_MAX_SIZE_CONFIG_KEY = "image_max_size"; |
| | | /** 文件上传,拓展名 */ |
| | | public static final String UPLOAD_FILE_EXT_STR_CONFIG_KEY = "file_ext_str"; |
| | | /** 文件上传,最大尺寸 */ |
| | | public static final String UPLOAD_FILE_MAX_SIZE_CONFIG_KEY = "file_max_size"; |
| | | |
| | | /** 移动端顶部logo */ |
| | | public static final String CONFIG_KEY_MOBILE_TOP_LOGO = "mobile_top_logo"; |
| | | /** 移动端登录 logo */ |
| | | public static final String CONFIG_KEY_MOBILE_LOGIN_LOGO = "mobile_login_logo"; |
| | | /** 商品分类页配置 */ |
| | | public static final String CONFIG_CATEGORY_CONFIG = "category_page_config"; |
| | | /** 是否隐藏一级分类 */ |
| | | public static final String CONFIG_IS_SHOW_CATEGORY = "is_show_category"; |
| | | /** 首页商品列表模板配置 */ |
| | | public static final String CONFIG_IS_PRODUCT_LIST_STYLE = "homePageSaleListStyle"; |
| | | |
| | | /** 底部导航—是否自定义 */ |
| | | public static final String CONFIG_BOTTOM_NAVIGATION_IS_CUSTOM = "bottom_navigation_is_custom"; |
| | | |
| | | /** 客服类型 */ |
| | | public static final String CONFIG_CONSUMER_TYPE = "consumer_type"; |
| | | /** 客户类型-H5 */ |
| | | public static final String CONSUMER_TYPE_H5 = "h5"; |
| | | /** 客户类型-热线 */ |
| | | public static final String CONSUMER_TYPE_HOTLINE = "hotline"; |
| | | /** 客服H5链接 */ |
| | | public static final String CONFIG_CONSUMER_H5_URL = "consumer_h5_url"; |
| | | /** 客服电话 */ |
| | | public static final String CONFIG_CONSUMER_HOTLINE = "consumer_hotline"; |
| | | /** 店铺街开关 */ |
| | | public static final String CONFIG_KEY_SHOP_STREET_SWITCH = "shop_street_switch"; |
| | | /** 客服电话 */ |
| | | public static final String CONFIG_CONSUMER_MESSAGE = "consumer_message"; |
| | | /** 客服邮箱 */ |
| | | public static final String CONFIG_CONSUMER_EMAIL = "consumer_email"; |
| | | |
| | | /** 自定义表单开关:关闭 */ |
| | | public static final String CONFIG_FORM_SWITCH_CLOSE = "'0'"; |
| | | /** 自定义表单开关:开启 */ |
| | | public static final String CONFIG_FORM_SWITCH_OPEN = "'1'"; |
| | | |
| | | /** 公共开关:0关闭 */ |
| | | public static final String COMMON_SWITCH_CLOSE = "0"; |
| | | /** 公共开关:1开启 */ |
| | | public static final String COMMON_SWITCH_OPEN = "1"; |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.iplatform.core.BeanContextAware; |
| | | import com.iplatform.core.util.ThreadUtils; |
| | | |
| | | import java.util.TimerTask; |
| | | import java.util.concurrent.ScheduledExecutorService; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * 异步任务管理器 |
| | | * |
| | | * @author Mike |
| | | * @date 2023-01-05 |
| | | */ |
| | | public class AsyncManager |
| | | { |
| | | /** |
| | | * 操作延迟10毫秒 |
| | | */ |
| | | private final int OPERATE_DELAY_TIME = 10; |
| | | |
| | | /** |
| | | * 异步操作任务调度线程池 |
| | | */ |
| | | private ScheduledExecutorService executor = (ScheduledExecutorService)BeanContextAware.getBeanByName("scheduledExecutorService"); |
| | | |
| | | /** |
| | | * 单例模式 |
| | | */ |
| | | private AsyncManager(){} |
| | | |
| | | private static AsyncManager me = new AsyncManager(); |
| | | |
| | | public static AsyncManager me() |
| | | { |
| | | return me; |
| | | } |
| | | |
| | | /** |
| | | * 执行任务 |
| | | * |
| | | * @param task 任务 |
| | | */ |
| | | public void execute(TimerTask task) |
| | | { |
| | | executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS); |
| | | } |
| | | |
| | | /** |
| | | * 执行一个异步任务 |
| | | * @param task 任务定义 |
| | | * @param millSeconds 延时执行(毫秒) |
| | | * @date 2023-08-17 |
| | | */ |
| | | public void execute(TimerTask task, long millSeconds){ |
| | | executor.schedule(task, millSeconds, TimeUnit.MILLISECONDS); |
| | | } |
| | | |
| | | /** |
| | | * 停止任务线程池 |
| | | */ |
| | | public void shutdown() |
| | | { |
| | | ThreadUtils.shutdownAndAwaitTermination(executor); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.iplatform.model.po.S_category; |
| | | import com.iplatform.model.vo.CategoryTreeVo; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 分类缓存对象。 |
| | | * @author 时克英 |
| | | * @date 2023-05-17 |
| | | */ |
| | | public interface CategoryCacheProvider { |
| | | |
| | | List<CategoryTreeVo> getTree(Integer type, Integer status, String name, List<Integer> categoryIdList, int owner); |
| | | |
| | | /** |
| | | * 返回分类树结构(目前只有两级) |
| | | * @param type 归属类别:1 产品分类,2 附件分类,3 文章分类, 4 设置分类, 5 菜单分类, 6 配置分类, 7 秒杀配置 |
| | | * @param status 状态:0正常,1失效 |
| | | * @param name 名称(目前未知) |
| | | * @param owner 归属(平台或商户) |
| | | * @return |
| | | */ |
| | | List<CategoryTreeVo> getListTree(Integer type, Integer status, String name, int owner); |
| | | |
| | | S_category get(int id); |
| | | |
| | | void save(S_category category); |
| | | |
| | | void update(S_category category); |
| | | |
| | | void remove(int id); |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | public class Constants { |
| | | |
| | | /** |
| | | * 超级管理员默认的登录名称。 |
| | | * @author 时克英 |
| | | * @date 2022-10-31 |
| | | */ |
| | | public static final String SUPERVISOR_NAME_DEFAULT = "supervisor"; |
| | | |
| | | /** |
| | | * 超级管理员ID = 0 |
| | | */ |
| | | public static final long SUPERVISOR_ID = 0L; |
| | | |
| | | /** |
| | | * 超级管理员姓名 |
| | | */ |
| | | public static final String SUPERVISOR_NAME_ZH = "主宰账号"; |
| | | |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | /** |
| | | * 用户缓存token前缀。 |
| | | * @date 2022-11-01 |
| | | */ |
| | | public static final String USER_ONLINE_PREFIX = "login_token:"; |
| | | |
| | | /** |
| | | * 验证码 redis key |
| | | * @date 2022-11-07 |
| | | */ |
| | | public static final String CAPTCHA_CODE_PREFIX = "captcha_codes:"; |
| | | |
| | | /** |
| | | * 当组织机构表没有记录时,默认显示机构名称。 |
| | | * @date 2022-12-01 |
| | | */ |
| | | public static final String DEFAULT_ORG_NAME = "默认单位"; |
| | | |
| | | /** |
| | | * 数据权限前缀。 |
| | | * @date 2022-12-21 |
| | | */ |
| | | public static final String DATA_SCOPE_NAME = "data_scope,"; |
| | | |
| | | /** |
| | | * 前端过来的提交参数,如果必须提供则需要检查,返回非法提示。 |
| | | * @date 2023-06-01 |
| | | */ |
| | | public static final String ERROR_ARGUMENT = "参数错误"; |
| | | |
| | | /** |
| | | * id查询校验不存在,返回非法提示。 |
| | | * @date 2023-06-01 |
| | | */ |
| | | public static final String ERROR_NOT_EXIST = "信息不存在,请刷新后重试"; |
| | | |
| | | /** |
| | | * 校验班级结班,返回非法提示。 |
| | | * @date 2023-06-01 |
| | | */ |
| | | public static final String ERROR_CLASS_IS_END = "班级已结班,无法操作"; |
| | | |
| | | /** |
| | | * 平台附件上传,映射的浏览路径。 |
| | | * @date 2023-06-09 |
| | | */ |
| | | public static final String FILE_CONTEXT_PATH_MAPPING = "/file/**"; |
| | | /** |
| | | * 平台附件上传,本地文件包含的路径,用于从路径中判断是否URL地址。 |
| | | * @date 2023-06-10 |
| | | */ |
| | | public static final String FILE_CONTEXT_PATH = "/file/"; |
| | | |
| | | /** |
| | | * 设置错误日志,内容最大长度,默认:255 |
| | | * @date 2023-08-13 |
| | | */ |
| | | public static final int LOG_ERROR_MAX_SIZE = 255; |
| | | |
| | | /** 数据状态:正常 */ |
| | | public static final int STATUS_NORMAL = 0; |
| | | /** 数据状态:禁用 */ |
| | | public static final int STATUS_DISABLE = 1; |
| | | /** 数据状态:删除 */ |
| | | public static final int STATUS_DELETE = 2; |
| | | |
| | | |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | //~ 缓存名称常量,2023-01-04 |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | public static final String CACHE_NAME_MENU = "cache.base.menu"; |
| | | public static final String CACHE_NAME_CAPTCHA = "cache.base.captcha"; |
| | | public static final String CACHE_NAME_DEPT = "cache.base.dept"; |
| | | public static final String CACHE_NAME_HOST = "cache.system.host"; |
| | | public static final String CACHE_NAME_USER = "cache.base.user"; |
| | | public static final String CACHE_NAME_ONLINE_USER = "cache.base.user_online"; |
| | | public static final String CACHE_NAME_ARGUMENTS = "cache.base.arguments"; |
| | | public static final String CACHE_NAME_DICT = "cache.base.dict"; |
| | | public static final String CACHE_NAME_PUSH = "cache.base.push"; |
| | | public static final String CACHE_NAME_CATEGORY = "cache.base.category"; |
| | | public static final String CACHE_NAME_FORM = "cache.base.form"; |
| | | public static final String CACHE_NAME_GROUP = "cache.base.group"; |
| | | public static final String CACHE_NAME_USER_LOGIN = "cache.base.user_login"; |
| | | public static final String CACHE_NAME_WECHAT = "cache.base.wechat"; |
| | | public static final String CACHE_NAME_NOTIFICATION_TEMPLATE = "cache.notify.template"; |
| | | |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | //~~ TCP 模块核心常量,2023-04-17 |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | public static final String QUEUE_TYPE_MEMORY = "memory"; |
| | | |
| | | /** |
| | | * 推送范围定义常量:data 普通单个,broadcast 广播。 |
| | | * @date 2023-04-21 |
| | | */ |
| | | public static final String PUSH_SCOPE_DATA = "data"; |
| | | public static final String PUSH_SCOPE_BROAD_CAST = "broadcast"; |
| | | |
| | | /** |
| | | * 模拟短信推送者ID |
| | | * @date 2023-04-25 |
| | | */ |
| | | public static final String PUSH_SMS_ID_MOCK = "mock_sms_push"; |
| | | |
| | | /** |
| | | * 推送平台提醒时,from字段默认值 |
| | | * @date 2023-04-25 |
| | | */ |
| | | public static final String PUSH_FROM_DEFAULT = "platform"; |
| | | public static final String PUSH_OPTION_TYPE_DEFAULT = "no_type"; |
| | | |
| | | /** |
| | | * 消息通知,存放临时缓存前缀 |
| | | * @date 2023-04-27 |
| | | */ |
| | | public static final String PUSH_CACHE_PREFIX = "notification:"; |
| | | |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | //~~ 导入导出相关,2023-05-08 |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | /** |
| | | * 生成导入模板文件前缀。 |
| | | * @date 2023-05-08 |
| | | */ |
| | | public static final String TEMPLATE_IMPORT_PREFIX = "template_"; |
| | | |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | //~~ 电商基础,2023-05-15 |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | /** |
| | | * 数据归属:平台,> 0 表示商户ID |
| | | */ |
| | | public static final int OWNER_PLATFORM = -1; |
| | | |
| | | /** |
| | | * 系统基础分类的type类型。<p></p> |
| | | * 类型,1 产品分类,2 附件分类,3 文章分类, 4 设置分类, 5 菜单分类, 6 配置分类, 7 秒杀配置 |
| | | * @date 2023-05-18 |
| | | */ |
| | | public static final int CATEGORY_TYPE_CONFIG = 6; |
| | | public static final int CATEGORY_TYPE_ATTACH = 2; |
| | | |
| | | /** 文件导出下载拦截关键字 */ |
| | | public static final String DOWNLOAD_FILE_KEYWORD = "downloadf"; |
| | | |
| | | /** 文件前端上传后下载关键字 */ |
| | | public static final String UPLOAD_AFTER_FILE_KEYWORD = "uploadf"; |
| | | public static final String UPLOAD_AFTER_IMAGE_KEYWORD = "uploadi"; |
| | | |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | //~~ 系统分组配置项,2023-06-23 |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | /** 首页banner滚动图 */ |
| | | public static final Integer GROUP_DATA_ID_INDEX_BANNER = 1; |
| | | /** 首页金刚区 */ |
| | | public static final Integer GROUP_DATA_ID_INDEX_MENU = 2; |
| | | /** 热门搜索 */ |
| | | public static final Integer GROUP_DATA_ID_INDEX_KEYWORDS = 3; |
| | | /** 移动端_充值套餐设置 */ |
| | | public static final Integer GROUP_DATA_ID_RECHARGE_PACKAGE = 4; |
| | | /** 个人中心菜单 */ |
| | | public static final Integer GROUP_DATA_ID_USER_CENTER_MENU = 5; |
| | | /** 个人中心轮播图 */ |
| | | public static final Integer GROUP_DATA_ID_USER_CENTER_BANNER = 7; |
| | | /** 分销推广海报Banner */ |
| | | public static final Integer GROUP_DATA_ID_SPREAD_BANNER_LIST = 10; |
| | | /** 移动端_订单状态_图 */ |
| | | public static final Integer GROUP_DATA_ID_ORDER_STATUS_IMAGE = 13; |
| | | /** 移动端_底部导航 */ |
| | | public static final Integer GROUP_DATA_ID_BOTTOM_NAVIGATION = 14; |
| | | |
| | | /** |
| | | * 分组配置数据中,图片关键词名字。 |
| | | * @date 2023-06-24 |
| | | */ |
| | | public static final String GROUP_DATA_IMAGE = "pic"; |
| | | |
| | | /** 公共开关:0关闭 */ |
| | | public static final String COMMON_SWITCH_CLOSE = "0"; |
| | | /** 公共开关:1开启 */ |
| | | public static final String COMMON_SWITCH_OPEN = "1"; |
| | | |
| | | /** 自定义表单开关:关闭 */ |
| | | public static final String CONFIG_FORM_SWITCH_CLOSE = "'0'"; |
| | | /** 自定义表单开关:开启 */ |
| | | public static final String CONFIG_FORM_SWITCH_OPEN = "'1'"; |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonIgnore; |
| | | import com.iplatform.model.po.S_user_core; |
| | | import com.walker.web.DataStatus; |
| | | import com.walker.web.LoginType; |
| | | import com.walker.web.UserType; |
| | | import com.walker.web.principal.AbstractUserPrincipal; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 平台默认的用户凭证对象,主要用于登录认证、权限拦截判断使用。 |
| | | * 业务模块不会使用该对象。 |
| | | * @author 时克英 |
| | | * @date 2022-10-31 |
| | | */ |
| | | public class DefaultUserPrincipal extends AbstractUserPrincipal<S_user_core> { |
| | | |
| | | private long lastLoginTime = 0; |
| | | private LoginType lastLoginType = LoginType.UserPassword; |
| | | |
| | | private List<String> roleIdList = new ArrayList<>(4); |
| | | |
| | | // 2022-12-21 用户菜单对应的数据权限 |
| | | // key = menuId, value = dept_org(如:本单位) |
| | | private Map<String, String> dataScopeMap = new HashMap<>(); |
| | | |
| | | public DefaultUserPrincipal(){} |
| | | |
| | | public DefaultUserPrincipal(S_user_core user_core){ |
| | | if(user_core == null){ |
| | | throw new IllegalArgumentException("user info is required!"); |
| | | } |
| | | this.setUserInfo(user_core); |
| | | this.setId(String.valueOf(user_core.getId())); |
| | | this.setUserName(user_core.getUser_name()); |
| | | this.setPassword(user_core.getPassword()); |
| | | } |
| | | |
| | | @JsonIgnore |
| | | @Override |
| | | public boolean isEnabled() { |
| | | return this.getUserInfo().getStatus() == DataStatus.CONST_NORMAL; |
| | | } |
| | | |
| | | @JsonIgnore |
| | | @Override |
| | | public boolean isTokenExpired(String token) { |
| | | // 这里暂未实现,集成后腰修改 |
| | | return false; |
| | | } |
| | | |
| | | @JsonIgnore |
| | | @Override |
| | | public boolean isAccountLocked() { |
| | | // 这里暂未实现,集成后腰修改 |
| | | return false; |
| | | } |
| | | |
| | | @JsonIgnore |
| | | @Override |
| | | public boolean validateMd5Password(String encryption) { |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public long getLastLoginTime() { |
| | | return this.lastLoginTime; |
| | | } |
| | | |
| | | @Override |
| | | public LoginType getLastLoginType() { |
| | | return this.lastLoginType; |
| | | } |
| | | |
| | | public void setLastLoginTime(long loginTime){ |
| | | this.lastLoginTime = loginTime; |
| | | } |
| | | |
| | | public void setLastLoginType(LoginType loginType){ |
| | | this.lastLoginType = loginType; |
| | | } |
| | | |
| | | /** |
| | | * 返回该用户拥有的角色ID集合。 |
| | | * @return |
| | | */ |
| | | public List<String> getRoleIdList() { |
| | | return roleIdList; |
| | | } |
| | | |
| | | public void setRoleIdList(List<String> roleIdList) { |
| | | this.roleIdList = roleIdList; |
| | | } |
| | | |
| | | @JsonIgnore |
| | | @Override |
| | | public boolean isSupervisor() { |
| | | return this.getUserInfo().getUser_type().intValue() == UserType.TYPE_SUPER; |
| | | } |
| | | |
| | | /** |
| | | * 添加一条数据权限 |
| | | * @param menuId 菜单ID,对应一个功能 |
| | | * @param dataScopeValue 数据权限标识 |
| | | * @date 2022-12-21 |
| | | */ |
| | | @JsonIgnore |
| | | public void addDataScope(String menuId, String dataScopeValue){ |
| | | this.dataScopeMap.put(menuId, dataScopeValue); |
| | | } |
| | | public void setDataScopeMap(Map<String, String> dataScopeMap){ |
| | | this.dataScopeMap = dataScopeMap; |
| | | } |
| | | |
| | | /** |
| | | * 根据菜单ID,查询是否具有特定的数据权限。 |
| | | * @param menuId |
| | | * @return |
| | | * @date 2022-12-21 |
| | | */ |
| | | @JsonIgnore |
| | | @Override |
| | | public String getDataScope(String menuId){ |
| | | return this.dataScopeMap.get(menuId); |
| | | } |
| | | |
| | | public Map<String, String> getDataScopeMap(){ |
| | | return this.dataScopeMap; |
| | | } |
| | | |
| | | /** |
| | | * 该方法测试redis序列化使用,暂时不用。 |
| | | * @param user_core |
| | | * @date 2022-11-15 |
| | | */ |
| | | @Deprecated |
| | | public void setup(S_user_core user_core){ |
| | | this.setUserInfo(user_core); |
| | | this.setId(String.valueOf(user_core.getId())); |
| | | this.setUserName(user_core.getUser_name()); |
| | | this.setPassword(user_core.getPassword()); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.iplatform.model.po.S_dept; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 组织机构缓存提供者使用规范。<p></p> |
| | | * 因为存在多种实现,如: Redis 或者 内存,因此需要抽象该接口。 |
| | | * @author 时克英 |
| | | * @date 2022-12-03 |
| | | */ |
| | | public interface DeptCacheProvider { |
| | | |
| | | /** |
| | | * 设置是否允许缓存机构的子机构关系,<br> |
| | | * 在机构数量非常庞大的时候,即便 Redis 也不太适合存储该关系,因为通常界面会展示较多数据,<br> |
| | | * 此时可能退化成数据库查询,或者通过其他 NoSQL 数据库实现。 |
| | | * @param allow |
| | | * @date 2022-12-03 |
| | | */ |
| | | void setAllowCacheChildren(boolean allow); |
| | | |
| | | S_dept getDept(long deptId); |
| | | |
| | | void updateDept(S_dept s_dept); |
| | | |
| | | void removeDept(long deptId); |
| | | |
| | | void putDept(S_dept s_dept); |
| | | |
| | | /** |
| | | * 返回给定机构,下一级子机构ID集合。 |
| | | * @param deptId 给定当前机构ID |
| | | * @return |
| | | * @date 2022-12-03 |
| | | */ |
| | | List<String> getChildrenDeptIdOneLevel(long deptId); |
| | | |
| | | /** |
| | | * 返回给定机构,下一级子机构对象集合。 |
| | | * @param deptId 给定当前机构ID |
| | | * @return |
| | | * @date 2022-12-03 |
| | | */ |
| | | List<S_dept> getChildrenDeptOneLevel(long deptId); |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.walker.file.FileInfo; |
| | | import com.walker.file.FileStoreType; |
| | | |
| | | import java.io.InputStream; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 文件操作提供者定义,由第三方实现文件管理功能,包括:上传、下载、获取文件信息等。 |
| | | * @author 时克英 |
| | | * @date 2023-02-15 |
| | | */ |
| | | public interface FileOperateSpi { |
| | | |
| | | byte[] downloadOssFile(String id); |
| | | |
| | | /** |
| | | * 清除给定文件地址的CDN前缀。如:https://qnyun.com/oss/12345678 |
| | | * <pre> |
| | | * 去掉前缀后,只剩下"12345678" |
| | | * </pre> |
| | | * @param path 给定的文件资源地址 |
| | | * @return |
| | | * @date 2023-05-17 |
| | | */ |
| | | String clearCdnPrefix(String path); |
| | | |
| | | /** |
| | | * 获取上传文件的CDN地址,根据使用的不同第三方服务从配置中查找。 |
| | | * @return |
| | | * @date 2023-05-17 |
| | | */ |
| | | String getCdnUrl(); |
| | | |
| | | FileInfo uploadFileToLocal(InputStream inputStream |
| | | , String fileName, String groupId, long fileSize, Integer businessType, String owner) throws Exception; |
| | | FileInfo[] uploadFileToLocal(InputStream[] inputStream |
| | | , String[] fileName, String groupId, long[] fileSize, Integer businessType, String owner) throws Exception; |
| | | |
| | | FileInfo uploadFileToFtp(InputStream inputStream |
| | | , String fileName, String groupId, long fileSize, Integer businessType, String owner) throws Exception; |
| | | FileInfo[] uploadFileToFtp(InputStream[] inputStream |
| | | , String[] fileName, String groupId, long[] fileSize, Integer businessType, String owner) throws Exception; |
| | | |
| | | FileInfo uploadFileToOss(InputStream inputStream |
| | | , String fileName, String groupId, long fileSize, Integer businessType, String owner, FileStoreType ossType) throws Exception; |
| | | FileInfo[] uploadFileToOss(InputStream[] inputStream |
| | | , String[] fileName, String groupId, long[] fileSize, Integer businessType, String owner, FileStoreType ossType) throws Exception; |
| | | |
| | | @Deprecated |
| | | FileInfo uploadFileToSystem(InputStream inputStream, String fileName, String groupId, long fileSize) throws Exception; |
| | | |
| | | @Deprecated |
| | | FileInfo uploadFileToFtp(InputStream inputStream, String fileName, String groupId, long fileSize) throws Exception; |
| | | |
| | | FileInfo getFileInfo(long id); |
| | | |
| | | List<FileInfo> getFileInfoList(List<String> ids); |
| | | |
| | | /** |
| | | * 返回本地文件系统存储根目录,如: d:/tmp/ |
| | | * @return |
| | | * @date 2023-02-15 |
| | | */ |
| | | String getFileRootConfig(); |
| | | |
| | | /** |
| | | * 调用远程上传文件,是否按照本地方式处理。 |
| | | * <pre> |
| | | * 1)该选项为了适应没有FTP等服务的情况,特别是在开发过程,如果设置为:true 则调用远程上传方法后文件仍然保存在本地。 |
| | | * 2)如果生产环境存在合适的文件存储服务,则需要设置为:false |
| | | * </pre> |
| | | * @return |
| | | * @date 2023-07-03 |
| | | */ |
| | | boolean isRemoteAsLocal(); |
| | | |
| | | FileStoreType getOssFileStoreType(); |
| | | |
| | | String getOssPrefix(); |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.walker.connector.LocalAddress; |
| | | import com.walker.db.DatabaseType; |
| | | import com.walker.db.TableInfo; |
| | | import com.walker.db.page.GenericPager; |
| | | import com.walker.dbmeta.DatabaseMetaEngine; |
| | | import com.walker.dbmeta.FieldInfo; |
| | | import com.walker.dbmeta.support.DamengMetaEngine; |
| | | import com.walker.dbmeta.support.MySQLMetaEngine; |
| | | import com.walker.dbmeta.support.OracleMetaEngine; |
| | | import com.walker.dbmeta.support.PostgresMetaEngine; |
| | | import com.walker.dbmeta.support.SqlserverMetaEngine; |
| | | import com.walker.security.SystemLogMan; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 定义本地数据库元数据引擎对象。<p></p> |
| | | * 用于查询数据库中表和字段记录。 |
| | | * @author 时克英 |
| | | * @date 2022-11-22 |
| | | */ |
| | | public class LocalDatabaseMetaEngine { |
| | | |
| | | private DatabaseMetaEngine engine; |
| | | |
| | | private LocalAddress localAddress; |
| | | |
| | | public void setLocalAddress(LocalAddress localAddress) { |
| | | if(localAddress == null){ |
| | | throw new IllegalArgumentException("LocalAddress 必须提供"); |
| | | } |
| | | this.localAddress = localAddress; |
| | | SystemLogMan.getInstance().checkMan(); |
| | | } |
| | | |
| | | public void setDatabaseType(DatabaseType databaseType){ |
| | | if(databaseType == DatabaseType.DERBY){ |
| | | throw new UnsupportedOperationException("不支持该数据库:" + databaseType.name()); |
| | | } else if(databaseType == DatabaseType.MYSQL){ |
| | | engine = new MySQLMetaEngine(); |
| | | |
| | | } else if(databaseType == DatabaseType.ORACLE){ |
| | | engine = new OracleMetaEngine(); |
| | | |
| | | } else if(databaseType == DatabaseType.POSTGRES){ |
| | | engine = new PostgresMetaEngine(); |
| | | |
| | | } else if(databaseType == DatabaseType.SQLSERVER){ |
| | | engine = new SqlserverMetaEngine(); |
| | | |
| | | } else if(databaseType == DatabaseType.DAMENG){ |
| | | // 2023-03-03 |
| | | engine = new DamengMetaEngine(); |
| | | |
| | | } else { |
| | | throw new IllegalArgumentException("unsupported database type: " + databaseType.name()); |
| | | } |
| | | System.out.println("创建:" + engine.getClass().getName()); |
| | | } |
| | | |
| | | public List<FieldInfo> getFieldsObject(String tableName){ |
| | | return engine.getFieldsObject(this.localAddress, tableName); |
| | | } |
| | | |
| | | public List<String> getTableNamesByLike(String tableNameLike){ |
| | | return engine.getTableNamesByLike(this.localAddress, tableNameLike); |
| | | } |
| | | |
| | | /** |
| | | * 分页返回表信息集合。当前页信息通过对象: ListPageContext.getCurrentPageIndex()方法获得。 |
| | | * @param tableNameLike 表名模糊查询,如果为空字符串则查询所有。 |
| | | * @return |
| | | * @date 2022-11-22 |
| | | */ |
| | | public GenericPager<TableInfo> queryPageTableNamesByLike(String tableNameLike |
| | | // , int pageIndex, int pageSize |
| | | ){ |
| | | return this.engine.queryPageTableNamesByLike(this.localAddress, tableNameLike); |
| | | } |
| | | |
| | | /** |
| | | * 返回指定表元数据信息。 |
| | | * @param tableName 表名称 |
| | | * @return |
| | | * @date 2022-11-26 |
| | | */ |
| | | public TableInfo queryOneTableInfo(String tableName){ |
| | | List<String> tableList = new ArrayList<>(2); |
| | | tableList.add(tableName); |
| | | Map<String, TableInfo> map = this.engine.getTableRows(this.localAddress, tableList); |
| | | if(map == null || map.size() == 0){ |
| | | return null; |
| | | } |
| | | return map.get(tableName); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.iplatform.model.vo.NotificationTemplateVo; |
| | | |
| | | /** |
| | | * 通知提醒,模板配置缓存定义。 |
| | | * @author 时克英 |
| | | * @date 2023-08-25 |
| | | */ |
| | | public interface NotificationTemplateCache { |
| | | |
| | | NotificationTemplateVo get(String mark); |
| | | |
| | | void save(NotificationTemplateVo category); |
| | | |
| | | void update(NotificationTemplateVo category); |
| | | |
| | | void remove(String mark); |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | /** |
| | | * 移植老程序代码,后续逐渐废弃使用。 |
| | | * @date 2023-08-25 |
| | | */ |
| | | public class NotifyConstants { |
| | | |
| | | /** 消息开关状态-不存在 */ |
| | | public static int SWITCH_NOT_EXIST = 0; |
| | | /** 消息开关状态-开启 */ |
| | | public static int SWITCH_OPEN = 1; |
| | | /** 消息开关状态-关闭 */ |
| | | public static int SWITCH_COLSE = 2; |
| | | |
| | | /** 详情类型——公众号模板消息 */ |
| | | public static String DETAIL_TYPE_WECHAT = "wechat"; |
| | | /** 详情类型——小程序模板消息 */ |
| | | public static String DETAIL_TYPE_ROUTINE = "routine"; |
| | | /** 详情类型——短信 */ |
| | | public static String DETAIL_TYPE_SMS = "sms"; |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.iplatform.base.pojo.form.FormData; |
| | | import com.iplatform.base.pojo.form.FormDataItem; |
| | | import com.iplatform.base.service.GroupServiceImpl; |
| | | import com.iplatform.core.BeanContextAware; |
| | | import com.iplatform.model.po.S_group_data; |
| | | import com.iplatform.model.vo.SystemGroupVo; |
| | | import com.walker.infrastructure.utils.JsonUtils; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 新界面,重构平台定义的基础控制器。 |
| | | * @author 时克英 |
| | | * @date 2023-05-15 |
| | | */ |
| | | public abstract class PlatformAdapterController extends SystemController{ |
| | | |
| | | protected SystemGroupCache getSystemGroupCache(){ |
| | | return BeanContextAware.getBeanByType(SystemGroupCache.class); |
| | | } |
| | | |
| | | private GroupServiceImpl getGroupService(){ |
| | | return BeanContextAware.getBeanByType(GroupServiceImpl.class); |
| | | } |
| | | |
| | | /** |
| | | * 根据分组项目ID,返回转换后的对象。 |
| | | * @param groupDataId |
| | | * @param clazz |
| | | * @param cdnUrl |
| | | * @return |
| | | * @param <T> |
| | | * @date 2023-09-11 |
| | | */ |
| | | protected <T> T acquireGroupDataNormal(int groupDataId, Class<T> clazz, String cdnUrl){ |
| | | S_group_data groupData = this.getGroupService().queryGroupData(groupDataId); |
| | | if(groupData == null || groupData.getStatus().intValue() == 0){ |
| | | return null; |
| | | } |
| | | |
| | | try { |
| | | FormData formData = JsonUtils.jsonStringToObject(groupData.getValue(), FormData.class); |
| | | if(StringUtils.isEmptyList(formData.getFields())){ |
| | | return null; |
| | | } |
| | | HashMap<String, Object> map = new HashMap<>(); |
| | | for(FormDataItem item : formData.getFields()){ |
| | | if(item.getName().equals(Constants.GROUP_DATA_IMAGE)){ |
| | | map.put(item.getName(), cdnUrl + item.getValue()); |
| | | } else { |
| | | map.put(item.getName(), item.getValue()); |
| | | } |
| | | } |
| | | map.put("id", groupData.getId()); |
| | | String json = JsonUtils.objectToJsonString(map); |
| | | return JsonUtils.jsonStringToObject(json, clazz); |
| | | |
| | | } catch (Exception ex){ |
| | | throw new PlatformRuntimeException("S_group_data.value转FormData错误:" + ex.getMessage(), ex); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 返回分组包含的动态添加项列表集合。 |
| | | * <pre> |
| | | * 1) 目前,在充值功能中使用,显示充值套餐列表。 |
| | | * </pre> |
| | | * @param groupId 分组ID |
| | | * @param status 是否可用 |
| | | * @param clazz 转换结果对象 |
| | | * @param cdnUrl 图片前缀 |
| | | * @return |
| | | * @param <T> |
| | | * @date 2023-09-11 |
| | | */ |
| | | protected <T> List<T> acquireGroupDataList(int groupId, boolean status, Class<T> clazz, String cdnUrl){ |
| | | SystemGroupVo vo = this.getSystemGroupCache().get(groupId); |
| | | if(vo == null){ |
| | | throw new IllegalStateException("缓存中未找到分组记录,groupId = " + groupId); |
| | | } |
| | | List<S_group_data> groupDataList = vo.getGroupDataList(); |
| | | if(StringUtils.isEmptyList(groupDataList)){ |
| | | return null; |
| | | } |
| | | |
| | | List<T> arrayList = new ArrayList<>(); |
| | | |
| | | try{ |
| | | FormData formData = null; |
| | | for(S_group_data data : groupDataList){ |
| | | formData = JsonUtils.jsonStringToObject(data.getValue(), FormData.class); |
| | | if(StringUtils.isEmptyList(formData.getFields())){ |
| | | continue; |
| | | } |
| | | if(status && data.getStatus().intValue() == 0){ |
| | | continue; |
| | | } |
| | | |
| | | HashMap<String, Object> map = new HashMap<>(); |
| | | T t; |
| | | for(FormDataItem item : formData.getFields()){ |
| | | if(item.getName().equals(Constants.GROUP_DATA_IMAGE)){ |
| | | map.put(item.getName(), cdnUrl + item.getValue()); |
| | | } else { |
| | | map.put(item.getName(), item.getValue()); |
| | | } |
| | | } |
| | | map.put("id", data.getId()); |
| | | String json = JsonUtils.objectToJsonString(map); |
| | | t = JsonUtils.jsonStringToObject(json, clazz); |
| | | arrayList.add(t); |
| | | } |
| | | return arrayList; |
| | | } catch (Exception ex){ |
| | | throw new PlatformRuntimeException("S_group_data.value转FormData错误:" + ex.getMessage(), ex); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 根据分组ID,返回分组包含的数据项配置集合信息。例如: |
| | | * <pre> |
| | | * 1)配置的APP首页底部导航。 |
| | | * </pre> |
| | | * @param groupId 分组ID |
| | | * @return |
| | | * @date 2023-06-23 |
| | | */ |
| | | protected List<HashMap<String, Object>> acquireGroupDataConfigList(int groupId, String cdnUrl){ |
| | | SystemGroupVo vo = this.getSystemGroupCache().get(groupId); |
| | | if(vo == null){ |
| | | throw new IllegalStateException("缓存中未找到分组记录,groupId = " + groupId); |
| | | } |
| | | List<S_group_data> groupDataList = vo.getGroupDataList(); |
| | | if(StringUtils.isEmptyList(groupDataList)){ |
| | | return new ArrayList<>(1); |
| | | } |
| | | |
| | | List<HashMap<String, Object>> arrayList = new ArrayList<>(); |
| | | |
| | | try { |
| | | FormData formData = null; |
| | | for (S_group_data data : groupDataList) { |
| | | formData = JsonUtils.jsonStringToObject(data.getValue(), FormData.class); |
| | | if(StringUtils.isEmptyList(formData.getFields())){ |
| | | continue; |
| | | } |
| | | |
| | | HashMap<String, Object> map = new HashMap<>(); |
| | | for(FormDataItem item : formData.getFields()){ |
| | | if(item.getName().equals(Constants.GROUP_DATA_IMAGE)){ |
| | | map.put(item.getName(), cdnUrl + item.getValue()); |
| | | } else { |
| | | map.put(item.getName(), item.getValue()); |
| | | } |
| | | } |
| | | map.put("id", data.getId()); |
| | | arrayList.add(map); |
| | | } |
| | | return arrayList; |
| | | |
| | | } catch (Exception ex){ |
| | | throw new PlatformRuntimeException("S_group_data.value转FormData错误:" + ex.getMessage(), ex); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 返回用户归属值,如果是平台为'-1',如果为租户(商户)则为定义的商户ID。 |
| | | * <pre> |
| | | * 注意要点: |
| | | * 1)因为系统框架中用户是长整形(Long),但商户中是(int)因此在实际添加商户数据时,需要按照序列来计算,这样只需要整形即可。 |
| | | * </pre> |
| | | * @return |
| | | * @date 2023-05-15 |
| | | */ |
| | | // protected int getOwner(){ |
| | | // S_user_core user = this.getCurrentUser(); |
| | | // int userType = user.getUser_type(); |
| | | // if(userType == UserType.TYPE_SUPER_MERCHANT || userType == UserType.TYPE_MERCHANT_ADMIN){ |
| | | // return user.getMer_id().intValue(); |
| | | //// throw new UnsupportedOperationException("对于其他租户(商户)归属应为:mer_id"); |
| | | // } |
| | | // return Constants.OWNER_PLATFORM; |
| | | // } |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.iplatform.model.po.S_user_core; |
| | | import com.walker.infrastructure.ApplicationCallback; |
| | | import com.walker.web.CaptchaProvider; |
| | | import com.walker.web.CaptchaResult; |
| | | import com.walker.web.TokenException; |
| | | import com.walker.web.UserPrincipal; |
| | | |
| | | /** |
| | | * 平台登录回调接口定义,便于支持多种用户(或设备)使用相同方式登录系统。 |
| | | * @author 时克英 |
| | | * @date 2023-01-26 |
| | | */ |
| | | public interface PlatformLoginCallback extends ApplicationCallback { |
| | | |
| | | /** |
| | | * 是否检测验证码,该方法意思是:在提交登录时,是否要验证。 |
| | | * <pre> |
| | | * 1)例如:在PC端会存在验证码。 |
| | | * 2)在APP端,通过短信登录时,不会有验证码(只会在生成短信验证码时才有验证操作) |
| | | * </pre> |
| | | * @return |
| | | */ |
| | | boolean isValidateCaptcha(); |
| | | |
| | | /** |
| | | * 根据用户登录ID,返回用户登录基本信息。<p></p> |
| | | * |
| | | * @param loginId |
| | | * @return object[0] = S_user_core user, object[1] = List<String> roleIdList |
| | | */ |
| | | Object[] queryLoginUser(String loginId); |
| | | |
| | | /** |
| | | * 校验密码回调方法。 |
| | | * @param userPrincipal |
| | | * @return |
| | | */ |
| | | boolean validatePassword(UserPrincipal<S_user_core> userPrincipal); |
| | | |
| | | /** |
| | | * 注销回调方法,当用户退出时触发调用。 |
| | | * @param token 客户端提交的token |
| | | */ |
| | | void onLogout(String token) throws TokenException; |
| | | |
| | | /** |
| | | * 返回登录回调配置的'验证码提供者' |
| | | * @return |
| | | * @date 2023-03-14 |
| | | */ |
| | | CaptchaProvider<CaptchaResult> getCaptchaProvider(); |
| | | |
| | | /** |
| | | * 设置登录回调配置的'验证码提供者',每个登录回调对象都需要配置一个。 |
| | | * @param captchaProvider |
| | | * @date 2023-03-14 |
| | | */ |
| | | void setCaptchaProvider(CaptchaProvider<CaptchaResult> captchaProvider); |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.walker.web.WebRuntimeException; |
| | | |
| | | /** |
| | | * 平台最基础的运行异常定义。 |
| | | * @author 时克英 |
| | | * @date 2023-05-20 |
| | | */ |
| | | public class PlatformRuntimeException extends WebRuntimeException { |
| | | |
| | | public PlatformRuntimeException(String msg) { |
| | | super(msg); |
| | | } |
| | | |
| | | public PlatformRuntimeException(String msg, Throwable caution){ |
| | | super(msg, caution); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.iplatform.model.po.S_user_core; |
| | | import com.walker.infrastructure.ApplicationCallback; |
| | | |
| | | /** |
| | | * 用户操作回调接口定义。 |
| | | * <pre> |
| | | * 1)业务可以配置实现自己的用户操作回调动作,如:当系统添加用户时,业务要初始设置用户默认积分等。 |
| | | * 2)实现该接口后,直接配置为<code>Sping Bean</code> 即可。 |
| | | * 3)注意:该方法会在数据库事务中调用,因此业务尽量在回调中只操作数据库,降低时间操作过长风险。 |
| | | * </pre> |
| | | * @date 2023-01-05 |
| | | */ |
| | | public interface PlatformUserCallback extends ApplicationCallback { |
| | | |
| | | /** |
| | | * 当系统创建新用户时,回调该接口 |
| | | * @param user |
| | | */ |
| | | public void onCreateNewUser(S_user_core user); |
| | | |
| | | /** |
| | | * 当系统更新用户时,回调该接口 |
| | | * @param user |
| | | */ |
| | | public void onUpdateUser(S_user_core user); |
| | | |
| | | /** |
| | | * 当系统删除用户时,回调该接口 |
| | | * @param userId |
| | | */ |
| | | public void onDeleteUser(long userId); |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | /** |
| | | * 推送提醒,缓存定义。存储临时并行通知的消息,2分钟内失效。 |
| | | * @author 时克英 |
| | | * @date 2023-04-27 |
| | | */ |
| | | public interface PushCacheProvider { |
| | | |
| | | void put(String key, String value); |
| | | |
| | | String get(String key); |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.iplatform.base.push.DefaultPushManager; |
| | | import com.iplatform.base.util.NotificationUtils; |
| | | import com.walker.infrastructure.utils.DateUtils; |
| | | import com.walker.infrastructure.utils.NumberGenerator; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.push.Notification; |
| | | import com.walker.push.NotificationChannel; |
| | | import com.walker.push.util.PushUtils; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | public abstract class PushController extends SystemController{ |
| | | |
| | | /** |
| | | * 发送短信验证码,登录与否都可调用。 |
| | | * @param code 发送的验证码 |
| | | * @param userIdOrMobile 用户ID 或者 手机号 |
| | | * @date 2023-04-26 |
| | | */ |
| | | protected void pushSmsValidateCode(String code, String userIdOrMobile){ |
| | | String creator = this.getCurrentUserPrincipal() == null? "creator" : this.getCurrentUserPrincipal().getId(); |
| | | ((DefaultPushManager)this.getPushManager()).pushSmsValidateCode(code, userIdOrMobile, creator); |
| | | } |
| | | |
| | | /** |
| | | * 推送短信内容,登录与否都可调用。 |
| | | * @param templateCode 短信模板代码 |
| | | * @param param 参数 |
| | | * @param userIdOrMobile 用户ID 或者 手机号 |
| | | * @date 2023-04-26 |
| | | */ |
| | | protected void pushSmsNotification(String templateCode, Map<String, String> param, String userIdOrMobile){ |
| | | String creator = this.getCurrentUserPrincipal() == null? "creator" : this.getCurrentUserPrincipal().getId(); |
| | | Notification notification = NotificationUtils |
| | | .acquireSmsNotification(templateCode, param, null, userIdOrMobile, creator); |
| | | this.getPushManager().pushSms(notification); |
| | | } |
| | | |
| | | /** |
| | | * 推送邮件通知,该方法无论登录都可调用。 |
| | | * <p>不登录的话,userIdOrMail 必须是邮件地址</p> |
| | | * @param title 标题 |
| | | * @param content 内容 |
| | | * @param userIdOrMail 用户ID(或邮件地址) |
| | | * @date 2023-04-26 |
| | | */ |
| | | protected void pushMailNotification(String title, String content, String userIdOrMail){ |
| | | if(StringUtils.isEmpty(title) |
| | | || StringUtils.isEmpty(content) |
| | | || StringUtils.isEmpty(userIdOrMail)){ |
| | | throw new IllegalArgumentException("推送邮件失败:参数为空!"); |
| | | } |
| | | String creator = this.getCurrentUserPrincipal() == null? "creator" : this.getCurrentUserPrincipal().getId(); |
| | | Notification notification = PushUtils.acquireEmailNotificationOne(title, content |
| | | , ((DefaultPushManager)this.getPushManager()).getMailFrom(), userIdOrMail, creator); |
| | | this.getPushManager().push(notification, null); |
| | | } |
| | | |
| | | /** |
| | | * 推送平台普通消息,不包括:邮件和短信。 |
| | | * <p>这些通知会保存到数据库中,一般为操作业务的各种通知,如:待办事项等。</p> |
| | | * @param pushData 业务传递的数据 |
| | | * @date 2023-04-26 |
| | | */ |
| | | protected void pushMessageNotification(PushData pushData){ |
| | | if(pushData == null){ |
| | | throw new IllegalArgumentException("pushData is null!"); |
| | | } |
| | | if(StringUtils.isEmpty(pushData.getBusinessType()) |
| | | || StringUtils.isEmpty(pushData.getBusinessId()) |
| | | || StringUtils.isEmpty(pushData.getUserId())){ |
| | | throw new IllegalArgumentException("推送业务消息缺少条件:businessType, businessId, userId"); |
| | | } |
| | | |
| | | String creator = this.getCurrentUserPrincipal() == null? "creator" : this.getCurrentUserPrincipal().getId(); |
| | | |
| | | Notification notification = new Notification(); |
| | | notification.setCreator(creator); |
| | | notification.setCreateTime(DateUtils.getDateTimeNumber()); |
| | | notification.setFrom(Constants.PUSH_FROM_DEFAULT); |
| | | notification.setTitle(pushData.getTitle()); |
| | | notification.setOptionId(pushData.getBusinessId()); |
| | | notification.setOptionType(pushData.getBusinessType()); |
| | | notification.setContent(pushData.toJson()); |
| | | notification.setId(NumberGenerator.getLongSequenceId()); |
| | | |
| | | List<String> receiverList = new ArrayList<>(2); |
| | | receiverList.add(pushData.getUserId()); |
| | | notification.setReceiverList(receiverList); |
| | | |
| | | // 根据平台配置实用通道 |
| | | List<NotificationChannel> channelList = new ArrayList<>(4); |
| | | for(String index : this.getPushManager().getMessageChannelNames()){ |
| | | channelList.add(NotificationChannel.getType(index)); |
| | | } |
| | | notification.setChannelList(channelList); |
| | | // 是否并行 |
| | | notification.setParallel(this.getPushManager().isMessageParallel()); |
| | | |
| | | this.getPushManager().push(notification, null); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.walker.infrastructure.utils.JsonUtils; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 平台定义的业务推送(消息)对象。<p>该对象在业务层使用。</p> |
| | | * @author 时克英 |
| | | * @date 2023-04-25 |
| | | */ |
| | | public class PushData implements Serializable { |
| | | |
| | | @Override |
| | | public String toString(){ |
| | | return new StringBuilder("[userId=").append(this.userId) |
| | | .append(", bizId=").append(this.businessId) |
| | | .append(", type=").append(this.businessType) |
| | | .append(", schema=").append(this.schema) |
| | | .append(", title=").append(this.title) |
| | | .append("]").toString(); |
| | | } |
| | | |
| | | public String toJson(){ |
| | | try { |
| | | return JsonUtils.objectToJsonString(this); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | public void addParameter(String key, Object value){ |
| | | if(this.parameter == null){ |
| | | this.parameter = new HashMap<>(2); |
| | | } |
| | | this.parameter.put(key, value); |
| | | } |
| | | |
| | | public String getUserId() { |
| | | return userId; |
| | | } |
| | | |
| | | public void setUserId(String userId) { |
| | | this.userId = userId; |
| | | } |
| | | |
| | | public String getBusinessId() { |
| | | return businessId; |
| | | } |
| | | |
| | | public void setBusinessId(String businessId) { |
| | | this.businessId = businessId; |
| | | } |
| | | |
| | | public String getBusinessType() { |
| | | return businessType; |
| | | } |
| | | |
| | | public void setBusinessType(String businessType) { |
| | | this.businessType = businessType; |
| | | } |
| | | |
| | | public String getSchema() { |
| | | return schema; |
| | | } |
| | | |
| | | public void setSchema(String schema) { |
| | | this.schema = schema; |
| | | } |
| | | |
| | | public String getTitle() { |
| | | return title; |
| | | } |
| | | |
| | | public void setTitle(String title) { |
| | | this.title = title; |
| | | } |
| | | |
| | | public Map<String, Object> getParameter() { |
| | | return parameter; |
| | | } |
| | | |
| | | public void setParameter(Map<String, Object> parameter) { |
| | | this.parameter = parameter; |
| | | } |
| | | |
| | | private String userId; |
| | | private String businessId; |
| | | private String businessType; |
| | | private String schema; |
| | | private String title; |
| | | private Map<String, Object> parameter = null; |
| | | |
| | | public static final String SCHEMA_HTTP = "https://"; |
| | | public static final String SCHEMA_APP = "app://"; |
| | | public static final String SCHEMA_SYSTEM = "system://"; |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.iplatform.base.cache.DictCacheProvider; |
| | | import com.iplatform.base.callback.PlatformCallbackPostProcessor; |
| | | import com.iplatform.base.di.PlatformDataImportEngine; |
| | | import com.walker.cache.CacheProvider; |
| | | import com.walker.push.PushManager; |
| | | import com.walker.web.CaptchaProvider; |
| | | import com.walker.web.CaptchaResult; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 系统业务bean配置总管理,用于测试在 SystemController 初始化后自动组装一些通用缓存对象。<p></p> |
| | | * 测试通过! |
| | | * @author 时克英 |
| | | * @date 2023-03-10 |
| | | */ |
| | | public class RootConfigBean { |
| | | |
| | | /** |
| | | * 触发自动设置各种公共 Bean 到系统控制器中,不用在创建时手动注入,也不需要依赖 spring的特定注解。 |
| | | * @date 2023-03-10 |
| | | */ |
| | | public void startup(){ |
| | | List<SystemController> systemControllerList = this.callbackPostProcessor.getSystemControllerList(); |
| | | if(systemControllerList != null){ |
| | | for(SystemController controller : systemControllerList){ |
| | | controller.setDictCacheProvider(this.dictCacheProvider); |
| | | controller.setDeptCacheProvider(this.deptCacheProvider); |
| | | controller.setUserCacheProvider(this.userCacheProvider); |
| | | controller.setPlatformDataImportEngine(this.platformDataImportEngine); |
| | | controller.setPushManager(this.pushManager); |
| | | controller.setSmsCaptchaProvider(this.smsCaptchaProvider); |
| | | controller.setCaptchaCacheProvider(this.captchaCacheProvider); |
| | | } |
| | | System.out.println("............... | RootConfigBean: startup()"); |
| | | } |
| | | } |
| | | |
| | | public void setCallbackPostProcessor(PlatformCallbackPostProcessor callbackPostProcessor) { |
| | | this.callbackPostProcessor = callbackPostProcessor; |
| | | } |
| | | |
| | | public void setDeptCacheProvider(DeptCacheProvider deptCacheProvider) { |
| | | this.deptCacheProvider = deptCacheProvider; |
| | | } |
| | | |
| | | public void setUserCacheProvider(UserCacheProvider userCacheProvider) { |
| | | this.userCacheProvider = userCacheProvider; |
| | | } |
| | | |
| | | public void setPlatformDataImportEngine(PlatformDataImportEngine platformDataImportEngine) { |
| | | this.platformDataImportEngine = platformDataImportEngine; |
| | | } |
| | | |
| | | public void setDictCacheProvider(DictCacheProvider dictCacheProvider) { |
| | | this.dictCacheProvider = dictCacheProvider; |
| | | } |
| | | |
| | | public void setPushManager(PushManager pushManager) { |
| | | this.pushManager = pushManager; |
| | | } |
| | | |
| | | public void setSmsCaptchaProvider(CaptchaProvider<CaptchaResult> smsCaptchaProvider) { |
| | | this.smsCaptchaProvider = smsCaptchaProvider; |
| | | } |
| | | |
| | | public void setCaptchaCacheProvider(CacheProvider<String> captchaCacheProvider) { |
| | | this.captchaCacheProvider = captchaCacheProvider; |
| | | } |
| | | |
| | | private CaptchaProvider<CaptchaResult> smsCaptchaProvider; |
| | | private CacheProvider<String> captchaCacheProvider; |
| | | |
| | | private PushManager pushManager; |
| | | private PlatformCallbackPostProcessor callbackPostProcessor = null; |
| | | |
| | | private DeptCacheProvider deptCacheProvider; |
| | | private UserCacheProvider userCacheProvider; |
| | | private PlatformDataImportEngine platformDataImportEngine; |
| | | private DictCacheProvider dictCacheProvider; |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | public class SecurityConstants { |
| | | |
| | | public static final String ROLE_SUPER_ADMIN = "ROLE_SUPERVISOR"; |
| | | public static final String ROLE_ADMIN = "ROLE_ADMIN"; |
| | | public static final String ROLE_USER = "ROLE_USER"; |
| | | |
| | | /** |
| | | * 顶级机构特有的权限角色,例如:商户独立角色(第三方) |
| | | * @date 2023-06-07 |
| | | */ |
| | | public static final String ROLE_MERCHANT = "ROLE_MERCHANT"; |
| | | |
| | | // /** |
| | | // * activiti7工作流强制使用的角色 |
| | | // * @date 2023-03-21 |
| | | // */ |
| | | // public static final String ROLE_ACTIVITI_USER = "ROLE_ACTIVITI_USER"; |
| | | |
| | | /** |
| | | * 工作流访问路径前缀。 |
| | | * @date 2023-03-21 |
| | | */ |
| | | public static final String URL_WORKFLOW_PREFIX = "/wf/"; |
| | | |
| | | /** |
| | | * 返回电商前端用户基本信息,用户KEY名称。 |
| | | * @date 2023-05-12 |
| | | */ |
| | | public static final String KEY_USER_INFO = "userInfo"; |
| | | |
| | | /** |
| | | * 移动端用户信息,关键字定义。 |
| | | * @date 2023-06-30 |
| | | */ |
| | | public static final String KEY_USER_INFO_APP = "userInfoApp"; |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.iplatform.base.exception.LoginException; |
| | | import com.iplatform.base.pojo.RequestLogin; |
| | | import com.iplatform.model.po.S_user_core; |
| | | import com.walker.web.UserPrincipal; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 安全提供者接口定义。<br> |
| | | * 通过该接口使得 iplatform-base-security 模块可以解耦。 |
| | | * @author 时克英 |
| | | * @date 2022-11-11 |
| | | */ |
| | | public interface SecuritySpi { |
| | | |
| | | /** |
| | | * 返回当前登录用户具有的角色ID集合。 |
| | | * @return |
| | | */ |
| | | List<String> getCurrentUserRoleIdList(); |
| | | |
| | | /** |
| | | * 返回当前登录用户凭证信息 |
| | | * @return |
| | | */ |
| | | UserPrincipal<S_user_core> getCurrentUserPrincipal(); |
| | | |
| | | /** |
| | | * 返回当前登录用户对象 |
| | | * @return |
| | | */ |
| | | S_user_core getCurrentUser(); |
| | | |
| | | /** |
| | | * 返回当前登录用户ID |
| | | * @return |
| | | */ |
| | | long getCurrentUserId(); |
| | | |
| | | /** |
| | | * 加密给定的明文密码 |
| | | * @param password |
| | | * @return 返回密文密码 |
| | | */ |
| | | String encryptPassword(String password); |
| | | |
| | | /** |
| | | * 比较给定的密码是否与加密相等。 |
| | | * @param rawPassword 原始明文密码 |
| | | * @param encodedPassword 加密的密码 |
| | | * @return |
| | | */ |
| | | boolean matchesPassword(String rawPassword, String encodedPassword); |
| | | |
| | | /** |
| | | * 是否允许移动端,在登录时手机号不存在直接注册? |
| | | * @return |
| | | * @date 2023-06-28 |
| | | */ |
| | | boolean isAllowMobileLoginRegister(); |
| | | |
| | | /** |
| | | * 用户登录系统过程方法,抽取该方法可以在自定义登录中灵活使用。 |
| | | * @param requestLogin |
| | | * @return |
| | | * @throws LoginException 登录异常抛出提示错误 |
| | | * @date 2023-06-28 |
| | | */ |
| | | Map<String, Object> login(RequestLogin requestLogin) throws LoginException; |
| | | |
| | | /** |
| | | * 以流程角色登录获取权限,activiti7专用,后续会废弃。 |
| | | * @author 时克英 |
| | | * @date 2023-03-21 |
| | | */ |
| | | @Deprecated |
| | | void loginAsWorkflowRole(); |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.iplatform.base.cache.DictCacheProvider; |
| | | import com.iplatform.base.di.PlatformDataImportEngine; |
| | | import com.iplatform.base.di.TemplateInfo; |
| | | import com.iplatform.base.service.DeptServiceImpl; |
| | | import com.iplatform.base.service.LogServiceImpl; |
| | | import com.iplatform.base.service.RoleServiceImpl; |
| | | import com.iplatform.base.service.UserServiceImpl; |
| | | import com.iplatform.base.support.strategy.LoginStrategyManager; |
| | | import com.iplatform.base.util.MenuUtils; |
| | | import com.iplatform.core.BeanContextAware; |
| | | import com.iplatform.model.po.S_dept; |
| | | import com.iplatform.model.po.S_dict_data; |
| | | import com.iplatform.model.po.S_oper_log; |
| | | import com.iplatform.model.po.S_user_core; |
| | | import com.iplatform.model.po.S_user_login; |
| | | import com.walker.cache.CacheProvider; |
| | | import com.walker.infrastructure.utils.DateUtils; |
| | | import com.walker.infrastructure.utils.FileCopyUtils; |
| | | import com.walker.infrastructure.utils.NumberGenerator; |
| | | import com.walker.infrastructure.utils.PhoneNumberUtils; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.push.PushManager; |
| | | import com.walker.web.CaptchaProvider; |
| | | import com.walker.web.CaptchaResult; |
| | | import com.walker.web.OrgType; |
| | | import com.walker.web.ResponseCode; |
| | | import com.walker.web.UserOnlineProvider; |
| | | import com.walker.web.UserPrincipal; |
| | | import com.walker.web.UserType; |
| | | import com.walker.web.WebAgentService; |
| | | import com.walker.web.WebUserAgent; |
| | | import com.walker.web.log.BusinessType; |
| | | import com.walker.web.log.OperateUser; |
| | | import com.walker.web.util.IdUtils; |
| | | import com.walker.web.util.ServletUtils; |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | | |
| | | import java.io.File; |
| | | import java.io.IOException; |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.TimerTask; |
| | | |
| | | /** |
| | | * 系统控制器对象,业务所有 <code>Controller</code> 对象,都要继承该对象。 |
| | | * @author 时克英 |
| | | * @date 2022-12-01 |
| | | */ |
| | | public abstract class SystemController extends AbstractFileOperateSpiController{ |
| | | |
| | | /** |
| | | * 更新给定用户登录缓存中的角色集合内容,roleIds。 |
| | | * <pre> |
| | | * 1) 当用户变更角色后,可以直接刷新界面(重新请求用户信息)获取新的对应菜单权限。 |
| | | * </pre> |
| | | * @param userId 用户ID |
| | | * @author 时克英 |
| | | * @date 2023-12-28 |
| | | */ |
| | | protected void updateLoginUserRoleListInCache(Long userId){ |
| | | S_user_core userCore = this.getUser(userId); |
| | | if(userCore == null){ |
| | | throw new PlatformRuntimeException("缓存中未查找到用户,这不正常,userId = " + userId, null); |
| | | } |
| | | S_user_login userLogin = this.getLoginStrategyManager().getUserLogin(userCore.getUser_name()); |
| | | if(userLogin == null){ |
| | | if(this.logger.isDebugEnabled()){ |
| | | this.logger.debug("用户:{}不存在登录缓存,无需更新角色(roleId)缓存,userName={}", userId, userCore.getUser_name()); |
| | | } |
| | | return; |
| | | } |
| | | |
| | | UserPrincipal<?> existUserPrincipal = BeanContextAware.getBeanByType(UserOnlineProvider.class).getUserPrincipal(userLogin.getUuid()); |
| | | if (existUserPrincipal==null) { |
| | | return; |
| | | } |
| | | List<String> existRoleIdList = existUserPrincipal.getRoleIdList(); |
| | | |
| | | // List<String> roleIdList = this.getUserService().queryUserRoleIdList(userId); |
| | | List<String> roleIdList = BeanContextAware.getBeanByType(RoleServiceImpl.class).queryUserRoleIdList(userId); |
| | | if(this.logger.isDebugEnabled()){ |
| | | this.logger.debug("给定用户:{},包含的角色:{}", userId, roleIdList); |
| | | } |
| | | if(StringUtils.isEmptyList(roleIdList)){ |
| | | roleIdList = new ArrayList<>(4); |
| | | } |
| | | // 把原来用户已有的系统级权限角色重新写入,否则用户会重新让登录 |
| | | if(existRoleIdList != null){ |
| | | for(String securityRoleName : existRoleIdList){ |
| | | if(securityRoleName.equals(SecurityConstants.ROLE_USER) |
| | | || securityRoleName.equals(SecurityConstants.ROLE_ADMIN) |
| | | || securityRoleName.equals(SecurityConstants.ROLE_SUPER_ADMIN) |
| | | || securityRoleName.equals(SecurityConstants.ROLE_MERCHANT)){ |
| | | roleIdList.add(securityRoleName); |
| | | } |
| | | } |
| | | } |
| | | |
| | | DefaultUserPrincipal userPrincipal = new DefaultUserPrincipal(userCore); |
| | | userPrincipal.setRoleIdList(roleIdList); |
| | | // 更新缓存的登录信息 |
| | | BeanContextAware.getBeanByType(UserOnlineProvider.class).cacheUserPrincipal(userLogin.getUuid(), userPrincipal, VariableConstants.DEFAULT_TOKEN_EXPIRED_MINUTES); |
| | | } |
| | | |
| | | protected UserLoginCache getUserLoginCache(){ |
| | | return BeanContextAware.getBeanByType(UserLoginCache.class); |
| | | } |
| | | |
| | | /** |
| | | * 获得通知提醒模板配置缓存。 |
| | | * @return |
| | | * @date 2023-08-25 |
| | | */ |
| | | protected NotificationTemplateCache getNotificationTemplateCache(){ |
| | | return BeanContextAware.getBeanByType(NotificationTemplateCache.class); |
| | | } |
| | | |
| | | /** |
| | | * 写入成功操作日志 |
| | | * @param userName 当前用户名,可以是登录ID或名字,可选 |
| | | * @param operateUser 操作用户类型 |
| | | * @param businessType 业务类型 |
| | | * @param title 标题描述,可选 |
| | | * @param input 输入参数,可选 |
| | | * @param output 输出参数,可选 |
| | | * @date 2023-08-13 |
| | | */ |
| | | protected void systemLogSuccess(String userName, OperateUser operateUser, BusinessType businessType |
| | | , String title, String input, String output){ |
| | | S_oper_log s_oper_log = this.acquireSystemLog(userName, operateUser, businessType, title, input, output); |
| | | AsyncManager.me().execute(new TimerTask() { |
| | | @Override |
| | | public void run() { |
| | | BeanContextAware.getBeanByType(LogServiceImpl.class).execInsertOperateLog(s_oper_log); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * 写入错误日志 |
| | | * @param userName 当前用户名,可以是登录ID或名字,可选 |
| | | * @param operateUser 操作用户类型,可选 |
| | | * @param businessType 业务类型,可选 |
| | | * @param title 标题描述,可选 |
| | | * @param input 输入参数,可选 |
| | | * @param error 错误内容,必填 |
| | | * @date 2023-08-13 |
| | | */ |
| | | protected void systemLogError(String userName, OperateUser operateUser, BusinessType businessType, String title, String input, String error){ |
| | | if(StringUtils.isEmpty(error)){ |
| | | logger.warn("调用写入错误日志,但未提供错误内容,日志将不会保存:systemLogError --> error is null!"); |
| | | return; |
| | | } |
| | | S_oper_log s_oper_log = this.acquireSystemLog(userName, operateUser, businessType, title, input, null); |
| | | s_oper_log.setStatus(ResponseCode.ERROR.getCode()); |
| | | s_oper_log.setError_msg(StringUtils.substring(error, 0, Constants.LOG_ERROR_MAX_SIZE)); |
| | | AsyncManager.me().execute(new TimerTask() { |
| | | @Override |
| | | public void run() { |
| | | BeanContextAware.getBeanByType(LogServiceImpl.class).execInsertOperateLog(s_oper_log); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | private S_oper_log acquireSystemLog(String userName, OperateUser operateUser, BusinessType businessType |
| | | , String title, String input, String output){ |
| | | if(operateUser == null){ |
| | | operateUser = OperateUser.Manage; |
| | | } |
| | | if(businessType == null){ |
| | | businessType = BusinessType.Other; |
| | | } |
| | | WebUserAgent agent = this.getCurrentWebUserAgent(); |
| | | S_oper_log s_oper_log = new S_oper_log(); |
| | | s_oper_log.setOper_id(NumberGenerator.getLongSequenceNumber()); |
| | | s_oper_log.setOper_time(DateUtils.getDateTimeNumber()); |
| | | s_oper_log.setStatus(ResponseCode.SUCCESS.getCode()); |
| | | s_oper_log.setOper_name(userName); |
| | | s_oper_log.setOperate_user(operateUser.getIndex()); |
| | | s_oper_log.setBusiness_type(businessType.getIndex()); |
| | | s_oper_log.setOper_ip(agent.getIp()); |
| | | s_oper_log.setOper_location(agent.getLocation()); |
| | | s_oper_log.setRequest_method(agent.getMethod()); |
| | | s_oper_log.setOper_url(agent.getUrl()); |
| | | s_oper_log.setTitle(title); |
| | | if(StringUtils.isNotEmpty(input)){ |
| | | s_oper_log.setOper_param(input); |
| | | } |
| | | if(StringUtils.isNotEmpty(output)){ |
| | | s_oper_log.setJson_result(output); |
| | | } |
| | | return s_oper_log; |
| | | } |
| | | |
| | | /** |
| | | * 返回登录策略管理器对象 |
| | | * @return |
| | | * @date 2023-08-05 |
| | | */ |
| | | protected LoginStrategyManager getLoginStrategyManager(){ |
| | | return BeanContextAware.getBeanByType(LoginStrategyManager.class); |
| | | } |
| | | |
| | | /** |
| | | * 返回当前web浏览器代理对象。 |
| | | * @return |
| | | * @date 2023-07-25 |
| | | */ |
| | | protected WebUserAgent getCurrentWebUserAgent(){ |
| | | HttpServletRequest request = this.getRequest(); |
| | | return this.getWebAgentService().getWebUserAgent(request.getHeader("User-Agent"), request); |
| | | } |
| | | |
| | | protected WebAgentService getWebAgentService(){ |
| | | return BeanContextAware.getBeanByType(WebAgentService.class); |
| | | } |
| | | |
| | | /** |
| | | * 判断短信验证码是否正确。 |
| | | * @param code 验证码 |
| | | * @param uuid 请求验证码标识 |
| | | * @return |
| | | * @date 2023-08-07 |
| | | */ |
| | | protected boolean validateSmsCode(String code, String uuid){ |
| | | CaptchaResult captchaResult = new CaptchaResult(); |
| | | captchaResult.setCode(code); |
| | | captchaResult.setUuid(uuid); |
| | | return this.smsCaptchaProvider.validateCaptcha(captchaResult); |
| | | } |
| | | |
| | | /** |
| | | * 发送短信验证码。 |
| | | * @param phoneNumber 手机号 |
| | | * @return 返回前端需要的uuid,提交登录使用 |
| | | * @throws PlatformRuntimeException |
| | | * @date 2023-06-28 |
| | | */ |
| | | protected Map<String, Object> sendSmsCodeValidation(String phoneNumber){ |
| | | if(!PhoneNumberUtils.isCellPhoneNumber(phoneNumber)){ |
| | | throw new PlatformRuntimeException("手机号码格式错误:" + phoneNumber); |
| | | } |
| | | String uuid = IdUtils.simpleUUID(); |
| | | Map<String, Object> data = new HashMap<>(4); |
| | | data.put("uuid", uuid); |
| | | String verifyKey = Constants.CAPTCHA_CODE_PREFIX + uuid; |
| | | CaptchaResult captchaResult = this.smsCaptchaProvider.generateCaptcha(phoneNumber); |
| | | if(captchaResult == null){ |
| | | // return ResponseValue.error("短信验证码生成错误, null"); |
| | | throw new PlatformRuntimeException("短信验证码生成错误, null"); |
| | | } |
| | | // 写入验证码 key 和 code 到缓存中 |
| | | this.captchaCacheProvider.putCacheData(verifyKey, captchaResult.getCode(), 120); |
| | | if(this.logger.isDebugEnabled()){ |
| | | this.logger.debug("生成短信验证码:{}, uuid:{}", captchaResult.getCode(), uuid); |
| | | } |
| | | data.put("message", "短信验证码已发送"); |
| | | return data; |
| | | } |
| | | |
| | | /** |
| | | * 返回用户归属值,如果是平台为'-1',如果为租户(商户)则为定义的商户ID。 |
| | | * <pre> |
| | | * 注意要点: |
| | | * 1)因为系统框架中用户是长整形(Long),但商户中是(int)因此在实际添加商户数据时,需要按照序列来计算,这样只需要整形即可。 |
| | | * </pre> |
| | | * @return |
| | | * @date 2023-06-05 |
| | | */ |
| | | protected long getOwner(){ |
| | | S_user_core user = this.getCurrentUser(); |
| | | int userType = user.getUser_type(); |
| | | if(userType == UserType.TYPE_SUPER){ |
| | | return Constants.OWNER_PLATFORM; |
| | | } |
| | | // 其他人需要根据机构中"menu_type"字段区分是平台机构,还是业务独立机构 |
| | | S_dept dept = this.getDept(user.getOrg_id()); |
| | | if(dept.getMenu_type().intValue() == MenuUtils.MENU_SCOPE_PLATFORM){ |
| | | return Constants.OWNER_PLATFORM; |
| | | } |
| | | // 机构ID就是业务创建的独立编号(如:商户id),这里商户是int,但系统机构中仍然使用bigint |
| | | return dept.getId(); |
| | | } |
| | | |
| | | /** |
| | | * 返回当前用户所在顶级单位,使用的菜单范围:平台0,商户(顶级独立单位菜单范围)4,后续可能会有其他值。 |
| | | * @return |
| | | * @date 2023-06-01 |
| | | */ |
| | | protected int getCurrentOrgMenuScope(){ |
| | | long orgId = this.getCurrentUser().getOrg_id(); |
| | | if(orgId == Constants.SUPERVISOR_ID){ |
| | | // 超级管理员,返回平台菜单范围 |
| | | return MenuUtils.MENU_SCOPE_PLATFORM; |
| | | } |
| | | return this.getDeptCacheProvider().getDept(orgId).getMenu_type(); |
| | | } |
| | | |
| | | /** |
| | | * 根据字典数据code,返回字典项名称。 |
| | | * @param dictCode 字典项编码(主键) |
| | | * @return |
| | | * @date 2023-03-26 |
| | | */ |
| | | protected String getDictName(long dictCode){ |
| | | S_dict_data dict_data = this.getDictCacheProvider().getCacheData(String.valueOf(dictCode)); |
| | | if(dict_data == null){ |
| | | throw new IllegalStateException("缓存中未找到字典名称,dict_code = " + dictCode); |
| | | } |
| | | return dict_data.getDict_label(); |
| | | } |
| | | |
| | | /** |
| | | * 返回给定机构的名字。 |
| | | * @param deptId 机构ID |
| | | * @return |
| | | * @date 2023-03-23 |
| | | */ |
| | | protected String getDeptName(long deptId){ |
| | | S_dept dept = this.getDept(deptId); |
| | | return dept == null ? "None":dept.getDept_name(); |
| | | } |
| | | |
| | | /** |
| | | * 返回给定id的部门对象 |
| | | * @param deptId 部门ID |
| | | * @return |
| | | * @author 时克英 |
| | | * @date 2023-03-23 |
| | | */ |
| | | protected S_dept getDept(long deptId){ |
| | | return this.getDeptCacheProvider().getDept(deptId); |
| | | } |
| | | |
| | | /** |
| | | * 从缓存中返回给定的用户 |
| | | * @param userId 用户id |
| | | * @return |
| | | * @date 2023-03-22 |
| | | */ |
| | | public S_user_core getUser(long userId){ |
| | | return this.getUserCacheProvider().getUser(userId); |
| | | } |
| | | |
| | | /** |
| | | * 下载数据导入模板,该模板由系统自动生成。<br> |
| | | * 业务需要提供数据库对应的'表名称',如:s_user_core |
| | | * @param tableName 表名 |
| | | * @date 2023-03-18 |
| | | */ |
| | | protected void downloadLocalImportTemplate(String tableName){ |
| | | if(StringUtils.isEmpty(tableName)){ |
| | | throw new IllegalArgumentException("请提供要导入数据的'表名称'!"); |
| | | } |
| | | // 本地文件存储根路径,如: d:/temp/ |
| | | String templatePath = this.acquireFileOperateSpi().getFileRootConfig(); |
| | | // 生成的模板文件名称,如:demo.xlsx |
| | | String templateFileName = Constants.TEMPLATE_IMPORT_PREFIX + tableName + "_" + DateUtils.getDateTimeSecondForShow() + ".xlsx"; |
| | | TemplateInfo templateInfo = new TemplateInfo(); |
| | | // 2023-05-07 设置模板生成具体路径。 |
| | | templateInfo.setTemplatePath(templatePath + templateFileName); |
| | | templateInfo.setTableName(tableName); |
| | | |
| | | logger.debug("templateInfo = {}", templateInfo); |
| | | |
| | | File templateFile = this.getDataImportEngine().generateTemplate(templateInfo); |
| | | try { |
| | | this.downloadSimpleFile(FileCopyUtils.copyToByteArray(templateFile), templateFileName); |
| | | } catch (IOException e) { |
| | | logger.error("下载模板错误:" + e.getMessage() + ", tableName=" + tableName, e); |
| | | ServletUtils.renderString(getResponse(), "下载模板错误:" + e.getMessage() + ", tableName=" + tableName); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 返回数据字典缓存对象。<p></p> |
| | | * 注意:这种写法后续要改掉,统一由平台自动注入,无需单独设置。 |
| | | * @return |
| | | * @date 2023-03-10 |
| | | */ |
| | | protected DictCacheProvider getDictCacheProvider(){ |
| | | // if(this.dictCacheProvider == null){ |
| | | // this.dictCacheProvider = BeanContextAware.getBeanByType(DictCacheProvider.class); |
| | | // } |
| | | return this.dictCacheProvider; |
| | | } |
| | | |
| | | /** |
| | | * 返回数据导入引擎实现对象,用来完成 Excel 导入功能。 |
| | | * @return |
| | | * @date 2023-02-07 |
| | | */ |
| | | protected PlatformDataImportEngine getDataImportEngine(){ |
| | | // return BeanContextAware.getBeanByType(PlatformDataImportEngine.class); |
| | | return this.platformDataImportEngine; |
| | | } |
| | | |
| | | public UserCacheProvider getUserCacheProvider() { |
| | | // if(this.userCacheProvider == null){ |
| | | // this.userCacheProvider = BeanContextAware.getBeanByType(UserCacheProvider.class); |
| | | // } |
| | | return userCacheProvider; |
| | | } |
| | | |
| | | public DeptCacheProvider getDeptCacheProvider() { |
| | | // if(this.deptCacheProvider == null){ |
| | | // this.deptCacheProvider = BeanContextAware.getBeanByType(DeptCacheProvider.class); |
| | | // } |
| | | return deptCacheProvider; |
| | | } |
| | | |
| | | /** |
| | | * 返回给定用户的顶级机构ID。 |
| | | * @param userId |
| | | * @return |
| | | * @date 2022-12-15 |
| | | */ |
| | | protected long getUserRootOrgId(long userId){ |
| | | this.checkUserCacheProvider(); |
| | | S_user_core user_core = this.userCacheProvider.getUser(userId); |
| | | if(user_core == null){ |
| | | throw new IllegalStateException("缓存中未找到用户: " + userId); |
| | | } |
| | | return user_core.getOrg_id(); |
| | | } |
| | | |
| | | /** |
| | | * 根据机构(部门等非顶级ID)返回顶级机构ID。 |
| | | * @param deptId |
| | | * @return |
| | | * @date 2022-12-12 |
| | | */ |
| | | protected long getRootOrgIdByDept(long deptId){ |
| | | if(this.deptCacheProvider == null){ |
| | | throw new IllegalArgumentException("请先设置controller对象: deptCacheProvider"); |
| | | } |
| | | S_dept dept = this.deptCacheProvider.getDept(deptId); |
| | | if(dept == null){ |
| | | throw new IllegalStateException("缓存中未找到机构: " + deptId); |
| | | } |
| | | return dept.getOrg_id(); |
| | | } |
| | | |
| | | /** |
| | | * 返回当前登录用户可选择的根机构列表,即:第一级机构,通常是集团公司等。<p></p> |
| | | * 这些也称为多租户,系统提供多单位(独立)维护,不同独立单位由各自管理员自行维护。 |
| | | * <pre> |
| | | * 1.超级管理员可以看到所有独立机构列表 |
| | | * 2.单位用户只能看到本单位(一个机构) |
| | | * </pre> |
| | | * @return |
| | | * @date 2022-12-01 |
| | | */ |
| | | protected List<S_dept> getOrgListScope(){ |
| | | DeptServiceImpl deptService = BeanContextAware.getBeanByType(DeptServiceImpl.class); |
| | | S_user_core currentUser = this.getCurrentUser(); |
| | | List<S_dept> list = null; |
| | | if(currentUser.getUser_type().intValue() == UserType.TYPE_SUPER){ |
| | | list = deptService.queryRootOrgList(0); |
| | | } else { |
| | | list = deptService.queryRootOrgList(currentUser.getOrg_id().longValue()); |
| | | } |
| | | if(StringUtils.isEmptyList(list)){ |
| | | // 不存在任何机构(数据库没有记录),需要创建默认机构 |
| | | list = new ArrayList<>(2); |
| | | list.add(this.createDefaultOrg()); |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | private void checkUserCacheProvider(){ |
| | | if(this.userCacheProvider == null){ |
| | | throw new IllegalStateException("UserCacheProvider 必须先设置到控制器中。"); |
| | | } |
| | | } |
| | | |
| | | private S_dept createDefaultOrg(){ |
| | | S_dept root = new S_dept(); |
| | | root.setId(0L); |
| | | root.setParent_id(0L); |
| | | root.setOrg_type(OrgType.TYPE_ORG); |
| | | root.setOrder_num(1); |
| | | root.setDept_name(Constants.DEFAULT_ORG_NAME); |
| | | return root; |
| | | } |
| | | |
| | | public void setDeptCacheProvider(DeptCacheProvider deptCacheProvider) { |
| | | this.deptCacheProvider = deptCacheProvider; |
| | | } |
| | | |
| | | public void setUserCacheProvider(UserCacheProvider userCacheProvider) { |
| | | this.userCacheProvider = userCacheProvider; |
| | | } |
| | | |
| | | public void setPlatformDataImportEngine(PlatformDataImportEngine platformDataImportEngine) { |
| | | this.platformDataImportEngine = platformDataImportEngine; |
| | | } |
| | | |
| | | public void setDictCacheProvider(DictCacheProvider dictCacheProvider) { |
| | | this.dictCacheProvider = dictCacheProvider; |
| | | } |
| | | |
| | | public void setPushManager(PushManager pushManager) { |
| | | this.pushManager = pushManager; |
| | | } |
| | | |
| | | public void setSmsCaptchaProvider(CaptchaProvider<CaptchaResult> smsCaptchaProvider) { |
| | | this.smsCaptchaProvider = smsCaptchaProvider; |
| | | } |
| | | |
| | | public void setCaptchaCacheProvider(CacheProvider<String> captchaCacheProvider) { |
| | | this.captchaCacheProvider = captchaCacheProvider; |
| | | } |
| | | |
| | | public CaptchaProvider<CaptchaResult> getSmsCaptchaProvider() { |
| | | return smsCaptchaProvider; |
| | | } |
| | | |
| | | public CacheProvider<String> getCaptchaCacheProvider() { |
| | | return captchaCacheProvider; |
| | | } |
| | | |
| | | protected UserServiceImpl getUserService(){ |
| | | return BeanContextAware.getBeanByType(UserServiceImpl.class); |
| | | } |
| | | |
| | | private CaptchaProvider<CaptchaResult> smsCaptchaProvider; |
| | | private CacheProvider<String> captchaCacheProvider; |
| | | |
| | | /** |
| | | * 返回推送管理器对象,只有在特殊情况下需要业务直接调用该对象。 |
| | | * @return |
| | | * @date 2023-04-25 |
| | | */ |
| | | protected PushManager getPushManager() { |
| | | return pushManager; |
| | | } |
| | | |
| | | private PushManager pushManager; |
| | | private DeptCacheProvider deptCacheProvider; |
| | | private UserCacheProvider userCacheProvider; |
| | | private PlatformDataImportEngine platformDataImportEngine; |
| | | private DictCacheProvider dictCacheProvider; |
| | | |
| | | @Override |
| | | public void afterPropertiesSet() throws Exception {} |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.iplatform.model.vo.SystemGroupVo; |
| | | |
| | | /** |
| | | * 系统分组数据缓存定义,目前主要电商模块使用。 |
| | | * <p>后续其他模块都可以作为标准化功能使用。</p> |
| | | * @author 时克英 |
| | | * @date 2023-06-23 |
| | | */ |
| | | public interface SystemGroupCache { |
| | | |
| | | SystemGroupVo get(int id); |
| | | |
| | | void save(SystemGroupVo category); |
| | | |
| | | void update(SystemGroupVo category); |
| | | |
| | | void remove(int id); |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.iplatform.base.exception.LoginException; |
| | | import com.iplatform.base.pojo.RequestLogin; |
| | | |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 第三方登录(集成)认证。 |
| | | * <pre> |
| | | * 1)该接口主要用于第三方系统直接登录平台方式。 |
| | | * 2)第三方传递给平台相关参数,然后平台直接登录并生成token给前端。 |
| | | * </pre> |
| | | * @date 2023-07-03 |
| | | */ |
| | | public interface ThirdPartyAuthentication { |
| | | |
| | | /** |
| | | * 调用第三方认证接口,依据参数获得用户详细信息(以便于转换成平台用户身份) |
| | | * @param parameter 第三方提供的参数 |
| | | * @return 返回平台登录参数,请求统一登录地址完成(无感)登录 |
| | | * @throws LoginException 如果错误抛出异常 |
| | | * @date 2023-07-03 |
| | | */ |
| | | RequestLogin authenticate(Map<String, Object> parameter) throws LoginException; |
| | | |
| | | /** |
| | | * 返回认证的唯一标识(或名称) |
| | | * @return |
| | | */ |
| | | String getName(); |
| | | |
| | | /** |
| | | * 返回认证对象的描述。 |
| | | * @return |
| | | */ |
| | | String getDescription(); |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import java.util.Map; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | |
| | | /** |
| | | * 第三方管理器默认实现。 |
| | | * @author 时克英 |
| | | * @date 2023-07-03 |
| | | */ |
| | | public class ThirdPartyManager { |
| | | |
| | | protected final transient Logger logger = LoggerFactory.getLogger(this.getClass()); |
| | | |
| | | private final Map<String, ThirdPartyAuthentication> authenticationMap = new ConcurrentHashMap<>(8); |
| | | |
| | | /** |
| | | * 注册一个第三方认证对象到平台。 |
| | | * <pre> |
| | | * 1)其中,name属性通常是第三方请求登录路径中的后缀部分,如:/third_party/login/aaa |
| | | * 2)平台支持多种第三方认证同时使用,只要在业务中注册即可。 |
| | | * </pre> |
| | | * @param thirdPartyAuthentication |
| | | * @date 2023-07-03 |
| | | */ |
| | | public void register(ThirdPartyAuthentication thirdPartyAuthentication){ |
| | | if(thirdPartyAuthentication == null){ |
| | | throw new IllegalArgumentException("注册第三方认证对象为空"); |
| | | } |
| | | String key = thirdPartyAuthentication.getName(); |
| | | if(StringUtils.isEmpty(key)){ |
| | | throw new IllegalArgumentException("自定义第三方认证对象名称不存在:getName()"); |
| | | } |
| | | if(this.authenticationMap.get(key) != null){ |
| | | throw new IllegalArgumentException("已经存在第三方认证定义:" + key); |
| | | } |
| | | this.authenticationMap.put(key, thirdPartyAuthentication); |
| | | logger.info("注册'第三方认证对象' = " + key + ", " + thirdPartyAuthentication.getDescription()); |
| | | } |
| | | |
| | | /** |
| | | * 返回一个第三方认证对象 |
| | | * @param key 认证对象的名称,参考:{@linkplain ThirdPartyAuthentication#getName()} |
| | | * @return |
| | | * @date 2023-07-03 |
| | | */ |
| | | public ThirdPartyAuthentication getThirdPartyAuthentication(String key){ |
| | | if(StringUtils.isEmpty(key)){ |
| | | throw new IllegalArgumentException("请提供第三方认证标识"); |
| | | } |
| | | return this.authenticationMap.get(key); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.iplatform.model.po.S_user_core; |
| | | |
| | | /** |
| | | * 用户缓存统一抽象,针对 Redis 或 内存做不同实现。 |
| | | * @author 时克英 |
| | | * @date 2022-12-13 |
| | | */ |
| | | public interface UserCacheProvider { |
| | | |
| | | /** |
| | | * 根据登录id查找缓存用户,如果不存在需要先初始化加载数据库。 |
| | | * @param loginId |
| | | * @return |
| | | * @date 2024-03-06 |
| | | */ |
| | | S_user_core getUserByLoginId(String loginId); |
| | | |
| | | S_user_core getUser(long userId); |
| | | |
| | | void updateUser(S_user_core user_core); |
| | | |
| | | void removeUser(long userId); |
| | | |
| | | void putUser(S_user_core user_core); |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.iplatform.model.po.S_user_login; |
| | | |
| | | /** |
| | | * 用户登录记录缓存定义。 |
| | | * <p>每个登录ID只会存在一条记录。</p> |
| | | * @author 时克英 |
| | | * @date 2023-07-11 |
| | | */ |
| | | public interface UserLoginCache { |
| | | |
| | | S_user_login getUserLogin(String loginId); |
| | | |
| | | void updateUserLogin(S_user_login user_login); |
| | | |
| | | void removeUserLogin(String loginId); |
| | | |
| | | void putUserLogin(S_user_login user_login); |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | /** |
| | | * 系统可配置的参数变量临时定义,等配置参数功能好了需要替换为动态参数: ArgumentsManager. |
| | | * @date 2022-11-02 |
| | | */ |
| | | @Deprecated |
| | | public class VariableConstants { |
| | | |
| | | /** |
| | | * token签名密钥 |
| | | */ |
| | | public static final String TOKEN_SECRET = "Ha2rEvsXPWovJH2y760OZUlzUOAx1dSnqYB9x1NWHwkGk0SqLn9divY8Rho+/tFkCKXSkUDFtwVmw9TuMbchyzJmlOAoXyDLd27lAo+Byhlysm71/mCOoLfAQIDAQAB"; |
| | | |
| | | // /** |
| | | // * 是否打开验证码选项 |
| | | // */ |
| | | // public static final boolean CAPTCHA_ENABLED = true; |
| | | |
| | | /** |
| | | * 创建token默认过期时间(分钟)<br> |
| | | * @date 2023-12-29 修改保底时间,尽量大一些,避免业务配置了10天,但缓存却太短数据已经不存在了! |
| | | */ |
| | | public static final long DEFAULT_TOKEN_EXPIRED_MINUTES = 60 * 24 * 30; |
| | | |
| | | // /** |
| | | // * 缓存用户登录时间(秒) |
| | | // */ |
| | | // public static final long DEFAULT_CACHE_USER_SECONDS = 3600; |
| | | |
| | | /** |
| | | * 缓存管理中,默认能显示的缓存明细记录数量,因为在redis方式下,缓存数量可能太大而无法展示。 |
| | | * @date 2023-01-05 |
| | | */ |
| | | public static final long MAX_CACHE_SHOW = 256; |
| | | |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | import com.fasterxml.jackson.databind.node.ObjectNode; |
| | | import com.iplatform.base.util.NotificationUtils; |
| | | import com.iplatform.base.util.RestTemplateUtils; |
| | | import com.iplatform.core.BeanContextAware; |
| | | import com.iplatform.model.vo.NotificationTemplateVo; |
| | | import com.iplatform.model.vo.WeChatAccessTokenVo; |
| | | import com.walker.infrastructure.arguments.Variable; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.push.Notification; |
| | | import org.springframework.web.client.RestTemplate; |
| | | |
| | | import java.text.MessageFormat; |
| | | import java.util.List; |
| | | |
| | | public abstract class WechatBaseController extends PlatformAdapterController{ |
| | | |
| | | // public void setRestTemplate(RestTemplate restTemplate) { |
| | | // this.restTemplate = restTemplate; |
| | | // } |
| | | // private RestTemplate restTemplate; |
| | | |
| | | /** |
| | | * 平台统一根据模板,发送提醒通知。 |
| | | * @param mark 通知标识,如:发货、订单等,从:sf_notification 表查询 |
| | | * @param variableList 业务数据,key,value |
| | | * @param userId 用户ID |
| | | * @date 2023-08-25 |
| | | */ |
| | | protected void pushNotificationWithTemplate(String mark, List<Variable> variableList, long userId){ |
| | | if(StringUtils.isEmpty(mark)){ |
| | | throw new IllegalArgumentException("必须输入通知模板标记:mark"); |
| | | } |
| | | if(StringUtils.isEmptyList(variableList)){ |
| | | throw new IllegalArgumentException("必须输入推送消息业务数据:variableList"); |
| | | } |
| | | NotificationTemplateVo templateVo = this.getNotificationTemplateCache().get(mark); |
| | | if(templateVo == null){ |
| | | logger.error("通知模板缓存不存在,mark={}", mark); |
| | | return; |
| | | } |
| | | |
| | | // 1:存在微信公众号推送方式 |
| | | if(templateVo.getWechat()){ |
| | | String openId = this.getUser(userId).getWx_open_id(); |
| | | if(StringUtils.isEmpty(openId)){ |
| | | logger.error("用户openId为空,无法发送微信公众号通知, userId={}", userId); |
| | | return; |
| | | } |
| | | String accessToken = this.acquirePublicAccessToken(); |
| | | if(StringUtils.isEmpty(accessToken)){ |
| | | logger.error("推送公众号消息失败,accessToken获取为空,mark={}, userId={}", mark, userId); |
| | | return; |
| | | } |
| | | |
| | | Notification notification = NotificationUtils.acquireWechatNotification(accessToken |
| | | , templateVo.getWechatTempId(), openId, variableList); |
| | | this.getPushManager().push(notification, null); |
| | | } |
| | | |
| | | // 2:存在短信推送 |
| | | if(templateVo.getSms()){ |
| | | String userPhone = this.getUser(userId).getPhonenumber(); |
| | | if(StringUtils.isEmpty(userPhone)){ |
| | | logger.error("用户手机号为空,无法发送短信通知, userId={}", userId); |
| | | return; |
| | | } |
| | | Notification smsNotification = NotificationUtils.acquireSmsNotification(templateVo.getSmsTempId(), userPhone, variableList, "短信通知"); |
| | | this.getPushManager().push(smsNotification, null); |
| | | } |
| | | |
| | | // 3:存在微信小程序推送方式 |
| | | if(templateVo.getRoutine()){ |
| | | throw new UnsupportedOperationException("未实现微信小程序消息通知"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获取微信小程序(access_token),并设置缓存。 |
| | | * @return |
| | | * @date 2023-09-16 |
| | | */ |
| | | protected String acquireMiniAccessToken(){ |
| | | String appId = this.getArgumentVariable(WechatConstants.WECHAT_MINI_APPID).getStringValue(); |
| | | if(StringUtils.isEmpty(appId)){ |
| | | throw new PlatformRuntimeException("请先配置微信参数:小程序appid"); |
| | | } |
| | | String miniAccessToken = this.getWechatCache().getMiniAccessToken(); |
| | | if(StringUtils.isNotEmpty(miniAccessToken)){ |
| | | logger.debug("缓存中已有'access_token':{}", miniAccessToken); |
| | | return miniAccessToken; |
| | | } |
| | | |
| | | String secret = this.getArgumentVariable(WechatConstants.WECHAT_MINI_APPSECRET).getStringValue(); |
| | | if (StringUtils.isEmpty(secret)) { |
| | | throw new PlatformRuntimeException("微信小程序secret未设置"); |
| | | } |
| | | // String url = MessageFormat.format(WechatConstants.WECHAT_ACCESS_TOKEN_URL, appId, secret); |
| | | // logger.debug("url = {}", url); |
| | | // ObjectNode objectNode = RestTemplateUtils.getData(url, BeanContextAware.getBeanByType(RestTemplate.class)); |
| | | // if(objectNode == null){ |
| | | // throw new PlatformRuntimeException("微信平台接口异常,没任何数据返回!"); |
| | | // } |
| | | // logger.debug(objectNode.toString()); |
| | | ObjectNode objectNode = this.acquireAccessTokenNode(appId, secret); |
| | | WeChatAccessTokenVo accessTokenVo = null; |
| | | |
| | | try { |
| | | // if (objectNode.has("errcode") && !objectNode.get("errcode").asText().equals("0")) { |
| | | // if (objectNode.has("errmsg")) { |
| | | // // 保存到微信异常表 |
| | | //// wxExceptionDispose(data, StrUtil.format("微信获取accessToken异常,{}端", type)); |
| | | // throw new PlatformRuntimeException("微信接口调用失败:" + objectNode.get("errcode") + objectNode.get("errmsg")); |
| | | // } |
| | | // } |
| | | this.checkStatusError(objectNode); |
| | | accessTokenVo = new WeChatAccessTokenVo(); |
| | | accessTokenVo.setAccessToken(objectNode.get("access_token").asText()); |
| | | accessTokenVo.setExpiresIn(objectNode.get("expires_in").asInt()); |
| | | // accessTokenVo = JsonUtils.jsonStringToObject(result, WeChatAccessTokenVo.class); |
| | | this.getWechatCache().putMiniAccessToken(accessTokenVo.getAccessToken(), accessTokenVo.getExpiresIn().longValue() - 1800L); |
| | | logger.info("调用一次微信远程接口获取'mini_accessToken',并缓存:{}", accessTokenVo.getAccessToken()); |
| | | return accessTokenVo.getAccessToken(); |
| | | |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("json字符串转对象错误:" + objectNode, e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获取微信公众号(普通)access_token |
| | | * @return |
| | | * @date 2023-08-23 |
| | | */ |
| | | protected String acquirePublicAccessToken( |
| | | // String appId, String type |
| | | ){ |
| | | String appId = this.getArgumentVariable(WechatConstants.WECHAT_PUBLIC_APPID).getStringValue(); |
| | | if(StringUtils.isEmpty(appId)){ |
| | | throw new PlatformRuntimeException("请先配置微信参数:公众号appid"); |
| | | } |
| | | String publicAccessToken = this.getWechatCache().getPublicAccessToken(); |
| | | if(StringUtils.isNotEmpty(publicAccessToken)){ |
| | | logger.debug("缓存中已有'access_token':{}", publicAccessToken); |
| | | return publicAccessToken; |
| | | } |
| | | String secret = this.getArgumentVariable(WechatConstants.WECHAT_PUBLIC_APPSECRET).getStringValue(); |
| | | if (StringUtils.isEmpty(secret)) { |
| | | throw new PlatformRuntimeException("微信公众号secret未设置"); |
| | | } |
| | | |
| | | // String url = MessageFormat.format(WechatConstants.WECHAT_ACCESS_TOKEN_URL, appId, secret); |
| | | // logger.debug("url = {}", url); |
| | | // ObjectNode objectNode = RestTemplateUtils.getData(url, BeanContextAware.getBeanByType(RestTemplate.class)); |
| | | // if(objectNode == null){ |
| | | // throw new PlatformRuntimeException("微信平台接口异常,没任何数据返回!"); |
| | | // } |
| | | // logger.debug(objectNode.toString()); |
| | | ObjectNode objectNode = this.acquireAccessTokenNode(appId, secret); |
| | | WeChatAccessTokenVo accessTokenVo = null; |
| | | try { |
| | | // if (objectNode.has("errcode") && !objectNode.get("errcode").asText().equals("0")) { |
| | | // if (objectNode.has("errmsg")) { |
| | | // // 保存到微信异常表 |
| | | //// wxExceptionDispose(data, StrUtil.format("微信获取accessToken异常,{}端", type)); |
| | | // throw new PlatformRuntimeException("微信接口调用失败:" + objectNode.get("errcode") + objectNode.get("errmsg")); |
| | | // } |
| | | // } |
| | | this.checkStatusError(objectNode); |
| | | accessTokenVo = new WeChatAccessTokenVo(); |
| | | accessTokenVo.setAccessToken(objectNode.get("access_token").asText()); |
| | | accessTokenVo.setExpiresIn(objectNode.get("expires_in").asInt()); |
| | | // accessTokenVo = JsonUtils.jsonStringToObject(result, WeChatAccessTokenVo.class); |
| | | this.getWechatCache().putPublicAccessToken(accessTokenVo.getAccessToken(), accessTokenVo.getExpiresIn().longValue() - 1800L); |
| | | logger.info("调用一次微信远程接口获取'public_accessToken',并缓存:{}", accessTokenVo.getAccessToken()); |
| | | return accessTokenVo.getAccessToken(); |
| | | |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("json字符串转对象错误:" + objectNode, e); |
| | | } |
| | | } |
| | | |
| | | private ObjectNode acquireAccessTokenNode(String appId, String secret){ |
| | | String url = MessageFormat.format(WechatConstants.WECHAT_ACCESS_TOKEN_URL, appId, secret); |
| | | logger.debug("url = {}", url); |
| | | ObjectNode objectNode = RestTemplateUtils.getData(url, BeanContextAware.getBeanByType(RestTemplate.class)); |
| | | if(objectNode == null){ |
| | | throw new PlatformRuntimeException("微信平台接口异常,没任何数据返回!"); |
| | | } |
| | | logger.debug(objectNode.toString()); |
| | | return objectNode; |
| | | } |
| | | |
| | | private void checkStatusError(ObjectNode objectNode){ |
| | | // ObjectNode objectNode = JsonUtils.jsonStringToObjectNode(result); |
| | | if (objectNode.has("errcode") && !objectNode.get("errcode").asText().equals("0")) { |
| | | if (objectNode.has("errmsg")) { |
| | | // 保存到微信异常表 |
| | | // wxExceptionDispose(data, StrUtil.format("微信获取accessToken异常,{}端", type)); |
| | | throw new PlatformRuntimeException("微信接口调用失败:" + objectNode.get("errcode") + objectNode.get("errmsg")); |
| | | } else { |
| | | throw new PlatformRuntimeException("微信接口调用失败:" + objectNode.get("errcode")); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 返回微信基础配置缓存对象。 |
| | | * @return |
| | | * @date 2023-08-23 |
| | | */ |
| | | protected WechatCacheProvider getWechatCache(){ |
| | | return BeanContextAware.getBeanByType(WechatCacheProvider.class); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | /** |
| | | * 微信登录相关配置缓存,目前:ticket、普通 access_token |
| | | * @author 时克英 |
| | | * @date 2023-08-23 从电商模块迁移到 base |
| | | */ |
| | | public interface WechatCacheProvider { |
| | | |
| | | /** |
| | | * 获取小程序access_token,生成小程序二维码使用。 |
| | | * @return |
| | | * @date 2023-09-16 |
| | | */ |
| | | String getMiniAccessToken(); |
| | | |
| | | /** |
| | | * 返回:JS-SDK的ticket, |
| | | * @return |
| | | */ |
| | | String getJsApiTicket(); |
| | | |
| | | /** |
| | | * 获取公共(公众号)accessToken |
| | | * @return |
| | | * @date 2023-07-16 |
| | | */ |
| | | String getPublicAccessToken(); |
| | | |
| | | /** |
| | | * 设置公共(公众号)accessToken,<p>缓存时间:accessTokenVo.getExpiresIn().longValue() - 1800L</p> |
| | | * @param value |
| | | * @date 2023-07-16 |
| | | */ |
| | | void putPublicAccessToken(String value, long expiredSeconds); |
| | | |
| | | /** |
| | | * 缓存ticket,默认:7100 秒后过期。 |
| | | * @param value |
| | | */ |
| | | void putJsApiTicket(String value); |
| | | |
| | | /** |
| | | * 设置(小程序)accessToken,<p>缓存时间:accessTokenVo.getExpiresIn().longValue() - 1800L</p> |
| | | * @param value |
| | | * @param expiredSeconds |
| | | * @date 2023-09-16 |
| | | */ |
| | | void putMiniAccessToken(String value, long expiredSeconds); |
| | | |
| | | /** |
| | | * 删除(小程序)accessToken. |
| | | * @date 2023-09-16 |
| | | */ |
| | | void removeMiniAccessToken(); |
| | | } |
New file |
| | |
| | | package com.iplatform.base; |
| | | |
| | | public class WechatConstants { |
| | | |
| | | /** 微信token类型-公众号 */ |
| | | public static final String WECHAT_TOKEN_TYPE_PUBLIC = "public"; |
| | | /** 微信token类型-小程序 */ |
| | | public static final String WECHAT_TOKEN_TYPE_MINI = "mini"; |
| | | /** 微信token类型-APP */ |
| | | public static final String WECHAT_TOKEN_TYPE_APP = "app"; |
| | | |
| | | //-------------------------------------------微信系统配置------------------------------------------------------------ |
| | | /** 公众号appId key */ |
| | | public static final String WECHAT_PUBLIC_APPID = "wechat_appid"; |
| | | /** 公众号appSecret key */ |
| | | public static final String WECHAT_PUBLIC_APPSECRET = "wechat_appsecret"; |
| | | /** 小程序appId key */ |
| | | public static final String WECHAT_MINI_APPID = "routine_appid"; |
| | | /** 小程序appSecret key */ |
| | | public static final String WECHAT_MINI_APPSECRET = "routine_appsecret"; |
| | | /** 小程序 名称 */ |
| | | public static final String WECHAT_MINI_NAME = "routine_name"; |
| | | |
| | | /** 公众号 支付商户号 */ |
| | | public static final String WECHAT_PAY_PUBLIC_MCHID = "pay_weixin_mchid"; |
| | | /** 公众号 支付key */ |
| | | public static final String WECHAT_PAY_PUBLIC_KEY = "pay_weixin_key"; |
| | | /** 公众号 支付证书地址 */ |
| | | public static final String WECHAT_PAY_PUBLIC_CERTIFICATE_PATH = "pay_weixin_certificate_path"; |
| | | /** 小程序 支付商户号 */ |
| | | public static final String WECHAT_PAY_MINI_MCHID = "pay_routine_mchid"; |
| | | /** 小程序 支付key */ |
| | | public static final String WECHAT_PAY_MINI_KEY = "pay_routine_key"; |
| | | /** 小程序 支付证书地址 */ |
| | | public static final String WECHAT_PAY_MINI_CERTIFICATE_PATH = "pay_routine_certificate_path"; |
| | | |
| | | /** 微信app appId */ |
| | | public static final String WECHAT_APP_APPID = "wechat_app_appid"; |
| | | /** 微信app 商户号 */ |
| | | public static final String WECHAT_PAY_APP_MCHID = "pay_weixin_app_mchid"; |
| | | /** 微信app 支付key */ |
| | | public static final String WECHAT_PAY_APP_KEY = "pay_weixin_app_key"; |
| | | /** 微信app 支付证书地址 */ |
| | | public static final String WECHAT_PAY_APP_CERTIFICATE_PATH = "pay_weixin_app_certificate_path"; |
| | | |
| | | //------------------------------------------------微信公众号------------------------------------------------ |
| | | //微信接口请求地址 |
| | | public static final String API_URL = "https://api.weixin.qq.com/"; |
| | | //获取token |
| | | public static final String API_TOKEN_URI = "cgi-bin/token?grant_type=client_credential"; |
| | | // 微信token 过期时间,娶了一个中间值 4000 官方的7200不靠谱 |
| | | public static final Long API_TOKEN_EXPIRES = 3000L; |
| | | //微信公众号菜单创建 |
| | | public static final String PUBLIC_API_MENU_CREATE_URI = "cgi-bin/menu/create"; |
| | | //微信公众号菜单获取 |
| | | public static final String PUBLIC_API_MENU_GET_URI = "cgi-bin/menu/get"; |
| | | //微信公众号菜单删除 |
| | | public static final String PUBLIC_API_MENU_DELETE_URI = "cgi-bin/menu/delete"; |
| | | //微信公众号,获取自定义菜单配置接口 |
| | | public static final String PUBLIC_API_MENU_SELF_SET_URI = "cgi-bin/get_current_selfmenu_info"; |
| | | //微信公众号,创建个性化菜单 |
| | | public static final String PUBLIC_API_MENU_ADD_CONDITIONAL_URI = "cgi-bin/menu/addconditional"; |
| | | //微信公众号,删除个性化菜单 |
| | | public static final String PUBLIC_API_MENU_DEL_CONDITIONAL_URI = "cgi-bin/menu/delconditional"; |
| | | //微信公众号,测试个性化菜单匹配结果 |
| | | public static final String PUBLIC_API_USER_INFO_URI = "cgi-bin/menu/trymatch"; |
| | | //获取公众号已创建的标签 |
| | | public static final String PUBLIC_API_TAG_LIST_URI = "cgi-bin/tags/get"; |
| | | //创建标签 |
| | | public static final String PUBLIC_API_TAG_CREATE_URI = "cgi-bin/tags/create"; |
| | | //编辑标签 |
| | | public static final String PUBLIC_API_TAG_UPDATE_URI = "cgi-bin/tags/update"; |
| | | //删除标签 |
| | | public static final String PUBLIC_API_TAG_DELETE_URI = "cgi-bin/tags/delete"; |
| | | //获取标签下粉丝列表 |
| | | public static final String PUBLIC_API_TAG_USER_GET_URI = "cgi-bin/user/tag/get"; |
| | | //批量为用户打标签 |
| | | public static final String PUBLIC_API_TAG_MEMBER_BATCH_URI = "cgi-bin/tags/members/batchtagging"; |
| | | //批量为用户取消标签 |
| | | public static final String PUBLIC_API_TAG_MEMBER_BATCH_UN_URI = "cgi-bin/tags/members/batchuntagging"; |
| | | //获取用户身上的标签列表 |
| | | public static final String PUBLIC_API_TAG_GET_ID_LIST_URI = "cgi-bin/tags/getidlist"; |
| | | //获取 JsApiTicket |
| | | public static final String PUBLIC_API_JS_API_TICKET = "cgi-bin/ticket/getticket"; |
| | | //发送公众号模板消息 |
| | | public static final String PUBLIC_API_PUBLIC_TEMPLATE_MESSAGE_SEND = "cgi-bin/message/template/send"; |
| | | //获取设置的行业信息 |
| | | public static final String PUBLIC_API_TEMPLATE_MESSAGE_INDUSTRY = "cgi-bin/template/get_industry"; |
| | | //新增其他类型永久素材 |
| | | public static final String PUBLIC_API_MEDIA_UPLOAD = "cgi-bin/material/add_material"; |
| | | //获取永久素材 |
| | | public static final String PUBLIC_API_MEDIA_GET = "cgi-bin/material/get_material"; |
| | | //获取微信素材总数 |
| | | public static final String PUBLIC_API_MEDIA_COUNT = "cgi-bin/material/get_materialcount"; |
| | | //发送客服消息 |
| | | public static final String PUBLIC_API_KF_MESSAGE_SEND = "cgi-bin/message/custom/send"; |
| | | |
| | | |
| | | //------------------------------------------------微信小程序------------------------------------------------ |
| | | //小程序行业消息 |
| | | public static final String PUBLIC_API_PROGRAM_CATEGORY = "wxaapi/newtmpl/getcategory"; |
| | | //小程序公共模板库 |
| | | public static final String PUBLIC_API_PROGRAM_PUBLIC_TEMP = "wxaapi/newtmpl/getpubtemplatetitles"; |
| | | //小程序模板关键词列表 |
| | | public static final String PUBLIC_API_PROGRAM_PUBLIC_TEMP_KEYWORDS = "wxaapi/newtmpl/getpubtemplatekeywords"; |
| | | //添加小程序订阅消息 |
| | | public static final String PUBLIC_API_ADD_PROGRAM_TEMPLATE = "wxaapi/newtmpl/addtemplate"; |
| | | //删除小程序订阅消息 |
| | | public static final String PUBLIC_API_DELETE_PROGRAM_TEMPLATE = "wxaapi/newtmpl/deltemplate"; |
| | | //发送小程序模板消息 |
| | | public static final String PUBLIC_API_PROGRAM_TEMPLATE_MESSAGE_SEND = "cgi-bin/message/subscribe/send"; |
| | | |
| | | //授权登录 |
| | | |
| | | //获取临时code跳转地址 |
| | | public static final String WE_CHAT_AUTHORIZE_REDIRECT_URI_URL = "/api/front/wechat/authorize/login"; |
| | | |
| | | //获取openId |
| | | public static final String WE_CHAT_AUTHORIZE_GET_OPEN_ID = "sns/oauth2/access_token"; |
| | | |
| | | //获取小程序openId |
| | | public static final String WE_CHAT_AUTHORIZE_PROGRAM_GET_OPEN_ID = "sns/jscode2session"; |
| | | |
| | | //获取用户信息 |
| | | public static final String WE_CHAT_AUTHORIZE_GET_USER_INFO = "sns/userinfo"; |
| | | |
| | | //生成二维码 |
| | | public static final String WE_CHAT_CREATE_QRCODE = "wxa/getwxacodeunlimit"; |
| | | |
| | | //微信消息存储队列 |
| | | public static final String WE_CHAT_MESSAGE_SEND_KEY = "we_chat_message_send_list"; |
| | | |
| | | //大家注意这里消息类型的定义,以 RESP 开头的表示返回的消息类型,以 REQ 表示微信服务器发来的消息类型 |
| | | /** |
| | | * 返回消息类型:文本 |
| | | */ |
| | | public static final String WE_CHAT_MESSAGE_RESP_MESSAGE_TYPE_TEXT = "text"; |
| | | /** |
| | | * 返回消息类型:音乐 |
| | | */ |
| | | public static final String WE_CHAT_MESSAGE_RESP_MESSAGE_TYPE_MUSIC = "music"; |
| | | /** |
| | | * 返回消息类型:图文 |
| | | */ |
| | | public static final String WE_CHAT_MESSAGE_RESP_MESSAGE_TYPE_NEWS = "news"; |
| | | /** |
| | | * 返回消息类型:图片 |
| | | */ |
| | | public static final String WE_CHAT_MESSAGE_RESP_MESSAGE_TYPE_IMAGE = "image"; |
| | | /** |
| | | * 返回消息类型:语音 |
| | | */ |
| | | public static final String WE_CHAT_MESSAGE_RESP_MESSAGE_TYPE_VOICE = "voice"; |
| | | /** |
| | | * 返回消息类型:视频 |
| | | */ |
| | | public static final String WE_CHAT_MESSAGE_RESP_MESSAGE_TYPE_VIDEO = "video"; |
| | | /** |
| | | * 请求消息类型:文本 |
| | | */ |
| | | public static final String WE_CHAT_MESSAGE_REQ_MESSAGE_TYPE_TEXT = "text"; |
| | | /** |
| | | * 请求消息类型:图片 |
| | | */ |
| | | public static final String WE_CHAT_MESSAGE_REQ_MESSAGE_TYPE_IMAGE = "image"; |
| | | /** |
| | | * 请求消息类型:链接 |
| | | */ |
| | | public static final String WE_CHAT_MESSAGE_REQ_MESSAGE_TYPE_LINK = "link"; |
| | | /** |
| | | * 请求消息类型:地理位置 |
| | | */ |
| | | public static final String WE_CHAT_MESSAGE_REQ_MESSAGE_TYPE_LOCATION = "location"; |
| | | /** |
| | | * 请求消息类型:音频 |
| | | */ |
| | | public static final String WE_CHAT_MESSAGE_REQ_MESSAGE_TYPE_VOICE = "voice"; |
| | | /** |
| | | * 请求消息类型:视频 |
| | | */ |
| | | public static final String WE_CHAT_MESSAGE_REQ_MESSAGE_TYPE_VIDEO = "video"; |
| | | /** |
| | | * 请求消息类型:推送 |
| | | */ |
| | | public static final String WE_CHAT_MESSAGE_REQ_MESSAGE_TYPE_EVENT = "event"; |
| | | /** |
| | | * 事件类型:subscribe(订阅) |
| | | */ |
| | | public static final String WE_CHAT_MESSAGE_EVENT_TYPE_SUBSCRIBE = "subscribe"; |
| | | /** |
| | | * 事件类型:unsubscribe(取消订阅) |
| | | */ |
| | | public static final String WE_CHAT_MESSAGE_EVENT_TYPE_UNSUBSCRIBE = "unsubscribe"; |
| | | /** |
| | | * 事件类型:CLICK(自定义菜单点击事件) |
| | | */ |
| | | public static final String WE_CHAT_MESSAGE_EVENT_TYPE_CLICK = "click"; |
| | | /** |
| | | * 事件类型:VIEW(自定义菜单 URl 视图) |
| | | */ |
| | | public static final String WE_CHAT_MESSAGE_EVENT_TYPE_VIEW = "view"; |
| | | /** |
| | | * 事件类型:LOCATION(上报地理位置事件) |
| | | */ |
| | | public static final String WE_CHAT_MESSAGE_EVENT_TYPE_LOCATION = "LOCATION"; |
| | | /** |
| | | * 事件类型:LOCATION(上报地理位置事件) |
| | | */ |
| | | public static final String WE_CHAT_MESSAGE_EVENT_TYPE_SCAN = "SCAN"; |
| | | |
| | | //无效关键字key |
| | | public static final String WE_CHAT_MESSAGE_DEFAULT_CONTENT_KEY = "default"; |
| | | //Js sdk api 列表 |
| | | public static final String PUBLIC_API_JS_API_SDK_LIST = "editAddress,openAddress,updateTimelineShareData,updateAppMessageShareData,onMenuShareTimeline,onMenuShareAppMessage,onMenuShareQQ,onMenuShareWeibo,onMenuShareQZone,startRecord,stopRecord,onVoiceRecordEnd,playVoice,pauseVoice,stopVoice,onVoicePlayEnd,uploadVoice,downloadVoice,chooseImage,previewImage,uploadImage,downloadImage,translateVoice,getNetworkType,openLocation,getLocation,hideOptionMenu,showOptionMenu,hideMenuItems,showMenuItems,hideAllNonBaseMenuItem,showAllNonBaseMenuItem,closeWindow,scanQRCode,chooseWXPay,openProductSpecificView,addCard,chooseCard,openCard"; |
| | | |
| | | |
| | | //token |
| | | public static final String REDIS_TOKEN_KEY = "wechat_token"; |
| | | public static final String REDIS_PROGRAM_TOKEN_KEY = "wechat_program_token"; |
| | | //tag |
| | | public static final String REDIS_TAGS_LIST_KEY = "wechat_tags_list"; |
| | | //user tag |
| | | public static final String REDIS_TAGS_LIST_USER_KEY = "wechat_tags_user_list"; |
| | | //微信菜单 |
| | | public static final String REDIS_PUBLIC_MENU_KEY = "wechat_public_menu_key"; |
| | | //微信自定义菜单 |
| | | public static final String REDIS_PUBLIC_MENU_SELF_KEY = "wechat_public_menu_self_key"; |
| | | |
| | | |
| | | |
| | | //授权请求地址 |
| | | public static final String WE_CHAT_AUTHORIZE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$appId}&redirect_uri={$redirectUri}&response_type=code&scope=snsapi_base&state=#wechat_redirect"; |
| | | |
| | | |
| | | //-------------------------------------------微信支付------------------------------------------------------------ |
| | | //微信支付接口请求地址 |
| | | public static final String PAY_API_URL = "https://api.mch.weixin.qq.com/"; |
| | | public static final String PAY_API_URI = "pay/unifiedorder"; |
| | | public static final String PAY_NOTIFY_API_URI_WECHAT = "/api/admin/payment/callback/wechat"; |
| | | // 公共号退款 |
| | | public static final String PAY_REFUND_API_URI_WECHAT = "secapi/pay/refund"; |
| | | |
| | | public static final String PAY_TYPE_JS = "JSAPI"; |
| | | public static final String PAY_TYPE_H5 = "MWEB"; |
| | | |
| | | // -------------------------------------------------------------------------------------------------------- |
| | | // 微信部分 |
| | | // -------------------------------------------------------------------------------------------------------- |
| | | |
| | | /** 获取accessToken的url */ |
| | | public static final String WECHAT_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}"; |
| | | /** 开放平台获取accessToken的url */ |
| | | public static final String WECHAT_OAUTH2_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code"; |
| | | /** 开放平台获取用户的url */ |
| | | public static final String WECHAT_SNS_USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo?access_token={0}&openid={1}&lang={2}"; |
| | | |
| | | /** 公众号js-sdk获取ticket的url */ |
| | | public static final String WECHAT_PUBLIC_JS_TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi"; |
| | | /** 公众号发送模板消息的url */ |
| | | public static final String WECHAT_PUBLIC_SEND_TEMPLATE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={}"; |
| | | /** 公众号获取自定义菜单配置的url */ |
| | | public static final String WECHAT_PUBLIC_MENU_GET_URL = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token={}"; |
| | | /** 公众号创建自定义菜单的url */ |
| | | public static final String WECHAT_PUBLIC_MENU_CREATE_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token={}"; |
| | | /** 公众号删除自定义菜单的url */ |
| | | public static final String WECHAT_PUBLIC_MENU_DELETE_URL = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token={}"; |
| | | /** 企业号上传其他类型永久素材的url */ |
| | | public static final String WECHAT_PUBLIC_QYAPI_ADD_MATERIAL_URL = "https://qyapi.weixin.qq.com/cgi-bin/material/add_material?type={}&access_token={}"; |
| | | /** 公众号获取模板列表(自己的) */ |
| | | public static final String WECHAT_PUBLIC_GET_ALL_PRIVATE_TEMPLATE_URL = "https://api.weixin.qq.com/cgi-bin/template/get_all_private_template?access_token={}"; |
| | | /** 公众号删除模板(自己的) */ |
| | | public static final String WECHAT_PUBLIC_DEL_PRIVATE_TEMPLATE_URL = "https://api.weixin.qq.com/cgi-bin/template/del_private_template?access_token={}"; |
| | | /** 公众号添加模板(自己的) */ |
| | | public static final String WECHAT_PUBLIC_API_ADD_TEMPLATE_URL = "https://api.weixin.qq.com/cgi-bin/template/api_add_template?access_token={}"; |
| | | |
| | | |
| | | /** 小程序登录凭证校验的url */ |
| | | public static final String WECHAT_MINI_SNS_AUTH_CODE2SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code"; |
| | | /** 小程序生成小程序码的url */ |
| | | public static final String WECHAT_MINI_QRCODE_UNLIMITED_URL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token={0}"; |
| | | /** 小程序发送订阅消息的url */ |
| | | public static final String WECHAT_MINI_SEND_SUBSCRIBE_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token={}"; |
| | | /** 小程序获取订阅列表(自己的) */ |
| | | public static final String WECHAT_MINI_GET_ALL_PRIVATE_TEMPLATE_URL = "https://api.weixin.qq.com/wxaapi/newtmpl/gettemplate?access_token={}"; |
| | | /** 小程序删除模板(自己的) */ |
| | | public static final String WECHAT_MINI_DEL_PRIVATE_TEMPLATE_URL = "https://api.weixin.qq.com/wxaapi/newtmpl/deltemplate?access_token={}"; |
| | | /** 小程序获取订阅模板(小程序的) */ |
| | | public static final String WECHAT_MINI_GET_TEMPLATE_URL = "https://api.weixin.qq.com/wxaapi/newtmpl/getpubtemplatekeywords?access_token={}&tid={}"; |
| | | /** 公众号添加模板(自己的) */ |
| | | public static final String WECHAT_MINI_API_ADD_TEMPLATE_URL = "https://api.weixin.qq.com/wxaapi/newtmpl/addtemplate?access_token={}"; |
| | | |
| | | /** 小程序accessToken redis key */ |
| | | public static final String REDIS_WECAHT_MINI_ACCESS_TOKEN_KEY = "wechat_mini_accessToken"; |
| | | /** 公众号accessToken redis key */ |
| | | public static final String REDIS_WECAHT_PUBLIC_ACCESS_TOKEN_KEY = "wechat_public_accessToken"; |
| | | /** 公众号JsApiTicket redis key */ |
| | | public static final String REDIS_PUBLIC_JS_API_TICKET = "wechat_js_api_ticket"; |
| | | public static final Long REDIS_PUBLIC_JS_API_TICKET_EXPRESS = 7100L; |
| | | |
| | | /** |
| | | * -------------------------------------------------------------------------------------------------------- |
| | | * 以下为视频号相关部分 |
| | | * -------------------------------------------------------------------------------------------------------- |
| | | */ |
| | | |
| | | /*------------------------------------------ 申请接入接口 START ---------------------------------------*/ |
| | | public static final String WECHAT_SHOP_BASE_DOME = "https://api.weixin.qq.com"; |
| | | |
| | | /* 申请接入申请 */ |
| | | public static final String WECHAT_SHOP_REGISTER_APPLY = WECHAT_SHOP_BASE_DOME.concat("/shop/register/apply?access_token={}"); |
| | | /* 获取接入状态 */ |
| | | public static final String WECHAT_SHOP_REGISTER_CHECK = WECHAT_SHOP_BASE_DOME.concat("/shop/register/check?access_token={}"); |
| | | /* 完成接入任务 */ |
| | | public static final String WECHAT_SHOP_REGISTER_FINISH_ACCESS = WECHAT_SHOP_BASE_DOME.concat("/shop/register/finish_access_info?access_token={}"); |
| | | /* 场景接入申请 在小程序上线之后 并且所有的api调用都通过了 才可以使用 调用申请成功之后就可以在视频号直播时选择线上商品了 */ |
| | | public static final String WECHAT_SHOP_REGISTER_APPLY_SCENE = WECHAT_SHOP_BASE_DOME.concat("/shop/register/apply_scene?access_token={}"); |
| | | |
| | | /*------------------------------------------ 申请接入接口 END ---------------------------------------*/ |
| | | |
| | | |
| | | /*------------------------------------------ 接入商品前必须接口 START ---------------------------------------*/ |
| | | /** 获取商品类目 */ |
| | | public static final String WECHAT_SHOP_CAT_GET_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/cat/get?access_token={}"); |
| | | /** 上传图片 **/ |
| | | public static final String WECHAT_SHOP_IMG_UPLOAD = WECHAT_SHOP_BASE_DOME.concat("/shop/img/upload?&access_token={}"); |
| | | /** 上传品牌信息 */ |
| | | public static final String WECHAT_SHOP_AUDIT_AUDIT_BRAND = WECHAT_SHOP_BASE_DOME.concat("/shop/audit/audit_brand?&access_token={}"); |
| | | /** 上传类目资质 */ |
| | | public static final String WECHAT_SHOP_AUDIT_AUDIT_CATEGORY = WECHAT_SHOP_BASE_DOME.concat("/shop/audit/audit_category?&access_token={}"); |
| | | /** 查询类目审核结果 */ |
| | | public static final String WECHAT_SHOP_AUDIT_RESULT= WECHAT_SHOP_BASE_DOME.concat("/shop/audit/result?access_token={}"); |
| | | /** 获取小程序提交过的入驻资质信息 */ |
| | | public static final String WECHAT_SHOP_AUDIT_GET_MINIAPP_CERTIFICATE= WECHAT_SHOP_BASE_DOME.concat("/shop/audit/get_miniapp_certificate?access_token={}"); |
| | | /*------------------------------------------ 接入商品前必须接口 END ---------------------------------------*/ |
| | | |
| | | |
| | | /*------------------------------------------ 商家入驻接口 START ---------------------------------------*/ |
| | | /** 获取类目列表 */ |
| | | public static final String WECHAT_SHOP_ACCOUNT_GET_CATEGORY_LIST = WECHAT_SHOP_BASE_DOME.concat("/shop/account/get_category_list?access_token={}"); |
| | | /** 获取品牌列表 */ |
| | | public static final String WECHAT_SHOP_ACCOUNT_GET_BRAND_LIST = WECHAT_SHOP_BASE_DOME.concat("/shop/account/get_brand_list?access_token={}"); |
| | | /** 更新商家信息 */ |
| | | public static final String WECHAT_SHOP_ACCOUNT_UPDATE_INFO = WECHAT_SHOP_BASE_DOME.concat("/shop/account/update_info?access_token={}"); |
| | | /** 获取商家信息 */ |
| | | public static final String WECHAT_SHOP_ACCOUNT_GET_INFO = WECHAT_SHOP_BASE_DOME.concat("/shop/account/get_info?access_token={}"); |
| | | /*------------------------------------------ 商家入驻接口 END ---------------------------------------*/ |
| | | |
| | | /*------------------------------------------ SPU 接口 START ---------------------------------------*/ |
| | | /** 添加商品 */ |
| | | public static final String WECHAT_SHOP_SPU_ADD_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/spu/add?access_token={}"); |
| | | /** 删除商品 */ |
| | | public static final String WECHAT_SHOP_SPU_DEL_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/spu/del?access_token={}"); |
| | | /** 撤回商品审核 */ |
| | | public static final String WECHAT_SHOP_SPU_DEL_AUDIT_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/spu/del_audit?access_token={}"); |
| | | /** 获取商品 */ |
| | | public static final String WECHAT_SHOP_SPU_GET_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/spu/get?access_token={}"); |
| | | /** 获取商品列表 */ |
| | | public static final String WECHAT_SHOP_SPU_GET_LIST_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/spu/get_list?access_token={}"); |
| | | /** 更新商品 */ |
| | | public static final String WECHAT_SHOP_SPU_UPDATE_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/spu/update?access_token={}"); |
| | | /** 上架商品 */ |
| | | public static final String WECHAT_SHOP_SPU_LISTING_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/spu/listing?access_token={}"); |
| | | /** 下架商品 */ |
| | | public static final String WECHAT_SHOP_SPU_DELISTING_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/spu/delisting?access_token={}"); |
| | | |
| | | /*------------------------------------------ SPU 接口 END ---------------------------------------*/ |
| | | |
| | | /*------------------------------------------ 订单 接口 START ---------------------------------------*/ |
| | | /** 检查场景值是否在支付校验范围内 */ |
| | | public static final String WECHAT_SHOP_SCENE_CHECK_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/scene/check?access_token={}"); |
| | | /** 生成订单并获取ticket */ |
| | | public static final String WECHAT_SHOP_ORDER_ADD_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/order/add?access_token={}"); |
| | | /** 视频号忽略此接口 同步订单支付结果 */ |
| | | public static final String WECHAT_SHOP_ORDER_PAY_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/order/pay?access_token={}"); |
| | | /** 生成支付参数 */ |
| | | public static final String WECHAT_SHOP_ORDER_PAYMENT_PARAMS_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/order/getpaymentparams?access_token={}"); |
| | | /** 获取订单 */ |
| | | public static final String WECHAT_SHOP_ORDER_GET_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/order/get?access_token={}"); |
| | | /** 按推广员获取订单 */ |
| | | public static final String WECHAT_SHOP_ORDER_GETBYFINDER_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/order/get_list_by_finder?access_token={}"); |
| | | /** 按分享员获取订单 */ |
| | | public static final String WECHAT_SHOP_ORDER_GETBYSHARER_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/order/get_list_by_sharer?access_token={}"); |
| | | /** 获取订单列表 */ |
| | | public static final String WECHAT_SHOP_ORDER_GET_LIST_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/order/get_list?access_token={}"); |
| | | /*------------------------------------------ 订单 接口 END ---------------------------------------*/ |
| | | |
| | | /*------------------------------------------ 物流 接口 START ---------------------------------------*/ |
| | | /** 获取快递公司列表 */ |
| | | public static final String WECHAT_SHOP_DELIVERY_GET_COMPANY_LIST_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/delivery/get_company_list?access_token={}"); |
| | | /** 订单发货 */ |
| | | public static final String WECHAT_SHOP_DELIVERY_SEND_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/delivery/send?access_token={}"); |
| | | /** 订单确认收货 */ |
| | | public static final String WECHAT_SHOP_DELIVERY_RECIEVE_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/delivery/recieve?access_token={}"); |
| | | /*------------------------------------------ 物流 接口 END ---------------------------------------*/ |
| | | |
| | | /*------------------------------------------ 售后 接口 START ---------------------------------------*/ |
| | | /** 创建售后 */ |
| | | public static final String WECHAT_SHOP_AFTERSALE_ADD_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/aftersale/add?access_token={}"); |
| | | /** 获取售后 */ |
| | | public static final String WECHAT_SHOP_AFTERSALE_GET_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/aftersale/get?access_token={}"); |
| | | /** 更新售后 */ |
| | | public static final String WECHAT_SHOP_AFTERSALE_UPDATE_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/aftersale/update?access_token={}"); |
| | | /*------------------------------------------ 售后 接口 END ---------------------------------------*/ |
| | | |
| | | /*------------------------------------------ 优惠券 接口 START 二期 ---------------------------------------*/ |
| | | /** 商家确认回调领券事件 */ |
| | | public static final String WECHAT_SHOP_COUPON_CONFIRM_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/coupon/confirm?access_token={}"); |
| | | /** 添加优惠券 */ |
| | | public static final String WECHAT_SHOP_COUPON_ADD_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/coupon/add?access_token={}"); |
| | | /** 获取优惠券信息 */ |
| | | public static final String WECHAT_SHOP_COUPON_GET_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/coupon/get?access_token={}"); |
| | | /** 获取优惠券列表 */ |
| | | public static final String WECHAT_SHOP_COUPON_GET_LIST_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/coupon/get_list?access_token={}"); |
| | | /** 更新优惠券信息 */ |
| | | public static final String WECHAT_SHOP_COUPON_UPDATE_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/coupon/update?access_token={}"); |
| | | /** 更新优惠券状态 */ |
| | | public static final String WECHAT_SHOP_COUPON_UPDATE_STATUS_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/coupon/update_status?access_token={}"); |
| | | /** 更新优惠券库存 */ |
| | | public static final String WECHAT_SHOP_COUPON_UPDATE_STOCK_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/coupon/update_coupon_stock?access_token={}"); |
| | | /** 添加用户优惠券 */ |
| | | public static final String WECHAT_SHOP_COUPON_ADD_USER_COUPON_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/coupon/add_user_coupon?access_token={}"); |
| | | /** 获取用户优惠券列表 */ |
| | | public static final String WECHAT_SHOP_COUPON_GET_USERCOUPON_LIST_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/coupon/get_usercoupon_list?access_token={}"); |
| | | /** 更新用户优惠券 */ |
| | | public static final String WECHAT_SHOP_COUPON_UPDATE_USER_COUPON_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/coupon/update_user_coupon?access_token={}"); |
| | | /** 更新用户优惠券状态 */ |
| | | public static final String WECHAT_SHOP_COUPON_UPDATE_USERCOUPON_STATUS_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/coupon/update_usercoupon_status?access_token={}"); |
| | | |
| | | /*------------------------------------------ 优惠券 接口 END 二期 ---------------------------------------*/ |
| | | |
| | | /*------------------------------------------ 推广员 接口 START 二期 ---------------------------------------*/ |
| | | /** 获取推广员列表 */ |
| | | public static final String WECHAT_SHOP_COUPON_PROMOTER_LIST_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/promoter/list?access_token={}"); |
| | | /*------------------------------------------ 推广员 接口 END 二期 ---------------------------------------*/ |
| | | |
| | | /*------------------------------------------ 分销员 接口 START 二期 ---------------------------------------*/ |
| | | /** 绑定分享员 */ |
| | | public static final String WECHAT_SHOP_SHARER_BIND_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/sharer/bind?access_token={}"); |
| | | /** 解绑分享员 */ |
| | | public static final String WECHAT_SHOP_SHARER_UNBIND_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/sharer/unbind?access_token={}"); |
| | | /** 获取已经绑定的分享员列表*/ |
| | | public static final String WECHAT_SHOP_SHARER_GET_SHARER_LIST_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/sharer/get_sharer_list?access_token={}"); |
| | | /** 获取分分享员 */ |
| | | public static final String WECHAT_SHOP_SHARER_SEARCH_SHARER_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/sharer/search_sharer?access_token={}"); |
| | | /** 获取分享员的中带货数据 */ |
| | | public static final String WECHAT_SHOP_SHARER_GET_SHARER_DATA_SUMMARY_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/sharer/get_sharer_data_summary?access_token={}"); |
| | | /** 获取分享员的直播间订单汇总 */ |
| | | public static final String WECHAT_SHOP_SHARER_GET_SHARER_LIVE_ORDER_LIST_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/sharer/get_sharer_live_order_list?access_token={}"); |
| | | /** 获取分享员的直播间带货数据汇总 */ |
| | | public static final String WECHAT_SHOP_SHARER_GET_SHARER_LIVE_SUMMARY_LIST_URL = WECHAT_SHOP_BASE_DOME.concat("/shop/sharer/get_sharer_live_summary_list?access_token={}"); |
| | | |
| | | /*------------------------------------------ 分销员 接口 END 二期 ---------------------------------------*/ |
| | | |
| | | /** 自定义组件,商品类型 redis key */ |
| | | public static final String REDIS_WECHAT_SHOP_CAT_KEY = "wechat_shop_cat"; |
| | | |
| | | /** 微信小程序回调,商品审核回调事件 */ |
| | | public static final String WECAHT_CALLBACK_EVENT_SPU_AUDIT = "open_product_spu_audit"; |
| | | /** 微信小程序回调,品牌审核回调事件 */ |
| | | public static final String WECAHT_CALLBACK_EVENT_BRAND_AUDIT = "open_product_brand_audit"; |
| | | |
| | | |
| | | /** 账户接入回调 */ |
| | | public static final String WECHAT_CALLBACK_EVENT_OPEN_PRODUCT_ACCOUNT_REGISTER = "open_product_account_register"; |
| | | |
| | | /** 场景审核回调 */ |
| | | public static final String WECHAT_CALLBACK_EVENT_OPEN_PRODUCT_SCENE_GROUP_AUDIT = "![CDATA[open_product_scene_group_audit]]"; |
| | | |
| | | /** 订单支付成功回调 */ |
| | | public static final String WECHAT_CALLBACK_EVENT_OPEN_PRODUCT_ORDER_PAY = "open_product_order_pay"; |
| | | |
| | | /** 商品系统下架回调 */ |
| | | public static final String WECHAT_CALLBACK_EVENT_OPEN_PRODUCT_SPU_STATUS_UPDATE = "open_product_spu_status_update"; |
| | | /** 类目审核回调 */ |
| | | public static final String WECHAT_CALLBACK_EVENT_OPEN_PRODUCT_CATEGORY_AUDIT = "open_product_category_audit"; |
| | | /** 分享员绑定解绑通知 */ |
| | | public static final String WECHAT_CALLBACK_EVENT_MINIPROGRAM_SHARER_BIND_STATUS_CHANGE = "miniprogram_sharer_bind_status_change"; |
| | | /** 用户领券回调 */ |
| | | public static final String WECHAT_CALLBACK_EVENT_OPEN_PRODUCT_RECEIVE_COUPON = "open_product_receive_coupon"; |
| | | |
| | | /** 素材上传图片最大值 */ |
| | | public static final Long OPEN_MEDIA_UPLOAD_IMAGE_MAX_SIZE = 1024 * 1024 * 10L; |
| | | /** 素材上传图片后缀类型 */ |
| | | public static final String OPEN_MEDIA_UPLOAD_IMAGE_SUFFIX_NAME = "bmp,png,jpeg,jpg,gif"; |
| | | /** 素材上传语音最大值 */ |
| | | public static final Long OPEN_MEDIA_UPLOAD_VOICE_MAX_SIZE = 1024 * 1024 * 2L; |
| | | /** 素材上传语音后缀类型 */ |
| | | public static final String OPEN_MEDIA_UPLOAD_VOICE_SUFFIX_NAME = "mp3,wma,wav,amr"; |
| | | |
| | | } |
New file |
| | |
| | | package com.iplatform.base.api; |
| | | |
| | | import com.iplatform.base.PlatformAdapterController; |
| | | import com.iplatform.base.service.UserDeptApiServiceImpl; |
| | | import com.iplatform.model.to.UserAndDeptTo; |
| | | import com.walker.web.ResponseValue; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RequestMethod; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | /** |
| | | * 提供对外接口,实现对平台机构人员的操作。 |
| | | * @author 时克英 |
| | | * @date 2023-06-06 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/api/platform/user_dept") |
| | | public class UserAndDeptApi extends PlatformAdapterController |
| | | // implements UserAndDeptServiceApi |
| | | { |
| | | |
| | | private UserDeptApiServiceImpl userDeptApiService; |
| | | |
| | | @Autowired |
| | | public UserAndDeptApi(UserDeptApiServiceImpl userDeptApiService){ |
| | | this.userDeptApiService = userDeptApiService; |
| | | } |
| | | |
| | | @RequestMapping(value = "/create", method = RequestMethod.POST) |
| | | public ResponseValue execInsertTopOrgAndAdmin(@RequestBody UserAndDeptTo userAndDeptTo) { |
| | | long loginId = this.getCurrentUserId(); |
| | | userAndDeptTo.setCreateId(String.valueOf(loginId)); |
| | | if(this.logger.isDebugEnabled()){ |
| | | logger.debug(userAndDeptTo.toString()); |
| | | } |
| | | return this.userDeptApiService.execInsertTopOrgAndAdmin(userAndDeptTo); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.service.CodeServiceImpl; |
| | | import com.iplatform.model.po.S_dict_data; |
| | | import com.iplatform.model.po.S_dict_type; |
| | | import com.walker.cache.tree.AbstractCacheTreeProvider; |
| | | import com.walker.cache.tree.CacheTreeNode; |
| | | import com.walker.cache.tree.DefaultCacheTreeNode; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Collection; |
| | | import java.util.Collections; |
| | | import java.util.Comparator; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.TreeMap; |
| | | |
| | | /** |
| | | * 数据字典缓存定义,该缓存因为树结构复杂,并没有提供'Redis'方式实现。<br> |
| | | * 不过一般字典数据变动很小,因此在集群环境中也是相对安全。<p></p> |
| | | * 1) 注意:如果生产环境字典变动较大,而且是集群环境则必须实现'Redis'集中存储缓存对象。 |
| | | * @author 时克英 |
| | | * @date 2023-03-10 |
| | | */ |
| | | public class DictCacheProvider extends AbstractCacheTreeProvider<S_dict_data> { |
| | | |
| | | private final SortComparator sort = new SortComparator(); |
| | | private final NodeComparator nodeSort = new NodeComparator(); |
| | | |
| | | // 2023-04-15 添加字典类型与id映射记录,因为 |
| | | private final Map<String, String> dictTypeIdMap = new HashMap<>(); |
| | | |
| | | /** |
| | | * 根据字典类型,找出对应id,因为前端若依框架中,需要传类型,但系统使用id查询。 |
| | | * @param dictType |
| | | * @return |
| | | * @date 2023-04-15 |
| | | */ |
| | | public String getDictTypeId(String dictType){ |
| | | String id = this.dictTypeIdMap.get(dictType); |
| | | if(id == null){ |
| | | throw new IllegalArgumentException("根据字典类型,未找到id:" + dictType); |
| | | } |
| | | return id; |
| | | } |
| | | |
| | | /** |
| | | * 返回代码集合对象,通常在数据库中可能会存储多个代码ID,可以通过此 方法获取代码集合。 |
| | | * @param codeIds 输入多个代码ID数组 |
| | | * @return |
| | | */ |
| | | public List<CacheTreeNode> getCodeList(String[] codeIds){ |
| | | List<CacheTreeNode> result = new ArrayList<CacheTreeNode>(2*2); |
| | | if(codeIds != null && codeIds.length > 0){ |
| | | for(String cid : codeIds){ |
| | | result.add(this.get(cid)); |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 返回给定代码表的子代码项,树结构 |
| | | * @param codeTableName 代码表ID |
| | | * @return |
| | | */ |
| | | public List<CacheTreeNode> getCodeChildrenList(String codeTableName){ |
| | | CacheTreeNode node = this.getOneRootNode(codeTableName); |
| | | if(node == null){ |
| | | throw new IllegalArgumentException("not found node: " + codeTableName); |
| | | } |
| | | Collection<CacheTreeNode> list = node.getChildren(); |
| | | if(list != null){ |
| | | List<CacheTreeNode> result = new ArrayList<CacheTreeNode>(); |
| | | for(CacheTreeNode n : list){ |
| | | result.add(n); |
| | | } |
| | | Collections.sort(result, nodeSort); |
| | | return result; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 返回代码表的下一级子代码集合,返回的是代码对象 |
| | | * @param codeTableName 代码表ID |
| | | * @return |
| | | */ |
| | | public List<S_dict_data> getRootChildrenOneLevelList(String codeTableName){ |
| | | CacheTreeNode node = this.getOneRootNode(codeTableName); |
| | | // CacheTreeNode node2 =this.getOneRootNode("101"); |
| | | // Object rootCacheNode = null; |
| | | // for(Iterator<Cachable> it = this.getCache().getIterator(); it.hasNext();){ |
| | | // rootCacheNode = it.next().getValue(); |
| | | // logger.debug("........ {}" + rootCacheNode); |
| | | // } |
| | | if(node == null){ |
| | | throw new IllegalArgumentException("not found node: " + codeTableName); |
| | | } |
| | | Collection<CacheTreeNode> list = node.getChildren(); |
| | | if(list != null){ |
| | | List<S_dict_data> result = new ArrayList<>(); |
| | | S_dict_data temp = null; |
| | | for(CacheTreeNode n : list){ |
| | | temp = (S_dict_data)n.getSource(); |
| | | // temp.setChildSum(n.getChildrenSize()); |
| | | result.add(temp); |
| | | } |
| | | Collections.sort(result, sort); |
| | | return result; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 根据某个代码ID,返回其下一级所有子代码集合 |
| | | * @param id |
| | | * @return |
| | | */ |
| | | public List<S_dict_data> getCodeChildrenOneLevelList(String id){ |
| | | CacheTreeNode parent = this.get(id); |
| | | if(parent == null){ |
| | | return null; |
| | | } |
| | | Collection<CacheTreeNode> list = parent.getChildren(); |
| | | if(list != null){ |
| | | List<S_dict_data> result = new ArrayList<>(); |
| | | for(CacheTreeNode n : list){ |
| | | result.add((S_dict_data)n.getSource()); |
| | | } |
| | | return result; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 返回某个代码下面的所有代码树。 |
| | | * @param id 给定的代码id |
| | | * @return |
| | | */ |
| | | public List<CacheTreeNode> getCodeChildrenTreeList(String id){ |
| | | CacheTreeNode parent = this.get(id); |
| | | if(parent == null){ |
| | | return null; |
| | | } |
| | | Collection<CacheTreeNode> list = parent.getChildren(); |
| | | if(list != null){ |
| | | List<CacheTreeNode> result = new ArrayList<CacheTreeNode>(); |
| | | for(CacheTreeNode n : list){ |
| | | result.add(n); |
| | | } |
| | | return result; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | // /** |
| | | // * 搜索代码树,支持多关键字搜索,返回集合数据展示给ztree,注意:返回结果只有一级不再分层 |
| | | // * @param codeTableId 代码表ID |
| | | // * @param keyLike 查询关键字,如:'锅炉' 或者 '锅炉 电 9号',多关键词用空格分隔 |
| | | // * @return |
| | | // */ |
| | | // public String searchLikeTreeNodeList(String codeTableId, String keyLike){ |
| | | //// Collection<CacheTreeNode> deptList = this.getRootList(); |
| | | // Collection<CacheTreeNode> deptList = this.getCodeChildrenList(codeTableId); |
| | | // JSONArray array = new JSONArray(); |
| | | // |
| | | // if(deptList != null){ |
| | | // // 过滤某个单位下的根数据集合,后续补充 |
| | | // // ... |
| | | // String[] keys = StringUtils.stringToArray(keyLike, " "); |
| | | // boolean multiKeys = false; |
| | | // if(keys != null && keys.length > 1){ |
| | | // multiKeys = true; |
| | | // } |
| | | // |
| | | // List<CacheTreeNode> tempList = null; |
| | | // for(CacheTreeNode node : deptList){ |
| | | // // 不是给定单位的数据不要 |
| | | //// if(((TypeTree)node.getSource()).getDept() != dept){ |
| | | //// continue; |
| | | //// } |
| | | // if(multiKeys){ |
| | | // logger.debug("------------------"); |
| | | // tempList = node.searchLike(keys); |
| | | // } else { |
| | | // tempList = node.searchLike(keyLike); |
| | | // } |
| | | // if(!StringUtils.isEmptyList(tempList)){ |
| | | // for(CacheTreeNode c : tempList){ |
| | | // array.add(CodeUtils.createJsonTree(c.getKey(), c.getText() |
| | | // , Constants.DEFAULT_TREE_ROOT_ID, false, true, CodeUtils.DEFAULT_SEARCH_ICON, false)); |
| | | // } |
| | | // } |
| | | // } |
| | | // } |
| | | // return array.toString(); |
| | | // } |
| | | |
| | | @Override |
| | | protected Map<String, CacheTreeNode> loadRootList() { |
| | | List<S_dict_type> rootList = this.codeService.queryRootCodeList(); |
| | | if(StringUtils.isEmptyList(rootList)){ |
| | | return null; |
| | | } |
| | | // 需要转成'S_dict_data'统一对象,老系统中代码表是一个表,这里是两个表。2023-03-10 |
| | | List<S_dict_data> dictList = new ArrayList<>(); |
| | | S_dict_data data = null; |
| | | for(S_dict_type type : rootList){ |
| | | data = new S_dict_data(); |
| | | data.setDict_code(type.getDict_id()); |
| | | data.setDict_label(type.getDict_name()); |
| | | data.setParent_id(0L); // 根节点不存在父id,默认;0 |
| | | dictList.add(data); |
| | | // |
| | | this.dictTypeIdMap.put(type.getDict_type(), String.valueOf(type.getDict_id())); |
| | | } |
| | | return obtainMap(dictList); |
| | | } |
| | | |
| | | @Override |
| | | protected Map<String, CacheTreeNode> loadChildList() { |
| | | List<S_dict_data> list = this.codeService.queryAllCodeItemList(); |
| | | return obtainMap(list); |
| | | } |
| | | |
| | | @Override |
| | | protected CacheTreeNode toCacheTreeNode(S_dict_data entity) { |
| | | return new DefaultCacheTreeNode(entity.getDict_code().toString() |
| | | , entity.getDict_label(), entity, entity.getParent_id().toString()); |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_DICT; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return S_dict_data.class; |
| | | } |
| | | |
| | | private Map<String, CacheTreeNode> obtainMap(List<S_dict_data> list){ |
| | | if(list != null && list.size() > 0){ |
| | | Map<String, CacheTreeNode> map = new TreeMap<String, CacheTreeNode>(); |
| | | for(S_dict_data code : list){ |
| | | map.put(code.getDict_code().toString(), toCacheTreeNode(code)); |
| | | } |
| | | return map; |
| | | } else |
| | | return null; |
| | | } |
| | | |
| | | private class SortComparator implements Comparator<S_dict_data> { |
| | | @Override |
| | | public int compare(S_dict_data o1, S_dict_data o2) { |
| | | return (int)(o1.getDict_sort() - o2.getDict_sort()); |
| | | } |
| | | } |
| | | private class NodeComparator implements Comparator<CacheTreeNode>{ |
| | | @Override |
| | | public int compare(CacheTreeNode o1, CacheTreeNode o2) { |
| | | S_dict_data n1 = (S_dict_data)o1.getSource(); |
| | | S_dict_data n2 = (S_dict_data)o2.getSource(); |
| | | return (int)(n1.getDict_sort() - n2.getDict_sort()); |
| | | } |
| | | } |
| | | |
| | | public void setCodeService(CodeServiceImpl codeService) { |
| | | this.codeService = codeService; |
| | | } |
| | | |
| | | private CodeServiceImpl codeService; |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.PlatformRuntimeException; |
| | | import com.iplatform.base.pojo.form.FormData; |
| | | import com.iplatform.base.pojo.form.FormDataItem; |
| | | import com.iplatform.base.service.ConfigFormServiceImpl; |
| | | import com.iplatform.base.util.ConfigFormValidateUtils; |
| | | import com.iplatform.model.po.S_config_form; |
| | | import com.iplatform.model.vo.ConfigFormItemConfigRegListVo; |
| | | import com.iplatform.model.vo.ConfigFormItemVo; |
| | | import com.iplatform.model.vo.ConfigFormVo; |
| | | import com.walker.cache.AbstractCacheProvider; |
| | | import com.walker.cache.Cache; |
| | | import com.walker.infrastructure.utils.JsonUtils; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 自定义表单缓存。 |
| | | * <p>1、因为这个数据不会动态变动,因此不需要Redis负载支持。</p> |
| | | * @author 时克英 |
| | | * @date 2023-05-18 |
| | | */ |
| | | public class FormCacheProvider extends AbstractCacheProvider<S_config_form> { |
| | | |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | //~~ 用于验证配置表单的相关方法,后续需要增加表单引擎(对象)来单独处理, |
| | | //~~ 现在临时使用缓存对象处理。2023-05-20 |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | /** |
| | | * 校验提交的表单是否正确。 |
| | | * <pre>1) 当前在功能:分组(组合数据)添加数据项时被调用。</pre> |
| | | * @param formData |
| | | * @date 2023-05-20 |
| | | */ |
| | | public void validateForm(FormData formData){ |
| | | //循环取出item数据, 组合成 key => val 的map格式 |
| | | Map<String, String> map = new HashMap<>(); |
| | | String formItemValue = null; |
| | | for (FormDataItem formDataItem : formData.getFields()) { |
| | | // 2023-05-21 把value中json转字符串时,包含的:\"去掉。 |
| | | // 由于还没有使用到,需要后续评估看用那种方法能获取值。 |
| | | // formItemValue = formDataItem.getValue(); |
| | | // if(StringUtils.isNotEmpty(formItemValue)){ |
| | | // formDataItem.setValue(formItemValue.replaceAll("\"", StringUtils.EMPTY_STRING)); |
| | | // } |
| | | |
| | | // 算法临时缓存 |
| | | map.put(formDataItem.getName(), formDataItem.getValue()); |
| | | } |
| | | |
| | | //取出表单模型的数据 |
| | | S_config_form form = this.getCacheData(formData.getId().toString()); |
| | | |
| | | //解析表单规则进行验证 |
| | | ConfigFormVo systemConfigFormVo = null; |
| | | try { |
| | | systemConfigFormVo = JsonUtils.jsonStringToObject(form.getContent(), ConfigFormVo.class); |
| | | } catch (Exception e) { |
| | | logger.error("formData.getId()=" + formData.getId() + ", " + e.getMessage(), e); |
| | | throw new PlatformRuntimeException("模板表单 【" + form.getName() + "】 内容不正确,请检查JSON格式!", e); |
| | | } |
| | | |
| | | // ConfigFormItemVo configFormItemVo; |
| | | // for (String item : systemConfigFormVo.getFields()) { |
| | | for (ConfigFormItemVo configFormItemVo : systemConfigFormVo.getFields()) { |
| | | // systemConfigFormItemVo = JSONObject.parseObject(item, SystemConfigFormItemVo.class); |
| | | // try { |
| | | // configFormItemVo = JsonUtils.jsonStringToObject(item, ConfigFormItemVo.class); |
| | | // } catch (Exception e) { |
| | | // throw new PlatformRuntimeException("ConfigFormItemVo转换错误:" + item, e); |
| | | // } |
| | | String model = configFormItemVo.get__vModel__(); //字段 name |
| | | |
| | | if(configFormItemVo.get__config__().getRequired() && map.get(model).equals(StringUtils.EMPTY_STRING)) { |
| | | throw new PlatformRuntimeException(configFormItemVo.get__config__().getLabel() + "不能为空!"); |
| | | } |
| | | //正则验证 |
| | | checkRule(configFormItemVo.get__config__().getRegList(), map.get(model), configFormItemVo.get__config__().getLabel()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 验证item规则 |
| | | * @param regList List<SystemConfigFormItemConfigRegListVo 正则表达式列表 |
| | | * @param value String 验证的值 |
| | | * @param name String 提示语字段名称 |
| | | |
| | | * @since 2020-04-16 |
| | | */ |
| | | private void checkRule(List<ConfigFormItemConfigRegListVo> regList, String value, String name) { |
| | | if(regList.size() > 0) { |
| | | for (ConfigFormItemConfigRegListVo systemConfigFormItemConfigRegListVo : regList) { |
| | | if(!ConfigFormValidateUtils.regular(value, name, systemConfigFormItemConfigRegListVo.getPattern())) { |
| | | throw new PlatformRuntimeException(systemConfigFormItemConfigRegListVo.getMessage()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | List<S_config_form> hosts = this.configFormService.selectAll(new S_config_form()); |
| | | if(!StringUtils.isEmptyList(hosts)){ |
| | | for(S_config_form h : hosts){ |
| | | cache.put(String.valueOf(h.getId()), h); |
| | | } |
| | | return hosts.size(); |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_FORM; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return S_config_form.class; |
| | | } |
| | | |
| | | public void setConfigFormService(ConfigFormServiceImpl configFormService) { |
| | | this.configFormService = configFormService; |
| | | } |
| | | |
| | | private ConfigFormServiceImpl configFormService; |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.walker.cache.AbstractCacheProvider; |
| | | import com.walker.cache.Cache; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 验证码(本地)缓存实现。 |
| | | * @author 时克英 |
| | | * @date 2022-11-07 |
| | | */ |
| | | public class LocalCaptchaCacheProvider extends AbstractCacheProvider<String> { |
| | | |
| | | private Map<String, Long> captchaKeyExpiredMap = new HashMap<>(); |
| | | |
| | | public LocalCaptchaCacheProvider(){ |
| | | this.runClearDirtyCacheTask(); |
| | | } |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_CAPTCHA; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return String.class; |
| | | } |
| | | |
| | | @Override |
| | | public void putCacheData(String key, String data, long expiredSeconds){ |
| | | this.putCacheData(key, data); |
| | | this.captchaKeyExpiredMap.put(key, expiredSeconds); |
| | | } |
| | | |
| | | private void runClearDirtyCacheTask(){ |
| | | logger.info("启动定时任务,定期清理过期的推送临时数据,但暂未实现。"); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.CategoryCacheProvider; |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.service.CategoryServiceImpl; |
| | | import com.iplatform.base.util.CategoryUtils; |
| | | import com.iplatform.base.util.cache.CategorySortComparator; |
| | | import com.iplatform.model.po.S_category; |
| | | import com.iplatform.model.vo.CategoryTreeVo; |
| | | import com.walker.cache.AbstractCacheProvider; |
| | | import com.walker.cache.Cachable; |
| | | import com.walker.cache.Cache; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.net.URLDecoder; |
| | | import java.util.ArrayList; |
| | | import java.util.Iterator; |
| | | import java.util.List; |
| | | |
| | | public class LocalCategoryCacheProvider extends AbstractCacheProvider<S_category> implements CategoryCacheProvider { |
| | | |
| | | private final CategorySortComparator sortComparator = new CategorySortComparator(); |
| | | |
| | | @Override |
| | | public List<CategoryTreeVo> getTree(Integer type, Integer status, String name, List<Integer> categoryIdList, int owner) { |
| | | List<S_category> allTree = new ArrayList<>(); |
| | | S_category tempCategory = null; |
| | | |
| | | for(Iterator<Cachable> it = this.getCache().getIterator(); it.hasNext();){ |
| | | tempCategory = (S_category) it.next().getValue(); |
| | | // if(owner != tempCategory.getOwner().intValue()){ |
| | | // continue; |
| | | // } |
| | | // if(type != null && type.intValue() != tempCategory.getType().intValue()){ |
| | | // continue; |
| | | // } |
| | | // if(status != null && status.intValue() != tempCategory.getStatus().intValue()){ |
| | | // continue; |
| | | // } |
| | | // if(!StringUtils.isEmptyList(categoryIdList) && !categoryIdList.contains(tempCategory.getId())){ |
| | | // logger.debug("不包含在给定的集合中'categoryIdList'"); |
| | | // continue; |
| | | // } |
| | | if(CategoryUtils.isCondition(tempCategory, type, status, name, categoryIdList, owner)){ |
| | | allTree.add(tempCategory); |
| | | } |
| | | } |
| | | |
| | | return CategoryUtils.acquireListTree(allTree, sortComparator); |
| | | // // 重新排序 |
| | | // Collections.sort(allTree, sortComparator); |
| | | // |
| | | // // |
| | | // List<CategoryTreeVo> treeList = new ArrayList<>(); |
| | | // if(allTree.size() == 0){ |
| | | // return treeList; |
| | | // } |
| | | // |
| | | // // |
| | | // for (S_category category : allTree) { |
| | | // treeList.add(CategoryUtils.toCategoryTreeVo(category)); |
| | | // } |
| | | // |
| | | // Map<Integer, CategoryTreeVo> map = new HashMap<>(treeList.size()); |
| | | // //ID 为 key 存储到map 中 |
| | | // for (CategoryTreeVo categoryTreeVo : treeList) { |
| | | // map.put(categoryTreeVo.getId(), categoryTreeVo); |
| | | // } |
| | | // |
| | | // List<CategoryTreeVo> list = new ArrayList<>(); |
| | | // CategoryTreeVo parentTree = null; |
| | | // for (CategoryTreeVo tree : treeList) { |
| | | // //子集ID返回对象,有则添加。 |
| | | // parentTree = map.get(tree.getPid()); |
| | | // if (parentTree != null) { |
| | | // parentTree.getChild().add(tree); |
| | | // } else { |
| | | // list.add(tree); |
| | | // } |
| | | // } |
| | | // return list; |
| | | } |
| | | |
| | | @Override |
| | | public List<CategoryTreeVo> getListTree(Integer type, Integer status, String name, int owner) { |
| | | if(StringUtils.isNotEmpty(name)){ |
| | | try { |
| | | name = URLDecoder.decode(name, StringUtils.DEFAULT_CHARSET_UTF8); |
| | | } catch (UnsupportedEncodingException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | return getTree(type, status, name, null, owner); |
| | | } |
| | | |
| | | @Override |
| | | public S_category get(int id) { |
| | | return this.getCacheData(String.valueOf(id)); |
| | | } |
| | | |
| | | @Override |
| | | public void save(S_category category) { |
| | | this.putCacheData(String.valueOf(category.getId()), category); |
| | | } |
| | | |
| | | @Override |
| | | public void update(S_category category) { |
| | | this.updateCacheData(String.valueOf(category.getId()), category); |
| | | } |
| | | |
| | | @Override |
| | | public void remove(int id) { |
| | | this.removeCacheData(String.valueOf(id)); |
| | | } |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | List<S_category> data = this.categoryService.selectAll(new S_category()); |
| | | if(!StringUtils.isEmptyList(data)){ |
| | | for(S_category d : data){ |
| | | cache.put(String.valueOf(d.getId()), d); |
| | | } |
| | | return data.size(); |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_CATEGORY; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return S_category.class; |
| | | } |
| | | |
| | | public void setCategoryService(CategoryServiceImpl categoryService) { |
| | | this.categoryService = categoryService; |
| | | } |
| | | |
| | | private CategoryServiceImpl categoryService; |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.DeptCacheProvider; |
| | | import com.iplatform.base.service.DeptServiceImpl; |
| | | import com.iplatform.base.util.DeptUtils; |
| | | import com.iplatform.model.po.S_dept; |
| | | import com.walker.cache.AbstractCacheProvider; |
| | | import com.walker.cache.Cache; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | |
| | | /** |
| | | * 基于本地内存实现的机构缓存提供者。 |
| | | * @author 时克英 |
| | | * @date 2022-12-05 |
| | | */ |
| | | public class LocalDeptCacheProvider extends AbstractCacheProvider<S_dept> implements DeptCacheProvider { |
| | | |
| | | private DeptServiceImpl deptService; |
| | | |
| | | private Map<String, List<String>> deptChildrenIdList = new ConcurrentHashMap<>(); |
| | | |
| | | public void setDeptService(DeptServiceImpl deptService) { |
| | | this.deptService = deptService; |
| | | } |
| | | |
| | | @Override |
| | | public void setAllowCacheChildren(boolean allow) { |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public S_dept getDept(long deptId) { |
| | | if(deptId == 0){ |
| | | return DeptUtils.SUPER_VISOR_DEPT; |
| | | } |
| | | return this.getCacheData(String.valueOf(deptId)); |
| | | } |
| | | |
| | | @Override |
| | | public void updateDept(S_dept s_dept) { |
| | | this.updateCacheData(String.valueOf(s_dept.getId()), s_dept); |
| | | } |
| | | |
| | | @Override |
| | | public void removeDept(long deptId) { |
| | | String key = String.valueOf(deptId); |
| | | String keyChildren = key + DeptUtils.KEY_CHILDREN_PREFIX; |
| | | S_dept current = this.getDept(deptId); |
| | | if(current == null){ |
| | | logger.warn("机构缓存已不存在,无需删除"); |
| | | return; |
| | | } |
| | | |
| | | // 删除该机构子机构缓存列表 |
| | | this.removeCacheData(keyChildren); |
| | | this.removeCacheData(key); |
| | | |
| | | // 更新父机构对应的childrenList |
| | | // String parentId = String.valueOf(current.getParent_id()); |
| | | List<String> parentChildrenList = this.getChildrenDeptIdOneLevel(current.getParent_id()); |
| | | if(parentChildrenList != null){ |
| | | parentChildrenList.remove(key); |
| | | // 由于在内存中,所以一旦删除,引用也就变了。2022-12-03 |
| | | // this.deptChildrenIdList.put(parentId + DeptUtils.KEY_CHILDREN_PREFIX, parentChildrenList); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void putDept(S_dept s_dept) { |
| | | String id = String.valueOf(s_dept.getId()); |
| | | try{ |
| | | this.putCacheData(id, s_dept); |
| | | this.deptChildrenIdList.put(id + DeptUtils.KEY_CHILDREN_PREFIX, new ArrayList<>()); |
| | | |
| | | if(s_dept.getParent_id().longValue() == 0L){ |
| | | // 顶级单位,没有父机构了 |
| | | logger.debug("顶级机构,不用更新父机构列表, " + id); |
| | | return; |
| | | } |
| | | // 更新父机构列表 |
| | | List<String> parentChildrenList = this.getChildrenDeptIdOneLevel(s_dept.getParent_id()); |
| | | if(StringUtils.isEmptyList(parentChildrenList)){ |
| | | parentChildrenList = new ArrayList<>(); |
| | | } |
| | | parentChildrenList.add(id); |
| | | this.deptChildrenIdList.put(String.valueOf(s_dept.getParent_id()) + DeptUtils.KEY_CHILDREN_PREFIX, parentChildrenList); |
| | | |
| | | } catch (Exception e){ |
| | | throw new RuntimeException("添加 [机构] 缓存错误:" + e.getMessage(), e); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public List<String> getChildrenDeptIdOneLevel(long deptId) { |
| | | String key = deptId + DeptUtils.KEY_CHILDREN_PREFIX; |
| | | List<String> childrenIdList = this.deptChildrenIdList.get(key); |
| | | if(childrenIdList == null){ |
| | | logger.error("未找到缓存中子机构列表: " + key); |
| | | return null; |
| | | } |
| | | return childrenIdList; |
| | | } |
| | | |
| | | @Override |
| | | public List<S_dept> getChildrenDeptOneLevel(long deptId) { |
| | | List<String> childrenIdList = this.getChildrenDeptIdOneLevel(deptId); |
| | | if(StringUtils.isEmptyList(childrenIdList)){ |
| | | return null; |
| | | } |
| | | List<S_dept> resultList = new ArrayList<>(); |
| | | S_dept s_dept = null; |
| | | for(String id : childrenIdList){ |
| | | s_dept = this.getDept(Long.parseLong(id)); |
| | | resultList.add(s_dept); |
| | | } |
| | | return resultList; |
| | | } |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | List<S_dept> list = this.deptService.queryAllDeptListForCache(); |
| | | if(!StringUtils.isEmptyList(list)){ |
| | | for(S_dept h : list){ |
| | | this.putDept(h); |
| | | } |
| | | return list.size(); |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_DEPT; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return S_dept.class; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.model.po.S_host; |
| | | import com.walker.cache.AbstractCacheProvider; |
| | | import com.walker.cache.Cache; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.jdbc.service.PubService; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 主机资源缓存定义(本机内存缓存)实现。 |
| | | * @author 时克英 |
| | | * @date 2022-09-20 |
| | | */ |
| | | public class LocalHostCacheProvider extends AbstractCacheProvider<S_host> { |
| | | |
| | | private PubService pubService; |
| | | |
| | | public void setPubService(PubService pubService) { |
| | | this.pubService = pubService; |
| | | } |
| | | |
| | | public LocalHostCacheProvider(){ |
| | | this.setLoadPage(false); |
| | | } |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | List<S_host> hosts = this.pubService.selectAll(new S_host()); |
| | | if(!StringUtils.isEmptyList(hosts)){ |
| | | for(S_host h : hosts){ |
| | | cache.put(String.valueOf(h.getId()), h); |
| | | } |
| | | return hosts.size(); |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_HOST; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return S_host.class; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.NotificationTemplateCache; |
| | | import com.iplatform.base.NotifyConstants; |
| | | import com.iplatform.base.service.NotificationServiceImpl; |
| | | import com.iplatform.model.po.SfNotification; |
| | | import com.iplatform.model.po.SfTemplateMessage; |
| | | import com.iplatform.model.vo.NotificationTemplateVo; |
| | | import com.walker.cache.AbstractCacheProvider; |
| | | import com.walker.cache.Cache; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | public class LocalNotificationTemplateCache extends AbstractCacheProvider<NotificationTemplateVo> implements NotificationTemplateCache { |
| | | |
| | | @Override |
| | | public NotificationTemplateVo get(String mark) { |
| | | return this.getCacheData(mark); |
| | | } |
| | | |
| | | @Override |
| | | public void save(NotificationTemplateVo category) { |
| | | this.putCacheData(category.getName(), category); |
| | | } |
| | | |
| | | @Override |
| | | public void update(NotificationTemplateVo category) { |
| | | this.updateCacheData(category.getName(), category); |
| | | } |
| | | |
| | | @Override |
| | | public void remove(String mark) { |
| | | this.removeCacheData(mark); |
| | | } |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | List<SfNotification> notificationList = this.notificationService.selectAll(new SfNotification()); |
| | | if(!StringUtils.isEmptyList(notificationList)){ |
| | | Map<Long, SfTemplateMessage> templateMessageMap = this.notificationService.queryTemplateIdMap(); |
| | | if(templateMessageMap.size() == 0){ |
| | | logger.warn("提醒模板未找到任何有效数据"); |
| | | return 0; |
| | | } |
| | | for(SfNotification h : notificationList){ |
| | | NotificationTemplateVo vo = new NotificationTemplateVo(); |
| | | vo.setName(h.getMark()); |
| | | if(h.getIsWechat().intValue() == NotifyConstants.SWITCH_OPEN){ |
| | | vo.setWechat(true); |
| | | vo.setWechatId(h.getWechatId()); |
| | | vo.setWechatTempId(templateMessageMap.get(h.getWechatId().longValue()).getTempId()); |
| | | } |
| | | if(h.getIsRoutine().intValue() == NotifyConstants.SWITCH_OPEN){ |
| | | vo.setRoutine(true); |
| | | vo.setRoutineId(h.getRoutineId()); |
| | | vo.setRoutineTempId(templateMessageMap.get(h.getRoutineId().longValue()).getTempId()); |
| | | } |
| | | if(h.getIsSms().intValue() == NotifyConstants.SWITCH_OPEN){ |
| | | vo.setSms(true); |
| | | vo.setSmsId(h.getSmsId()); |
| | | vo.setSmsTempId(templateMessageMap.get(h.getSmsId().longValue()).getTempId()); |
| | | } |
| | | cache.put(h.getMark(), vo); |
| | | } |
| | | return notificationList.size(); |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_NOTIFICATION_TEMPLATE; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return NotificationTemplateVo.class; |
| | | } |
| | | |
| | | public void setNotificationService(NotificationServiceImpl notificationService) { |
| | | this.notificationService = notificationService; |
| | | } |
| | | |
| | | private NotificationServiceImpl notificationService; |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.PushCacheProvider; |
| | | import com.walker.cache.AbstractCacheProvider; |
| | | import com.walker.cache.Cache; |
| | | |
| | | public class LocalPushCacheProvider extends AbstractCacheProvider<String> implements PushCacheProvider { |
| | | |
| | | public LocalPushCacheProvider(){ |
| | | this.runClearDirtyCacheTask(); |
| | | } |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | // 初始化不需要加载数据,缓存中数据2分钟失效 |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_PUSH; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return String.class; |
| | | } |
| | | |
| | | @Override |
| | | public void put(String key, String value) { |
| | | this.putCacheData(key, value, 60); |
| | | } |
| | | |
| | | @Override |
| | | public String get(String key) { |
| | | return this.getCacheData(key); |
| | | } |
| | | |
| | | private void runClearDirtyCacheTask(){ |
| | | logger.info("启动定时任务,定期清理过期的用户登录信息,但暂未实现。"); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.SystemGroupCache; |
| | | import com.iplatform.base.service.GroupServiceImpl; |
| | | import com.iplatform.model.po.S_group; |
| | | import com.iplatform.model.po.S_group_data; |
| | | import com.iplatform.model.vo.SystemGroupVo; |
| | | import com.walker.cache.AbstractCacheProvider; |
| | | import com.walker.cache.Cache; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | public class LocalSystemGroupCache extends AbstractCacheProvider<SystemGroupVo> implements SystemGroupCache { |
| | | |
| | | @Override |
| | | public SystemGroupVo get(int id) { |
| | | return this.getCacheData(String.valueOf(id)); |
| | | } |
| | | |
| | | @Override |
| | | public void save(SystemGroupVo category) { |
| | | this.putCacheData(String.valueOf(category.getId()), category); |
| | | } |
| | | |
| | | @Override |
| | | public void update(SystemGroupVo category) { |
| | | this.updateCacheData(String.valueOf(category.getId()), category); |
| | | } |
| | | |
| | | @Override |
| | | public void remove(int id) { |
| | | this.removeCacheData(String.valueOf(id)); |
| | | } |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | List<S_group> hosts = this.groupService.selectAll(new S_group()); |
| | | if(!StringUtils.isEmptyList(hosts)){ |
| | | List<SystemGroupVo> groupVoList = new ArrayList<>(hosts.size()); |
| | | List<S_group_data> groupDataList = this.groupService.queryAllGroupDataList(); |
| | | for(S_group h : hosts){ |
| | | groupVoList.add(new SystemGroupVo(h)); |
| | | } |
| | | |
| | | if(!StringUtils.isEmptyList(groupDataList)){ |
| | | for(S_group_data data : groupDataList){ |
| | | for(SystemGroupVo vo : groupVoList){ |
| | | if(data.getGid().intValue() == vo.getId().intValue()){ |
| | | vo.addGroupData(data); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | for(SystemGroupVo h : groupVoList){ |
| | | cache.put(String.valueOf(h.getId()), h); |
| | | } |
| | | return hosts.size(); |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_GROUP; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return SystemGroupVo.class; |
| | | } |
| | | |
| | | public void setGroupService(GroupServiceImpl groupService) { |
| | | this.groupService = groupService; |
| | | } |
| | | |
| | | private GroupServiceImpl groupService; |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.UserCacheProvider; |
| | | import com.iplatform.base.service.UserServiceImpl; |
| | | import com.iplatform.model.po.S_user_core; |
| | | import com.walker.cache.AbstractCacheProvider; |
| | | import com.walker.cache.Cache; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 本地用户缓存实现。 |
| | | * @author 时克英 |
| | | * @date 2022-11-06 |
| | | */ |
| | | public class LocalUserCacheProvider extends AbstractCacheProvider<S_user_core> implements UserCacheProvider { |
| | | |
| | | private UserServiceImpl userService = null; |
| | | |
| | | public void setUserService(UserServiceImpl userService) { |
| | | this.userService = userService; |
| | | } |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | List<S_user_core> hosts = this.userService.selectAll(new S_user_core()); |
| | | if(!StringUtils.isEmptyList(hosts)){ |
| | | for(S_user_core h : hosts){ |
| | | cache.put(String.valueOf(h.getId()), h); |
| | | } |
| | | return hosts.size(); |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_USER; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return S_user_core.class; |
| | | } |
| | | |
| | | @Override |
| | | public S_user_core getUserByLoginId(String loginId) { |
| | | S_user_core userCore = this.getCacheData(loginId); |
| | | if(userCore == null){ |
| | | userCore = this.userService.queryLoginUserOnly(loginId); |
| | | if(userCore == null){ |
| | | logger.warn("从s_user_core未查询到用户" + ",无法缓存,loginId = {}", loginId); |
| | | return null; |
| | | } |
| | | this.putCacheData(loginId, userCore); |
| | | } |
| | | return userCore; |
| | | } |
| | | |
| | | @Override |
| | | public S_user_core getUser(long userId) { |
| | | return this.getCacheData(String.valueOf(userId)); |
| | | } |
| | | |
| | | @Override |
| | | public void updateUser(S_user_core user_core) { |
| | | this.updateCacheData(String.valueOf(user_core.getId()), user_core); |
| | | } |
| | | |
| | | @Override |
| | | public void removeUser(long userId) { |
| | | this.removeCacheData(String.valueOf(userId)); |
| | | } |
| | | |
| | | @Override |
| | | public void putUser(S_user_core user_core) { |
| | | this.putCacheData(String.valueOf(user_core.getId()), user_core); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.UserLoginCache; |
| | | import com.iplatform.model.po.S_user_login; |
| | | import com.walker.cache.AbstractCacheProvider; |
| | | import com.walker.cache.Cache; |
| | | |
| | | public class LocalUserLoginCache extends AbstractCacheProvider<S_user_login> implements UserLoginCache { |
| | | |
| | | @Override |
| | | public S_user_login getUserLogin(String loginId) { |
| | | return this.getCacheData(loginId); |
| | | } |
| | | |
| | | @Override |
| | | public void updateUserLogin(S_user_login user_login) { |
| | | this.updateCacheData(user_login.getUser_name(), user_login); |
| | | } |
| | | |
| | | @Override |
| | | public void removeUserLogin(String loginId) { |
| | | this.removeCacheData(loginId); |
| | | } |
| | | |
| | | @Override |
| | | public void putUserLogin(S_user_login user_login) { |
| | | this.putCacheData(user_login.getUser_name(), user_login); |
| | | } |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | // 本地缓存情况下,不考虑重启后加载缓存。 |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_USER_LOGIN; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return S_user_login.class; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.VariableConstants; |
| | | import com.iplatform.base.util.TokenUtils; |
| | | import com.walker.cache.AbstractCacheProvider; |
| | | import com.walker.cache.Cache; |
| | | import com.walker.web.UserOnlineProvider; |
| | | import com.walker.web.UserPrincipal; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 基于内存实现的在线用户提供者实现。 |
| | | * @author 时克英 |
| | | * @date 2022-11-01 |
| | | */ |
| | | public class LocalUserOnlineProvider extends AbstractCacheProvider<UserPrincipal<?>> implements UserOnlineProvider { |
| | | |
| | | // 存储用户: key --> 登录过期时间 |
| | | private Map<String, Long> captchaKeyExpiredMap = new HashMap<>(); |
| | | |
| | | public LocalUserOnlineProvider(){ |
| | | this.runClearDirtyCacheTask(); |
| | | } |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | // 内存无法持久化,因此这里无需启动时加载已有缓存 |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_ONLINE_USER; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return UserPrincipal.class; |
| | | } |
| | | |
| | | @Override |
| | | public UserPrincipal<?> getUserPrincipal(String token) { |
| | | UserPrincipal<?> userPrincipal = this.getCacheData(token); |
| | | if(userPrincipal == null){ |
| | | logger.warn("UserOnlineProvider 缓存用户不存在, token = " + token); |
| | | } |
| | | return userPrincipal; |
| | | } |
| | | |
| | | @Deprecated |
| | | @Override |
| | | public boolean cacheUserPrincipal(String token, UserPrincipal<?> userPrincipal) { |
| | | logger.debug("写入用户登录缓存: " + token + ", " + userPrincipal.getUserName()); |
| | | this.putCacheData(token, userPrincipal, TokenUtils.acquireCacheUserExpiredSeconds(VariableConstants.DEFAULT_TOKEN_EXPIRED_MINUTES)); |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public boolean cacheUserPrincipal(String token, UserPrincipal<?> userPrincipal, long expiredMintues) { |
| | | this.putCacheData(token, userPrincipal, TokenUtils.acquireCacheUserExpiredSeconds(expiredMintues)); |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public boolean updateUserPrincipalTimeStamp(String token) { |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public boolean removeUserPrincipal(String token) { |
| | | this.removeCacheData(token); |
| | | this.captchaKeyExpiredMap.remove(token); |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public void putCacheData(String key, UserPrincipal<?> userPrincipal, long expiredSeconds){ |
| | | this.putCacheData(key, userPrincipal); |
| | | this.captchaKeyExpiredMap.put(key, expiredSeconds); |
| | | } |
| | | |
| | | private void runClearDirtyCacheTask(){ |
| | | logger.info("启动定时任务,定期清理过期的用户登录信息,但暂未实现。"); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.WechatCacheProvider; |
| | | import com.iplatform.base.WechatConstants; |
| | | import com.walker.cache.AbstractCacheProvider; |
| | | import com.walker.cache.Cache; |
| | | |
| | | public class LocalWechatCache extends AbstractCacheProvider<String> implements WechatCacheProvider { |
| | | |
| | | @Override |
| | | public String getMiniAccessToken() { |
| | | return this.getCacheData(WechatConstants.REDIS_WECAHT_MINI_ACCESS_TOKEN_KEY); |
| | | } |
| | | |
| | | @Override |
| | | public String getJsApiTicket() { |
| | | return this.getCacheData(WechatConstants.REDIS_PUBLIC_JS_API_TICKET); |
| | | } |
| | | |
| | | @Override |
| | | public String getPublicAccessToken() { |
| | | // throw new UnsupportedOperationException("请使用Redis实现"); |
| | | return this.getCacheData(WechatConstants.REDIS_WECAHT_PUBLIC_ACCESS_TOKEN_KEY); |
| | | } |
| | | |
| | | @Override |
| | | public void putPublicAccessToken(String value, long expiredSeconds) { |
| | | // throw new UnsupportedOperationException("请使用Redis实现"); |
| | | this.putCacheData(WechatConstants.REDIS_WECAHT_PUBLIC_ACCESS_TOKEN_KEY, value, expiredSeconds); |
| | | } |
| | | |
| | | @Override |
| | | public void putJsApiTicket(String value) { |
| | | // throw new UnsupportedOperationException("请使用Redis实现"); |
| | | this.putCacheData(WechatConstants.REDIS_PUBLIC_JS_API_TICKET, value, WechatConstants.REDIS_PUBLIC_JS_API_TICKET_EXPRESS); |
| | | } |
| | | |
| | | @Override |
| | | public void putMiniAccessToken(String value, long expiredSeconds) { |
| | | this.putCacheData(WechatConstants.REDIS_WECAHT_MINI_ACCESS_TOKEN_KEY, value, expiredSeconds); |
| | | } |
| | | |
| | | @Override |
| | | public void removeMiniAccessToken() { |
| | | this.removeCacheData(WechatConstants.REDIS_WECAHT_MINI_ACCESS_TOKEN_KEY); |
| | | } |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_WECHAT; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return String.class; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.SecurityConstants; |
| | | import com.iplatform.base.service.MenuServiceImpl; |
| | | import com.iplatform.base.util.MenuUtils; |
| | | import com.iplatform.base.util.menu.SystemMenu; |
| | | import com.iplatform.model.po.S_menu; |
| | | import com.iplatform.model.vo.MetaVo; |
| | | import com.iplatform.model.vo.RouterVo; |
| | | import com.walker.cache.AbstractCacheProvider; |
| | | import com.walker.cache.Cachable; |
| | | import com.walker.cache.Cache; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.Comparator; |
| | | import java.util.HashSet; |
| | | import java.util.Iterator; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * 菜单本地缓存,因为不需要集群环境,因此只有内存模式(没有redis方式) |
| | | * @author 时克英 |
| | | * @date 2022-11-01 |
| | | * @date 2024-04-09 增加修改时间戳,在集群环境中能被动触发重新加载本机节点。 |
| | | */ |
| | | public class MenuCacheProvider extends AbstractCacheProvider<S_menu> { |
| | | //public class MenuCacheProvider extends RedisCacheProvider<S_menu> { |
| | | |
| | | /* public MenuCacheProvider(){ |
| | | this.setUseRedis(true); |
| | | this.setLoadPage(false); |
| | | // 缓存可展示最大值,超过该值调用getIterator会报错 |
| | | CacheConfig.setInitCachemapSize(20480); |
| | | }*/ |
| | | |
| | | private MenuServiceImpl menuService; |
| | | |
| | | public void setMenuService(MenuServiceImpl menuService) { |
| | | this.menuService = menuService; |
| | | } |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | List<S_menu> list = this.menuService.selectAll(new S_menu()); |
| | | if(!StringUtils.isEmptyList(list)){ |
| | | for(S_menu h : list){ |
| | | cache.put(h.getMenu_id(), h); |
| | | } |
| | | // 每次启动,记录当前加载数据时间戳 |
| | | this.reloadMills = System.currentTimeMillis(); |
| | | return list.size(); |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_MENU; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return S_menu.class; |
| | | } |
| | | |
| | | /** |
| | | * 给定的菜单,是否包含子菜单。 |
| | | * @param menuId 给定菜单ID |
| | | * @return |
| | | * @date 2022-12-29 |
| | | */ |
| | | public boolean isHasChildren(String menuId){ |
| | | List<S_menu> menuAll = this.getCacheMenuList(true, MenuUtils.MENU_SCOPE_PLATFORM); |
| | | for(S_menu menu : menuAll){ |
| | | if(menu.getParent_id().equals(menuId)){ |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * 返回菜单集合列表(不是树结构),目前该方法在代码生成功能中使用,展示选择生成在哪个菜单模块。 |
| | | * @param roleIdList |
| | | * @param menuScope 菜单范围:0 平台(目前也有3),4 独立单位, -1 表示显示所有菜单,>4 表示机构特定菜单,如班主任菜单。 |
| | | * @return |
| | | * @date 2022-11-27 |
| | | * @date 2023-06-05 添加参数 menuScope |
| | | * @date 2023-10-11 menuScope 参数增加值(-1)可以展示所有菜单,邮政集团模式 |
| | | * @date 2023-10-24 menuScope 参数增加值(大于4),表示特定人员的特定菜单(如:班主任的菜单) |
| | | */ |
| | | public List<SystemMenu> getMenuList(List<String> roleIdList, int menuScope){ |
| | | if(StringUtils.isEmptyList(roleIdList)){ |
| | | // 没有给定角色集合,说明是管理员,显示所有菜单数据 |
| | | return this.toSystemMenuList(this.getCacheMenuList(true, menuScope)); |
| | | } |
| | | |
| | | // 2024-04-09 |
| | | this.checkReloadForceLocalMemory(); |
| | | |
| | | // 根据角色权限加载不同菜单集合 |
| | | List<SystemMenu> menuList = new ArrayList<>(32); |
| | | List<String> menuIdList = this.menuService.queryRoleMenuIdList(roleIdList); |
| | | if(StringUtils.isEmptyList(menuIdList)){ |
| | | logger.warn("用户没有任何权限,menuIdList = null, roleIdList = {}", roleIdList); |
| | | return menuList; |
| | | } |
| | | |
| | | S_menu menu = null; |
| | | for(String menuId : menuIdList){ |
| | | menu = this.getCacheData(menuId); |
| | | // 2023-10-11 增加这个if判断,如果是不区分范围,则加载所有菜单 |
| | | // if(menuScope != MenuUtils.MENU_SCOPE_ALL){ |
| | | // if(menuScope == MenuUtils.MENU_SCOPE_PLATFORM){ |
| | | // // 如果要展示菜单范围是:平台,则菜单中 >= 4的分类都不要,这些是顶级机构业务独立菜单。 |
| | | // if(menu.getType().intValue() >= MenuUtils.MENU_SCOPE_ORG){ |
| | | // continue; |
| | | // } |
| | | // } else if(menuScope == MenuUtils.MENU_SCOPE_ORG){ |
| | | //// if(menu.getType().intValue() < MenuUtils.MENU_SCOPE_ORG){ |
| | | // if(menu.getType().intValue() != MenuUtils.MENU_SCOPE_ORG){ |
| | | // // 如果要展示菜单范围是:顶级机构业务的独立菜单,则平台菜单不显示。2023-06-01 |
| | | // continue; |
| | | // } |
| | | // } else if(menuScope > MenuUtils.MENU_SCOPE_ORG){ |
| | | // // 对于大于机构菜单的,都属于机构特定菜单,必须与传入范围完全一致,如:班主任菜单等。2023-10-24 |
| | | // if(menu.getType().intValue() != menuScope){ |
| | | // continue; |
| | | // } |
| | | // } |
| | | // } |
| | | if(MenuUtils.menuScopeNotMatch(menuScope, menu)){ |
| | | continue; |
| | | } |
| | | menuList.add(new SystemMenu(menu)); |
| | | } |
| | | |
| | | // 2023-10-13,查找每个菜单上级,如果上级范围类型与下级菜单不一致,也需要加入列表中 |
| | | for(String menuId : menuIdList){ |
| | | if(MenuUtils.containMenu(menuList, menuId)){ |
| | | continue; |
| | | } |
| | | menu = this.getCacheData(menuId); |
| | | menuList.add(new SystemMenu(menu)); |
| | | } |
| | | // if(!StringUtils.isEmptyList(menuList)){ |
| | | // String pid = null; |
| | | // for(SystemMenu systemMenu : menuList){ |
| | | // pid = systemMenu.getParent_id(); |
| | | // if(pid.equals(MenuUtils.MENU_ID_ROOT)){ |
| | | // continue; |
| | | // } |
| | | // if(menuIdList.contains(pid)){ |
| | | // this.addParentMenu2Collection(menuList, pid); |
| | | // } |
| | | // } |
| | | // } |
| | | |
| | | // Collections.sort(menuList, new ParentMenuComparator()); |
| | | // Collections.sort(menuList, new MenuOrderNumComparator()); |
| | | // Collections.sort(menuList); |
| | | List<SystemMenu> collect = menuList.stream().sorted(Comparator.comparing(SystemMenu::getParent_id).thenComparing(SystemMenu::getOrder_num,Comparator.reverseOrder())).collect(Collectors.toList()); |
| | | logger.info("+++++++++++++++++++++"); |
| | | return collect; |
| | | } |
| | | |
| | | // private List<SystemMenu> addParentMenu2Collection(List<SystemMenu> menuList, String menuId){ |
| | | // List<SystemMenu> addList = null; |
| | | // boolean exist = false; |
| | | // for(SystemMenu menu : menuList){ |
| | | // if(menu.getMenu_id().equals(menuId)){ |
| | | // exist = true; |
| | | // break; |
| | | // } |
| | | // } |
| | | // if(!exist){ |
| | | // S_menu menu = this.getCacheData(menuId); |
| | | // if(addList == null){ |
| | | // addList = new ArrayList<>(8); |
| | | // } |
| | | // addList.add(new SystemMenu(menu)); |
| | | // } |
| | | // return addList; |
| | | // } |
| | | |
| | | public List<SystemMenu> toSystemMenuList(List<S_menu> srcMenuList){ |
| | | List<SystemMenu> list = new ArrayList<>(32); |
| | | if(StringUtils.isEmptyList(srcMenuList)){ |
| | | return list; |
| | | } |
| | | for(S_menu menu : srcMenuList){ |
| | | list.add(new SystemMenu(menu)); |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | /** |
| | | * 获得缓存菜单列表 |
| | | * @param containButton 是否包含按钮权限菜单 |
| | | * @param menuScope 菜单范围,对独立顶级机构,可以显示机构设置的分类菜单范围,目前有:0-平台(包含3),4-顶级单位独立菜单 |
| | | * @return |
| | | * @date 2023-06-01 |
| | | */ |
| | | public List<S_menu> getCacheMenuList(boolean containButton, int menuScope){ |
| | | |
| | | // 2024-04-09 |
| | | this.checkReloadForceLocalMemory(); |
| | | |
| | | List<S_menu> data = new ArrayList<>(); |
| | | S_menu menu = null; |
| | | for(Iterator<Cachable> it = this.getCache().getIterator(); it.hasNext();){ |
| | | menu = (S_menu) it.next().getValue(); |
| | | |
| | | // 2023-10-24 |
| | | if(MenuUtils.menuScopeNotMatch(menuScope, menu)){ |
| | | continue; |
| | | } |
| | | |
| | | if(menu.getStatus().intValue() == MenuUtils.MENU_STATUS_DISABLED){ |
| | | // 去掉禁用菜单 |
| | | continue; |
| | | } |
| | | if(menu.getMenu_type().equals(MenuUtils.MENU_TYPE_BUTTON)){ |
| | | if(containButton){ |
| | | data.add(menu); |
| | | } |
| | | } else { |
| | | data.add(menu); |
| | | } |
| | | } |
| | | // TODO 前端报错 暂时注释 |
| | | // Collections.sort(data, new ParentMenuComparator()); |
| | | // Collections.sort(data, new MenuOrderNumComparator()); |
| | | // Collections.sort(data); |
| | | List<S_menu> dataOrder = data.stream().sorted(Comparator.comparing(S_menu::getParent_id).thenComparing(S_menu::getOrder_num,Comparator.reverseOrder())).collect(Collectors.toList()); |
| | | |
| | | return dataOrder; |
| | | } |
| | | |
| | | /** |
| | | * 根据父节点的ID获取所有子节点 |
| | | * |
| | | * @param list 分类表 |
| | | * @param parentId 传入的父节点ID |
| | | * @return String |
| | | */ |
| | | public List<SystemMenu> getChildPerms(List<SystemMenu> list, String parentId) { |
| | | List<SystemMenu> returnList = new ArrayList<>(); |
| | | for (Iterator<SystemMenu> iterator = list.iterator(); iterator.hasNext();) { |
| | | SystemMenu t = iterator.next(); |
| | | // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点 |
| | | if (t.getParent_id().equals(parentId)) { |
| | | recursionFn(list, t); |
| | | returnList.add(t); |
| | | } |
| | | } |
| | | return returnList; |
| | | } |
| | | |
| | | /** |
| | | * 递归列表 |
| | | * |
| | | * @param list |
| | | * @param t |
| | | */ |
| | | private void recursionFn(List<SystemMenu> list, SystemMenu t) { |
| | | // 得到子节点列表 |
| | | List<SystemMenu> childList = getChildList(list, t); |
| | | t.setChildren(childList); |
| | | for (SystemMenu tChild : childList) { |
| | | if (hasChild(list, tChild)) { |
| | | recursionFn(list, tChild); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 得到子节点列表 |
| | | */ |
| | | private List<SystemMenu> getChildList(List<SystemMenu> list, SystemMenu t) { |
| | | List<SystemMenu> tlist = new ArrayList<>(); |
| | | Iterator<SystemMenu> it = list.iterator(); |
| | | while (it.hasNext()) { |
| | | SystemMenu n = it.next(); |
| | | if (n.getParent_id().equals(t.getMenu_id())) { |
| | | tlist.add(n); |
| | | } |
| | | } |
| | | return tlist; |
| | | } |
| | | |
| | | /** |
| | | * 判断是否有子节点 |
| | | */ |
| | | private boolean hasChild(List<SystemMenu> list, SystemMenu t) { |
| | | return getChildList(list, t).size() > 0; |
| | | } |
| | | |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | //~ 以下为用户登录菜单展示使用,2022-11-12 |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | /** |
| | | * 返回菜单权限标识字符串集合,该方法若依前端使用。<p></p> |
| | | * 后续会去掉前端对权限点的依赖。 |
| | | * @param menuIdList |
| | | * @param showAll 是否显示所有权限点 |
| | | * @param menuScope 菜单范围,对独立顶级机构,可以显示机构设置的分类菜单范围,目前有:0-平台(包含3),4-顶级单位独立菜单 |
| | | * @return |
| | | * @date 2022-11-12 |
| | | * @date 2023-03-20 如果给定菜单id为空,则不返回任何权限点信息。时克英 |
| | | * @date 2023-06-07 对于独立单位(商户)则会显示所有该单位的菜单权限信息 |
| | | */ |
| | | public Set<String> getPermissionSet(List<String> menuIdList, boolean showAll, int menuScope){ |
| | | |
| | | // 2024-04-09 |
| | | this.checkReloadForceLocalMemory(); |
| | | |
| | | if(StringUtils.isEmptyList(menuIdList) && !showAll){ |
| | | return new HashSet<>(); |
| | | } |
| | | List<String> permsList = new ArrayList<>(64); |
| | | // List<S_menu> menuAll = this.getCacheMenuList(true, MenuUtils.MENU_SCOPE_PLATFORM); |
| | | List<S_menu> menuAll = this.getCacheMenuList(true, menuScope); |
| | | if(!StringUtils.isEmptyList(menuAll)){ |
| | | for(S_menu menu : menuAll){ |
| | | |
| | | // 2023-10-11 增加这个if判断,如果是不区分范围,则加载所有菜单 |
| | | // if(menuScope != MenuUtils.MENU_SCOPE_ALL){ |
| | | // |
| | | // // 2023-06-07 |
| | | // if(menuScope == MenuUtils.MENU_SCOPE_PLATFORM){ |
| | | // // 如果要展示菜单范围是:平台,则菜单中 >= 4的分类都不要,这些是顶级机构业务独立菜单。 |
| | | // if(menu.getType().intValue() >= MenuUtils.MENU_SCOPE_ORG){ |
| | | // continue; |
| | | // } |
| | | // } else if(menu.getType().intValue() < MenuUtils.MENU_SCOPE_ORG){ |
| | | // // 如果要展示菜单范围是:顶级机构业务的独立菜单,则平台菜单不显示。2023-06-01 |
| | | // continue; |
| | | // } |
| | | // } |
| | | // 2023-10-24 |
| | | if(MenuUtils.menuScopeNotMatch(menuScope, menu)){ |
| | | continue; |
| | | } |
| | | |
| | | if(StringUtils.isEmpty(menu.getPerms())){ |
| | | continue; |
| | | } |
| | | if(StringUtils.isEmptyList(menuIdList)){ |
| | | // 如果没有限制,全部加上 |
| | | permsList.add(menu.getPerms()); |
| | | } else if(menuIdList.contains(menu.getMenu_id())){ |
| | | // 如果限制有,则只添加给定的 |
| | | permsList.add(menu.getPerms()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | Set<String> permsSet = new HashSet<>(); |
| | | for(String perms : permsList){ |
| | | if (StringUtils.isNotEmpty(perms)) { |
| | | permsSet.addAll(Arrays.asList(perms.trim().split(","))); |
| | | } |
| | | } |
| | | return permsSet; |
| | | } |
| | | |
| | | /** |
| | | * 返回菜单树形结果,列表中包含多个菜单根节点,menuIdList 为空时,允许返回所有的。 |
| | | * @param menuIdList |
| | | * @param containButton |
| | | * @return |
| | | * @date 2023-03-22 |
| | | */ |
| | | public List<SystemMenu> getMenuTreeAll(List<String> menuIdList, boolean containButton, int menuScope){ |
| | | return this.getMenuTree(menuIdList, containButton, true, menuScope); |
| | | } |
| | | |
| | | /** |
| | | * 返回菜单树形结果,列表中包含多个菜单根节点。 |
| | | * @param menuIdList 指定显示的菜单,如果为空表示不特别限制 |
| | | * @param containButton 是否包含按钮权限 |
| | | * @param showAll 当给定'menuIdList'为空时,是否显示所有菜单 |
| | | * @return |
| | | * @date 2022-12-18 更新 |
| | | * @date 2023-03-22 添加参数'showAll' |
| | | */ |
| | | public List<SystemMenu> getMenuTree(List<String> menuIdList, boolean containButton, boolean showAll, int menuScope){ |
| | | List<SystemMenu> menuGroupList = new ArrayList<>(32); |
| | | if(StringUtils.isEmptyList(menuIdList) && !showAll){ |
| | | // 2023-03-22 给定为空菜单id,并且不允许显示所有,返回空菜单树。 |
| | | return getChildPerms(menuGroupList, "0"); |
| | | } |
| | | // List<S_menu> menuAll = this.getCacheMenuList(false); |
| | | List<S_menu> menuAll = this.getCacheMenuList(containButton, menuScope); |
| | | if(!StringUtils.isEmptyList(menuAll)){ |
| | | for(S_menu menu : menuAll){ |
| | | if(menuIdList == null){ |
| | | // 如果没有限制,全部加上 |
| | | menuGroupList.add(new SystemMenu(menu)); |
| | | } else if(menuIdList.contains(menu.getMenu_id())){ |
| | | // 如果限制有,则只添加给定的 |
| | | menuGroupList.add(new SystemMenu(menu)); |
| | | } |
| | | } |
| | | } |
| | | List<SystemMenu> menuGroupListOrder = menuGroupList.stream().sorted(Comparator.comparing(SystemMenu::getParent_id).thenComparing(SystemMenu::getOrder_num,Comparator.reverseOrder())).collect(Collectors.toList()); |
| | | return getChildPerms(menuGroupListOrder, "0"); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 构建前端路由所需要的菜单(若依) |
| | | * |
| | | * @param menus 菜单列表 |
| | | * @return 路由列表 |
| | | */ |
| | | @Deprecated |
| | | public List<RouterVo> buildMenus(List<SystemMenu> menus) { |
| | | List<RouterVo> routers = new LinkedList<RouterVo>(); |
| | | for (SystemMenu menu : menus) { |
| | | RouterVo router = new RouterVo(); |
| | | router.setHidden(MenuUtils.MENU_INVISIBLE.equals(menu.getVisible())); |
| | | router.setName(MenuUtils.getRouteName(menu)); |
| | | router.setPath(MenuUtils.getRouterPath(menu)); |
| | | router.setComponent(MenuUtils.getComponent(menu)); |
| | | router.setQuery(menu.getQuery()); |
| | | router.setMeta(new MetaVo(menu.getMenu_name(), menu.getIcon(), menu.getIs_cache().intValue() == MenuUtils.MENU_CACHE_DISABLE, menu.getPath())); |
| | | List<SystemMenu> cMenus = menu.getChildren(); |
| | | if (!cMenus.isEmpty() && cMenus.size() > 0 && menu.getMenu_type().equals(MenuUtils.MENU_TYPE_FOLDER)) { |
| | | router.setAlwaysShow(true); |
| | | router.setRedirect("noRedirect"); |
| | | router.setChildren(buildMenus(cMenus)); |
| | | } |
| | | else if (MenuUtils.isMenuFrame(menu)) { |
| | | router.setMeta(null); |
| | | List<RouterVo> childrenList = new ArrayList<RouterVo>(); |
| | | RouterVo children = new RouterVo(); |
| | | children.setPath(menu.getPath()); |
| | | children.setComponent(menu.getComponent()); |
| | | children.setName(StringUtils.capitalize(menu.getPath())); |
| | | children.setMeta(new MetaVo(menu.getMenu_name(), menu.getIcon(), menu.getIs_cache().intValue() == MenuUtils.MENU_CACHE_DISABLE, menu.getPath())); |
| | | children.setQuery(menu.getQuery()); |
| | | childrenList.add(children); |
| | | router.setChildren(childrenList); |
| | | } |
| | | else if (menu.getParent_id().equals(MenuUtils.MENU_ID_ROOT) && MenuUtils.isInnerLink(menu)) { |
| | | router.setMeta(new MetaVo(menu.getMenu_name(), menu.getIcon())); |
| | | router.setPath("/"); |
| | | List<RouterVo> childrenList = new ArrayList<RouterVo>(); |
| | | RouterVo children = new RouterVo(); |
| | | String routerPath = MenuUtils.innerLinkReplaceEach(menu.getPath()); |
| | | children.setPath(routerPath); |
| | | children.setComponent(MenuUtils.INNER_LINK); |
| | | children.setName(StringUtils.capitalize(routerPath)); |
| | | children.setMeta(new MetaVo(menu.getMenu_name(), menu.getIcon(), menu.getPath())); |
| | | childrenList.add(children); |
| | | router.setChildren(childrenList); |
| | | } |
| | | routers.add(router); |
| | | } |
| | | return routers; |
| | | } |
| | | |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | //~ 以下为系统权限管理使用,2022-11-02 |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | /** |
| | | * 返回系统所有角色与url关联数据,security权限配置实用。<p></p> |
| | | * 该方法会有重复数据,例如:多个角色具有相同的URL,由业务去除重复。<p></p> |
| | | * list[0] = role_id, list[1] = url <p></p> |
| | | * 因为Map对象相同key会覆盖value,所以换成List集合返回。 |
| | | * @return |
| | | * @date 2022-11-02 |
| | | */ |
| | | public List<String[]> getAllRoleMenuMap(){ |
| | | List<String[]> result = new ArrayList<>(); |
| | | List<Map<String, Object>> list = this.menuService.queryRolesPermList(); |
| | | if(StringUtils.isEmptyList(list)){ |
| | | return result; |
| | | } |
| | | |
| | | String perms = null; |
| | | String menuId = null; |
| | | S_menu menu = null; |
| | | |
| | | for(Map<String, Object> map : list){ |
| | | menuId = map.get("menu_id").toString(); |
| | | menu = this.getCacheData(menuId); |
| | | if(menu == null){ |
| | | throw new IllegalArgumentException("缓存中未找到菜单:" + menuId); |
| | | } |
| | | perms = menu.getPerms(); |
| | | if(StringUtils.isEmpty(perms)){ |
| | | continue; |
| | | } |
| | | // result.put(map.get("role_id").toString(), MenuUtils.acquireUrlFromPerms(perms)); |
| | | result.add(new String[]{map.get("role_id").toString(), MenuUtils.acquireUrlFromPerms(perms)}); |
| | | } |
| | | |
| | | // 2023-06-07 |
| | | // 商户(顶级机构)特有的菜单,也需要加入到角色中,设置默认三方角色:ROLE_MERCHANT |
| | | Set<String> merchantPermSet = this.getPermissionSet(null, true, MenuUtils.MENU_SCOPE_ORG); |
| | | if(merchantPermSet != null){ |
| | | for(String onePerms : merchantPermSet){ |
| | | result.add(new String[]{SecurityConstants.ROLE_MERCHANT, MenuUtils.acquireUrlFromPerms(onePerms)}); |
| | | } |
| | | logger.debug("添加商户(顶级机构)角色权限:{}", merchantPermSet.size()); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 返回系统所有菜单包含权限的url集合,即:所有perms存在的菜单。 |
| | | * @return |
| | | * @date 2022-11-02 |
| | | */ |
| | | public List<String> getAllMenuUrlList(){ |
| | | // 2024-04-09 |
| | | this.checkReloadForceLocalMemory(); |
| | | |
| | | List<String> urlList = new ArrayList<>(32); |
| | | S_menu menu = null; |
| | | String perms = null; |
| | | for(Iterator<Cachable> it = this.getCache().getIterator(); it.hasNext();){ |
| | | menu = (S_menu) it.next().getValue(); |
| | | perms = menu.getPerms(); |
| | | if(StringUtils.isEmpty(perms)){ |
| | | continue; |
| | | } |
| | | urlList.add(MenuUtils.acquireUrlFromPerms(perms)); |
| | | } |
| | | return urlList; |
| | | } |
| | | |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | //~ 必须重写写入、更新方法,以触发写入更新时间戳。2024-04-09 |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | @Override |
| | | public void putCacheData(String key, S_menu s_menu){ |
| | | super.putCacheData(key, s_menu); |
| | | this.menuUpdateCache.triggerTimeUpdate(); |
| | | } |
| | | |
| | | @Override |
| | | public void updateCacheData(String key, S_menu s_menu){ |
| | | super.updateCacheData(key, s_menu); |
| | | this.menuUpdateCache.triggerTimeUpdate(); |
| | | } |
| | | |
| | | /** |
| | | * <pre> |
| | | * 1) 从更新缓存中,找出更新时间; |
| | | * 2) 如果不存在则不更新,如果存在比较当前加载时间,大于初始加载时间则更新 |
| | | * </pre> |
| | | * @date 2024-04-09 |
| | | */ |
| | | private void checkReloadForceLocalMemory(){ |
| | | try{ |
| | | Long timeStamp = this.menuUpdateCache.getTimeUpdate(); |
| | | if(timeStamp == null){ |
| | | return; |
| | | } |
| | | |
| | | if(timeStamp.longValue() > this.reloadMills){ |
| | | synchronized (this._lock){ |
| | | logger.info("当前节点,菜单缓存存在更新时间:{},需要重新加载...", timeStamp); |
| | | this.reload(); |
| | | logger.debug("this.reloadMills = {}", this.reloadMills); |
| | | } |
| | | } |
| | | |
| | | } catch (Exception ex){ |
| | | logger.error("获取菜单更新时间缓存异常,获取不到时间,不重新加载:" + ex.getMessage(), ex); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | public void setMenuUpdateCache(RedisMenuUpdateCache menuUpdateCache) { |
| | | this.menuUpdateCache = menuUpdateCache; |
| | | } |
| | | |
| | | private long reloadMills = 0; // 缓存重新加载的时间(毫秒值) |
| | | private final Object _lock = new Object(); |
| | | |
| | | private RedisMenuUpdateCache menuUpdateCache; |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.walker.cache.Cache; |
| | | import com.walker.support.redis.cache.RedisCacheProvider; |
| | | |
| | | /** |
| | | * 验证码(Redis)缓存实现。 |
| | | * @date 2022-11-07 |
| | | */ |
| | | public class RedisCaptchaCacheProvider extends RedisCacheProvider<String> { |
| | | |
| | | public RedisCaptchaCacheProvider(){ |
| | | this.setUseRedis(true); |
| | | this.setLoadPage(false); |
| | | // 2024-01-05 设置支持缓存失效,该参数很重要,如果需要失效而没有设置在调用后会出现数据无法失效! |
| | | this.setSupportExpiredCache(true); |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_CAPTCHA; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return String.class; |
| | | } |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache){ |
| | | // 无需启动加载数据 |
| | | return 0; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.CategoryCacheProvider; |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.service.CategoryServiceImpl; |
| | | import com.iplatform.base.util.CategoryUtils; |
| | | import com.iplatform.base.util.cache.CategorySortComparator; |
| | | import com.iplatform.model.po.S_category; |
| | | import com.iplatform.model.vo.CategoryTreeVo; |
| | | import com.walker.cache.Cache; |
| | | import com.walker.infrastructure.ApplicationRuntimeException; |
| | | import com.walker.infrastructure.utils.JsonUtils; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.support.redis.cache.RedisCache; |
| | | import com.walker.support.redis.cache.RedisCacheProvider; |
| | | |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.net.URLDecoder; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 平台分类数据,Redis缓存实现。 |
| | | * @author 时克英 |
| | | * @date 2023-05-17 |
| | | */ |
| | | public class RedisCategoryCacheProvider extends RedisCacheProvider<S_category> implements CategoryCacheProvider { |
| | | |
| | | private final CategorySortComparator sortComparator = new CategorySortComparator(); |
| | | |
| | | public RedisCategoryCacheProvider(){ |
| | | this.setUseRedis(true); |
| | | this.setLoadPage(false); |
| | | } |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | List<S_category> hosts = this.categoryService.selectAll(new S_category()); |
| | | if(!StringUtils.isEmptyList(hosts)){ |
| | | // ------------------------- 切换成普通缓存步骤:3 |
| | | if(this.isUseRedis()){ |
| | | // 如果redis中缓存数量和数据库中不一致(少),则清空redis缓存,重新加载数据库数据到缓存中。 |
| | | long totalCache = cache.getPersistentSize(); |
| | | if(totalCache != hosts.size()){ |
| | | logger.info("redis缓存中Category数量小于实际用户,需要清空缓存重新加载! cache = " + totalCache + ", db = " + hosts.size()); |
| | | cache.clear(); |
| | | |
| | | for(S_category h : hosts){ |
| | | cache.put(String.valueOf(h.getId()), h); |
| | | } |
| | | } |
| | | }//------------------------------------------ |
| | | return hosts.size(); |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public List<CategoryTreeVo> getTree(Integer type, Integer status, String name, List<Integer> categoryIdList, int owner) { |
| | | List<S_category> allTree = new ArrayList<>(); |
| | | S_category tempCategory = null; |
| | | |
| | | for(String value : ((RedisCache)this.getCache()).getIterator(null)){ |
| | | try{ |
| | | tempCategory = JsonUtils.jsonStringToObject(value, S_category.class); |
| | | } catch (Exception ex){ |
| | | throw new ApplicationRuntimeException("redis存储'S_category'解析错误:" + value, ex); |
| | | } |
| | | if(CategoryUtils.isCondition(tempCategory, type, status, name, categoryIdList, owner)){ |
| | | allTree.add(tempCategory); |
| | | } |
| | | } |
| | | return CategoryUtils.acquireListTree(allTree, sortComparator); |
| | | } |
| | | |
| | | @Override |
| | | public List<CategoryTreeVo> getListTree(Integer type, Integer status, String name, int owner) { |
| | | if(StringUtils.isNotEmpty(name)){ |
| | | try { |
| | | name = URLDecoder.decode(name, StringUtils.DEFAULT_CHARSET_UTF8); |
| | | } catch (UnsupportedEncodingException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | return getTree(type, status, name, null, owner); |
| | | } |
| | | |
| | | @Override |
| | | public S_category get(int id) { |
| | | return this.getCacheData(String.valueOf(id)); |
| | | } |
| | | |
| | | @Override |
| | | public void save(S_category category) { |
| | | this.putCacheData(String.valueOf(category.getId()), category); |
| | | } |
| | | |
| | | @Override |
| | | public void update(S_category category) { |
| | | this.updateCacheData(String.valueOf(category.getId()), category); |
| | | } |
| | | |
| | | @Override |
| | | public void remove(int id) { |
| | | this.removeCacheData(String.valueOf(id)); |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_CATEGORY; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return S_category.class; |
| | | } |
| | | |
| | | public void setCategoryService(CategoryServiceImpl categoryService) { |
| | | this.categoryService = categoryService; |
| | | } |
| | | |
| | | private CategoryServiceImpl categoryService; |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.DeptCacheProvider; |
| | | import com.iplatform.base.service.DeptServiceImpl; |
| | | import com.iplatform.base.util.DeptUtils; |
| | | import com.iplatform.model.po.S_dept; |
| | | import com.walker.cache.Cache; |
| | | import com.walker.infrastructure.utils.JsonUtils; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.support.redis.cache.RedisCacheProvider; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | public class RedisDeptCacheProvider extends RedisCacheProvider<String> implements DeptCacheProvider { |
| | | |
| | | private boolean allowCacheChildren = true; |
| | | |
| | | private DeptServiceImpl deptService; |
| | | |
| | | public void setDeptService(DeptServiceImpl deptService) { |
| | | this.deptService = deptService; |
| | | } |
| | | |
| | | public RedisDeptCacheProvider(){ |
| | | this.setUseRedis(true); |
| | | this.setLoadPage(false); |
| | | } |
| | | |
| | | @Override |
| | | public void setAllowCacheChildren(boolean allow) { |
| | | this.allowCacheChildren = allow; |
| | | } |
| | | |
| | | @Override |
| | | public S_dept getDept(long deptId) { |
| | | // 超级用户虚拟一个机构 |
| | | if(deptId == 0){ |
| | | return DeptUtils.SUPER_VISOR_DEPT; |
| | | } |
| | | |
| | | String data = this.getCacheData(String.valueOf(deptId)); |
| | | if(StringUtils.isEmpty(data)){ |
| | | logger.error("查询机构缓存不存在,重新加载:" + deptId); |
| | | S_dept s_dept = this.deptService.queryOneDept(deptId); |
| | | if(s_dept == null){ |
| | | throw new IllegalStateException("数据库加载机构不存在,id=" + deptId); |
| | | } |
| | | try { |
| | | if(this.allowCacheChildren){ |
| | | this.putDept(s_dept); |
| | | } else { |
| | | this.putCacheData(String.valueOf(deptId), JsonUtils.objectToJsonString(s_dept)); |
| | | } |
| | | return s_dept; |
| | | } catch (Exception ex){ |
| | | throw new RuntimeException("添加 [机构] 缓存错误:" + ex.getMessage(), ex); |
| | | } |
| | | } |
| | | try { |
| | | return JsonUtils.jsonStringToObject(data, S_dept.class); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("获得机构缓存错误:" + deptId + ", " + e.getMessage(), e); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void updateDept(S_dept s_dept) { |
| | | try { |
| | | this.updateCacheData(String.valueOf(s_dept.getId()), JsonUtils.objectToJsonString(s_dept)); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("更新机构缓存错误:" + s_dept.getId() + ", " + e.getMessage(), e); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void removeDept(long deptId) { |
| | | String key = String.valueOf(deptId); |
| | | String keyChildren = key + DeptUtils.KEY_CHILDREN_PREFIX; |
| | | |
| | | S_dept current = this.getDept(deptId); |
| | | if(current == null){ |
| | | logger.warn("机构缓存已不存在,无需删除"); |
| | | return; |
| | | } |
| | | |
| | | // 删除该机构子机构缓存列表 |
| | | this.removeCacheData(keyChildren); |
| | | this.removeCacheData(key); |
| | | |
| | | if(current.getParent_id().longValue() == 0){ |
| | | return; |
| | | } |
| | | |
| | | // 2023-07-17,针对机构较大的项目,是不需要把机构树放Redis缓存的。 |
| | | if(this.allowCacheChildren){ |
| | | // 更新父机构对应的childrenList |
| | | String parentId = String.valueOf(current.getParent_id()); |
| | | List<String> parentChildrenList = this.getChildrenDeptIdOneLevel(current.getParent_id()); |
| | | if(parentChildrenList != null){ |
| | | parentChildrenList.remove(String.valueOf(deptId)); |
| | | try { |
| | | this.updateCacheData(parentId + DeptUtils.KEY_CHILDREN_PREFIX, JsonUtils.objectToJsonString(parentChildrenList)); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("删除机构缓存时,更新父节点childrenList报错:" + e.getMessage(), e); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void putDept(S_dept s_dept) { |
| | | String id = String.valueOf(s_dept.getId()); |
| | | try { |
| | | // 添加机构对象缓存 |
| | | this.putCacheData(id, JsonUtils.objectToJsonString(s_dept)); |
| | | if(this.allowCacheChildren){ |
| | | // 2023-07-17 |
| | | // 添加机构子机构列表,目前为空列表 |
| | | this.putCacheData(id + DeptUtils.KEY_CHILDREN_PREFIX, JsonUtils.objectToJsonString(new ArrayList<String>(2))); |
| | | } |
| | | |
| | | if(s_dept.getParent_id().longValue() == 0){ |
| | | // 顶级单位,没有父机构了 |
| | | logger.debug("顶级机构,不用更新父机构列表, " + id); |
| | | return; |
| | | } |
| | | |
| | | if(this.allowCacheChildren){ |
| | | // 2023-07-17 |
| | | // 更新父机构列表 |
| | | List<String> parentChildrenList = this.getChildrenDeptIdOneLevel(s_dept.getParent_id()); |
| | | if(StringUtils.isEmptyList(parentChildrenList)){ |
| | | parentChildrenList = new ArrayList<>(); |
| | | } |
| | | parentChildrenList.add(id); |
| | | this.updateCacheData(String.valueOf(s_dept.getParent_id()) + DeptUtils.KEY_CHILDREN_PREFIX, JsonUtils.objectToJsonString(parentChildrenList)); |
| | | if(logger.isDebugEnabled()){ |
| | | logger.debug("添加机构缓存,parentChildrenList = " + parentChildrenList); |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("添加 [机构] 缓存错误:" + e.getMessage(), e); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public List<String> getChildrenDeptIdOneLevel(long deptId) { |
| | | if(this.allowCacheChildren){ |
| | | String key = String.valueOf(deptId) + DeptUtils.KEY_CHILDREN_PREFIX; |
| | | String data = this.getCacheData(key); |
| | | if(StringUtils.isEmpty(data)){ |
| | | logger.error("未找到缓存中子机构列表: " + key); |
| | | return null; |
| | | } |
| | | try { |
| | | return JsonUtils.jsonStringToObject(data, List.class); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } else { |
| | | // 2023-07-17,不支持缓存树结构,从数据库查询 |
| | | throw new UnsupportedOperationException("暂未实现代码:从数据库加载:"+ deptId + " 下一级所有子机构ID集合"); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public List<S_dept> getChildrenDeptOneLevel(long deptId) { |
| | | List<String> childrenIdList = this.getChildrenDeptIdOneLevel(deptId); |
| | | if(StringUtils.isEmptyList(childrenIdList)){ |
| | | return null; |
| | | } |
| | | |
| | | List<S_dept> resultList = new ArrayList<>(); |
| | | S_dept s_dept = null; |
| | | for(String id : childrenIdList){ |
| | | s_dept = this.getDept(Long.parseLong(id)); |
| | | resultList.add(s_dept); |
| | | } |
| | | return resultList; |
| | | } |
| | | |
| | | // @Override |
| | | // protected int loadDataToCache(Cache cache) { |
| | | // List<S_dept> list = this.deptService.queryAllDeptListForCache(); |
| | | // if(!StringUtils.isEmptyList(list)){ |
| | | // // 如果redis中缓存数量和数据库中不一致(少),则清空redis缓存,重新加载数据库数据到缓存中。 |
| | | // long totalCache = cache.getPersistentSize(); |
| | | // if(totalCache < list.size()){ |
| | | // logger.info("redis缓存中[机构]数量小于实际用户,需要清空缓存重新加载! cache = " + totalCache + ", db = " + list.size()); |
| | | // cache.clear(); |
| | | // for(S_dept h : list){ |
| | | // this.putDept(h); |
| | | // } |
| | | // } |
| | | // return list.size(); |
| | | // } |
| | | // return 0; |
| | | // } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_DEPT; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return String.class; |
| | | } |
| | | |
| | | // private static final String KEY_CHILDREN_PREFIX = ".children"; |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.model.po.S_host; |
| | | import com.walker.cache.Cache; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.jdbc.service.PubService; |
| | | import com.walker.support.redis.cache.RedisCacheProvider; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 主机资源缓存(Redis方式)实现。 |
| | | * @author 时克英 |
| | | * @date 2022-09-20 |
| | | */ |
| | | public class RedisHostCacheProvider extends RedisCacheProvider<S_host> { |
| | | |
| | | private PubService pubService; |
| | | |
| | | public RedisHostCacheProvider(){ |
| | | this.setUseRedis(true); |
| | | this.setLoadPage(false); |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_HOST; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return S_host.class; |
| | | } |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | List<S_host> hosts = this.pubService.selectAll(new S_host()); |
| | | if(!StringUtils.isEmptyList(hosts)){ |
| | | // ------------------------- 切换成普通缓存步骤:3 |
| | | if(this.isUseRedis()){ |
| | | // 如果redis中缓存数量和数据库中不一致(少),则清空redis缓存,重新加载数据库数据到缓存中。 |
| | | long totalCache = cache.getPersistentSize(); |
| | | if(totalCache < hosts.size()){ |
| | | logger.info("redis缓存中用户数量小于实际用户,需要清空缓存重新加载! cache = " + totalCache + ", db = " + hosts.size()); |
| | | cache.clear(); |
| | | |
| | | for(S_host h : hosts){ |
| | | cache.put(String.valueOf(h.getId()), h); |
| | | } |
| | | } |
| | | }//------------------------------------------ |
| | | return hosts.size(); |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | public void setPubService(PubService pubService) { |
| | | this.pubService = pubService; |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.walker.infrastructure.utils.NumberGenerator; |
| | | import com.walker.support.redis.cache.RedisCacheProvider; |
| | | |
| | | /** |
| | | * 记录菜单缓存更新时间的缓存。 |
| | | * <pre> |
| | | * 1) 由于菜单缓存未使用Redis持久化,导致在集群环境中,无法触发全量更新。 |
| | | * 2) 因此采用记录更新时间记录到redis,当用户修改菜单数据后,记录修改时间; |
| | | * 3) 各个节点在调用方法前,检查时间,如果存在新时间则重新加载本地缓存。 |
| | | * </pre> |
| | | * @author 时克英 |
| | | * @date 2024-04-09 |
| | | */ |
| | | public class RedisMenuUpdateCache extends RedisCacheProvider<Long> { |
| | | |
| | | public RedisMenuUpdateCache(){ |
| | | this.setUseRedis(true); |
| | | this.setLoadPage(false); |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return "cache.base.menu_update"; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return Long.class; |
| | | } |
| | | |
| | | public void triggerTimeUpdate(){ |
| | | this.putCacheData(KEY_TIME_UPDATE, NumberGenerator.getSequenceNumber()); |
| | | } |
| | | |
| | | public Long getTimeUpdate(){ |
| | | return this.getCacheData(KEY_TIME_UPDATE); |
| | | } |
| | | |
| | | public static final String KEY_TIME_UPDATE = "time_update"; |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.NotificationTemplateCache; |
| | | import com.iplatform.base.NotifyConstants; |
| | | import com.iplatform.base.service.NotificationServiceImpl; |
| | | import com.iplatform.model.po.SfNotification; |
| | | import com.iplatform.model.po.SfTemplateMessage; |
| | | import com.iplatform.model.vo.NotificationTemplateVo; |
| | | import com.walker.cache.Cache; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.support.redis.cache.RedisCacheProvider; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | public class RedisNotificationTemplateCache extends RedisCacheProvider<NotificationTemplateVo> implements NotificationTemplateCache { |
| | | |
| | | public RedisNotificationTemplateCache(){ |
| | | this.setUseRedis(true); |
| | | this.setLoadPage(false); |
| | | } |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | List<SfNotification> notificationList = this.notificationService.selectAll(new SfNotification()); |
| | | if(!StringUtils.isEmptyList(notificationList)){ |
| | | // ------------------------- 切换成普通缓存步骤:3 |
| | | if(this.isUseRedis()){ |
| | | // 如果redis中缓存数量和数据库中不一致(少),则清空redis缓存,重新加载数据库数据到缓存中。 |
| | | long totalCache = cache.getPersistentSize(); |
| | | if(totalCache != notificationList.size()){ |
| | | logger.info(Constants.CACHE_NAME_NOTIFICATION_TEMPLATE + ": redis缓存中用户数量小于实际用户,需要清空缓存重新加载! cache = " + totalCache + ", db = " + notificationList.size()); |
| | | cache.clear(); |
| | | |
| | | Map<Long, SfTemplateMessage> templateMessageMap = this.notificationService.queryTemplateIdMap(); |
| | | if(templateMessageMap.size() == 0){ |
| | | logger.warn("提醒模板未找到任何有效数据"); |
| | | return 0; |
| | | } |
| | | for(SfNotification h : notificationList){ |
| | | NotificationTemplateVo vo = new NotificationTemplateVo(); |
| | | vo.setName(h.getMark()); |
| | | if(h.getIsWechat().intValue() == NotifyConstants.SWITCH_OPEN){ |
| | | vo.setWechat(true); |
| | | vo.setWechatId(h.getWechatId()); |
| | | vo.setWechatTempId(templateMessageMap.get(h.getWechatId().longValue()).getTempId()); |
| | | } |
| | | if(h.getIsRoutine().intValue() == NotifyConstants.SWITCH_OPEN){ |
| | | vo.setRoutine(true); |
| | | vo.setRoutineId(h.getRoutineId()); |
| | | vo.setRoutineTempId(templateMessageMap.get(h.getRoutineId().longValue()).getTempId()); |
| | | } |
| | | if(h.getIsSms().intValue() == NotifyConstants.SWITCH_OPEN){ |
| | | vo.setSms(true); |
| | | vo.setSmsId(h.getSmsId()); |
| | | vo.setSmsTempId(templateMessageMap.get(h.getSmsId().longValue()).getTempId()); |
| | | } |
| | | cache.put(h.getMark(), vo); |
| | | } |
| | | } |
| | | }//------------------------------------------ |
| | | return notificationList.size(); |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public NotificationTemplateVo get(String mark) { |
| | | return this.getCacheData(mark); |
| | | } |
| | | |
| | | @Override |
| | | public void save(NotificationTemplateVo category) { |
| | | this.putCacheData(category.getName(), category); |
| | | } |
| | | |
| | | @Override |
| | | public void update(NotificationTemplateVo category) { |
| | | this.updateCacheData(category.getName(), category); |
| | | } |
| | | |
| | | @Override |
| | | public void remove(String mark) { |
| | | this.removeCacheData(mark); |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_NOTIFICATION_TEMPLATE; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return NotificationTemplateVo.class; |
| | | } |
| | | |
| | | public void setNotificationService(NotificationServiceImpl notificationService) { |
| | | this.notificationService = notificationService; |
| | | } |
| | | |
| | | private NotificationServiceImpl notificationService; |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.PushCacheProvider; |
| | | import com.walker.support.redis.cache.RedisCacheProvider; |
| | | |
| | | public class RedisPushCacheProvider extends RedisCacheProvider<String> implements PushCacheProvider { |
| | | |
| | | public RedisPushCacheProvider(){ |
| | | this.setUseRedis(true); |
| | | this.setLoadPage(false); |
| | | // 2024-01-05 设置支持缓存失效,该参数很重要,如果需要失效而没有设置在调用后会出现数据无法失效! |
| | | this.setSupportExpiredCache(true); |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_PUSH; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return String.class; |
| | | } |
| | | |
| | | @Override |
| | | public void put(String key, String value) { |
| | | this.putCacheData(key, value, 60); |
| | | } |
| | | |
| | | @Override |
| | | public String get(String key) { |
| | | return this.getCacheData(key); |
| | | } |
| | | } |
New file |
| | |
| | | package com.iplatform.base.cache; |
| | | |
| | | import com.iplatform.base.Constants; |
| | | import com.iplatform.base.SystemGroupCache; |
| | | import com.iplatform.base.service.GroupServiceImpl; |
| | | import com.iplatform.model.po.S_group; |
| | | import com.iplatform.model.po.S_group_data; |
| | | import com.iplatform.model.vo.SystemGroupVo; |
| | | import com.walker.cache.Cache; |
| | | import com.walker.infrastructure.utils.StringUtils; |
| | | import com.walker.support.redis.cache.RedisCacheProvider; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | public class RedisSystemGroupCache extends RedisCacheProvider<SystemGroupVo> implements SystemGroupCache { |
| | | |
| | | public RedisSystemGroupCache(){ |
| | | this.setUseRedis(true); |
| | | this.setLoadPage(false); |
| | | } |
| | | |
| | | @Override |
| | | public SystemGroupVo get(int id) { |
| | | return this.getCacheData(String.valueOf(id)); |
| | | } |
| | | |
| | | @Override |
| | | public void save(SystemGroupVo category) { |
| | | this.putCacheData(String.valueOf(category.getId()), category); |
| | | } |
| | | |
| | | @Override |
| | | public void update(SystemGroupVo category) { |
| | | this.updateCacheData(String.valueOf(category.getId()), category); |
| | | } |
| | | |
| | | @Override |
| | | public void remove(int id) { |
| | | this.removeCacheData(String.valueOf(id)); |
| | | } |
| | | |
| | | @Override |
| | | protected int loadDataToCache(Cache cache) { |
| | | List<S_group> hosts = this.groupService.selectAll(new S_group()); |
| | | if(!StringUtils.isEmptyList(hosts)){ |
| | | if(this.isUseRedis()){ |
| | | // 如果redis中缓存数量和数据库中不一致(少),则清空redis缓存,重新加载数据库数据到缓存中。 |
| | | long totalCache = cache.getPersistentSize(); |
| | | if(totalCache != hosts.size()){ |
| | | logger.info("redis缓存中用户数量小于实际用户,需要清空缓存重新加载! cache = " + totalCache + ", db = " + hosts.size()); |
| | | cache.clear(); |
| | | |
| | | List<SystemGroupVo> groupVoList = new ArrayList<>(hosts.size()); |
| | | List<S_group_data> groupDataList = this.groupService.queryAllGroupDataList(); |
| | | for(S_group h : hosts){ |
| | | groupVoList.add(new SystemGroupVo(h)); |
| | | } |
| | | |
| | | if(!StringUtils.isEmptyList(groupDataList)){ |
| | | for(S_group_data data : groupDataList){ |
| | | for(SystemGroupVo vo : groupVoList){ |
| | | if(data.getGid().intValue() == vo.getId().intValue()){ |
| | | vo.addGroupData(data); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | for(SystemGroupVo h : groupVoList){ |
| | | cache.put(String.valueOf(h.getId()), h); |
| | | } |
| | | } |
| | | } |
| | | return hosts.size(); |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public String getProviderName() { |
| | | return Constants.CACHE_NAME_GROUP; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> getProviderType() { |
| | | return SystemGroupVo.class; |
| | | } |
| | | |
| | | public void setGroupService(GroupServiceImpl groupService) { |
| | | this.groupService = groupService; |
| | | } |
| | | |
| | | private GroupServiceImpl groupService; |
| | | } |
iplatform-base/src/main/java/com/iplatform/base/cache/RedisUserCacheProvider.java
iplatform-base/src/main/java/com/iplatform/base/cache/RedisUserLoginCache.java
iplatform-base/src/main/java/com/iplatform/base/cache/RedisUserOnlineProvider.java
iplatform-base/src/main/java/com/iplatform/base/cache/RedisWechatCache.java
iplatform-base/src/main/java/com/iplatform/base/callback/AfterLoginCallback.java
iplatform-base/src/main/java/com/iplatform/base/callback/GeneralLoginCallback.java
iplatform-base/src/main/java/com/iplatform/base/callback/PlatformCallbackPostProcessor.java
iplatform-base/src/main/java/com/iplatform/base/callback/SecurityCallback.java
iplatform-base/src/main/java/com/iplatform/base/callback/TestAfterLoginCallback.java
iplatform-base/src/main/java/com/iplatform/base/callback/TestUserCallback.java
iplatform-base/src/main/java/com/iplatform/base/callback/UserProfileCallback.java
iplatform-base/src/main/java/com/iplatform/base/captcha/AbstractCaptchaProvider.java
iplatform-base/src/main/java/com/iplatform/base/captcha/BlockPuzzleCaptchaProvider.java
iplatform-base/src/main/java/com/iplatform/base/captcha/DefaultCaptchaProvider.java
iplatform-base/src/main/java/com/iplatform/base/captcha/JigsawCaptchaProvider.java
iplatform-base/src/main/java/com/iplatform/base/captcha/JigsawResult.java
iplatform-base/src/main/java/com/iplatform/base/captcha/NoneCaptchaProvider.java
iplatform-base/src/main/java/com/iplatform/base/captcha/SmsCaptchaProvider.java
iplatform-base/src/main/java/com/iplatform/base/captcha/TextCaptchaProvider.java
iplatform-base/src/main/java/com/iplatform/base/captcha/ThirdPartyCaptchaProvider.java
iplatform-base/src/main/java/com/iplatform/base/config/ApiProperties.java
iplatform-base/src/main/java/com/iplatform/base/config/BeanPostProcessorConfig.java
iplatform-base/src/main/java/com/iplatform/base/config/CacheConfiguration.java
iplatform-base/src/main/java/com/iplatform/base/config/CacheProperties.java
iplatform-base/src/main/java/com/iplatform/base/config/CaptchaConfig.java
iplatform-base/src/main/java/com/iplatform/base/config/CaptchaProperties.java
iplatform-base/src/main/java/com/iplatform/base/config/DataImportConfig.java
iplatform-base/src/main/java/com/iplatform/base/config/DatabaseMetaConfig.java
iplatform-base/src/main/java/com/iplatform/base/config/DruidMonitorConfig.java
iplatform-base/src/main/java/com/iplatform/base/config/FileProperties.java
iplatform-base/src/main/java/com/iplatform/base/config/JacksonConfig.java
iplatform-base/src/main/java/com/iplatform/base/config/LocalCacheConfig.java
iplatform-base/src/main/java/com/iplatform/base/config/LogProperties.java
iplatform-base/src/main/java/com/iplatform/base/config/LoginStrategyProperties.java
iplatform-base/src/main/java/com/iplatform/base/config/PushConfig.java
iplatform-base/src/main/java/com/iplatform/base/config/PushProperties.java
iplatform-base/src/main/java/com/iplatform/base/config/PushWechatConfig.java
iplatform-base/src/main/java/com/iplatform/base/config/RedisCacheConfig.java
iplatform-base/src/main/java/com/iplatform/base/config/RestTemplateProperties.java
iplatform-base/src/main/java/com/iplatform/base/config/SecurityUserProperties.java
iplatform-base/src/main/java/com/iplatform/base/config/SpiConfig.java
iplatform-base/src/main/java/com/iplatform/base/config/TcpProperties.java
iplatform-base/src/main/java/com/iplatform/base/config/ThirdPartyConfig.java
iplatform-base/src/main/java/com/iplatform/base/config/ThreadPoolConfig.java
iplatform-base/src/main/java/com/iplatform/base/config/WebCommonConfig.java
iplatform-base/src/main/java/com/iplatform/base/controller/CaptchaController.java
iplatform-base/src/main/java/com/iplatform/base/controller/IndexController.java
iplatform-base/src/main/java/com/iplatform/base/controller/TestMenuController.java
iplatform-base/src/main/java/com/iplatform/base/controller/WechatCallbackApi.java
iplatform-base/src/main/java/com/iplatform/base/di/AbstractDataImportEngine.java
iplatform-base/src/main/java/com/iplatform/base/di/DataImportEngine.java
iplatform-base/src/main/java/com/iplatform/base/di/FileDataImportEngine.java
iplatform-base/src/main/java/com/iplatform/base/di/JdbcExcelDataImportor.java
iplatform-base/src/main/java/com/iplatform/base/di/PlatformDataImportEngine.java
iplatform-base/src/main/java/com/iplatform/base/di/PlatformExcelTemplateGenerator.java
iplatform-base/src/main/java/com/iplatform/base/di/TemplateInfo.java
iplatform-base/src/main/java/com/iplatform/base/event/RoleSecurityChangeEvent.java
iplatform-base/src/main/java/com/iplatform/base/exception/CaptchaException.java
iplatform-base/src/main/java/com/iplatform/base/exception/LoginException.java
iplatform-base/src/main/java/com/iplatform/base/pojo/CaptchaParam.java
iplatform-base/src/main/java/com/iplatform/base/pojo/ConfigParam.java
iplatform-base/src/main/java/com/iplatform/base/pojo/DeptParam.java
iplatform-base/src/main/java/com/iplatform/base/pojo/GroupDataParam.java
iplatform-base/src/main/java/com/iplatform/base/pojo/KeywordsParam.java
iplatform-base/src/main/java/com/iplatform/base/pojo/MenuParam.java
iplatform-base/src/main/java/com/iplatform/base/pojo/RequestLogin.java
iplatform-base/src/main/java/com/iplatform/base/pojo/UserInfo.java
iplatform-base/src/main/java/com/iplatform/base/pojo/UserInfoRequest.java
iplatform-base/src/main/java/com/iplatform/base/pojo/UserParam.java
iplatform-base/src/main/java/com/iplatform/base/pojo/dict/DictParam.java
iplatform-base/src/main/java/com/iplatform/base/pojo/form/FormData.java
iplatform-base/src/main/java/com/iplatform/base/pojo/form/FormDataItem.java
iplatform-base/src/main/java/com/iplatform/base/pojo/form/RequestForm.java
iplatform-base/src/main/java/com/iplatform/base/pojo/group/GroupData.java
iplatform-base/src/main/java/com/iplatform/base/pojo/log/LoginLogParam.java
iplatform-base/src/main/java/com/iplatform/base/pojo/log/OperateLogParam.java
iplatform-base/src/main/java/com/iplatform/base/pojo/notify/InfoParam.java
iplatform-base/src/main/java/com/iplatform/base/pojo/notify/NotificationParam.java
iplatform-base/src/main/java/com/iplatform/base/pojo/role/RoleAuthParam.java
iplatform-base/src/main/java/com/iplatform/base/pojo/role/RoleParam.java
iplatform-base/src/main/java/com/iplatform/base/pojo/role/RoleUserParam.java
iplatform-base/src/main/java/com/iplatform/base/push/DefaultPushListener.java
iplatform-base/src/main/java/com/iplatform/base/push/DefaultPushManager.java
iplatform-base/src/main/java/com/iplatform/base/push/MockSmsPush.java
iplatform-base/src/main/java/com/iplatform/base/push/SystemPush.java
iplatform-base/src/main/java/com/iplatform/base/service/ApiTimeServiceImpl.java
iplatform-base/src/main/java/com/iplatform/base/service/CategoryServiceImpl.java
iplatform-base/src/main/java/com/iplatform/base/service/CodeServiceImpl.java
iplatform-base/src/main/java/com/iplatform/base/service/CommonServiceImpl.java
iplatform-base/src/main/java/com/iplatform/base/service/ConfigArgumentServiceImpl.java
iplatform-base/src/main/java/com/iplatform/base/service/ConfigFormServiceImpl.java
iplatform-base/src/main/java/com/iplatform/base/service/DataImportServiceImpl.java
iplatform-base/src/main/java/com/iplatform/base/service/DeptServiceImpl.java
iplatform-base/src/main/java/com/iplatform/base/service/GroupServiceImpl.java
iplatform-base/src/main/java/com/iplatform/base/service/LogServiceImpl.java
iplatform-base/src/main/java/com/iplatform/base/service/LoginServiceImpl.java
iplatform-base/src/main/java/com/iplatform/base/service/MenuServiceImpl.java
iplatform-base/src/main/java/com/iplatform/base/service/NotificationServiceImpl.java
iplatform-base/src/main/java/com/iplatform/base/service/PushServiceImpl.java
iplatform-base/src/main/java/com/iplatform/base/service/RoleServiceImpl.java
iplatform-base/src/main/java/com/iplatform/base/service/UserDeptApiServiceImpl.java
iplatform-base/src/main/java/com/iplatform/base/service/UserServiceImpl.java
iplatform-base/src/main/java/com/iplatform/base/service_api/UserAndDeptServiceApi.java
iplatform-base/src/main/java/com/iplatform/base/support/CtomsDataSource.java
iplatform-base/src/main/java/com/iplatform/base/support/DatabaseArgumentsManager.java
iplatform-base/src/main/java/com/iplatform/base/support/DeptTreeGenerator.java
iplatform-base/src/main/java/com/iplatform/base/support/DictTreeGenerator.java
iplatform-base/src/main/java/com/iplatform/base/support/LoadBalanceFileOperateSpi.java
iplatform-base/src/main/java/com/iplatform/base/support/LogAspect.java
iplatform-base/src/main/java/com/iplatform/base/support/NothingSecuritySpi.java
iplatform-base/src/main/java/com/iplatform/base/support/PlatformOperationInterceptor.java
iplatform-base/src/main/java/com/iplatform/base/support/RedisArgumentsManager.java
iplatform-base/src/main/java/com/iplatform/base/support/TimeStatisticsInterceptor.java
iplatform-base/src/main/java/com/iplatform/base/support/strategy/AbstractLoginStrategy.java
iplatform-base/src/main/java/com/iplatform/base/support/strategy/LoginStrategyManager.java
iplatform-base/src/main/java/com/iplatform/base/support/strategy/MobileOnceLoginStrategy.java
iplatform-base/src/main/java/com/iplatform/base/support/strategy/WebOnceLoginStrategy.java
iplatform-base/src/main/java/com/iplatform/base/util/ArgumentsManagerUtils.java
iplatform-base/src/main/java/com/iplatform/base/util/CaptchaUtils.java
iplatform-base/src/main/java/com/iplatform/base/util/CategoryUtils.java
iplatform-base/src/main/java/com/iplatform/base/util/ConfigFormValidateUtils.java
iplatform-base/src/main/java/com/iplatform/base/util/DataImportUtils.java
iplatform-base/src/main/java/com/iplatform/base/util/DeptUtils.java
iplatform-base/src/main/java/com/iplatform/base/util/MenuUtils.java
iplatform-base/src/main/java/com/iplatform/base/util/NotificationUtils.java
iplatform-base/src/main/java/com/iplatform/base/util/PlatformRSAUtils.java
iplatform-base/src/main/java/com/iplatform/base/util/RandomUtils.java
iplatform-base/src/main/java/com/iplatform/base/util/ResponseValueUtils.java
iplatform-base/src/main/java/com/iplatform/base/util/RestTemplateUtils.java
iplatform-base/src/main/java/com/iplatform/base/util/RoleUtils.java
iplatform-base/src/main/java/com/iplatform/base/util/TextUtils.java
iplatform-base/src/main/java/com/iplatform/base/util/TokenUtils.java
iplatform-base/src/main/java/com/iplatform/base/util/UserUtils.java
iplatform-base/src/main/java/com/iplatform/base/util/VerifyImgUtil.java
iplatform-base/src/main/java/com/iplatform/base/util/cache/CacheInfo.java
iplatform-base/src/main/java/com/iplatform/base/util/cache/CategorySortComparator.java
iplatform-base/src/main/java/com/iplatform/base/util/dept/SystemDept.java
iplatform-base/src/main/java/com/iplatform/base/util/dict/SystemDictData.java
iplatform-base/src/main/java/com/iplatform/base/util/menu/MenuOrderNumComparator.java
iplatform-base/src/main/java/com/iplatform/base/util/menu/MenuTree.java
iplatform-base/src/main/java/com/iplatform/base/util/menu/ParentMenuComparator.java
iplatform-base/src/main/java/com/iplatform/base/util/menu/SystemMenu.java
iplatform-base/src/main/java/com/iplatform/base/util/role/SystemRole.java
iplatform-base/src/main/java/com/iplatform/base/util/user/SystemUser.java
iplatform-base/src/main/resources/images/demo.txt
iplatform-base/src/main/resources/images/jigsaw/original/1.png
iplatform-base/src/main/resources/images/jigsaw/original/2.png
iplatform-base/src/main/resources/images/jigsaw/original/3.png
iplatform-base/src/main/resources/images/jigsaw/original/4.png
iplatform-base/src/main/resources/images/jigsaw/original/5.png
iplatform-base/src/main/resources/images/jigsaw/original/6.png
iplatform-base/src/main/resources/images/jigsaw/slidingBlock/1.png
iplatform-base/src/main/resources/images/jigsaw/slidingBlock/2.png
iplatform-base/src/main/resources/images/jigsaw/slidingBlock/3.png
iplatform-base/src/main/resources/images/jigsaw/slidingBlock/4.png
iplatform-base/src/main/resources/images/jigsaw/slidingBlock/5.png
iplatform-base/src/main/resources/images/jigsaw/slidingBlock/6.png
iplatform-base/src/main/resources/images/jigsaw_bg/1.jpg
iplatform-base/src/main/resources/images/jigsaw_bg/10.jpg
iplatform-base/src/main/resources/images/jigsaw_bg/11.jpg
iplatform-base/src/main/resources/images/jigsaw_bg/11.png
iplatform-base/src/main/resources/images/jigsaw_bg/12.jpg
iplatform-base/src/main/resources/images/jigsaw_bg/13.jpg
iplatform-base/src/main/resources/images/jigsaw_bg/14.jpg
iplatform-base/src/main/resources/images/jigsaw_bg/15.jpg
iplatform-base/src/main/resources/images/jigsaw_bg/16.jpg
iplatform-base/src/main/resources/images/jigsaw_bg/2.jpg
iplatform-base/src/main/resources/images/jigsaw_bg/3.jpg
iplatform-base/src/main/resources/images/jigsaw_bg/4.jpg
iplatform-base/src/main/resources/images/jigsaw_bg/5.jpg
iplatform-base/src/main/resources/images/jigsaw_bg/6.jpg
iplatform-base/src/main/resources/images/jigsaw_bg/7.jpg
iplatform-base/src/main/resources/images/jigsaw_bg/8.jpg
iplatform-base/src/main/resources/images/jigsaw_bg/9.jpg
iplatform-base/src/main/resources/images/jigsaw_block/1.png
iplatform-base/src/main/resources/images/jigsaw_block/10.png
iplatform-base/src/main/resources/images/jigsaw_block/11.png
iplatform-base/src/main/resources/images/jigsaw_block/12.png
iplatform-base/src/main/resources/images/jigsaw_block/13.png
iplatform-base/src/main/resources/images/jigsaw_block/14.png
iplatform-base/src/main/resources/images/jigsaw_block/15.png
iplatform-base/src/main/resources/images/jigsaw_block/16.png
iplatform-base/src/main/resources/images/jigsaw_block/17.png
iplatform-base/src/main/resources/images/jigsaw_block/18.png
iplatform-base/src/main/resources/images/jigsaw_block/19.png
iplatform-base/src/main/resources/images/jigsaw_block/2.png
iplatform-base/src/main/resources/images/jigsaw_block/20.png
iplatform-base/src/main/resources/images/jigsaw_block/21.png
iplatform-base/src/main/resources/images/jigsaw_block/22.png
iplatform-base/src/main/resources/images/jigsaw_block/3.png
iplatform-base/src/main/resources/images/jigsaw_block/4.png
iplatform-base/src/main/resources/images/jigsaw_block/5.png
iplatform-base/src/main/resources/images/jigsaw_block/6.png
iplatform-base/src/main/resources/images/jigsaw_block/7.png
iplatform-base/src/main/resources/images/jigsaw_block/8.png
iplatform-base/src/main/resources/images/jigsaw_block/9.png
iplatform-base/src/test/java/com/iplatform/base/MenuCacheProvider.java
iplatform-base/src/test/java/com/iplatform/base/TestCaptcha.java
iplatform-base/src/test/java/com/iplatform/base/TestEntity.java
iplatform-base/src/test/java/com/iplatform/base/TestMenu.java
iplatform-base/src/test/java/com/iplatform/base/redis/MenuCacheProvider.java
iplatform-core/pom.xml
iplatform-core/src/main/java/com/iplatform/core/BeanContextAware.java
iplatform-core/src/main/java/com/iplatform/core/LoginStrategy.java
iplatform-core/src/main/java/com/iplatform/core/PlatformConfiguration.java
iplatform-core/src/main/java/com/iplatform/core/PlatformException.java
iplatform-core/src/main/java/com/iplatform/core/RegularConstants.java
iplatform-core/src/main/java/com/iplatform/core/SimpleVariable.java
iplatform-core/src/main/java/com/iplatform/core/TokenAwareContext.java
iplatform-core/src/main/java/com/iplatform/core/TokenEntity.java
iplatform-core/src/main/java/com/iplatform/core/UserMerchantType.java
iplatform-core/src/main/java/com/iplatform/core/config/BasicConfig.java
iplatform-core/src/main/java/com/iplatform/core/config/LoadBalanceProperties.java
iplatform-core/src/main/java/com/iplatform/core/config/PropertyPostProcessorConfig.java
iplatform-core/src/main/java/com/iplatform/core/config/enc/EncryptionWrapperDetector.java
iplatform-core/src/main/java/com/iplatform/core/config/enc/PropertySourcePostProcessor.java
iplatform-core/src/main/java/com/iplatform/core/config/enc/PropertySourceWrapper.java
iplatform-core/src/main/java/com/iplatform/core/util/AESUtils.java
iplatform-core/src/main/java/com/iplatform/core/util/ThreadUtils.java
iplatform-core/src/main/java/com/iplatform/core/workflow/AbstractContext.java
iplatform-core/src/main/java/com/iplatform/core/workflow/Actorable.java
iplatform-core/src/main/java/com/iplatform/core/workflow/Constants.java
iplatform-core/src/main/java/com/iplatform/core/workflow/Context.java
iplatform-core/src/main/java/com/iplatform/core/workflow/WorkflowCallback.java
iplatform-core/src/main/java/com/iplatform/core/workflow/WorkflowForm.java
iplatform-file-server/pom.xml
iplatform-file-server/src/main/java/com/iplatform/App.java
iplatform-file-server/src/main/java/com/iplatform/file/DefaultFileOperateSpi.java
iplatform-file-server/src/main/java/com/iplatform/file/FileEngineFactory.java
iplatform-file-server/src/main/java/com/iplatform/file/FileStoreCallback.java
iplatform-file-server/src/main/java/com/iplatform/file/config/FileConfig.java
iplatform-file-server/src/main/java/com/iplatform/file/config/FileWebConfig.java
iplatform-file-server/src/main/java/com/iplatform/file/config/FtpProperties.java
iplatform-file-server/src/main/java/com/iplatform/file/controller/AttachmentController.java
iplatform-file-server/src/main/java/com/iplatform/file/controller/FileController.java
iplatform-file-server/src/main/java/com/iplatform/file/controller/OssFileApi.java
iplatform-file-server/src/main/java/com/iplatform/file/service/FileServiceImpl.java
iplatform-file-server/src/main/java/com/iplatform/file/support/AbstractOssFileEngine.java
iplatform-file-server/src/main/java/com/iplatform/file/support/AliOssFileEngine.java
iplatform-file-server/src/main/java/com/iplatform/file/support/AttachmentJdbcCallback.java
iplatform-file-server/src/main/java/com/iplatform/file/support/AwsOssFileEngine.java
iplatform-file-server/src/main/java/com/iplatform/file/support/DefaultFileSystemEngine.java
iplatform-file-server/src/main/java/com/iplatform/file/support/DefaultFtpFileEngine.java
iplatform-file-server/src/main/java/com/iplatform/file/support/JdbcCallback.java
iplatform-file-server/src/main/java/com/iplatform/file/support/QnOssFileEngine.java
iplatform-file-server/src/main/java/com/iplatform/file/support/TxOssFileEngine.java
iplatform-file-server/src/main/java/com/iplatform/file/util/FileResultUtils.java
iplatform-file-server/src/main/java/com/iplatform/file/util/FileStoreUtils.java
iplatform-file-server/src/main/java/com/iplatform/file/util/ImageUtils.java
iplatform-file-server/src/main/java/com/iplatform/model/po/S_file.java
iplatform-file-server/src/main/java/com/iplatform/model/po/S_file_mapper.java
iplatform-file-server/src/main/java/com/iplatform/model/po/SfAttachment.java
iplatform-file-server/src/main/java/com/iplatform/model/po/SfAttachment_mapper.java
iplatform-file-server/src/main/java/com/iplatform/model/vo/FileResultVo.java
iplatform-file-server/src/test/java/com/iplatform/file/TestOss.java
iplatform-model-pojo/pom.xml
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_category.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_category_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_chat.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_chat_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_class_ext.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_class_ext_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_code.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_code_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_config.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_config_form.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_config_form_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_config_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_dept.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_dept_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_dialog_history.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_dialog_history_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_dialog_run.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_dialog_run_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_dict_data.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_dict_data_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_dict_type.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_dict_type_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_group.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_group_data.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_group_data_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_group_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_host.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_host_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_login_info.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_login_info_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_menu.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_menu_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_message.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_message_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_oper_log.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_oper_log_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_role.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_role_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_user_core.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_user_core_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_user_login.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_user_login_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_user_profile.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/S_user_profile_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/SfNotification.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/SfNotification_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/SfTemplateMessage.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/SfTemplateMessage_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/TcpEquip.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/TcpEquipHistory.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/TcpEquipHistory_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/TcpEquipStatus.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/TcpEquipStatus_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/po/TcpEquip_mapper.java
iplatform-model-pojo/src/main/java/com/iplatform/model/to/UserAndDeptTo.java
iplatform-model-pojo/src/main/java/com/iplatform/model/to/UserAndDeptToResult.java
iplatform-model-pojo/src/main/java/com/iplatform/model/vo/ApiTime.java
iplatform-model-pojo/src/main/java/com/iplatform/model/vo/CategoryTreeVo.java
iplatform-model-pojo/src/main/java/com/iplatform/model/vo/ConfigFormItemConfigRegListVo.java
iplatform-model-pojo/src/main/java/com/iplatform/model/vo/ConfigFormItemConfigVo.java
iplatform-model-pojo/src/main/java/com/iplatform/model/vo/ConfigFormItemVo.java
iplatform-model-pojo/src/main/java/com/iplatform/model/vo/ConfigFormVo.java
iplatform-model-pojo/src/main/java/com/iplatform/model/vo/CopyRightVo.java
iplatform-model-pojo/src/main/java/com/iplatform/model/vo/MenuVo.java
iplatform-model-pojo/src/main/java/com/iplatform/model/vo/MetaVo.java
iplatform-model-pojo/src/main/java/com/iplatform/model/vo/NotificationConfigVo.java
iplatform-model-pojo/src/main/java/com/iplatform/model/vo/NotificationTemplateVo.java
iplatform-model-pojo/src/main/java/com/iplatform/model/vo/OrderCenterNumVo.java
iplatform-model-pojo/src/main/java/com/iplatform/model/vo/RouterVo.java
iplatform-model-pojo/src/main/java/com/iplatform/model/vo/SystemGroupVo.java
iplatform-model-pojo/src/main/java/com/iplatform/model/vo/WeChatAccessTokenVo.java
pom.xml |