# travel-tms **Repository Path**: liulisuiyue_admin/travel-tms ## Basic Information - **Project Name**: travel-tms - **Description**: No description available - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-02-08 - **Last Updated**: 2022-03-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 1.git地址 > http://10.1.20.170/yanjing/yjtms.git > sql地址:zlt-doc下 # gsoft-plateform ## 一、环境准备 > 1.redis > 2.nacos > 3.mysql 5.7+ ,8.0.14+ ## 二、项目启动 ### ### 2.1 启动认证中心 > 运行 zlt-uaa ### 2.2启动用户中心 > 运行 User-Center ### 2.3 启动网关 > 运行 sc-gateway ### 2.4 启动前端工程 > 运行 zlt-web ### 2.5 文件中心(选启) > 运行 file-center ### 2.6 分布式调度中心(选启) > 运行 job-admin ## 三、教程 ### 3.1 url 说明 1. ``` url: config.base_server + 'api-user/users' api-user 用户服务 --api断言 users 接口映射名称 ``` ​ ### 3.2 自定义异常与检查不通过返回 ``` if (checkAdmin(id)) { return Result.failed("用户无权限!"); //throw new BusinessException("用户无权限!"); } ``` ### 3.3 增删改查 规范 ``` /** * 查询 */ @ApiOperation(value = "查询") @GetMapping("/{id}") public Result findUserById(@PathVariable Long id) { OrdOrder model = ordOrderService.getById(id); return Result.succeed(model, "查询成功"); } /** * 新增or更新 */ @ApiOperation(value = "保存") @PostMapping public Result save(@RequestBody OrdOrder ordOrder) { ordOrderService.saveOrUpdate(ordOrder); return Result.succeed("保存成功"); } /** * 删除 */ @ApiOperation(value = "删除") @DeleteMapping("/{id}") public Result delete(@PathVariable Long id) { ordOrderService.removeById(id); return Result.succeed("删除成功"); } ``` ### 3.4 查询分页对象 ``` /** * 订单查询 * * @param params * @return */ @ApiOperation(value = "用户查询列表") @ApiImplicitParams({ @ApiImplicitParam(name = "page", value = "分页起始位置", required = true, dataType = "Integer"), @ApiImplicitParam(name = "limit", value = "分页结束位置", required = true, dataType = "Integer") }) @GetMapping("/orders") public PageResult findOrders(@RequestParam Map params) { return ordOrderService.findList(params); } ``` ### 3.5上传、下载图片和文件 ``` //图片上传 upload.render({ elem: '#fileBtn' , url: config.base_server + 'api-file/files-anon', accept: 'file' , auto: true , headers: {"Authorization" : "Bearer " + config.getToken().access_token}, before: function(obj){ layer.load(); //上传loading //预读本地文件示例,不支持ie8 obj.preview(function (index, file, result) { $(".layui-upload-img").remove(); $('#demo2').append('' + file.name + '') }); }, done: function(data){ layer.closeAll('loading'); console.log(data); $("[name=headImgUrl]").val(data.url); }, error: function (data) { layer.closeAll('loading'); } }); ``` ``` //文件上传 var importUrl = config.base_server + 'api-user/users/import'; upload.render({ elem: '#user-btn-import' ,url: importUrl ,accept: 'file' //普通文件 ,multiple: false ,headers: {"Authorization" : "Bearer " + config.getToken().access_token} ,done: function(data){ if (data.resp_code == 0) { layer.msg(data.resp_msg, {icon: 1, time: 500}); table.reload('user-table', {}); } else { layer.msg(data.resp_msg, {icon: 2, time: 500}); } } }); -----后台 @PostMapping(value = "/users/import") public Result importExcl(@RequestParam("file") MultipartFile excl) throws Exception { int rowNum = 0; if(!excl.isEmpty()) { List list = ExcelUtil.importExcel(excl, 0, 1, SysUserExcel.class); rowNum = list.size(); if (rowNum > 0) { List users = new ArrayList<>(rowNum); list.forEach(u -> { SysUser user = new SysUser(); BeanUtil.copyProperties(u, user); user.setPassword(CommonConstant.DEF_USER_PASSWORD); user.setType(UserType.BACKEND.name()); users.add(user); }); appUserService.saveBatch(users); } } return Result.succeed("导入数据成功,一共【"+rowNum+"】行"); } ``` ### 3.6 创建定时任务 3.6.1 先在项目中创建jobhandle 3.6.2 在后台任务管理页面配置对应的执行规则和对应的jobhandle ### 3.7 服务之间调用方式 3.7.1 依赖被调用方的api 3.7.2 创建feign 客户端去调用接口 ### 3.8 导出 ``` // 导出 $('#user-btn-export').click(function () { var url = config.base_server + 'api-user/users/export'; var xhr = new XMLHttpRequest(); xhr.open('POST', url, true); xhr.responseType = "blob"; xhr.setRequestHeader("client_type", "DESKTOP_WEB"); xhr.setRequestHeader("Authorization", "Bearer " + config.getToken().access_token); xhr.onload = function() { if (this.status == 200) { var fileName = "user.xlsx"; var blob = this.response; var a = document.createElement('a'); a.innerHTML = fileName; // 指定生成的文件名 a.download = fileName; a.href = URL.createObjectURL(blob); document.body.appendChild(a); var evt = document.createEvent("MouseEvents"); evt.initEvent("click", false, false); a.dispatchEvent(evt); document.body.removeChild(a); } } xhr.send(); }); ``` ``` List result = appUserService.findAllUsers(params); //导出操作 ExcelUtil.exportExcel(result, null, "用户", SysUserExcel.class, "user", response); ``` ### 3.9 流水生成器 ``` @Autowired private ISerialNumberService serialNumberService; String orderCode = serialNumberService.generateNum(key); log.info(port+"---流水号"+orderCode); ``` ### 3.10 token请求方式2 ``` http://10.1.20.222:9900/api-user/roles?access_token=2600442e-7f39-4236-aa20-717e4726d38e&page=1&limit=10 ``` ### 3.11 分布式事务seata1.2 1. 导入nacos配置,文件在zlt-doc/seata/下 2. 下载seat1.2版本,并修改file.conf,register.conf 3. 启动 4. 测试样例 ``` @ApiOperation(value = "修改用户状态") @GetMapping("/users/updateEnabled") @ApiImplicitParams({ @ApiImplicitParam(name = "id", value = "用户id", required = true, dataType = "Integer"), @ApiImplicitParam(name = "enabled", value = "是否启用", required = true, dataType = "Boolean") }) @GlobalTransactional public Result updateEnabled(@RequestParam Map params) { Long id = MapUtils.getLong(params, "id"); if (checkAdmin(id)) { //return Result.failed("用户无权限!"); } Result result = appUserService.updateEnabled(params); //测试服务2事务 //更改订单状态 OrdOrder one = ordOrderServiceFeign.findOne("1"); log.info(MessageFormat.format("更改前订单状态;{0}",one.getStatus())); one.setStatus("200"); OrdOrder orderDb= ordOrderServiceFeign.updateOrdStatus(one); log.info(MessageFormat.format("更改前订单状态;{0}",orderDb.getStatus())); //int i=1/0; return result; } ``` 5. 配置文件 file.conf ``` ## transaction log store, only used in seata-server store { ## store mode: file、db mode = "db" ## file store property file { ## store location dir dir = "sessionStore" # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions maxBranchSessionSize = 16384 # globe session size , if exceeded throws exceptions maxGlobalSessionSize = 512 # file buffer size , if exceeded allocate new buffer fileWriteBufferCacheSize = 16384 # when recover batch read size sessionReloadReadSize = 100 # async, sync flushDiskMode = async } ## database store property db { ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc. datasource = "druid" ## mysql/oracle/postgresql/h2/oceanbase etc. dbType = "mysql" driverClassName = "com.mysql.cj.jdbc.Driver" url = "jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai" user = "root" password = "root" minConn = 5 maxConn = 30 globalTable = "global_table" branchTable = "branch_table" lockTable = "lock_table" queryLimit = 100 maxWait = 5000 } } ``` register.conf ``` registry { # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa type = "nacos" nacos { application = "seata-server" serverAddr = "localhost" namespace = "" cluster = "testCluster" username = "nacos" password = "nacos" } } config { # file、nacos 、apollo、zk、consul、etcd3 type = "nacos" nacos { serverAddr = "127.0.0.1:8848" namespace = "" group = "SEATA_GROUP" username = "nacos" password = "nacos" } } ``` ### 3.12 前台按钮自动化控制 注:每次更改过权限后,重新登录才生效; 1. 增加按钮权限资源 以用户添加按钮为例: 在菜单管理添加: ``` 菜单名称:用户添加 菜单URL:/api-user/users/saveOrUpdate 菜单PATH:user-btn-add 菜单图标:请输入菜单图标 是否隐藏 : 否 是否为菜单: 否 请求方法 : POST ``` 2. 给用户分配该权限 在角色管理处,分配该用户是否拥有该按钮权限 3. 前台代码: 在需要控制的按钮上添加 style="display: none" ``` //判断权限,没有权限则隐藏按钮(需在每个要控制的html页面添加) let resList = ['user-btn-add','user-btn-export','user-btn-import']; //控制的按钮权限 for(let i = 0; i < resList.length; i++){ if (admin.hasPerm(resList[i])) { //有的话 再显示,这样避免,刷新页面的时候,用户看到从有到无消失的那一瞬间 $('#'+resList[i]).show(); } } ``` # 开发规范 ### maven规范 * 除了根工程的pom.xml之外,子工程的pom.xml引入的jar都不予许设置version属性 * 基本的包版本控制主要由以下3个来控制 ``` spring-boot-dependencies platform-bom spring-cloud-dependencies ``` * 新增加jar包依赖的步骤如下 1. 先查看父工程/根工程是否已引入该jar 2. 查看根工程的dependencyManagement是否已经有该jar的管理 3. 如果没有则查看以下地址的Appendix A. Dependency versions 是否有该jar的管理 ``` ``` ``` 4. 都没有的话则自己添加该jar的管理,先去根工程的properties里添加版本号,再去dependencyManagement里添加该jar ### 3.9 获取当前登录人 > //例1:只有id、username 和 roles public void test(@LoginUser SysUser user) > > //例2:能获取SysUser对象的所有信息 public void test(@LoginUser(isFull = true) SysUser user) ### 接口规范 * 按照restful接口设计规范 GET (SELECT):从服务器检索特定资源,或资源列表。 POST (CREATE):在服务器上创建一个新的资源。 PUT (UPDATE):更新服务器上的资源,提供整个资源。 PATCH (UPDATE):更新服务器上的资源,仅提供更改的属性。 DELETE (DELETE):从服务器删除资源。 * 接口尽量使用名词,禁止使用动词,下面是一些例子 ​```java GET /zoos:列出所有动物园 POST /zoos:新建一个动物园 GET /zoos/{id}:获取某个指定动物园的信息 PUT /zoos/{id}:更新某个指定动物园的信息(提供该动物园的全部信息) PATCH /zoos/{id}:更新某个指定动物园的信息(提供该动物园的部分信息) DELETE /zoos/{id}:删除某个动物园 GET /zoos/{id}/animals:列出某个指定动物园的所有动物 DELETE /zoos/{zId}/animals/{aId}:删除某个指定动物园的指定动物 ``` * 反例: ``` /getAllCars /createNewCar /deleteAllRedCars ``` ### 后端返回JSON * 后端统一返回 com.central.common.model.Result 对象 * datas:具体响应的其他信息 * resp_code:响应码,目前0是成功、1是失败 * resp_msg:响应消息 ### ### Q&S 1. 前端页面id不要一样,容易引起冲突 ``` 1.最常见的就是表格id一样,会渲染冲突 2.页面标签id在所有的html页面保持唯一 3.规范: id="user-form-submit" id="user-btn-import" 注释:当前目录name-按钮-name ``` 2. 存放临时数据 ``` admin.putTempData('t_user', data); //取值 // 回显user数据 var user = admin.getTempData('t_user'); ``` 3. 表单提交 ``` // 表单提交事件 form.on('submit(order-form-submit)', function (data) {}); ``` 4.