新增app登录模块

This commit is contained in:
wanggeng888 2021-04-07 23:10:57 +08:00
parent ad2824c6dd
commit 5437d02aa0
29 changed files with 2851 additions and 0 deletions

22
login-app/pom.xml Normal file
View File

@ -0,0 +1,22 @@
<?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>wg-basic</artifactId>
<groupId>ink.wgink</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>login-app</artifactId>
<dependencies>
<dependency>
<groupId>ink.wgink</groupId>
<artifactId>login-base</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,66 @@
package ink.wgink.login.app.controller.api.appsign;
import ink.wgink.annotation.CheckRequestBodyAnnotation;
import ink.wgink.exceptions.ParamsException;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.login.app.pojo.vos.appsign.AppLoginDefaultVO;
import ink.wgink.login.app.pojo.vos.appsign.AppLoginPhoneVO;
import ink.wgink.login.app.service.appsign.IAppSignService;
import ink.wgink.pojo.result.ErrorResult;
import ink.wgink.pojo.result.SuccessResultData;
import ink.wgink.util.RegexUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.springframework.beans.factory.annotation.Autowired;
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;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: AppSignController
* @Description: 登录
* @Author: wanggeng
* @Date: 2021/4/7 3:55 下午
* @Version: 1.0
*/
@Api(tags = ISystemConstant.API_TAGS_APP_PREFIX + "登录")
@RestController
@RequestMapping(ISystemConstant.APP_PREFIX + "/sign")
public class AppSignController {
@Autowired
private IAppSignService appSignService;
@ApiOperation(value = "APP用户名密码登录", notes = "APP用户名密码登录接口")
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@PostMapping("default")
@CheckRequestBodyAnnotation
public synchronized SuccessResultData<String> defaultSign(@RequestBody AppLoginDefaultVO appLoginDefaultVO) throws Exception {
return new SuccessResultData<>(appSignService.defaultSign(appLoginDefaultVO));
}
@ApiOperation(value = "APP手机验证码登录", notes = "APP手机验证码登录接口")
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@PostMapping("phone")
@CheckRequestBodyAnnotation
public synchronized SuccessResultData<String> phone(@RequestBody AppLoginPhoneVO appLoginPhoneVO) throws Exception {
if (!RegexUtil.isPhone(appLoginPhoneVO.getUsername())) {
throw new ParamsException("用户名非手机格式");
}
// String verificationCode = VerificationCodeManager.getInstance().getVerificationCode(appLoginPhoneVO.getUsername());
// if (StringUtils.isBlank(verificationCode)) {
// throw new ParamsException("验证码为空");
// }
// if (!StringUtils.equalsIgnoreCase(verificationCode, appLoginPhoneVO.getVerificationCode())) {
// throw new ParamsException("验证码错误");
// }
return new SuccessResultData<>(appSignService.phoneSign(appLoginPhoneVO));
}
}

View File

@ -0,0 +1,147 @@
package ink.wgink.login.app.controller.api.appverion;
import ink.wgink.annotation.CheckRequestBodyAnnotation;
import ink.wgink.common.base.DefaultBaseController;
import ink.wgink.exceptions.RemoveException;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.login.app.pojo.dtos.appversion.AppVersionDTO;
import ink.wgink.login.app.pojo.vos.appversion.AppVersionSaveVO;
import ink.wgink.login.app.pojo.vos.appversion.AppVersionVO;
import ink.wgink.login.app.service.appversion.IAppVersionService;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.result.ErrorResult;
import ink.wgink.pojo.result.SuccessResult;
import ink.wgink.pojo.result.SuccessResultList;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* @ClassName: AppVersionController
* @Description: app版本
* @Author: admin
* @Date: 2019-08-26 14:50:40
* @Version: 1.0
**/
@Api(tags = ISystemConstant.API_TAGS_SYSTEM_PREFIX + "app版本管理接口")
@RestController
@RequestMapping(ISystemConstant.API_PREFIX + "/appversion")
public class AppVersionController extends DefaultBaseController {
@Autowired
private IAppVersionService appVersionService;
@ApiOperation(value = "app版本新增", notes = "app版本新增接口")
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@PostMapping("save")
@CheckRequestBodyAnnotation
public SuccessResult saveAppVersion(@RequestBody AppVersionSaveVO appVersionSaveVO) {
appVersionService.save(appVersionSaveVO);
return new SuccessResult();
}
@ApiOperation(value = "app版本删除", notes = "通过id列表批量删除app版本接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "ids", value = "app版本ID列表用下划线分隔", paramType = "path", example = "1_2_3")
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@DeleteMapping("remove/{ids}")
public SuccessResult remove(@PathVariable("ids") String ids) throws RemoveException {
appVersionService.remove(Arrays.asList(ids.split("\\_")));
return new SuccessResult();
}
@ApiOperation(value = "app版本修改", notes = "app版本修改接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "appVersionId", value = "app版本ID", paramType = "path")
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@PutMapping("update/{appVersionId}")
@CheckRequestBodyAnnotation
public SuccessResult update(@PathVariable("appVersionId") String appVersionId, @RequestBody AppVersionVO appVersionVO) {
appVersionService.update(appVersionId, appVersionVO);
return new SuccessResult();
}
@ApiOperation(value = "更新APP接口锁定状态", notes = "更新APP接口锁定状态接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "appVersionId", value = "app版本ID", paramType = "path"),
@ApiImplicitParam(name = "appApiLock", value = "接口版本锁定", paramType = "path")
})
@PutMapping("update-api-lock/{appVersionId}/{appApiLock}")
public SuccessResult updateAppApiLock(@PathVariable("appVersionId") String appVersionId, @PathVariable("appApiLock") Integer appApiLock) {
appVersionService.updateApiLock(appVersionId, appApiLock);
return new SuccessResult();
}
@ApiOperation(value = "更新APP为发布状态", notes = "更新APP为发布状态接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "appVersionId", value = "app版本ID", paramType = "path"),
})
@PutMapping("update-release/{appVersionId}")
public SuccessResult updateRelease(@PathVariable("appVersionId") String appVersionId) {
appVersionService.updateRelease(appVersionId, 1);
return new SuccessResult();
}
@ApiOperation(value = "更新APP为未发布状态", notes = "更新APP为未发布状态接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "appVersionId", value = "app版本ID", paramType = "path"),
})
@PutMapping("update-unrelease/{appVersionId}")
public SuccessResult updateUnRelease(@PathVariable("appVersionId") String appVersionId) {
appVersionService.updateRelease(appVersionId, 0);
return new SuccessResult();
}
@ApiOperation(value = "app版本列表", notes = "app版本列表接口")
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@GetMapping("list")
public List<AppVersionDTO> listAppVersion() {
Map<String, Object> params = getParams();
return appVersionService.list(params);
}
@ApiOperation(value = "app版本详情", notes = "app版本详情接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "appVersionId", value = "app版本ID", paramType = "path")
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@GetMapping("get/{appVersionId}")
public AppVersionDTO get(@PathVariable("appVersionId") String appVersionId) {
return appVersionService.get(appVersionId);
}
@ApiOperation(value = "分页app版本列表", notes = "分页app版本列表接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "page", value = "当前页码", paramType = "query", dataType = "int", defaultValue = "1"),
@ApiImplicitParam(name = "rows", value = "显示数量", paramType = "query", dataType = "int", defaultValue = "20"),
@ApiImplicitParam(name = "keywords", value = "关键字", paramType = "query", dataType = "String"),
@ApiImplicitParam(name = "startTime", value = "开始时间", paramType = "query", dataType = "String"),
@ApiImplicitParam(name = "endTime", value = "结束时间", paramType = "query", dataType = "String")
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@GetMapping("listpage")
public SuccessResultList<List<AppVersionDTO>> listPageAppVersion(ListPage page) {
Map<String, Object> params = requestParams();
page.setParams(params);
return appVersionService.listPage(page);
}
@ApiOperation(value = "获取app二维码", notes = "获取app二维码接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "appVersionId", value = "app版本ID", paramType = "path")
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@GetMapping("downloadqrcode/{appVersionId}")
public void downloadQrCode(@PathVariable("appVersionId") String appVersionId, HttpServletResponse response) throws IOException {
appVersionService.downloadQrCode(appVersionId, response);
}
}

View File

@ -0,0 +1,61 @@
package ink.wgink.login.app.controller.app.api.appversion;
import ink.wgink.common.base.DefaultBaseController;
import ink.wgink.exceptions.FileException;
import ink.wgink.exceptions.SearchException;
import ink.wgink.exceptions.UpdateException;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.login.app.service.appversion.IAppVersionService;
import ink.wgink.pojo.result.ErrorResult;
import ink.wgink.pojo.result.SuccessResultData;
import io.swagger.annotations.*;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.AbstractController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: AppVersionAppController
* @Description: app版本
* @Author: WangGeng
* @Date: 2019/8/26 4:30 下午
* @Version: 1.0
**/
@Api(tags = ISystemConstant.API_TAGS_APP_PREFIX + "app版本管理接口")
@RestController
@RequestMapping(ISystemConstant.APP_PREFIX + "/appversion")
public class AppVersionAppController extends DefaultBaseController {
@Autowired
private IAppVersionService appVersionService;
@ApiOperation(value = "获取app当前版本", notes = "获取app当前版本接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "appVersionId", value = "app版本ID", paramType = "path")
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@GetMapping("get-number/{appVersionId}")
public SuccessResultData<Integer> getNumber(@PathVariable("appVersionId") String appVersionId) throws SearchException {
return new SuccessResultData<>(appVersionService.getNumber(appVersionId));
}
@ApiOperation(value = "下载app", notes = "下载app接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "appVersionId", value = "app版本ID", paramType = "path")
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@GetMapping("download/{appVersionId}")
public void download(@PathVariable("appVersionId") String appVersionId, HttpServletRequest request, HttpServletResponse response) throws SearchException, FileException, UpdateException {
appVersionService.download(appVersionId, request, response);
}
}

View File

@ -0,0 +1,40 @@
package ink.wgink.login.app.controller.route.appversion;
import ink.wgink.interfaces.consts.ISystemConstant;
import io.swagger.annotations.Api;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: LogRouteController
* @Description: 日志
* @Author: wanggeng
* @Date: 2021/3/1 10:41 上午
* @Version: 1.0
*/
@Api(tags = ISystemConstant.API_TAGS_APP_ROUTE_PREFIX + "版本控制")
@Controller
@RequestMapping(ISystemConstant.ROUTE_PREFIX + "/appversion")
public class AppVersionRouteController {
@GetMapping("list")
public ModelAndView list() {
return new ModelAndView("appversion/list");
}
@GetMapping("save")
public ModelAndView save() {
return new ModelAndView("appversion/save");
}
@GetMapping("update")
public ModelAndView update() {
return new ModelAndView("appversion/update");
}
}

View File

@ -0,0 +1,68 @@
package ink.wgink.login.app.dao.appdeviceuser;
import ink.wgink.exceptions.RemoveException;
import ink.wgink.exceptions.SaveException;
import ink.wgink.exceptions.SearchException;
import ink.wgink.exceptions.UpdateException;
import ink.wgink.login.app.pojo.dtos.appdeviceuser.AppDeviceUserDTO;
import ink.wgink.login.app.pojo.pos.appdeviceuser.AppDeviceUserPO;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: IAppDeviceUserDao
* @Description: app设备用户
* @Author: wanggeng
* @Date: 2021/4/7 4:23 下午
* @Version: 1.0
*/
@Repository
public interface IAppDeviceUserDao {
/**
* 建表
*
* @throws UpdateException
*/
void createTable() throws UpdateException;
/**
* 保存
*
* @param params
* @throws SaveException
*/
void save(Map<String, Object> params) throws SaveException;
/**
* 删除物理
*
* @param params
* @throws RemoveException
*/
void delete(Map<String, Object> params) throws RemoveException;
/**
* 列表
*
* @param params
* @return
* @throws SearchException
*/
List<AppDeviceUserDTO> list(Map<String, Object> params) throws SearchException;
/**
* 列表
*
* @param params
* @return
* @throws SearchException
*/
List<AppDeviceUserPO> listPO(Map<String, Object> params) throws SearchException;
}

View File

@ -0,0 +1,118 @@
package ink.wgink.login.app.dao.appversion;
import ink.wgink.exceptions.RemoveException;
import ink.wgink.exceptions.SaveException;
import ink.wgink.exceptions.SearchException;
import ink.wgink.exceptions.UpdateException;
import ink.wgink.login.app.pojo.dtos.appversion.AppVersionDTO;
import ink.wgink.login.app.pojo.pos.appversion.AppVersionPO;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: IAppDeviceDao
* @Description: app设备
* @Author: wanggeng
* @Date: 2021/4/7 4:22 下午
* @Version: 1.0
*/
@Repository
public interface IAppVersionDao {
/**
* 建表
*
* @throws UpdateException
*/
void createTable() throws UpdateException;
/**
* 新增app版本
*
* @param params
* @throws SaveException
*/
void save(Map<String, Object> params) throws SaveException;
/**
* 删除app版本
*
* @param params
* @throws RemoveException
*/
void remove(Map<String, Object> params) throws RemoveException;
/**
* 修改app版本
*
* @param params
* @throws UpdateException
*/
void update(Map<String, Object> params) throws UpdateException;
/**
* 更新下载次数
*
* @param appVersionId
* @throws UpdateException
*/
void updateDownloadCount(String appVersionId) throws UpdateException;
/**
* 更新APP接口锁定状态
*
* @param params
* @throws UpdateException
*/
void updateApiLock(Map<String, Object> params) throws UpdateException;
/**
* 更新APP的发布状态
*
* @param params
* @throws UpdateException
*/
void updateRelease(Map<String, Object> params) throws UpdateException;
/**
* app版本列表
*
* @param params
* @return
* @throws SearchException
*/
List<AppVersionDTO> list(Map<String, Object> params) throws SearchException;
/**
* 详情
*
* @param params
* @return
* @throws SearchException
*/
AppVersionDTO get(Map<String, Object> params) throws SearchException;
/**
* app版本列表
*
* @param params
* @return
* @throws SearchException
*/
List<AppVersionPO> listPO(Map<String, Object> params) throws SearchException;
/**
* 详情
*
* @param params
* @return
* @throws SearchException
*/
AppVersionPO getPO(Map<String, Object> params) throws SearchException;
}

View File

@ -0,0 +1,42 @@
package ink.wgink.login.app.pojo.dtos.appdeviceuser;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: AppDeviceUserDTO
* @Description: app设备用户
* @Author: wanggeng
* @Date: 2021/4/7 4:34 下午
* @Version: 1.0
*/
@ApiModel
public class AppDeviceUserDTO implements Serializable {
private static final long serialVersionUID = 7352338869750340418L;
@ApiModelProperty(name = "userId", value = "用户ID")
private String userId;
@ApiModelProperty(name = "deviceNo", value = "设备编号")
private String deviceNo;
public String getUserId() {
return userId == null ? "" : userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getDeviceNo() {
return deviceNo == null ? "" : deviceNo;
}
public void setDeviceNo(String deviceNo) {
this.deviceNo = deviceNo;
}
}

View File

@ -0,0 +1,134 @@
package ink.wgink.login.app.pojo.dtos.appversion;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: AppDeviceDTO
* @Description: app设备
* @Author: wanggeng
* @Date: 2021/4/7 4:33 下午
* @Version: 1.0
*/
@ApiModel
public class AppVersionDTO {
@ApiModelProperty(name = "appVersionId", value = "app版本ID")
private String appVersionId;
@ApiModelProperty(name = "appName", value = "APP名称")
private String appName;
@ApiModelProperty(name = "appSummary", value = "APP说明")
private String appSummary;
@ApiModelProperty(name = "appVersion", value = "APP版本号")
private Integer appVersion;
@ApiModelProperty(name = "appDownloadCount", value = "下载次数")
private Integer appDownloadCount;
@ApiModelProperty(name = "appFile", value = "APP文件")
private String appFile;
@ApiModelProperty(name = "appApiLock", value = "接口版本锁定")
private Integer appApiLock;
@ApiModelProperty(name = "isNecessary", value = "强制更新0:否1:是")
private Integer isNecessary;
@ApiModelProperty(name = "isRelease", value = "是否发布0:否1:是")
private Integer isRelease;
public String getAppVersionId() {
return appVersionId == null ? "" : appVersionId;
}
public void setAppVersionId(String appVersionId) {
this.appVersionId = appVersionId;
}
public String getAppName() {
return appName == null ? "" : appName;
}
public void setAppName(String appName) {
this.appName = appName;
}
public String getAppSummary() {
return appSummary == null ? "" : appSummary;
}
public void setAppSummary(String appSummary) {
this.appSummary = appSummary;
}
public Integer getAppVersion() {
return appVersion == null ? 0 : appVersion;
}
public void setAppVersion(Integer appVersion) {
this.appVersion = appVersion;
}
public Integer getAppDownloadCount() {
return appDownloadCount == null ? 0 : appDownloadCount;
}
public void setAppDownloadCount(Integer appDownloadCount) {
this.appDownloadCount = appDownloadCount;
}
public String getAppFile() {
return appFile == null ? "" : appFile;
}
public void setAppFile(String appFile) {
this.appFile = appFile;
}
public Integer getAppApiLock() {
return appApiLock == null ? 0 : appApiLock;
}
public void setAppApiLock(Integer appApiLock) {
this.appApiLock = appApiLock;
}
public Integer getIsNecessary() {
return isNecessary == null ? 0 : isNecessary;
}
public void setIsNecessary(Integer isNecessary) {
this.isNecessary = isNecessary;
}
public Integer getIsRelease() {
return isRelease == null ? 0 : isRelease;
}
public void setIsRelease(Integer isRelease) {
this.isRelease = isRelease;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"appVersionId\":\"")
.append(appVersionId).append('\"');
sb.append(",\"appName\":\"")
.append(appName).append('\"');
sb.append(",\"appSummary\":\"")
.append(appSummary).append('\"');
sb.append(",\"appVersion\":")
.append(appVersion);
sb.append(",\"appDownloadCount\":")
.append(appDownloadCount);
sb.append(",\"appFile\":\"")
.append(appFile).append('\"');
sb.append(",\"appApiLock\":")
.append(appApiLock);
sb.append(",\"isNecessary\":")
.append(isNecessary);
sb.append(",\"isRelease\":")
.append(isRelease);
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,47 @@
package ink.wgink.login.app.pojo.pos.appdeviceuser;
import java.io.Serializable;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: AppDeviceUserPO
* @Description: app设备用户
* @Author: wanggeng
* @Date: 2021/4/7 4:34 下午
* @Version: 1.0
*/
public class AppDeviceUserPO implements Serializable {
private static final long serialVersionUID = -3532724359534273591L;
private String userId;
private String deviceNo;
public String getUserId() {
return userId == null ? "" : userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getDeviceNo() {
return deviceNo == null ? "" : deviceNo;
}
public void setDeviceNo(String deviceNo) {
this.deviceNo = deviceNo;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"userId\":\"")
.append(userId).append('\"');
sb.append(",\"deviceNo\":\"")
.append(deviceNo).append('\"');
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,126 @@
package ink.wgink.login.app.pojo.pos.appversion;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: AppDevicePO
* @Description: app设备
* @Author: wanggeng
* @Date: 2021/4/7 4:33 下午
* @Version: 1.0
*/
public class AppVersionPO implements Serializable {
private static final long serialVersionUID = 6906701658888507376L;
private String appVersionId;
private String appName;
private String appSummary;
private Integer appVersion;
private Integer appDownloadCount;
private String appFile;
private Integer appApiLock;
private Integer isNecessary;
private Integer isRelease;
public String getAppVersionId() {
return appVersionId == null ? "" : appVersionId;
}
public void setAppVersionId(String appVersionId) {
this.appVersionId = appVersionId;
}
public String getAppName() {
return appName == null ? "" : appName;
}
public void setAppName(String appName) {
this.appName = appName;
}
public String getAppSummary() {
return appSummary == null ? "" : appSummary;
}
public void setAppSummary(String appSummary) {
this.appSummary = appSummary;
}
public Integer getAppVersion() {
return appVersion == null ? 0 : appVersion;
}
public void setAppVersion(Integer appVersion) {
this.appVersion = appVersion;
}
public Integer getAppDownloadCount() {
return appDownloadCount == null ? 0 : appDownloadCount;
}
public void setAppDownloadCount(Integer appDownloadCount) {
this.appDownloadCount = appDownloadCount;
}
public String getAppFile() {
return appFile == null ? "" : appFile;
}
public void setAppFile(String appFile) {
this.appFile = appFile;
}
public Integer getAppApiLock() {
return appApiLock == null ? 0 : appApiLock;
}
public void setAppApiLock(Integer appApiLock) {
this.appApiLock = appApiLock;
}
public Integer getIsNecessary() {
return isNecessary == null ? 0 : isNecessary;
}
public void setIsNecessary(Integer isNecessary) {
this.isNecessary = isNecessary;
}
public Integer getIsRelease() {
return isRelease == null ? 0 : isRelease;
}
public void setIsRelease(Integer isRelease) {
this.isRelease = isRelease;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"appVersionId\":\"")
.append(appVersionId).append('\"');
sb.append(",\"appName\":\"")
.append(appName).append('\"');
sb.append(",\"appSummary\":\"")
.append(appSummary).append('\"');
sb.append(",\"appVersion\":")
.append(appVersion);
sb.append(",\"appDownloadCount\":")
.append(appDownloadCount);
sb.append(",\"appFile\":\"")
.append(appFile).append('\"');
sb.append(",\"appApiLock\":")
.append(appApiLock);
sb.append(",\"isNecessary\":")
.append(isNecessary);
sb.append(",\"isRelease\":")
.append(isRelease);
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,40 @@
package ink.wgink.login.app.pojo.vos.appsign;
import ink.wgink.annotation.CheckEmptyAnnotation;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: LoginDefault
* @Description: 默认登录
* @Author: WangGeng
* @Date: 2020/6/3 9:11
* @Version: 1.0
**/
@ApiModel
public class AppLoginDefaultVO extends AppLoginVO {
@ApiModelProperty(name = "password", value = "密码")
@CheckEmptyAnnotation(name = "密码")
private String password;
public String getPassword() {
return password == null ? "" : password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"password\":\"")
.append(password).append('\"');
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,40 @@
package ink.wgink.login.app.pojo.vos.appsign;
import ink.wgink.annotation.CheckEmptyAnnotation;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: LoginVO
* @Description: 登录
* @Author: WangGeng
* @Date: 2019-08-01 14:33
* @Version: 1.0
**/
@ApiModel
public class AppLoginPhoneVO extends AppLoginVO {
@ApiModelProperty(name = "verificationCode", value = "验证码")
@CheckEmptyAnnotation(name = "验证码")
private String verificationCode;
public String getVerificationCode() {
return verificationCode == null ? "" : verificationCode;
}
public void setVerificationCode(String verificationCode) {
this.verificationCode = verificationCode;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"verificationCode\":\"")
.append(verificationCode).append('\"');
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,100 @@
package ink.wgink.login.app.pojo.vos.appsign;
import ink.wgink.annotation.CheckEmptyAnnotation;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: LoginVO
* @Description: 登录
* @Author: WangGeng
* @Date: 2019-08-01 14:33
* @Version: 1.0
**/
@ApiModel
public class AppLoginVO {
@ApiModelProperty(name = "username", value = "用户名")
@CheckEmptyAnnotation(name = "用户名")
private String username;
@ApiModelProperty(name = "deviceNo", value = "设备编号")
private String deviceNo;
@ApiModelProperty(name = "longitude", value = "经度")
private String longitude;
@ApiModelProperty(name = "latitude", value = "纬度")
private String latitude;
@ApiModelProperty(name = "appId", value = "appId")
private String appId;
@ApiModelProperty(name = "appVersion", value = "app版本")
private Integer appVersion;
public String getUsername() {
return username == null ? "" : username.trim();
}
public void setUsername(String username) {
this.username = username;
}
public String getDeviceNo() {
return deviceNo == null ? "" : deviceNo.trim();
}
public void setDeviceNo(String deviceNo) {
this.deviceNo = deviceNo;
}
public String getLongitude() {
return longitude == null ? "" : longitude.trim();
}
public void setLongitude(String longitude) {
this.longitude = longitude;
}
public String getLatitude() {
return latitude == null ? "" : latitude.trim();
}
public void setLatitude(String latitude) {
this.latitude = latitude;
}
public String getAppId() {
return appId == null ? "" : appId.trim();
}
public void setAppId(String appId) {
this.appId = appId;
}
public Integer getAppVersion() {
return appVersion;
}
public void setAppVersion(Integer appVersion) {
this.appVersion = appVersion;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"username\":")
.append("\"").append(username).append("\"");
sb.append(",\"deviceNo\":")
.append("\"").append(deviceNo).append("\"");
sb.append(",\"longitude\":")
.append("\"").append(longitude).append("\"");
sb.append(",\"latitude\":")
.append("\"").append(latitude).append("\"");
sb.append(",\"appId\":")
.append("\"").append(appId).append("\"");
sb.append(",\"appVersion\":")
.append(appVersion);
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,35 @@
package ink.wgink.login.app.pojo.vos.appversion;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* @ClassName: AppVersionVO
* @Description: app版本
* @Author: admin
* @Date: 2019-08-26 14:50:40
* @Version: 1.0
**/
@ApiModel
public class AppVersionSaveVO extends AppVersionVO {
@ApiModelProperty(name = "appName", value = "APP名称")
private String appName;
public String getAppName() {
return appName;
}
public void setAppName(String appName) {
this.appName = appName;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"appName\":\"")
.append(appName).append('\"');
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,77 @@
package ink.wgink.login.app.pojo.vos.appversion;
import ink.wgink.annotation.CheckEmptyAnnotation;
import ink.wgink.annotation.CheckNumberAnnotation;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* @ClassName: AppVersionVO
* @Description: app版本
* @Author: admin
* @Date: 2019-08-26 14:50:40
* @Version: 1.0
**/
@ApiModel
public class AppVersionVO {
@ApiModelProperty(name = "appSummary", value = "APP说明")
@CheckEmptyAnnotation(name = "APP说明")
private String appSummary;
@ApiModelProperty(name = "isNecessary", value = "强制更新")
@CheckNumberAnnotation(name = "强制更新")
private Integer isNecessary;
@ApiModelProperty(name = "isRelease", value = "是否发布")
@CheckNumberAnnotation(name = "是否发布")
private Integer isRelease;
@ApiModelProperty(name = "appFile", value = "APP文件")
@CheckEmptyAnnotation(name = "APP文件")
private String appFile;
public String getAppSummary() {
return appSummary;
}
public void setAppSummary(String appSummary) {
this.appSummary = appSummary;
}
public Integer getIsNecessary() {
return isNecessary;
}
public void setIsNecessary(Integer isNecessary) {
this.isNecessary = isNecessary;
}
public Integer getIsRelease() {
return isRelease;
}
public void setIsRelease(Integer isRelease) {
this.isRelease = isRelease;
}
public String getAppFile() {
return appFile;
}
public void setAppFile(String appFile) {
this.appFile = appFile;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"appSummary\":\"")
.append(appSummary).append('\"');
sb.append(",\"isNecessary\":")
.append(isNecessary);
sb.append(",\"isRelease\":")
.append(isRelease);
sb.append(",\"appFile\":\"")
.append(appFile).append('\"');
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,72 @@
package ink.wgink.login.app.service.appdeviceuser;
import ink.wgink.login.app.pojo.dtos.appdeviceuser.AppDeviceUserDTO;
import ink.wgink.login.app.pojo.pos.appdeviceuser.AppDeviceUserPO;
import ink.wgink.util.date.DateUtil;
import java.util.List;
import java.util.Map;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: IAppDeviceUserService
* @Description: 设备用户
* @Author: wanggeng
* @Date: 2021/4/7 4:21 下午
* @Version: 1.0
*/
public interface IAppDeviceUserService {
/**
* 保存
*
* @param deviceNo 设备号
* @param userId 用户ID
*/
void save(String deviceNo, String userId);
/**
* 列表
*
* @param params
* @return
*/
List<AppDeviceUserDTO> list(Map<String, Object> params);
/**
* 列表
*
* @param userId 用户ID
* @return
*/
List<AppDeviceUserDTO> listByUserId(String userId);
/**
* 列表
*
* @param params
* @return
*/
List<AppDeviceUserPO> listPO(Map<String, Object> params);
/**
* 列表
*
* @param userId 用户ID
* @return
*/
List<AppDeviceUserPO> listPOByUserId(String userId);
/**
* 判断APP是否能登录
*
* @param userId
* @param deviceNo
* @return
*/
boolean canSign(String userId, String deviceNo);
}

View File

@ -0,0 +1,95 @@
package ink.wgink.login.app.service.appdeviceuser.impl;
import ink.wgink.common.base.DefaultBaseService;
import ink.wgink.login.app.dao.appdeviceuser.IAppDeviceUserDao;
import ink.wgink.login.app.pojo.dtos.appdeviceuser.AppDeviceUserDTO;
import ink.wgink.login.app.pojo.pos.appdeviceuser.AppDeviceUserPO;
import ink.wgink.login.app.service.appdeviceuser.IAppDeviceUserService;
import ink.wgink.login.base.manager.ConfigManager;
import ink.wgink.util.date.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: AppDeviceUserServiceImpl
* @Description: 设备用户
* @Author: wanggeng
* @Date: 2021/4/7 4:21 下午
* @Version: 1.0
*/
@Service
public class AppDeviceUserServiceImpl extends DefaultBaseService implements IAppDeviceUserService {
@Autowired
private IAppDeviceUserDao appDeviceUserDao;
@Override
public void save(String deviceNo, String userId) {
Map<String, Object> params = getHashMap(2);
params.put("deviceNo", deviceNo);
params.put("userId", userId);
params.put("gmtCreate", DateUtil.getTime());
appDeviceUserDao.save(params);
}
@Override
public List<AppDeviceUserDTO> list(Map<String, Object> params) {
return appDeviceUserDao.list(params);
}
@Override
public List<AppDeviceUserDTO> listByUserId(String userId) {
Map<String, Object> params = getHashMap(2);
params.put("userId", userId);
return list(params);
}
@Override
public List<AppDeviceUserPO> listPO(Map<String, Object> params) {
return appDeviceUserDao.listPO(params);
}
@Override
public List<AppDeviceUserPO> listPOByUserId(String userId) {
Map<String, Object> params = getHashMap(2);
params.put("userId", userId);
return listPO(params);
}
@Override
public boolean canSign(String userId, String deviceNo) {
Object appDeviceCountObject = ConfigManager.getInstance().getConfig().get("appDeviceCount");
if (Objects.isNull(appDeviceCountObject)) {
return true;
}
Integer appDeviceCount = Integer.parseInt(appDeviceCountObject.toString());
if (appDeviceCount == 0) {
return true;
}
List<AppDeviceUserPO> appDeviceUserPOs = listPOByUserId(userId);
boolean canLogin = false;
if (!appDeviceUserPOs.isEmpty()) {
for (AppDeviceUserPO appDeviceUserPO : appDeviceUserPOs) {
if (StringUtils.equals(deviceNo, appDeviceUserPO.getDeviceNo())) {
canLogin = true;
break;
}
}
}
if (!canLogin && appDeviceUserPOs.size() < appDeviceCount) {
LOG.debug("绑定设备");
save(deviceNo, userId);
canLogin = true;
}
return canLogin;
}
}

View File

@ -0,0 +1,36 @@
package ink.wgink.login.app.service.appsign;
import ink.wgink.interfaces.app.IAppSignBaseService;
import ink.wgink.login.app.pojo.vos.appsign.AppLoginDefaultVO;
import ink.wgink.login.app.pojo.vos.appsign.AppLoginPhoneVO;
import java.io.UnsupportedEncodingException;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: IAppSignService
* @Description: 登录
* @Author: wanggeng
* @Date: 2021/4/7 3:58 下午
* @Version: 1.0
*/
public interface IAppSignService extends IAppSignBaseService {
/**
* APP用户名密码登录
*
* @param appLoginDefaultVO
* @return token
*/
String defaultSign(AppLoginDefaultVO appLoginDefaultVO) throws UnsupportedEncodingException;
/**
* APP手机验证码登录
*
* @param appLoginPhoneVO
* @return token
*/
String phoneSign(AppLoginPhoneVO appLoginPhoneVO) throws UnsupportedEncodingException;
}

View File

@ -0,0 +1,126 @@
package ink.wgink.login.app.service.appsign.impl;
import ink.wgink.exceptions.AppDeviceException;
import ink.wgink.exceptions.AppVersionException;
import ink.wgink.exceptions.SearchException;
import ink.wgink.exceptions.UpdateException;
import ink.wgink.login.app.pojo.vos.appsign.AppLoginDefaultVO;
import ink.wgink.login.app.pojo.vos.appsign.AppLoginPhoneVO;
import ink.wgink.login.app.pojo.vos.appsign.AppLoginVO;
import ink.wgink.login.app.service.appdeviceuser.IAppDeviceUserService;
import ink.wgink.login.app.service.appsign.IAppSignService;
import ink.wgink.login.app.service.appversion.IAppVersionService;
import ink.wgink.login.base.service.BaseAppSignService;
import ink.wgink.service.user.pojo.pos.UserPO;
import ink.wgink.service.user.service.IUserService;
import ink.wgink.util.date.DateUtil;
import ink.wgink.util.request.RequestUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: AppSignServiceImpl
* @Description: 登录
* @Author: wanggeng
* @Date: 2021/4/7 3:59 下午
* @Version: 1.0
*/
@Service
public class AppSignServiceImpl extends BaseAppSignService implements IAppSignService {
@Autowired
private IAppDeviceUserService appDeviceUserService;
@Autowired
private IAppVersionService appVersionService;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private IUserService userService;
@Override
public String defaultSign(AppLoginDefaultVO appLoginDefaultVO) throws UnsupportedEncodingException {
String userPassword = appLoginDefaultVO.getPassword();
checkApiLock(appLoginDefaultVO);
UserPO userPO = userService.getPOByUsername(appLoginDefaultVO.getUsername());
if (userPO == null) {
throw new SearchException("用户不存在");
}
if (!passwordEncoder.matches(userPassword, userPO.getUserPassword())) {
throw new SearchException("用户名或密码错误");
}
userLogin(appLoginDefaultVO, userPO);
return getToken(userPO);
}
@Override
public String phoneSign(AppLoginPhoneVO appLoginPhoneVO) throws UnsupportedEncodingException {
UserPO userPO = userService.getPOByUsername(appLoginPhoneVO.getUsername());
if (userPO == null) {
throw new SearchException("用户不存在");
}
userLogin(appLoginPhoneVO, userPO);
return getToken(userPO);
}
/**
* 用户登陆如果设备编号存在则通过设备编号判断是否可以登录
*
* @param appLoginVO
* @param userPO
*/
private void userLogin(AppLoginVO appLoginVO, UserPO userPO) {
if (userPO.getUserState() == 1) {
throw new SearchException("账号已冻结");
}
if (userPO.getUserState() == 2) {
throw new SearchException("账号已锁定");
}
LOG.debug("校验设备");
if (!StringUtils.isBlank(appLoginVO.getDeviceNo()) && !appDeviceUserService.canSign(userPO.getUserId(), appLoginVO.getDeviceNo())) {
throw new AppDeviceException("非法登录设备");
}
LOG.debug("更新登录信息");
updateLoginInfo(userPO, appLoginVO.getLongitude(), appLoginVO.getLatitude());
}
/**
* 更新登录信息
*
* @param userPO
* @param userLongitude
* @param userLatitude
* @throws UpdateException
*/
private void updateLoginInfo(UserPO userPO, Object userLongitude, Object userLatitude) throws UpdateException {
String currentTime = DateUtil.getTime();
Map<String, Object> params = new HashMap<>(0);
params.put("userId", userPO.getUserId());
params.put("lastLoginAddress", RequestUtil.getRequestIp());
params.put("lastLoginTime", currentTime);
params.put("userLongitude", userLongitude);
params.put("userLatitude", userLatitude);
params.put("gmtModified", currentTime);
params.put("modifier", userPO.getUserId());
userService.updateLoginInfo(params);
}
/**
* 校验是否版本锁定锁定后如果有升级提示下载
*/
private void checkApiLock(AppLoginVO appLoginVO) {
if (!StringUtils.isBlank(appLoginVO.getAppId()) &&
appVersionService.canApiLock(appLoginVO.getAppId(), appLoginVO.getAppVersion() == null ? null : appLoginVO.getAppVersion().toString())) {
throw new AppVersionException("app版本过低请重新下载");
}
}
}

View File

@ -0,0 +1,162 @@
package ink.wgink.login.app.service.appversion;
import ink.wgink.exceptions.FileException;
import ink.wgink.exceptions.SearchException;
import ink.wgink.exceptions.UpdateException;
import ink.wgink.login.app.pojo.dtos.appversion.AppVersionDTO;
import ink.wgink.login.app.pojo.pos.appversion.AppVersionPO;
import ink.wgink.login.app.pojo.vos.appversion.AppVersionSaveVO;
import ink.wgink.login.app.pojo.vos.appversion.AppVersionVO;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.result.SuccessResultData;
import ink.wgink.pojo.result.SuccessResultList;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: IAppDeviceService
* @Description: app设备
* @Author: wanggeng
* @Date: 2021/4/7 4:19 下午
* @Version: 1.0
*/
public interface IAppVersionService {
/**
* 新增app版本
*
* @param appVersionSaveVO
* @return
*/
void save(AppVersionSaveVO appVersionSaveVO);
/**
* 删除
*
* @param ids
*/
void remove(List<String> ids);
/**
* 修改
*
* @param appVersionId
* @param appVersionVO
*/
void update(String appVersionId, AppVersionVO appVersionVO);
/**
* 更新APP接口锁定状态
*
* @param appVersionId
* @param appApiLock
*/
void updateApiLock(String appVersionId, Integer appApiLock);
/**
* 更新APP为发布状态
*
* @param appVersionId
* @param isRelease
*/
void updateRelease(String appVersionId, int isRelease);
/**
* APP接口是否锁定如果锁定必须升级APP
*
* @param appVersionId
* @param appVersion
* @return
*/
boolean canApiLock(String appVersionId, String appVersion);
/**
* 详情
*
* @param params
* @return
*/
AppVersionDTO get(Map<String, Object> params);
/**
* 详情
*
* @param appVersionId
* @return
*/
AppVersionDTO get(String appVersionId);
/**
* 详情
*
* @param params
* @return
*/
AppVersionPO getPO(Map<String, Object> params);
/**
* 详情
*
* @param appVersionId
* @return
*/
AppVersionPO getPO(String appVersionId);
/**
* 详情
*
* @param appVersionId
* @param isRelease
* @return
*/
AppVersionPO getPO(String appVersionId, int isRelease);
/**
* 列表
*
* @param params
* @return
*/
List<AppVersionDTO> list(Map<String, Object> params);
/**
* 列表分页
*
* @param page
* @return
*/
SuccessResultList<List<AppVersionDTO>> listPage(ListPage page);
/**
* 获取app二维码
*
* @param appVersionId
* @param response
*/
void downloadQrCode(String appVersionId, HttpServletResponse response) throws IOException;
/**
* 获取APP当前版本号
*
* @param appVersionId
* @return
* @throws SearchException
*/
Integer getNumber(String appVersionId) throws SearchException;
/**
* 下载APP
*
* @param appVersionId
* @param request
* @param response
*/
void download(String appVersionId, HttpServletRequest request, HttpServletResponse response);
}

View File

@ -0,0 +1,192 @@
package ink.wgink.login.app.service.appversion.impl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import ink.wgink.common.base.DefaultBaseService;
import ink.wgink.exceptions.SearchException;
import ink.wgink.login.app.dao.appversion.IAppVersionDao;
import ink.wgink.login.app.pojo.dtos.appversion.AppVersionDTO;
import ink.wgink.login.app.pojo.pos.appversion.AppVersionPO;
import ink.wgink.login.app.pojo.vos.appversion.AppVersionSaveVO;
import ink.wgink.login.app.pojo.vos.appversion.AppVersionVO;
import ink.wgink.login.app.service.appversion.IAppVersionService;
import ink.wgink.module.file.service.IFileService;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.result.SuccessResultList;
import ink.wgink.util.QRCodeUtil;
import ink.wgink.util.UUIDUtil;
import ink.wgink.util.map.HashMapUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: AppDeviceServiceImpl
* @Description: app设备
* @Author: wanggeng
* @Date: 2021/4/7 4:20 下午
* @Version: 1.0
*/
@Service
public class AppVersionServiceImpl extends DefaultBaseService implements IAppVersionService {
@Autowired
private IAppVersionDao appVersionDao;
@Autowired
private IFileService fileService;
@Value("${server.url}")
private String serverUrl;
@Override
public void save(AppVersionSaveVO appVersionSaveVO) {
Map<String, Object> params = HashMapUtil.beanToMap(appVersionSaveVO);
params.put("appVersion", "1");
params.put("appDownloadCount", "0");
params.put("appVersionId", UUIDUtil.getUUID());
setSaveInfo(params);
appVersionDao.save(params);
}
@Override
public void remove(List<String> ids) {
Map<String, Object> params = getHashMap(2);
params.put("appVersionIds", ids);
setUpdateInfo(params);
appVersionDao.remove(params);
}
@Override
public void update(String appVersionId, AppVersionVO appVersionVO) {
Map<String, Object> params = HashMapUtil.beanToMap(appVersionVO);
setUpdateInfo(params);
appVersionDao.update(params);
}
@Override
public void updateApiLock(String appVersionId, Integer appApiLock) {
Map<String, Object> params = getHashMap(8);
params.put("appApiLock", appApiLock);
params.put("appVersionId", appVersionId);
setUpdateInfo(params);
appVersionDao.updateApiLock(params);
}
@Override
public void updateRelease(String appVersionId, int isRelease) {
Map<String, Object> params = getHashMap(8);
params.put("isRelease", isRelease);
params.put("appVersionId", appVersionId);
setUpdateInfo(params);
appVersionDao.updateRelease(params);
}
@Override
public AppVersionDTO get(Map<String, Object> params) {
return appVersionDao.get(params);
}
@Override
public AppVersionDTO get(String appVersionId) {
Map<String, Object> params = getHashMap(2);
params.put("appVersionId", appVersionId);
return get(params);
}
@Override
public AppVersionPO getPO(Map<String, Object> params) {
return appVersionDao.getPO(params);
}
@Override
public AppVersionPO getPO(String appVersionId) {
Map<String, Object> params = getHashMap(2);
params.put("appVersionId", appVersionId);
return getPO(params);
}
@Override
public AppVersionPO getPO(String appVersionId, int isRelease) {
Map<String, Object> params = getHashMap(2);
params.put("appVersionId", appVersionId);
params.put("isRelease", isRelease);
return getPO(params);
}
@Override
public List<AppVersionDTO> list(Map<String, Object> params) {
return appVersionDao.list(params);
}
@Override
public SuccessResultList<List<AppVersionDTO>> listPage(ListPage page) {
PageHelper.startPage(page.getPage(), page.getRows());
List<AppVersionDTO> appVersionDTOs = list(page.getParams());
PageInfo<AppVersionDTO> pageInfo = new PageInfo<>(appVersionDTOs);
return new SuccessResultList<>(appVersionDTOs, pageInfo.getPageNum(), pageInfo.getTotal());
}
@Override
public void downloadQrCode(String appVersionId, HttpServletResponse response) throws IOException {
String qrContent = String.format("%s/app/appversion/download/%s", serverUrl, appVersionId);
response.setContentType("image/png");
BufferedImage bufferedImage = QRCodeUtil.createQrCode(300, 300, qrContent, null);
ImageIO.write(bufferedImage, "png", response.getOutputStream());
}
@Override
public Integer getNumber(String appVersionId) throws SearchException {
AppVersionPO appVersionPO = getPO(appVersionId, 1);
if (appVersionPO == null) {
throw new SearchException("app不存在或未发布");
}
return appVersionPO.getAppVersion();
}
@Override
public void download(String appVersionId, HttpServletRequest request, HttpServletResponse response) {
LOG.debug("获取当前APP");
AppVersionPO appVersionPO = getPO(appVersionId, 1);
if (appVersionPO == null) {
throw new SearchException("app不存在或未发布");
}
LOG.debug("下载APP");
Map<String, Object> params = getHashMap(4);
params.put("fileId", appVersionPO.getAppFile());
params.put("isOpen", false);
fileService.downLoadFile(request, response, params, false);
LOG.debug("更新下载次数");
appVersionDao.updateDownloadCount(appVersionPO.getAppVersionId());
}
@Override
public boolean canApiLock(String appVersionId, String appVersion) {
AppVersionPO appVersionPO = getPO(appVersionId);
if (Objects.isNull(appVersionPO)) {
throw new SearchException("app不存在");
}
if (appVersionPO.getAppApiLock() == 0) {
return false;
}
if (StringUtils.isBlank(appVersion)) {
throw new SearchException("app版本号不能为空");
}
if (Integer.parseInt(appVersion) < appVersionPO.getAppVersion()) {
return true;
}
return false;
}
}

View File

@ -0,0 +1,47 @@
package ink.wgink.login.app.startup;
import ink.wgink.login.app.dao.appdeviceuser.IAppDeviceUserDao;
import ink.wgink.login.app.dao.appversion.IAppVersionDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: LoginAppStartUp
* @Description: app登录
* @Author: wanggeng
* @Date: 2021/4/7 7:00 下午
* @Version: 1.0
*/
@Component
public class LoginAppStartUp implements ApplicationRunner {
private static final Logger LOG = LoggerFactory.getLogger(LoginAppStartUp.class);
@Autowired
private IAppVersionDao appVersionDao;
@Autowired
private IAppDeviceUserDao appDeviceUserDao;
@Override
public void run(ApplicationArguments args) throws Exception {
initTable();
}
/**
* 建表
*/
private void initTable() {
LOG.debug("创建 app_version 表");
appVersionDao.createTable();
LOG.debug("创建 app_device_user 表");
appDeviceUserDao.createTable();
}
}

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="ink.wgink.login.app.dao.appdeviceuser.IAppDeviceUserDao">
<cache flushInterval="3600000"/>
<resultMap id="appDeviceUserPO" type="ink.wgink.login.app.pojo.pos.appdeviceuser.AppDeviceUserPO">
<result property="userId" column="user_id"/>
<result property="deviceNo" column="device_no"/>
</resultMap>
<resultMap id="appDeviceUserDTO" type="ink.wgink.login.app.pojo.dtos.appdeviceuser.AppDeviceUserDTO">
<result property="userId" column="user_id"/>
<result property="deviceNo" column="device_no"/>
</resultMap>
<!-- 建表 -->
<update id="createTable">
CREATE TABLE IF NOT EXISTS `app_device_user` (
`device_no` varchar(255) DEFAULT NULL,
`user_id` char(36) DEFAULT NULL,
KEY `device_no` (`device_no`),
KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
</update>
<!-- 保存 -->
<insert id="save" parameterType="map" flushCache="true">
INSERT INTO app_device_user(
device_no,
user_id,
gmt_create
) VALUES(
#{deviceNo},
#{userId},
#{gmtCreate}
)
</insert>
<!-- 删除 -->
<delete id="delete" parameterType="map" flushCache="true">
DELETE FROM
app_device_user
WHERE
device_no = #{deviceNo}
AND
user_id = #{userId}
</delete>
<!-- 列表 -->
<select id="list" parameterType="map" resultMap="appDeviceUserDTO" useCache="true">
SELECT
*
FROM
app_device_user
WHERE
user_id = #{userId}
</select>
<!-- 列表 -->
<select id="listPO" parameterType="map" resultMap="appDeviceUserPO" useCache="true">
SELECT
*
FROM
app_device_user
WHERE
user_id = #{userId}
</select>
</mapper>

View File

@ -0,0 +1,252 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="ink.wgink.login.app.dao.appversion.IAppVersionDao">
<cache flushInterval="3600000"/>
<resultMap id="appVersionDTO" type="ink.wgink.login.app.pojo.dtos.appversion.AppVersionDTO">
<id property="appVersionId" column="app_version_id"/>
<result property="appName" column="app_name"/>
<result property="appSummary" column="app_summary"/>
<result property="appVersion" column="app_version"/>
<result property="appDownloadCount" column="app_download_count"/>
<result property="appFile" column="app_file"/>
<result property="appApiLock" column="app_api_lock"/>
<result property="isNecessary" column="is_necessary"/>
<result property="isRelease" column="is_release"/>
</resultMap>
<resultMap id="appVersionPO" type="ink.wgink.login.app.pojo.pos.appversion.AppVersionPO">
<id property="appVersionId" column="app_version_id"/>
<result property="appName" column="app_name"/>
<result property="appSummary" column="app_summary"/>
<result property="appVersion" column="app_version"/>
<result property="appDownloadCount" column="app_download_count"/>
<result property="appFile" column="app_file"/>
<result property="appApiLock" column="app_api_lock"/>
<result property="isNecessary" column="is_necessary"/>
<result property="isRelease" column="is_release"/>
</resultMap>
<!-- 建表 -->
<update id="createTable">
CREATE TABLE IF NOT EXISTS `app_version` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`app_version_id` char(36) NOT NULL COMMENT '主键',
`app_name` varchar(255) NOT NULL COMMENT 'APP名称',
`app_summary` varchar(255) NOT NULL COMMENT 'APP说明',
`app_version` int(11) DEFAULT '0' COMMENT 'APP版本号',
`app_download_count` int(11) DEFAULT '0' COMMENT '下载次数',
`app_file` char(36) NOT NULL COMMENT 'APP文件',
`app_api_lock` int(1) DEFAULT '0' COMMENT '接口版本锁定',
`is_necessary` int(1) DEFAULT '0' COMMENT '强制更新',
`is_release` int(1) DEFAULT '0' COMMENT '是否发布',
`creator` char(36) DEFAULT NULL,
`gmt_create` datetime DEFAULT NULL,
`modifier` char(36) DEFAULT NULL,
`gmt_modified` datetime DEFAULT NULL,
`is_delete` int(1) DEFAULT '0',
PRIMARY KEY (`id`,`app_version_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
</update>
<!-- 新增app版本 -->
<insert id="save" parameterType="map" flushCache="true">
INSERT INTO app_version(
app_version_id,
app_name,
app_summary,
app_version,
app_download_count,
app_file,
is_necessary,
is_release,
creator,
gmt_create,
modifier,
gmt_modified,
is_delete
) VALUES(
#{appVersionId},
#{appName},
#{appSummary},
#{appVersion},
#{appDownloadCount},
#{appFile},
#{isNecessary},
#{isRelease},
#{creator},
#{gmtCreate},
#{modifier},
#{gmtModified},
#{isDelete}
)
</insert>
<!-- 删除app版本 -->
<update id="remove" parameterType="map" flushCache="true">
UPDATE
app_version
SET
is_delete = 1,
modifier = #{modifier},
gmt_modified = #{gmtModified}
WHERE
app_version_id IN
<foreach collection="appVersionIds" index="index" open="(" separator="," close=")">
#{appVersionIds[${index}]}
</foreach>
</update>
<!-- 修改app版本 -->
<update id="updateVersion" parameterType="map" flushCache="true">
UPDATE
app_version
SET
<if test="appSummary != null and appSummary != ''">
app_summary = #{appSummary},
</if>
app_file = #{appFile},
is_necessary = #{isNecessary},
is_release = #{isRelease},
app_version = app_version + 1,
modifier = #{modifier},
gmt_modified = #{gmtModified}
WHERE
app_version_id = #{appVersionId}
</update>
<!-- 更新APP下载次数 -->
<update id="updateDownloadCount" parameterType="String" flushCache="true">
UPDATE
app_version
SET
app_download_count = app_download_count + 1
WHERE
app_version_id = #{_parameter}
</update>
<!-- 更新APP的锁定状态 -->
<update id="updateApiLock" parameterType="map" flushCache="true">
UPDATE
app_version
SET
app_api_lock = #{appApiLock},
modifier = #{modifier},
gmt_modified = #{gmtModified}
WHERE
is_delete = 0
AND
app_version_id = #{appVersionId}
</update>
<!-- 更新APP的发布状态 -->
<update id="updateRelease" parameterType="map" flushCache="true">
UPDATE
app_version
SET
is_release = #{isRelease},
modifier = #{modifier},
gmt_modified = #{gmtModified}
WHERE
is_delete = 0
AND
app_version_id = #{appVersionId}
</update>
<!-- app版本列表 -->
<select id="list" parameterType="map" resultMap="appVersionDTO" useCache="true">
SELECT
t1.*
FROM
app_version t1
WHERE
t1.is_delete = 0
<if test="keywords != null and keywords != ''">
AND
t1.app_name LIKE CONCAT('%', #{keywords}, '%')
</if>
<if test="startTime != null and startTime != ''">
AND
LEFT(t1.gmt_create, 10) <![CDATA[ >= ]]> #{startTime}
</if>
<if test="endTime != null and endTime != ''">
AND
LEFT(t1.gmt_create, 10) <![CDATA[ <= ]]> #{endTime}
</if>
<if test="appVersionIds != null and appVersionIds.size > 0">
AND
t1.app_version_id IN
<foreach collection="appVersionIds" index="index" open="(" separator="," close=")">
#{appVersionIds[${index}]}
</foreach>
</if>
</select>
<!-- app版本详情 -->
<select id="get" parameterType="map" resultMap="appVersionDTO" useCache="true">
SELECT
t1.*
FROM
app_version t1
WHERE
t1.is_delete = 0
<if test="appVersionId != null and appVersionId != ''">
AND
t1.app_version_id = #{appVersionId}
</if>
<if test="isRelease != null">
AND
t1.is_release = #{isRelease}
</if>
</select>
<!-- app版本列表 -->
<select id="listPO" parameterType="map" resultMap="appVersionPO" useCache="true">
SELECT
t1.*
FROM
app_version t1
WHERE
t1.is_delete = 0
<if test="keywords != null and keywords != ''">
AND
t1.app_name LIKE CONCAT('%', #{keywords}, '%')
</if>
<if test="startTime != null and startTime != ''">
AND
LEFT(t1.gmt_create, 10) <![CDATA[ >= ]]> #{startTime}
</if>
<if test="endTime != null and endTime != ''">
AND
LEFT(t1.gmt_create, 10) <![CDATA[ <= ]]> #{endTime}
</if>
<if test="appVersionIds != null and appVersionIds.size > 0">
AND
t1.app_version_id IN
<foreach collection="appVersionIds" index="index" open="(" separator="," close=")">
#{appVersionIds[${index}]}
</foreach>
</if>
</select>
<!-- app版本详情 -->
<select id="getPO" parameterType="map" resultMap="appVersionPO" useCache="true">
SELECT
t1.*
FROM
app_version t1
WHERE
t1.is_delete = 0
<if test="appVersionId != null and appVersionId != ''">
AND
t1.app_version_id = #{appVersionId}
</if>
<if test="isRelease != null">
AND
t1.is_release = #{isRelease}
</if>
</select>
</mapper>

View File

@ -0,0 +1,308 @@
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<base th:href="${#request.getContextPath() + '/'}">
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, appversion-scalable=0">
<link rel="stylesheet" href="assets/fonts/font-awesome/css/font-awesome.css"/>
<link rel="stylesheet" type="text/css" href="assets/js/vendor/viewer/viewer.min.css">
<link rel="stylesheet" href="assets/layuiadmin/layui/css/layui.css" media="all">
<link rel="stylesheet" href="assets/layuiadmin/style/admin.css" media="all">
</head>
<body>
<div class="layui-fluid layui-anim layui-anim-fadein">
<div class="layui-row">
<div class="layui-col-md12">
<div class="layui-card">
<div class="layui-card-body">
<div class="test-table-reload-btn" style="margin-bottom: 10px;">
<div class="layui-inline">
<input type="text" id="keywords" class="layui-input search-item" placeholder="输入关键字">
</div>
<button type="button" id="search" class="layui-btn layui-btn-sm">
<i class="fa fa-lg fa-search"></i> 搜索
</button>
</div>
<table class="layui-hide" id="dataTable" lay-filter="dataTable"></table>
<!-- 表头按钮组 -->
<script type="text/html" id="headerToolBar">
<div class="layui-btn-group">
<button type="button" class="layui-btn layui-btn-sm" lay-event="save">
<i class="fa fa-lg fa-plus"></i> 新增
</button>
<button type="button" class="layui-btn layui-btn-normal layui-btn-sm" lay-event="update">
<i class="fa fa-lg fa-edit"></i> 编辑
</button>
<button type="button" class="layui-btn layui-btn-danger layui-btn-sm" lay-event="remove">
<i class="fa fa-lg fa-trash"></i> 删除
</button>
</div>
</script>
</div>
</div>
</div>
</div>
</div>
<script src="assets/layuiadmin/layui/layui.js"></script>
<script src="assets/js/vendor/viewer/viewer.min.js"></script>
<script>
layui.config({
base: 'assets/layuiadmin/'
}).extend({
index: 'lib/index'
}).use(['index', 'table', 'laydate'], function() {
var $ = layui.$;
var $win = $(window);
var table = layui.table;
var admin = layui.admin;
var laydate = layui.laydate;
var resizeTimeout = null;
var tableUrl = 'api/appversion/listpage';
// 初始化表格
function initTable() {
table.render({
elem: '#dataTable',
id: 'dataTable',
url: top.restAjax.path(tableUrl, []),
width: admin.screen() > 1 ? '100%' : '',
height: $win.height() - 90,
limit: 20,
limits: [20, 40, 60, 80, 100, 200],
toolbar: '#headerToolBar',
request: {
pageName: 'page',
limitName: 'rows'
},
cols: [
[
{type:'checkbox', fixed: 'left'},
{field:'rowNum', width:80, title: '序号', fixed: 'left', align:'center', templet: '<span>{{d.LAY_INDEX}}</span>'},
{field:'appName', width:140, title: 'APP名称', align:'center',
templet: function(item) {
return '<a href="javascript:void(0);" lay-event="downLoadFile">'+ item.appName +'</a>';
}
},
{field:'appSummary', width:140, title: 'APP说明', align:'center'},
{field:'appVersion', width:80, title: '版本号', align:'center'},
{field:'appApiLock', width: 120, title: '接口版本锁定', align:'center',
templet: function(item) {
var value = '<button type="button" class="layui-btn layui-btn-warn layui-btn-sm" lay-event="appApiLock">锁定</button>';
if(item.appApiLock == 1) {
value = '<button type="button" class="layui-btn layui-btn-danger layui-btn-sm" lay-event="appApiUnLock">解锁</button>';
}
return value;
}
},
{field:'appQRCode', width: 80, title: '二维码', align:'center',
templet: function(item) {
var value = '<img id="qrCode_'+ item.appVersionId +'" src="api/appversion/downloadqrcode/'+ item.appVersionId +'" style="width:25px;height:25px;cursor:pointer;"/>';
setTimeout(function() {
new Viewer(document.getElementById('qrCode_'+ item.appVersionId));
}, 50);
return value;
}
},
{field:'isNecessary', width: 90, title: '强制更新', align:'center',
templet: function(item) {
var value = '否';
if(item.isNecessary == 1) {
value = '是';
}
return value;
}
},
{field:'isRelease', width: 100, title: '强制发布', align:'center',
templet: function(item) {
var value = '<button class="layui-btn layui-btn-sm layui-btn-normal" lay-event="releaseApp">点击发布</button>';
if(item.isRelease == 1) {
value = '<button class="layui-btn layui-btn-sm layui-btn-danger" lay-event="unReleaseApp">取消发布</button>';
}
return value;
}
},
{field:'appDownloadCount', width: 100, title: '下载次数', align:'center'},
{field:'appDownloadUrl', width: 300, title: '下载链接', align:'center',
'templet': function(item) {
return '/app/appversion/download/'+ item.appVersionId;
}
},
]
],
page: true,
parseData: function(data) {
return {
'code': 0,
'msg': '',
'count': data.total,
'data': data.rows
};
},
});
}
// 重载表格
function reloadTable(currentPage) {
table.reload('dataTable', {
url: top.restAjax.path(tableUrl, []),
where: {
keywords: $('#keywords').val(),
},
page: {
curr: currentPage
},
height: $win.height() - 90,
});
}
// 初始化日期
function initDate() {}
// 删除
function removeData(ids) {
top.dialog.msg(top.dataMessage.delete, {
time: 0,
btn: [top.dataMessage.button.yes, top.dataMessage.button.no],
shade: 0.3,
yes: function (index) {
top.dialog.close(index);
var layIndex;
top.restAjax.delete(top.restAjax.path('api/appversion/remove/{ids}', [ids]), {}, null, function (code, data) {
top.dialog.msg(top.dataMessage.deleteSuccess, {time: 1000}, function () {
reloadTable();
});
}, function (code, data) {
top.dialog.msg(data.msg);
}, function () {
layIndex = top.dialog.msg(top.dataMessage.deleting, {icon: 16, time: 0, shade: 0.3});
}, function () {
top.dialog.close(layIndex);
});
}
});
}
initTable();
initDate();
// 事件 - 页面变化
$win.on('resize', function() {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(function() {
reloadTable();
}, 500);
});
// 事件 - 搜索
$(document).on('click', '#search', function() {
reloadTable(1);
});
// 事件 - 增删改
table.on('toolbar(dataTable)', function(obj) {
var layEvent = obj.event;
var checkStatus = table.checkStatus('dataTable');
var checkDatas = checkStatus.data;
if(layEvent === 'save') {
layer.open({
type: 2,
title: false,
closeBtn: 0,
area: ['100%', '100%'],
shadeClose: true,
anim: 2,
content: top.restAjax.path('route/appversion/save', []),
end: function() {
reloadTable();
}
});
} else if(layEvent === 'update') {
if(checkDatas.length === 0) {
top.dialog.msg(top.dataMessage.table.selectEdit);
} else if(checkDatas.length > 1) {
top.dialog.msg(top.dataMessage.table.selectOneEdit);
} else {
layer.open({
type: 2,
title: false,
closeBtn: 0,
area: ['100%', '100%'],
shadeClose: true,
anim: 2,
content: top.restAjax.path('route/appversion/update?appVersionId={id}', [checkDatas[0].appVersionId]),
end: function() {
reloadTable();
}
});
}
} else if(layEvent === 'remove') {
if(checkDatas.length === 0) {
top.dialog.msg(top.dataMessage.table.selectDelete);
} else {
var ids = '';
for(var i = 0, item; item = checkDatas[i++];) {
if(i > 1) {
ids += '_';
}
ids += item.appVersionId;
}
removeData(ids);
}
}
});
// 解锁和绑定
function appApiLock(appVersionId, appApiLock) {
top.dialog.confirm('确定修改锁定状态吗?', function() {
var loadLayerIndex;
top.restAjax.put(top.restAjax.path('api/appversion/update-api-lock/{appVersionId}/{appApiLock}', [appVersionId, appApiLock]), self.formObject, null, function(code, data) {
top.dialog.msg(top.dataMessage.updated, {time: 1000});
reloadTable();
}, function(code, data) {
top.dialog.msg(data.msg);
}, function() {
loadLayerIndex = top.dialog.msg(top.dataMessage.updating, {icon: 16, time: 0, shade: 0.3});
}, function() {
top.dialog.close(loadLayerIndex);
});
});
}
table.on('tool(dataTable)', function(obj) {
var layEvent = obj.event;
var data = obj.data;
if(layEvent === 'downLoadFile') {
top.dialog.confirm('确定下载吗?', function() {
window.open('route/file/download/false/'+ data.appFile);
});
} else if(layEvent === 'appApiLock') {
appApiLock(data.appVersionId, '1');
} else if(layEvent === 'appApiUnLock') {
appApiLock(data.appVersionId, '0');
} else if(layEvent === 'releaseApp') {
top.dialog.confirm('确定发布该APP吗发布后APP可以正常下载。', function() {
top.restAjax.put(top.restAjax.path('api/appversion/update-release/{appVersionId}', [data.appVersionId]), {}, null, function(code, data) {
top.dialog.msg('发布成功');
reloadTable();
}, function(code, data) {
top.dialog.msg(data.msg);
});
});
} else if(layEvent === 'unReleaseApp') {
top.dialog.confirm('确定取消发布该APP吗取消后APP将无法下载', function() {
top.restAjax.put(top.restAjax.path('api/appversion/update-unrelease/{appVersionId}', [data.appVersionId]), {}, null, function(code, data) {
top.dialog.msg('取消成功');
reloadTable();
}, function(code, data) {
top.dialog.msg(data.msg);
});
});
}
});
// 事件-排序
table.on('sort(dataTable)', function(obj) {
table.reload('dataTable', {
initSort: obj,
where: {
sort: obj.field,
order: obj.type
}
});
});
});
</script>
</body>
</html>

View File

@ -0,0 +1,157 @@
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<base th:href="${#request.getContextPath() + '/'}">
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="assets/fonts/font-awesome/css/font-awesome.css"/>
<link rel="stylesheet" href="assets/layuiadmin/layui/css/layui.css" media="all">
<link rel="stylesheet" href="assets/layuiadmin/style/admin.css" media="all">
</head>
<body>
<div class="layui-fluid layui-anim layui-anim-fadein">
<div class="layui-card">
<div class="layui-card-header">
<span class="layui-breadcrumb" lay-filter="breadcrumb" style="visibility: visible;">
<a class="close" href="javascript:void(0);">上级列表</a><span lay-separator="">/</span>
<a href="javascript:void(0);"><cite>新增内容</cite></a>
</span>
</div>
<div class="layui-card-body" style="padding: 15px;">
<form class="layui-form" lay-filter="dataForm">
<div class="layui-form-item">
<label class="layui-form-label">APP名称 *</label>
<div class="layui-input-block">
<input type="text" name="appName" lay-verify="required" placeholder="请输入APP名称" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">APP说明</label>
<div class="layui-input-block">
<textarea name="appSummary" placeholder="请输入APP说明" maxlength="255" class="layui-textarea" rows="4"></textarea>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">强制更新 *</label>
<div class="layui-input-block">
<input type="radio" name="isNecessary" value="0" title="否" checked>
<input type="radio" name="isNecessary" value="1" title="是">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">是否发布 *</label>
<div class="layui-input-block">
<input type="radio" name="isRelease" value="0" title="否" checked>
<input type="radio" name="isRelease" value="1" title="是">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">APP文件 *</label>
<div class="layui-input-block">
<input type="hidden" id="appFile" name="appFile">
<span id="appFileBox"></span>
<button type="button" class="layui-btn" lay-form-button lay-filter="uploadFile">
<i class="fa fa-cloud-upload"></i> 上传APP
</button>
</div>
</div>
<div class="layui-form-item layui-layout-admin">
<div class="layui-input-block">
<div class="layui-footer" style="left: 0;">
<button type="button" class="layui-btn" lay-submit lay-filter="submitForm">提交新增</button>
<button type="button" class="layui-btn layui-btn-primary close">返回上级</button>
</div>
</div>
</div>
</form>
</div>
</div>
<script id="appFileDownload" type="text/html">
{{# if(d.appFile != '') { }}
<span class="layui-btn-group">
<a class="layui-btn layui-btn-normal" href="route/file/download/false/{{d.appFile}}" target="_blank">点击下载此文件</a>
<a class="layui-btn layui-btn-danger text-danger" href="javascript:void(0);" lay-form-button lay-filter="removeAppFile">删除</a>
</span>
{{# } }}
</script>
</div>
<script src="assets/layuiadmin/layui/layui.js"></script>
<script>
layui.config({
base: 'assets/layuiadmin/' //静态资源所在路径
}).extend({
index: 'lib/index' //主入口模块
}).use(['index', 'form', 'laydate', 'laytpl'], function(){
var $ = layui.$;
var form = layui.form;
var laytpl = layui.laytpl;
function closeBox() {
parent.layer.close(parent.layer.getFrameIndex(window.name));
}
// 提交表单
form.on('submit(submitForm)', function(formData) {
top.dialog.confirm(top.dataMessage.commit, function(index) {
top.dialog.close(index);
var loadLayerIndex;
top.restAjax.post(top.restAjax.path('api/appversion/save', []), formData.field, null, function(code, data) {
var layerIndex = top.dialog.msg(top.dataMessage.commitSuccess, {
time: 0,
btn: [top.dataMessage.button.yes, top.dataMessage.button.no],
shade: 0.3,
yes: function(index) {
top.dialog.close(index);
window.location.reload();
},
btn2: function() {
closeBox();
}
});
}, function(code, data) {
top.dialog.msg(data.msg);
}, function() {
loadLayerIndex = top.dialog.msg(top.dataMessage.committing, {icon: 16, time: 0, shade: 0.3});
}, function() {
top.dialog.close(loadLayerIndex);
});
});
return false;
});
function refreshAppDownloadTemplet(appFile) {
form.val('dataForm', {
appFile: appFile
});
laytpl(document.getElementById('appFileDownload').innerHTML).render({
appFile: $('#appFile').val()
}, function(html) {
document.getElementById('appFileBox').innerHTML = html;
});
}
form.on('button(removeAppFile)', function(obj) {
refreshAppDownloadTemplet(null);
});
form.on('button(uploadFile)', function(obj) {
top.dialog.file({
type: 'file',
title: '上传APP',
width: '400px',
height: '420px',
maxFileCount: '1',
onClose: function() {
var uploadFileArray = top.dialog.dialogData.uploadFileArray;
if(typeof(uploadFileArray) != 'undefined' && uploadFileArray.length > 0) {
refreshAppDownloadTemplet(uploadFileArray[0].data);
}
}
});
})
$('.close').on('click', function() {
closeBox();
});
});
</script>
</body>
</html>

View File

@ -0,0 +1,170 @@
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<base th:href="${#request.getContextPath() + '/'}">
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="assets/fonts/font-awesome/css/font-awesome.css"/>
<link rel="stylesheet" href="assets/layuiadmin/layui/css/layui.css" media="all">
<link rel="stylesheet" href="assets/layuiadmin/style/admin.css" media="all">
</head>
<body>
<div class="layui-fluid layui-anim layui-anim-fadein">
<div class="layui-card">
<div class="layui-card-header">
<span class="layui-breadcrumb" lay-filter="breadcrumb" style="visibility: visible;">
<a class="close" href="javascript:void(0);">上级列表</a><span lay-separator="">/</span>
<a href="javascript:void(0);"><cite>编辑内容</cite></a>
</span>
</div>
<div class="layui-card-body" style="padding: 15px;">
<form class="layui-form" lay-filter="dataForm">
<div class="layui-form-item">
<label class="layui-form-label">APP说明</label>
<div class="layui-input-block">
<textarea name="appSummary" placeholder="请输入APP说明" maxlength="255" class="layui-textarea" rows="4"></textarea>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">强制更新 *</label>
<div class="layui-input-block">
<input type="radio" name="isNecessary" value="0" title="否" checked>
<input type="radio" name="isNecessary" value="1" title="是">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">是否发布 *</label>
<div class="layui-input-block">
<input type="radio" name="isRelease" value="0" title="否" checked>
<input type="radio" name="isRelease" value="1" title="是">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">APP文件 *</label>
<div class="layui-input-block">
<input type="hidden" id="appFile" name="appFile">
<span id="appFileBox"></span>
<button type="button" class="layui-btn" lay-form-button lay-filter="uploadFile">
<i class="fa fa-cloud-upload"></i> 上传APP
</button>
</div>
</div>
<div class="layui-form-item layui-layout-admin">
<div class="layui-input-block">
<div class="layui-footer" style="left: 0;">
<button type="button" class="layui-btn" lay-submit lay-filter="submitForm">提交编辑</button>
<button type="button" class="layui-btn layui-btn-primary close">返回上级</button>
</div>
</div>
</div>
</form>
</div>
</div>
<script id="appFileDownload" type="text/html">
{{# if(d.appFile != '') { }}
<span class="layui-btn-group">
<a class="layui-btn layui-btn-normal" href="route/file/downloadfile/false/{{d.appFile}}" target="_blank">点击下载此文件</a>
<a class="layui-btn layui-btn-danger text-danger" href="javascript:void(0);" lay-form-button lay-filter="removeAppFile">删除</a>
</span>
{{# } }}
</script>
</div>
<script src="assets/layuiadmin/layui/layui.js"></script>
<script>
layui.config({
base: 'assets/layuiadmin/' //静态资源所在路径
}).extend({
index: 'lib/index' //主入口模块
}).use(['index', 'form', 'laydate', 'laytpl'], function(){
var $ = layui.$;
var form = layui.form;
var laytpl = layui.laytpl;
var appVersionId = top.restAjax.params(window.location.href).appVersionId;
function closeBox() {
parent.layer.close(parent.layer.getFrameIndex(window.name));
}
// 初始化
function initData() {
var loadLayerIndex;
top.restAjax.get(top.restAjax.path('api/appversion/get/{appVersionId}', [appVersionId]), {}, null, function(code, data) {
form.val('dataForm', {
appSummary: data.appSummary,
isNecessary: data.isNecessary
});
form.render(null, 'dataForm');
}, function(code, data) {
top.DialogBox.msg(data.msg);
}, function() {
loadLayerIndex = top.dialog.msg(top.dataMessage.loading, {icon: 16, time: 0, shade: 0.3});
}, function() {
top.dialog.close(loadLayerIndex);
});
}
initData();
// 提交表单
form.on('submit(submitForm)', function(formData) {
top.dialog.confirm(top.dataMessage.commit, function(index) {
top.dialog.close(index);
var loadLayerIndex;
top.restAjax.put(top.restAjax.path('api/appversion/update/{appVersionId}', [appVersionId]), formData.field, null, function(code, data) {
var layerIndex = top.dialog.msg(top.dataMessage.commitSuccess, {
time: 0,
btn: [top.dataMessage.button.yes, top.dataMessage.button.no],
shade: 0.3,
yes: function(index) {
top.dialog.close(index);
window.location.reload();
},
btn2: function() {
closeBox();
}
});
}, function(code, data) {
top.dialog.msg(data.msg);
}, function() {
loadLayerIndex = top.dialog.msg(top.dataMessage.committing, {icon: 16, time: 0, shade: 0.3});
}, function() {
top.dialog.close(loadLayerIndex);
});
});
return false;
});
function refreshAppDownloadTemplet(appFile) {
form.val('dataForm', {
appFile: appFile
});
laytpl(document.getElementById('appFileDownload').innerHTML).render({
appFile: $('#appFile').val()
}, function(html) {
document.getElementById('appFileBox').innerHTML = html;
});
}
form.on('button(removeAppFile)', function(obj) {
refreshAppDownloadTemplet(null);
});
form.on('button(uploadFile)', function(obj) {
top.dialog.file({
type: 'file',
title: '上传APP',
width: '400px',
height: '420px',
maxFileCount: '1',
onClose: function() {
var uploadFileArray = top.dialog.dialogData.uploadFileArray;
if(typeof(uploadFileArray) != 'undefined' && uploadFileArray.length > 0) {
refreshAppDownloadTemplet(uploadFileArray[0].data);
}
}
});
})
$('.close').on('click', function() {
closeBox();
});
});
</script>
</body>
</html>

View File

@ -26,6 +26,7 @@
<module>service-group</module>
<module>service-position</module>
<module>login-base</module>
<module>login-app</module>
</modules>
<packaging>pom</packaging>