add websocket push
This commit is contained in:
parent
5eb73ca7a1
commit
b3a3cf5ec8
@ -29,6 +29,10 @@
|
|||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>me.chyxion.tigon</groupId>
|
||||||
|
<artifactId>tigon-web-controller</artifactId>
|
||||||
|
</dependency>
|
||||||
<!-- Log -->
|
<!-- Log -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
@ -2,7 +2,7 @@ package com.pudonghot.ambition.crm.auth;
|
|||||||
|
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import me.chyxion.tigon.mybatis.Search;
|
|
||||||
import me.chyxion.tigon.model.ViewModel;
|
import me.chyxion.tigon.model.ViewModel;
|
||||||
import me.chyxion.tigon.shiro.AuthRealm;
|
import me.chyxion.tigon.shiro.AuthRealm;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
@ -62,13 +62,13 @@ public class AuthRealmSupport implements AuthRealm<Principal, String> {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Collection<String> roles(final Principal principal) {
|
public Collection<String> roles(final Principal principal) {
|
||||||
val user = userService.find(new Search(User.EMPLOYEE_ID, principal));
|
val user = userService.find(principal.getUserId());
|
||||||
val roles = new ArrayList<String>(4);
|
val roles = new ArrayList<String>(4);
|
||||||
if (user.isAdmin()) {
|
if (user.isAdmin()) {
|
||||||
roles.add(User.ROLE_ADMIN);
|
roles.add(User.ROLE_ADMIN);
|
||||||
}
|
}
|
||||||
val account = user.getAccount();
|
val account = user.getAccount();
|
||||||
if (ArrayUtils.contains(new String[] {User.ROLE_LELI, User.ROLE_CHYXION}, account)) {
|
if (ArrayUtils.contains(new String[] {User.ROLE_LELI, User.ROLE_DONGHUANG}, account)) {
|
||||||
roles.add(account);
|
roles.add(account);
|
||||||
}
|
}
|
||||||
return roles;
|
return roles;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.pudonghot.ambition.crm.controller;
|
package com.pudonghot.ambition.crm.common.controller;
|
||||||
|
|
||||||
|
import com.pudonghot.ambition.crm.controller.AbstractBaseController;
|
||||||
import me.chyxion.tigon.model.ViewModel;
|
import me.chyxion.tigon.model.ViewModel;
|
||||||
import com.pudonghot.ambition.crm.model.User;
|
import com.pudonghot.ambition.crm.model.User;
|
||||||
import me.chyxion.tigon.shiro.service.AuthService;
|
import me.chyxion.tigon.shiro.service.AuthService;
|
@ -1,4 +1,4 @@
|
|||||||
package com.pudonghot.ambition.crm.controller;
|
package com.pudonghot.ambition.crm.common.controller;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
@ -1,6 +1,7 @@
|
|||||||
package com.pudonghot.ambition.crm.controller;
|
package com.pudonghot.ambition.crm.common.controller;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
|
||||||
import me.chyxion.tigon.form.FC2;
|
import me.chyxion.tigon.form.FC2;
|
||||||
import me.chyxion.tigon.model.M0;
|
import me.chyxion.tigon.model.M0;
|
||||||
import me.chyxion.tigon.model.ViewModel;
|
import me.chyxion.tigon.model.ViewModel;
|
@ -1,4 +1,4 @@
|
|||||||
package com.pudonghot.ambition.crm.controller;
|
package com.pudonghot.ambition.crm.common.controller;
|
||||||
|
|
||||||
import me.chyxion.tigon.form.FC2;
|
import me.chyxion.tigon.form.FC2;
|
||||||
import me.chyxion.tigon.model.M0;
|
import me.chyxion.tigon.model.M0;
|
@ -1,7 +1,7 @@
|
|||||||
package com.pudonghot.ambition.crm.controller;
|
package com.pudonghot.ambition.crm.common.controller;
|
||||||
|
|
||||||
|
import com.pudonghot.ambition.crm.common.controller.BaseController;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import me.chyxion.tigon.model.M0;
|
|
||||||
import me.chyxion.tigon.mybatis.Search;
|
import me.chyxion.tigon.mybatis.Search;
|
||||||
import me.chyxion.tigon.model.ViewModel;
|
import me.chyxion.tigon.model.ViewModel;
|
||||||
import me.chyxion.tigon.model.ListResult;
|
import me.chyxion.tigon.model.ListResult;
|
||||||
@ -19,8 +19,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
* May 10, 2016 4:50:58 PM
|
* May 10, 2016 4:50:58 PM
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class BaseQueryController<Model extends M0<String>>
|
public class BaseQueryController<Model> extends BaseController {
|
||||||
extends BaseController {
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
protected BaseQueryService<String, Model> queryService;
|
protected BaseQueryService<String, Model> queryService;
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.pudonghot.ambition.crm.common.request;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import me.chyxion.tigon.web.controller2.request.BaseListCtrlrReqApi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Donghuang
|
||||||
|
* @date Jun 18, 2022 13:27:22
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class BaseListCtrlrReq implements BaseListCtrlrReqApi {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private Integer start;
|
||||||
|
private Integer limit;
|
||||||
|
private String search;
|
||||||
|
private String filters;
|
||||||
|
private String orders;
|
||||||
|
}
|
@ -177,7 +177,7 @@ public abstract class AbstractBaseController {
|
|||||||
}
|
}
|
||||||
if (StringUtils.isNotBlank(strSearch)) {
|
if (StringUtils.isNotBlank(strSearch)) {
|
||||||
val orSearch = new Search();
|
val orSearch = new Search();
|
||||||
for (final String col : searchCols()) {
|
for (val col : searchCols()) {
|
||||||
orSearch.or(new Search().like(col, decodeLike(strSearch)));
|
orSearch.or(new Search().like(col, decodeLike(strSearch)));
|
||||||
}
|
}
|
||||||
search.and(orSearch);
|
search.and(orSearch);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.pudonghot.ambition.crm.controller;
|
package com.pudonghot.ambition.crm.controller;
|
||||||
|
|
||||||
|
import com.pudonghot.ambition.crm.common.controller.BaseQueryController;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -1,20 +1,19 @@
|
|||||||
package com.pudonghot.ambition.crm.controller;
|
package com.pudonghot.ambition.crm.controller;
|
||||||
|
|
||||||
|
import lombok.val;
|
||||||
|
import org.apache.shiro.SecurityUtils;
|
||||||
|
import me.chyxion.tigon.mybatis.Search;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import me.chyxion.tigon.model.ViewModel;
|
||||||
|
import com.pudonghot.ambition.crm.model.User;
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import me.chyxion.tigon.kit.bean.BeanService;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import me.chyxion.tigon.shiro.service.AuthService;
|
||||||
|
import com.pudonghot.ambition.crm.service.UserService;
|
||||||
import com.pudonghot.ambition.crm.auth.SessionAbility;
|
import com.pudonghot.ambition.crm.auth.SessionAbility;
|
||||||
import com.pudonghot.ambition.crm.auth.model.AuthToken;
|
import com.pudonghot.ambition.crm.auth.model.AuthToken;
|
||||||
import com.pudonghot.ambition.crm.auth.model.Principal;
|
import com.pudonghot.ambition.crm.auth.model.Principal;
|
||||||
import lombok.val;
|
|
||||||
import me.chyxion.tigon.kit.bean.BeanService;
|
|
||||||
import me.chyxion.tigon.mybatis.Search;
|
|
||||||
import org.apache.shiro.SecurityUtils;
|
|
||||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
|
||||||
import org.apache.shiro.util.Assert;
|
|
||||||
import me.chyxion.tigon.model.ViewModel;
|
|
||||||
import com.pudonghot.ambition.crm.model.User;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import me.chyxion.tigon.shiro.service.AuthService;
|
|
||||||
import javax.validation.constraints.NotBlank;
|
|
||||||
import com.pudonghot.ambition.crm.service.UserService;
|
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
@ -45,8 +44,10 @@ public class AuthController implements SessionAbility {
|
|||||||
@RequestParam("password")
|
@RequestParam("password")
|
||||||
String password) {
|
String password) {
|
||||||
|
|
||||||
val user = userService.find(new Search(User.ACCOUNT, loginId));
|
val user = findUser(loginId);
|
||||||
Assert.state(user != null, "Unknown account");
|
Assert.state(user != null, () -> "Incorrect account or password");
|
||||||
|
Assert.state(user.getEnabled(), "Account is disabled, please contact admin");
|
||||||
|
|
||||||
val principal = new Principal();
|
val principal = new Principal();
|
||||||
principal.setAccount(loginId);
|
principal.setAccount(loginId);
|
||||||
principal.setUserId(user.getId());
|
principal.setUserId(user.getId());
|
||||||
@ -69,4 +70,12 @@ public class AuthController implements SessionAbility {
|
|||||||
public ViewModel<User> info() {
|
public ViewModel<User> info() {
|
||||||
return userService.findViewModel(getUserId());
|
return userService.findViewModel(getUserId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
User findUser(final String loginId) {
|
||||||
|
val user = userService.find(new Search(User.ACCOUNT, loginId));
|
||||||
|
if (user != null) {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
return userService.find(new Search(User.EMPLOYEE_ID, loginId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package com.pudonghot.ambition.crm.controller;
|
package com.pudonghot.ambition.crm.controller;
|
||||||
|
|
||||||
|
import com.pudonghot.ambition.crm.common.controller.BaseQueryController;
|
||||||
|
import com.pudonghot.ambition.crm.service.ExportTaskService;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
@ -14,6 +16,7 @@ import javax.validation.constraints.NotBlank;
|
|||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import com.pudonghot.ambition.crm.model.User;
|
import com.pudonghot.ambition.crm.model.User;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import com.pudonghot.ambition.crm.model.Customer;
|
import com.pudonghot.ambition.crm.model.Customer;
|
||||||
@ -107,6 +110,9 @@ public class CustomerController
|
|||||||
Pair.of(CRITERION_COLS.get("issue"), Boolean.class));
|
Pair.of(CRITERION_COLS.get("issue"), Boolean.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ExportTaskService exportTaskService;
|
||||||
|
|
||||||
@RequestMapping("/list")
|
@RequestMapping("/list")
|
||||||
public ListResult<ViewModel<Customer>> list(
|
public ListResult<ViewModel<Customer>> list(
|
||||||
@Min(0)
|
@Min(0)
|
||||||
@ -164,6 +170,12 @@ public class CustomerController
|
|||||||
return FileDownloadUtils.toResponseEntity(((CustomerService) queryService).exportCSV(getUserId()), null);
|
return FileDownloadUtils.toResponseEntity(((CustomerService) queryService).exportCSV(getUserId()), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiresRoles(User.ROLE_ADMIN)
|
||||||
|
@RequestMapping("/async-export")
|
||||||
|
public void asyncExportCSV() {
|
||||||
|
exportTaskService.doExport(getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
@RequiresRoles(User.ROLE_ADMIN)
|
@RequiresRoles(User.ROLE_ADMIN)
|
||||||
@PostMapping("/delete")
|
@PostMapping("/delete")
|
||||||
public void delete(@NotBlank @RequestParam("id") String id) {
|
public void delete(@NotBlank @RequestParam("id") String id) {
|
||||||
|
@ -4,6 +4,8 @@ import java.util.List;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import javax.validation.constraints.Max;
|
import javax.validation.constraints.Max;
|
||||||
|
|
||||||
|
import com.pudonghot.ambition.crm.common.controller.BaseQueryController;
|
||||||
import me.chyxion.tigon.model.ViewModel;
|
import me.chyxion.tigon.model.ViewModel;
|
||||||
import javax.validation.constraints.Min;
|
import javax.validation.constraints.Min;
|
||||||
import me.chyxion.tigon.model.ListResult;
|
import me.chyxion.tigon.model.ListResult;
|
||||||
|
@ -3,6 +3,8 @@ package com.pudonghot.ambition.crm.controller;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
|
||||||
|
import com.pudonghot.ambition.crm.common.controller.BaseQueryController;
|
||||||
import me.chyxion.tigon.mybatis.Search;
|
import me.chyxion.tigon.mybatis.Search;
|
||||||
import javax.validation.constraints.Max;
|
import javax.validation.constraints.Max;
|
||||||
import javax.validation.constraints.Min;
|
import javax.validation.constraints.Min;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package com.pudonghot.ambition.crm.controller;
|
package com.pudonghot.ambition.crm.controller;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
import com.pudonghot.ambition.crm.common.controller.BaseController;
|
||||||
import com.pudonghot.ambition.crm.model.User;
|
import com.pudonghot.ambition.crm.model.User;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
package com.pudonghot.ambition.crm.controller;
|
||||||
|
|
||||||
|
import lombok.val;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import me.chyxion.tigon.mybatis.Search;
|
||||||
|
import com.pudonghot.ambition.crm.model.User;
|
||||||
|
import me.chyxion.tigon.web.controller2.ArgQuery;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import com.pudonghot.ambition.crm.model.ExportTask;
|
||||||
|
import com.pudonghot.ambition.crm.auth.SessionAbility;
|
||||||
|
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import me.chyxion.tigon.web.controller2.BaseQueryController;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import com.pudonghot.ambition.crm.ws.service.WebSocketService;
|
||||||
|
import me.chyxion.tigon.web.controller2.response.ListCtrlrResp;
|
||||||
|
import com.pudonghot.ambition.crm.common.request.BaseListCtrlrReq;
|
||||||
|
import com.pudonghot.ambition.crm.ws.model.ExportTaskUpdatedWsResp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Donghuang
|
||||||
|
* @date Jun 18, 2022 09:47:30
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/export-task")
|
||||||
|
public class ExportTaskController
|
||||||
|
extends BaseQueryController<Long,
|
||||||
|
BaseListCtrlrReq,
|
||||||
|
ExportTask,
|
||||||
|
ExportTask>
|
||||||
|
implements SessionAbility {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@RequiresRoles(User.ROLE_ADMIN)
|
||||||
|
public ListCtrlrResp<ExportTask> list(@Valid final BaseListCtrlrReq req) {
|
||||||
|
return list(req, new Search());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void before(final ArgQuery<?> arg) {
|
||||||
|
super.before(arg);
|
||||||
|
val search = arg.getSearch();
|
||||||
|
search.eq(ExportTask.CREATED_BY, getUserId());
|
||||||
|
if (arg.getType() == ArgQuery.Type.LIST) {
|
||||||
|
search.desc(ExportTask.DATE_CREATED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WebSocketService webSocketService;
|
||||||
|
|
||||||
|
@PostMapping("/test-push")
|
||||||
|
@RequiresRoles(User.ROLE_ADMIN)
|
||||||
|
public void testPush(@RequestBody ExportTaskUpdatedWsResp resp) {
|
||||||
|
resp.setEmployeeKey(getUserId());
|
||||||
|
webSocketService.publish(resp);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package com.pudonghot.ambition.crm.controller;
|
package com.pudonghot.ambition.crm.controller;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
|
||||||
|
import com.pudonghot.ambition.crm.common.controller.BaseQueryController;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import javax.validation.constraints.Max;
|
import javax.validation.constraints.Max;
|
||||||
import javax.validation.constraints.Min;
|
import javax.validation.constraints.Min;
|
||||||
|
@ -2,6 +2,8 @@ package com.pudonghot.ambition.crm.controller;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import com.pudonghot.ambition.crm.common.controller.BaseQueryController;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import me.chyxion.tigon.model.ViewModel;
|
import me.chyxion.tigon.model.ViewModel;
|
||||||
import javax.validation.constraints.Max;
|
import javax.validation.constraints.Max;
|
||||||
@ -30,7 +32,7 @@ public class ImportRecordController
|
|||||||
"u.name",
|
"u.name",
|
||||||
"u.en_name",
|
"u.en_name",
|
||||||
"u.account",
|
"u.account",
|
||||||
"u.employee_id" );
|
"u.employee_id");
|
||||||
|
|
||||||
@RequestMapping("/list")
|
@RequestMapping("/list")
|
||||||
@RequiresRoles(User.ROLE_ADMIN)
|
@RequiresRoles(User.ROLE_ADMIN)
|
||||||
|
@ -4,6 +4,7 @@ import java.util.List;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
|
||||||
|
import com.pudonghot.ambition.crm.common.controller.BaseQueryController;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import me.chyxion.tigon.mybatis.Search;
|
import me.chyxion.tigon.mybatis.Search;
|
||||||
@ -71,14 +72,14 @@ public class LocalProductController
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresRoles(value = {User.ROLE_LELI, User.ROLE_CHYXION, User.ROLE_ADMIN}, logical = Logical.OR)
|
@RequiresRoles(value = {User.ROLE_LELI, User.ROLE_DONGHUANG, User.ROLE_ADMIN}, logical = Logical.OR)
|
||||||
@RequestMapping(value = "/create", method = RequestMethod.POST)
|
@RequestMapping(value = "/create", method = RequestMethod.POST)
|
||||||
public void create(
|
public void create(
|
||||||
@Valid LocalProductFormForCreate form) {
|
@Valid LocalProductFormForCreate form) {
|
||||||
((LocalProductService) queryService).create(form);
|
((LocalProductService) queryService).create(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresRoles(value = {User.ROLE_LELI, User.ROLE_CHYXION, User.ROLE_ADMIN}, logical = Logical.OR)
|
@RequiresRoles(value = {User.ROLE_LELI, User.ROLE_DONGHUANG, User.ROLE_ADMIN}, logical = Logical.OR)
|
||||||
@RequestMapping(value = "/update", method = RequestMethod.POST)
|
@RequestMapping(value = "/update", method = RequestMethod.POST)
|
||||||
public void update(
|
public void update(
|
||||||
@Valid LocalProductFormForUpdate form) {
|
@Valid LocalProductFormForUpdate form) {
|
||||||
@ -98,7 +99,7 @@ public class LocalProductController
|
|||||||
return viewModel;
|
return viewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresRoles(value = {User.ROLE_LELI, User.ROLE_CHYXION, User.ROLE_ADMIN}, logical = Logical.OR)
|
@RequiresRoles(value = {User.ROLE_LELI, User.ROLE_DONGHUANG, User.ROLE_ADMIN}, logical = Logical.OR)
|
||||||
@RequestMapping(value = "/add-image", method = RequestMethod.POST)
|
@RequestMapping(value = "/add-image", method = RequestMethod.POST)
|
||||||
public ViewModel<AttachedImage> addImage(
|
public ViewModel<AttachedImage> addImage(
|
||||||
@Valid LocalProductImageFormForCreate form) {
|
@Valid LocalProductImageFormForCreate form) {
|
||||||
@ -106,19 +107,19 @@ public class LocalProductController
|
|||||||
return new ViewModel<>(((LocalProductService) queryService).addImage(form));
|
return new ViewModel<>(((LocalProductService) queryService).addImage(form));
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresRoles(value = {User.ROLE_LELI, User.ROLE_CHYXION, User.ROLE_ADMIN}, logical = Logical.OR)
|
@RequiresRoles(value = {User.ROLE_LELI, User.ROLE_DONGHUANG, User.ROLE_ADMIN}, logical = Logical.OR)
|
||||||
@RequestMapping(value = "/remove-image", method = RequestMethod.POST)
|
@RequestMapping(value = "/remove-image", method = RequestMethod.POST)
|
||||||
public void removeImage(@NotBlank @RequestParam("id") String id) {
|
public void removeImage(@NotBlank @RequestParam("id") String id) {
|
||||||
((LocalProductService) queryService).removeImage(id);
|
((LocalProductService) queryService).removeImage(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresRoles(value = {User.ROLE_LELI, User.ROLE_CHYXION, User.ROLE_ADMIN}, logical = Logical.OR)
|
@RequiresRoles(value = {User.ROLE_LELI, User.ROLE_DONGHUANG, User.ROLE_ADMIN}, logical = Logical.OR)
|
||||||
@RequestMapping(value = "/update-image", method = RequestMethod.POST)
|
@RequestMapping(value = "/update-image", method = RequestMethod.POST)
|
||||||
public void updateImage(@Valid LocalProductImageFormForUpdate form) {
|
public void updateImage(@Valid LocalProductImageFormForUpdate form) {
|
||||||
((LocalProductService) queryService).updateImage(form);
|
((LocalProductService) queryService).updateImage(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresRoles(value = {User.ROLE_LELI, User.ROLE_CHYXION, User.ROLE_ADMIN}, logical = Logical.OR)
|
@RequiresRoles(value = {User.ROLE_LELI, User.ROLE_DONGHUANG, User.ROLE_ADMIN}, logical = Logical.OR)
|
||||||
@RequestMapping(value = "/add-attachment", method = RequestMethod.POST)
|
@RequestMapping(value = "/add-attachment", method = RequestMethod.POST)
|
||||||
public ViewModel<AttachedFile> addAttachment(
|
public ViewModel<AttachedFile> addAttachment(
|
||||||
@Valid LocalProductAttachedFileFormForCreate form) {
|
@Valid LocalProductAttachedFileFormForCreate form) {
|
||||||
@ -131,13 +132,13 @@ public class LocalProductController
|
|||||||
((LocalProductService) queryService).removeAttachment(id);
|
((LocalProductService) queryService).removeAttachment(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresRoles(value = {User.ROLE_LELI, User.ROLE_CHYXION, User.ROLE_ADMIN}, logical = Logical.OR)
|
@RequiresRoles(value = {User.ROLE_LELI, User.ROLE_DONGHUANG, User.ROLE_ADMIN}, logical = Logical.OR)
|
||||||
@RequestMapping(value = "/update-attachment", method = RequestMethod.POST)
|
@RequestMapping(value = "/update-attachment", method = RequestMethod.POST)
|
||||||
public void updateImage(@Valid LocalProductAttachedFileFormForUpdate form) {
|
public void updateImage(@Valid LocalProductAttachedFileFormForUpdate form) {
|
||||||
((LocalProductService) queryService).updateAttachment(form);
|
((LocalProductService) queryService).updateAttachment(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresRoles(value = {User.ROLE_LELI, User.ROLE_CHYXION, User.ROLE_ADMIN}, logical = Logical.OR)
|
@RequiresRoles(value = {User.ROLE_LELI, User.ROLE_DONGHUANG, User.ROLE_ADMIN}, logical = Logical.OR)
|
||||||
@RequestMapping(value = "/delete", method = RequestMethod.POST)
|
@RequestMapping(value = "/delete", method = RequestMethod.POST)
|
||||||
public void delete(@NotBlank @RequestParam("id") String id) {
|
public void delete(@NotBlank @RequestParam("id") String id) {
|
||||||
((LocalProductService) queryService).delete(id);
|
((LocalProductService) queryService).delete(id);
|
||||||
|
@ -5,6 +5,8 @@ import java.util.List;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
|
||||||
|
import com.pudonghot.ambition.crm.common.controller.BaseQueryController;
|
||||||
import me.chyxion.tigon.mybatis.Search;
|
import me.chyxion.tigon.mybatis.Search;
|
||||||
import javax.validation.constraints.Max;
|
import javax.validation.constraints.Max;
|
||||||
import javax.validation.constraints.Min;
|
import javax.validation.constraints.Min;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package com.pudonghot.ambition.crm.controller;
|
package com.pudonghot.ambition.crm.controller;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import com.pudonghot.ambition.crm.common.controller.BaseQueryController;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package com.pudonghot.ambition.crm.service;
|
package com.pudonghot.ambition.crm.service;
|
||||||
|
|
||||||
import javax.validation.constraints.NotBlank;
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
import com.pudonghot.ambition.crm.model.ExportTask;
|
||||||
|
import me.chyxion.tigon.service2.BaseQueryService;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -8,13 +11,20 @@ import org.springframework.validation.annotation.Validated;
|
|||||||
* @date May 29, 2022 21:24:42
|
* @date May 29, 2022 21:24:42
|
||||||
*/
|
*/
|
||||||
@Validated
|
@Validated
|
||||||
public interface ExportTaskService {
|
public interface ExportTaskService extends BaseQueryService<Long, ExportTask> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* do export
|
* do export
|
||||||
*
|
*
|
||||||
* @param operator
|
* @param employeeKey employee key
|
||||||
*/
|
*/
|
||||||
void doExport(@NotBlank String operator);
|
void doExport(@NotBlank String employeeKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* notify task updated
|
||||||
|
*
|
||||||
|
* @param employeeKey employee key
|
||||||
|
*/
|
||||||
|
void notifyTaskUpdated(@NotBlank String employeeKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,32 +1,102 @@
|
|||||||
package com.pudonghot.ambition.crm.service.support;
|
package com.pudonghot.ambition.crm.service.support;
|
||||||
|
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Date;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import me.chyxion.tigon.mybatis.Search;
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import com.pudonghot.ambition.crm.model.ExportTask;
|
||||||
import org.springframework.core.task.TaskExecutor;
|
import org.springframework.core.task.TaskExecutor;
|
||||||
|
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||||
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import com.pudonghot.ambition.crm.mapper.ExportTaskMapper;
|
||||||
import com.pudonghot.ambition.crm.service.CustomerService;
|
import com.pudonghot.ambition.crm.service.CustomerService;
|
||||||
import com.pudonghot.ambition.crm.service.ExportTaskService;
|
import com.pudonghot.ambition.crm.service.ExportTaskService;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import com.pudonghot.ambition.crm.ws.service.WebSocketService;
|
||||||
|
import me.chyxion.tigon.service.support2.BaseQueryServiceSupport;
|
||||||
|
import com.pudonghot.ambition.crm.enumeration.EnumExportTaskStatus;
|
||||||
|
import com.pudonghot.ambition.crm.ws.model.ExportTaskUpdatedWsResp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Donghuang
|
* @author Donghuang
|
||||||
* @date May 29, 2022 21:29:06
|
* @date May 29, 2022 21:29:06
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class ExportTaskServiceSupport implements ExportTaskService {
|
public class ExportTaskServiceSupport
|
||||||
|
extends BaseQueryServiceSupport<Long, ExportTask, ExportTaskMapper, ExportTask>
|
||||||
|
implements ExportTaskService {
|
||||||
|
|
||||||
|
private final ConcurrentMap<String, Long> LOCK_MAP = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier("exportTaskExecutor")
|
@Qualifier("exportTaskExecutor")
|
||||||
private TaskExecutor threadPoolTaskExecutor;
|
private TaskExecutor threadPoolTaskExecutor;
|
||||||
@Autowired
|
@Autowired
|
||||||
private CustomerService customerService;
|
private CustomerService customerService;
|
||||||
|
@Value("${export.location:/data/export}")
|
||||||
|
private String exportLocation;
|
||||||
|
@Autowired
|
||||||
|
private WebSocketService webSocketService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void doExport(final String operator) {
|
public void doExport(final String employeeKey) {
|
||||||
|
val now = Long.valueOf(System.currentTimeMillis());
|
||||||
|
Assert.state(now.equals(LOCK_MAP.putIfAbsent(employeeKey, now)),
|
||||||
|
"There is a running export task, please try again later!");
|
||||||
|
|
||||||
threadPoolTaskExecutor.execute(() ->{
|
threadPoolTaskExecutor.execute(() ->{
|
||||||
val exportFile = customerService.exportCSV(operator);
|
try {
|
||||||
|
val exportTask = new ExportTask();
|
||||||
|
exportTask.setCreatedBy(employeeKey);
|
||||||
|
exportTask.setDateCreated(new Date());
|
||||||
|
exportTask.setStatus(EnumExportTaskStatus.RUNNING);
|
||||||
|
mapper.insert(exportTask);
|
||||||
|
|
||||||
|
try {
|
||||||
|
val exportFile = customerService.exportCSV(employeeKey);
|
||||||
|
val distDir = new File(new File(exportLocation),
|
||||||
|
DateFormatUtils.format(now, "yyyyMMdd"));
|
||||||
|
FileUtils.moveFileToDirectory(exportFile, distDir, true);
|
||||||
|
exportTask.setStatus(EnumExportTaskStatus.DONE);
|
||||||
|
exportTask.setLocation(new File(distDir, exportFile.getName()).getPath());
|
||||||
|
exportTask.setDateUpdated(new Date());
|
||||||
|
mapper.update(exportTask);
|
||||||
|
} catch (final Throwable e) {
|
||||||
|
log.error("Export file error caused.", e);
|
||||||
|
exportTask.setStatus(EnumExportTaskStatus.FAILED);
|
||||||
|
exportTask.setNote(ExceptionUtils.getStackTrace(e));
|
||||||
|
exportTask.setDateUpdated(new Date());
|
||||||
|
mapper.update(exportTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyTaskUpdated(employeeKey);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
LOCK_MAP.remove(employeeKey);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void notifyTaskUpdated(final String employeeKey) {
|
||||||
|
webSocketService.publish(
|
||||||
|
new ExportTaskUpdatedWsResp(employeeKey,
|
||||||
|
mapper.count(new Search(ExportTask.CREATED_BY, employeeKey)
|
||||||
|
.isFalse(ExportTask.DOWNLOADED))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,16 @@
|
|||||||
package com.pudonghot.ambition.crm.util;
|
package com.pudonghot.ambition.crm.util;
|
||||||
|
|
||||||
import com.pudonghot.ambition.crm.exception.CVSFileImportingException;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import lombok.val;
|
|
||||||
import org.apache.commons.csv.CSVFormat;
|
|
||||||
import org.apache.commons.csv.CSVParser;
|
|
||||||
import org.apache.commons.csv.CSVRecord;
|
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.core.io.InputStreamResource;
|
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import lombok.val;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.Charset;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Iterator;
|
import org.springframework.http.MediaType;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.core.io.InputStreamResource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Donghuang
|
* @author Donghuang
|
||||||
@ -27,7 +18,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class FileDownloadUtils {
|
public class FileDownloadUtils {
|
||||||
private static final AtomicBoolean lock = new AtomicBoolean(false);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* file to response entity
|
* file to response entity
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.pudonghot.ambition.crm.ws.model;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Donghuang
|
||||||
|
* @date Jun 17, 2022 15:01:49
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
public class BaseWsResp implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
private String employeeKey;
|
||||||
|
@NotBlank
|
||||||
|
private String type;
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.pudonghot.ambition.crm.ws.model;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Donghuang
|
||||||
|
* @date Jun 17, 2022 15:01:49
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
public class ExportTaskUpdatedWsResp extends BaseWsResp {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private Integer countUndownloaded;
|
||||||
|
private Integer countFailed;
|
||||||
|
|
||||||
|
public ExportTaskUpdatedWsResp() {
|
||||||
|
setType("EXPORT_TASK_UPDATED");
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExportTaskUpdatedWsResp(final String employeeKey, final Integer countUndownloaded) {
|
||||||
|
this();
|
||||||
|
this.countUndownloaded = countUndownloaded;
|
||||||
|
setEmployeeKey(employeeKey);
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,10 @@
|
|||||||
package com.pudonghot.ambition.crm.ws.service;
|
package com.pudonghot.ambition.crm.ws.service;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import javax.validation.constraints.NotBlank;
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
import com.pudonghot.ambition.crm.ws.model.BaseWsResp;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,8 +17,16 @@ public interface WebSocketService {
|
|||||||
/**
|
/**
|
||||||
* publish websocket message
|
* publish websocket message
|
||||||
*
|
*
|
||||||
* @param employeeKey
|
* @param resp resp
|
||||||
* @param payload
|
*/
|
||||||
|
void publish(@NotNull @Valid BaseWsResp resp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* publish websocket message
|
||||||
|
*
|
||||||
|
* @param employeeKey employee key
|
||||||
|
* @param payload payload
|
||||||
*/
|
*/
|
||||||
void publish(@NotBlank String employeeKey, @NotNull Object payload);
|
void publish(@NotBlank String employeeKey, @NotNull Object payload);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.pudonghot.ambition.crm.ws.service.impl;
|
|||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import com.pudonghot.ambition.crm.ws.model.BaseWsResp;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import com.pudonghot.ambition.crm.ws.service.WebSocketService;
|
import com.pudonghot.ambition.crm.ws.service.WebSocketService;
|
||||||
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
||||||
@ -17,6 +18,16 @@ public class WebSocketServiceImpl implements WebSocketService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SimpMessagingTemplate message;
|
private SimpMessagingTemplate message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void publish(final BaseWsResp resp) {
|
||||||
|
publish(resp.getEmployeeKey(), resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
public void publish(final String employeeKey,
|
public void publish(final String employeeKey,
|
||||||
final Object payload) {
|
final Object payload) {
|
||||||
log.debug("Publish websocket message [{}] -> [{}].", employeeKey, payload);
|
log.debug("Publish websocket message [{}] -> [{}].", employeeKey, payload);
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit a69a6519311d6a5ec932f2f7e1e71bb381a04a20
|
Subproject commit 56a42f79cac7f8369bacf51e323242c0ae202e55
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.pudonghot.ambition.crm;
|
||||||
|
|
||||||
|
public class Test {
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
/**
|
||||||
|
* @author Donghuang
|
||||||
|
* @date Jun 18, 2022 10:07:26
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
<!DOCTYPE mapper PUBLIC
|
||||||
|
"-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.pudonghot.ambition.crm.mapper.ExportTaskMapper">
|
||||||
|
</mapper>
|
@ -4,18 +4,20 @@ import lombok.Getter;
|
|||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import me.chyxion.tigon.mybatis.BasicEntity;
|
||||||
import me.chyxion.tigon.mybatis.NotUpdate;
|
import me.chyxion.tigon.mybatis.NotUpdate;
|
||||||
import lombok.experimental.FieldNameConstants;
|
import lombok.experimental.FieldNameConstants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Shaun Chyxion <br>
|
* Base Database model
|
||||||
* chyxion@163.com <br>
|
*
|
||||||
* Aug 09, 2017 22:24:40
|
* @author Donghuang
|
||||||
|
* @date Jun 18, 2022 09:39:26
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@FieldNameConstants(prefix = "")
|
@FieldNameConstants(prefix = "")
|
||||||
public class BaseDbModel implements Serializable {
|
public class BaseDbModel implements Serializable, BasicEntity {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private Long id;
|
private Long id;
|
||||||
@ -25,6 +27,37 @@ public class BaseDbModel implements Serializable {
|
|||||||
private Date dateCreated;
|
private Date dateCreated;
|
||||||
private String updatedBy;
|
private String updatedBy;
|
||||||
private Date dateUpdated;
|
private Date dateUpdated;
|
||||||
private boolean enabled;
|
private Boolean enabled;
|
||||||
private String note;
|
private String note;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* convenient method
|
||||||
|
*
|
||||||
|
* @return true if is enabled
|
||||||
|
*/
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled != null && enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* init date created
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void beforeInsert() {
|
||||||
|
if (dateCreated == null) {
|
||||||
|
dateCreated = new Date();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enabled == null) {
|
||||||
|
enabled = Boolean.TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* update date updated
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void beforeUpdate() {
|
||||||
|
dateUpdated = new Date();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,9 @@ package com.pudonghot.ambition.crm.model;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import me.chyxion.tigon.mybatis.Table;
|
import me.chyxion.tigon.mybatis.Table;
|
||||||
import me.chyxion.tigon.mybatis.NotUpdate;
|
|
||||||
import lombok.experimental.FieldNameConstants;
|
import lombok.experimental.FieldNameConstants;
|
||||||
|
import me.chyxion.tigon.mybatis.UseGeneratedKeys;
|
||||||
|
import me.chyxion.tigon.mybatis.NotUpdateWhenNull;
|
||||||
import com.pudonghot.ambition.crm.enumeration.EnumExportTaskStatus;
|
import com.pudonghot.ambition.crm.enumeration.EnumExportTaskStatus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -13,6 +14,7 @@ import com.pudonghot.ambition.crm.enumeration.EnumExportTaskStatus;
|
|||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
|
@UseGeneratedKeys
|
||||||
@Table("crm_export_task")
|
@Table("crm_export_task")
|
||||||
@FieldNameConstants(prefix = "")
|
@FieldNameConstants(prefix = "")
|
||||||
public class ExportTask extends BaseDbModel {
|
public class ExportTask extends BaseDbModel {
|
||||||
@ -20,6 +22,7 @@ public class ExportTask extends BaseDbModel {
|
|||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
private EnumExportTaskStatus status;
|
private EnumExportTaskStatus status;
|
||||||
@NotUpdate
|
@NotUpdateWhenNull
|
||||||
private String location;
|
private String location;
|
||||||
|
private boolean downloaded;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import me.chyxion.tigon.model.M3;
|
|||||||
import me.chyxion.tigon.mybatis.Table;
|
import me.chyxion.tigon.mybatis.Table;
|
||||||
import me.chyxion.tigon.mybatis.Transient;
|
import me.chyxion.tigon.mybatis.Transient;
|
||||||
import lombok.experimental.FieldNameConstants;
|
import lombok.experimental.FieldNameConstants;
|
||||||
|
import me.chyxion.tigon.mybatis.UseGeneratedKeys;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @version 0.0.1
|
* @version 0.0.1
|
||||||
@ -16,6 +17,7 @@ import lombok.experimental.FieldNameConstants;
|
|||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
|
@UseGeneratedKeys
|
||||||
@Table("crm_file_info")
|
@Table("crm_file_info")
|
||||||
@FieldNameConstants(prefix = "")
|
@FieldNameConstants(prefix = "")
|
||||||
public class FileInfo extends M3<String, String> {
|
public class FileInfo extends M3<String, String> {
|
||||||
|
@ -25,9 +25,9 @@ public class User extends M3<String, String> {
|
|||||||
// roles
|
// roles
|
||||||
public static final String ROLE_ADMIN = "ADMIN";
|
public static final String ROLE_ADMIN = "ADMIN";
|
||||||
public static final String ROLE_LELI = "leli";
|
public static final String ROLE_LELI = "leli";
|
||||||
public static final String ROLE_CHYXION = "donghuang";
|
public static final String ROLE_DONGHUANG = "donghuang";
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
private String account;
|
private String account;
|
||||||
@NotUpdate
|
@NotUpdate
|
||||||
private String employeeId;
|
private String employeeId;
|
||||||
|
@ -6,16 +6,6 @@ export default Service.extend({
|
|||||||
ajax: service('ajax'),
|
ajax: service('ajax'),
|
||||||
connect() {
|
connect() {
|
||||||
const me = this;
|
const me = this;
|
||||||
if (me.get('connected')) {
|
|
||||||
console.info('Websocket is connected, reconnect.');
|
|
||||||
me.disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
// connect
|
|
||||||
if (!me.get('stompClient')) {
|
|
||||||
me.set('stompClient', Stomp.over(new SockJS('/stomp')));
|
|
||||||
}
|
|
||||||
|
|
||||||
const user = me.get('ajax.user');
|
const user = me.get('ajax.user');
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
@ -23,15 +13,57 @@ export default Service.extend({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
me.get('stompClient').connect({}, function() {
|
if (me.get('connected')) {
|
||||||
console.info('Connect websocket.', user);
|
console.info('Websocket is connected, reconnect.');
|
||||||
me.stompClient.subscribe('/topic/' + user.id, function(msg) {
|
me.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = new StompJs.Client({
|
||||||
|
// brokerURL: 'ws://localhost:15674/ws',
|
||||||
|
webSocketFactory: function () {
|
||||||
|
// Note that the URL is different from the WebSocket URL
|
||||||
|
return new SockJS('/stomp');
|
||||||
|
},
|
||||||
|
connectHeaders: {
|
||||||
|
user: user.id,
|
||||||
|
// passcode: 'password',
|
||||||
|
},
|
||||||
|
debug: function (str) {
|
||||||
|
console.log(str);
|
||||||
|
},
|
||||||
|
reconnectDelay: 5000,
|
||||||
|
heartbeatIncoming: 4000,
|
||||||
|
heartbeatOutgoing: 4000,
|
||||||
|
});
|
||||||
|
|
||||||
|
client.onConnect = function(frame) {
|
||||||
|
// Do something, all subscribes must be done is this callback
|
||||||
|
// This is needed because this will be executed after a (re)connect
|
||||||
|
console.info('Websocket connected: ', frame);
|
||||||
|
me.set('subscription', client.subscribe('/topic/' + user.id, function(msg) {
|
||||||
console.info('On websocket message: ', msg);
|
console.info('On websocket message: ', msg);
|
||||||
$.trigger('WEBSOCKET', JSON.parse(msg.body));
|
$.trigger('WEBSOCKET', JSON.parse(msg.body));
|
||||||
});
|
}));
|
||||||
me.set('connected', true);
|
me.set('connected', true);
|
||||||
console.info('Websocket connected.');
|
};
|
||||||
});
|
|
||||||
|
client.onDisconnect = function(frame) {
|
||||||
|
console.log('On websocket disconnect: ', frame);
|
||||||
|
me.set('connected', false);
|
||||||
|
};
|
||||||
|
|
||||||
|
client.onStompError = function (frame) {
|
||||||
|
// Will be invoked in case of error encountered at Broker
|
||||||
|
// Bad login/passcode typically will cause an error
|
||||||
|
// Complaint brokers will set `message` header with a brief message. Body may contain details.
|
||||||
|
// Compliant brokers will terminate the connection after any error
|
||||||
|
console.log('Broker reported error: ', frame.headers['message']);
|
||||||
|
console.log('Additional details: ', frame.body);
|
||||||
|
me.set('connected', false);
|
||||||
|
};
|
||||||
|
|
||||||
|
client.activate();
|
||||||
|
me.set('client', client);
|
||||||
},
|
},
|
||||||
willDestroy() {
|
willDestroy() {
|
||||||
const me = this;
|
const me = this;
|
||||||
@ -40,10 +72,8 @@ export default Service.extend({
|
|||||||
},
|
},
|
||||||
disconnect() {
|
disconnect() {
|
||||||
const me = this;
|
const me = this;
|
||||||
if (me.get('connected') && me.get('stompClient')) {
|
if (me.get('connected') && me.get('client')) {
|
||||||
me.get('stompClient').disconnect();
|
me.get('client').deactivate();
|
||||||
me.set('connected', false);
|
|
||||||
console.info('Websocket disconnected.');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,8 +110,9 @@ module.exports = function(defaults) {
|
|||||||
importVendor(app, 'node_modules/bootstrap-wysiwyg/src/bootstrap-wysiwyg.js');
|
importVendor(app, 'node_modules/bootstrap-wysiwyg/src/bootstrap-wysiwyg.js');
|
||||||
|
|
||||||
// WebSocket
|
// WebSocket
|
||||||
|
importVendor(app, 'node_modules/@stomp/stompjs/bundles/stomp.umd.js');
|
||||||
importVendor(app, 'node_modules/sockjs-client/dist/sockjs.js');
|
importVendor(app, 'node_modules/sockjs-client/dist/sockjs.js');
|
||||||
importVendor(app, 'node_modules/stomp-websocket/lib/stomp.js');
|
// importVendor(app, 'node_modules/stomp-websocket/lib/stomp.js');
|
||||||
|
|
||||||
// Bootstrap Toolkit
|
// Bootstrap Toolkit
|
||||||
importVendor(app, 'node_modules/responsive-toolkit/dist/bootstrap-toolkit.js');
|
importVendor(app, 'node_modules/responsive-toolkit/dist/bootstrap-toolkit.js');
|
||||||
|
158
web/package.json
158
web/package.json
@ -1,79 +1,79 @@
|
|||||||
{
|
{
|
||||||
"name": "ambition-crm",
|
"name": "ambition-crm",
|
||||||
"version": "0.0.2",
|
"version": "0.0.2",
|
||||||
"description": "Ambition CRM",
|
"description": "Ambition CRM",
|
||||||
"private": true,
|
"private": true,
|
||||||
"directories": {
|
"directories": {
|
||||||
"doc": "doc",
|
"doc": "doc",
|
||||||
"test": "tests"
|
"test": "tests"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "ember build",
|
"build": "ember build",
|
||||||
"start": "ember server",
|
"start": "ember server",
|
||||||
"test": "ember test"
|
"test": "ember test"
|
||||||
},
|
},
|
||||||
"repository": "",
|
"repository": "",
|
||||||
"author": "Shaun Chyxion",
|
"author": "Shaun Chyxion",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ember/jquery": "1.1.0",
|
"@ember/jquery": "1.1.0",
|
||||||
"@ember/optional-features": "^1.3.0",
|
"@ember/optional-features": "^1.3.0",
|
||||||
"@ember/test-helpers": "^2.8.1",
|
"@ember/test-helpers": "^2.8.1",
|
||||||
"bootbox": "5.1.3",
|
"bootbox": "5.1.3",
|
||||||
"bootstrap": "3.4.1",
|
"bootstrap": "3.4.1",
|
||||||
"bootstrap-colorpicker": "^2.5.2",
|
"bootstrap-colorpicker": "^2.5.2",
|
||||||
"bootstrap-tagsinput": "^0.7.1",
|
"bootstrap-tagsinput": "^0.7.1",
|
||||||
"bootstrap-wysiwyg": "^2.0.1",
|
"bootstrap-wysiwyg": "^2.0.1",
|
||||||
"broccoli-asset-rev": "^3.0.0",
|
"broccoli-asset-rev": "^3.0.0",
|
||||||
"ember-ajax": "^5.0.0",
|
"ember-ajax": "^5.0.0",
|
||||||
"ember-auto-import": "^2.4.2",
|
"ember-auto-import": "^2.4.2",
|
||||||
"ember-cli": "3.28.5",
|
"ember-cli": "3.28.5",
|
||||||
"ember-cli-app-version": "^5.0.0",
|
"ember-cli-app-version": "^5.0.0",
|
||||||
"ember-cli-babel": "^7.19.0",
|
"ember-cli-babel": "^7.19.0",
|
||||||
"ember-cli-clipboard": "^0.16.0",
|
"ember-cli-clipboard": "^0.16.0",
|
||||||
"ember-cli-dependency-checker": "^3.1.0",
|
"ember-cli-dependency-checker": "^3.1.0",
|
||||||
"ember-cli-eslint": "^5.1.0",
|
"ember-cli-eslint": "^5.1.0",
|
||||||
"ember-cli-htmlbars": "^6.0.1",
|
"ember-cli-htmlbars": "^6.0.1",
|
||||||
"ember-cli-inject-live-reload": "^2.0.2",
|
"ember-cli-inject-live-reload": "^2.0.2",
|
||||||
"ember-cli-less": "^3.0.1",
|
"ember-cli-less": "^3.0.1",
|
||||||
"ember-cli-moment-shim": "^3.7.1",
|
"ember-cli-moment-shim": "^3.7.1",
|
||||||
"ember-cli-shims": "^1.2.0",
|
"ember-cli-shims": "^1.2.0",
|
||||||
"ember-cli-sri": "^2.1.1",
|
"ember-cli-sri": "^2.1.1",
|
||||||
"ember-cli-template-lint": "^2.0.2",
|
"ember-cli-template-lint": "^2.0.2",
|
||||||
"ember-cli-uglify": "^3.0.0",
|
"ember-cli-uglify": "^3.0.0",
|
||||||
"ember-composable-helpers": "^3.1.1",
|
"ember-composable-helpers": "^3.1.1",
|
||||||
"ember-export-application-global": "^2.0.0",
|
"ember-export-application-global": "^2.0.0",
|
||||||
"ember-load-initializers": "^2.1.1",
|
"ember-load-initializers": "^2.1.1",
|
||||||
"ember-maybe-import-regenerator": "^1.0.0",
|
"ember-maybe-import-regenerator": "^1.0.0",
|
||||||
"ember-moment": "^10.0.0",
|
"ember-moment": "^10.0.0",
|
||||||
"ember-qunit": "^5.1.5",
|
"ember-qunit": "^5.1.5",
|
||||||
"ember-radio-button": "^2.0.1",
|
"ember-radio-button": "^2.0.1",
|
||||||
"ember-resolver": "^8.0.0",
|
"ember-resolver": "^8.0.0",
|
||||||
"ember-route-action-helper": "^2.0.8",
|
"ember-route-action-helper": "^2.0.8",
|
||||||
"ember-source": "3.28.9",
|
"ember-source": "3.28.9",
|
||||||
"ember-truth-helpers": "^3.0.0",
|
"ember-truth-helpers": "^3.0.0",
|
||||||
"emberx-select": "3.1.1",
|
"emberx-select": "3.1.1",
|
||||||
"eslint-plugin-ember": "^10.6.1",
|
"eslint-plugin-ember": "^10.6.1",
|
||||||
"font-awesome": "^4.7.0",
|
"font-awesome": "^4.7.0",
|
||||||
"fuelux": "^3.17.0",
|
"fuelux": "^3.17.0",
|
||||||
"glob": "^8.0.3",
|
"glob": "^8.0.3",
|
||||||
"jquery-colorbox": "^1.6.4",
|
"jquery-colorbox": "^1.6.4",
|
||||||
"json-format-highlight": "^1.0.4",
|
"json-format-highlight": "^1.0.4",
|
||||||
"loader.js": "^4.7.0",
|
"loader.js": "^4.7.0",
|
||||||
"moment": "^2.24.0",
|
"moment": "^2.24.0",
|
||||||
"qunit": "^2.19.1",
|
"qunit": "^2.19.1",
|
||||||
"qunit-dom": "^2.0.0",
|
"qunit-dom": "^2.0.0",
|
||||||
"responsive-toolkit": "^2.6.3",
|
"responsive-toolkit": "^2.6.3",
|
||||||
"select2": "^4.0.13",
|
"select2": "^4.0.13",
|
||||||
"toastr": "^2.1.4",
|
"toastr": "^2.1.4",
|
||||||
"validate.js": "^0.13.1",
|
"validate.js": "^0.13.1",
|
||||||
"webpack": "^5.73.0"
|
"webpack": "^5.73.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"sockjs-client": "^1.6.1",
|
"@stomp/stompjs": "^6.1.2",
|
||||||
"stomp-websocket": "^2.3.4-next"
|
"sockjs-client": "^1.6.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "6.* || 8.* || >= 10.*"
|
"node": "6.* || 8.* || >= 10.*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user