Commit 54e4643f authored by 法拉51246's avatar 法拉51246

修改部门信息强制踢下线

大屏过滤null数据,解决导致的异常
数据权限全部增加完毕
带出来客户数据增加带出所属部门
parent a4897ed0
......@@ -33,4 +33,7 @@ public class PageParam implements Serializable {
@Max(value = 100, message = "每页条数最大值为 100")
private Integer pageSize = PAGE_SIZE;
//控制数据权限
private Long companyId;
}
......@@ -52,5 +52,12 @@ public abstract class BaseDO implements Serializable, TransPojo {
*/
@TableLogic
private Boolean deleted;
/**
* 所在部门,目前使用 部门编号
*
*
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long companyId;
}
......@@ -42,6 +42,12 @@ public class DefaultDBFieldHandler implements MetaObjectHandler {
if (Objects.nonNull(userName) && Objects.isNull(baseDO.getUpdater())) {
baseDO.setUpdater(userName);
}
//自动插入登录人所属分公司id
Long userDeptId = WebFrameworkUtils.getLoginUserDeptId();
if (Objects.nonNull(userDeptId)) {
baseDO.setCompanyId(userDeptId);
}
}
}
......@@ -59,5 +65,11 @@ public class DefaultDBFieldHandler implements MetaObjectHandler {
if (Objects.nonNull(userId) && Objects.isNull(modifier)) {
setFieldValByName("updater", userId.toString(), metaObject);
}
//自动插入登录人所属分公司id
Long userDeptId = WebFrameworkUtils.getLoginUserDeptId();
if (Objects.nonNull(userDeptId)) {
setFieldValByName("companyId", userDeptId, metaObject);
}
}
}
......@@ -134,6 +134,14 @@ public class SecurityFrameworkUtils {
.orElse("未知");
WebFrameworkUtils.setLoginUserName(request, nickname);
Long deptId = Optional.ofNullable(loginUser.getInfo())
.map(info -> info.get("deptId"))
.map(Object::toString)
.map(Long::valueOf)
.orElse(null);
WebFrameworkUtils.setLoginUserDept(request, deptId);
WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType());
}
......
......@@ -22,6 +22,7 @@ public class WebFrameworkUtils {
private static final String REQUEST_ATTRIBUTE_LOGIN_USER_ID = "login_user_id";
private static final String REQUEST_ATTRIBUTE_LOGIN_USER_NAME = "login_user_name";
private static final String REQUEST_ATTRIBUTE_LOGIN_USER_DEPT = "login_user_dept";
private static final String REQUEST_ATTRIBUTE_LOGIN_USER_TYPE = "login_user_type";
private static final String REQUEST_ATTRIBUTE_COMMON_RESULT = "common_result";
......@@ -79,6 +80,15 @@ public class WebFrameworkUtils {
public static void setLoginUserName(ServletRequest request, String nickname) {
request.setAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_NAME, nickname);
}
/**
* 登录用户的所属分公司
*
* @param request 登录用户
* @param deptid 用户
*/
public static void setLoginUserDept(ServletRequest request, Long deptid) {
request.setAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_DEPT, deptid);
}
/**
* 设置用户类型
......@@ -111,6 +121,15 @@ public class WebFrameworkUtils {
.map(Object::toString)
.orElse("");
}
public static Long getLoginUserDeptId(HttpServletRequest request) {
if (request == null) {
return null;
}
return Optional.ofNullable(request.getAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_DEPT))
.map(Object::toString)
.map(Long::valueOf)
.orElse(null);
}
/**
* 获得当前用户的类型
......@@ -151,6 +170,10 @@ public class WebFrameworkUtils {
HttpServletRequest request = getRequest();
return getLoginUserName(request);
}
public static Long getLoginUserDeptId() {
HttpServletRequest request = getRequest();
return getLoginUserDeptId(request);
}
public static Integer getTerminal() {
HttpServletRequest request = getRequest();
......
......@@ -14,10 +14,12 @@ import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.token.OAuth2AccessTokenPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2RefreshTokenDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper;
import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2AccessTokenMapper;
import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2RefreshTokenMapper;
import cn.iocoder.yudao.module.system.dal.redis.oauth2.OAuth2AccessTokenRedisDAO;
......@@ -57,6 +59,9 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
@Lazy // 懒加载,避免循环依赖
private AdminUserService adminUserService;
@Resource
private DeptMapper deptMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public OAuth2AccessTokenDO createAccessToken(Long userId, Integer userType, String clientId, List<String> scopes) {
......@@ -199,8 +204,9 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
private Map<String, String> buildUserInfo(Long userId, Integer userType) {
if (userType.equals(UserTypeEnum.ADMIN.getValue())) {
AdminUserDO user = adminUserService.getUser(userId);
Long branchDeptId = findBranchDeptId(user.getDeptId(), 100L);//找到分公司Id,这里的100L是总公司的ID,未来某一天如果有变,就改这里
return MapUtil.builder(LoginUser.INFO_KEY_NICKNAME, user.getNickname())
.put(LoginUser.INFO_KEY_DEPT_ID, StrUtil.toStringOrNull(user.getDeptId())).build();
.put(LoginUser.INFO_KEY_DEPT_ID, StrUtil.toStringOrNull(branchDeptId)).build();
} else if (userType.equals(UserTypeEnum.MEMBER.getValue())) {
// 注意:目前 Member 暂时不读取,可以按需实现
return Collections.emptyMap();
......@@ -208,6 +214,30 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
return null;
}
//找出自己所在分公司
public Long findBranchDeptId(Long currentDeptId, Long rootDeptId) {
Long lastDeptId = null;
while (currentDeptId != null && currentDeptId != 0) {
DeptDO dept = deptMapper.selectById(currentDeptId);
if (dept == null) break;
Long parentId = dept.getParentId();
// 如果当前部门的 parent 是 rootDeptId,说明当前就是直属分公司
if (parentId != null && parentId.equals(rootDeptId)) {
return currentDeptId;
}
lastDeptId = currentDeptId;
currentDeptId = parentId;
}
return null; // 没找到直属分公司
}
private static String generateAccessToken() {
return IdUtil.fastSimpleUUID();
}
......
......@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
......@@ -12,9 +13,12 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthRegisterReqVO;
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.token.OAuth2AccessTokenPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportExcelVO;
......@@ -23,11 +27,14 @@ import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqV
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.UserPostDO;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.dept.UserPostMapper;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.dept.PostService;
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
import com.google.common.annotations.VisibleForTesting;
......@@ -86,6 +93,9 @@ public class AdminUserServiceImpl implements AdminUserService {
@Resource
private ConfigApi configApi;
@Resource
private OAuth2TokenService oauth2TokenService;
@Override
@Transactional(rollbackFor = Exception.class)
@LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_CREATE_SUB_TYPE, bizNo = "{{#user.id}}",
......@@ -159,6 +169,20 @@ public class AdminUserServiceImpl implements AdminUserService {
userMapper.updateById(updateObj);
// 2.2 更新岗位
updateUserPost(updateReqVO, updateObj);
// 新增:先判断修改的这个用户是不是自己
if (ObjectUtil.notEqual(updateReqVO.getId(), SecurityFrameworkUtils.getLoginUserId())) {
//进入这里说明不是自己,那就根据逻辑是否强制下线
// 新增:如果更新了部门编号,则先查看该用户的id,根据id删除该用户token,强制下线重新登录
if (Objects.nonNull(updateReqVO.getDeptId())&& !oldUser.getDeptId().equals(updateObj.getDeptId()) ) {
OAuth2AccessTokenPageReqVO reqVO = new OAuth2AccessTokenPageReqVO();
reqVO.setUserId(oldUser.getId());
PageResult<OAuth2AccessTokenDO> accessTokenPage = oauth2TokenService.getAccessTokenPage(reqVO);
for (OAuth2AccessTokenDO accessToken : accessTokenPage.getList()) {
oauth2TokenService.removeAccessToken(accessToken.getAccessToken());
}
}
}
//修改的是自己前端会刷新token,所以不能再t下线了,要保持登陆状态
// 3. 记录操作日志上下文
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldUser, UserSaveReqVO.class));
......
......@@ -57,6 +57,10 @@
<version>2.4.2-jdk8-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-protection</artifactId>
</dependency>
</dependencies>
</project>
package cn.iocoder.yudao.module.visit.controller.admin.customerinfo;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.idempotent.core.annotation.Idempotent;
import cn.iocoder.yudao.module.visit.controller.admin.product.vo.ProductImportExcelVO;
import cn.iocoder.yudao.module.visit.controller.admin.product.vo.ProductImportRespVO;
import cn.iocoder.yudao.module.visit.controller.admin.product.vo.ProductSimpleReqVO;
......@@ -51,6 +52,7 @@ public class CustomerInfoController {
@PostMapping("/create")
@Operation(summary = "创建客户信息")
@PreAuthorize("@ss.hasPermission('visit:customer-info:create')")
@Idempotent(timeout = 10, message = "重复请求,请稍后重试")
public CommonResult<Long> createCustomerInfo(@Valid @RequestBody CustomerInfoSaveReqVO createReqVO) {
return success(customerInfoService.createCustomerInfo(createReqVO));
}
......@@ -58,6 +60,7 @@ public class CustomerInfoController {
@PutMapping("/update")
@Operation(summary = "更新客户信息")
@PreAuthorize("@ss.hasPermission('visit:customer-info:update')")
@Idempotent(timeout = 10, message = "重复请求,请稍后重试")
public CommonResult<Boolean> updateCustomerInfo(@Valid @RequestBody CustomerInfoSaveReqVO updateReqVO) {
customerInfoService.updateCustomerInfo(updateReqVO);
return success(true);
......@@ -67,6 +70,7 @@ public class CustomerInfoController {
@Operation(summary = "删除客户信息")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('visit:customer-info:delete')")
@Idempotent(timeout = 10, message = "重复请求,请稍后重试")
public CommonResult<Boolean> deleteCustomerInfo(@RequestParam("id") Long id) {
customerInfoService.deleteCustomerInfo(id);
return success(true);
......@@ -154,6 +158,7 @@ public class CustomerInfoController {
@Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true")
})
@PreAuthorize("@ss.hasPermission('visit:customer-info:import')")
@Idempotent(timeout = 10, message = "重复请求,请稍后重试")
public CommonResult<CustomerImportRespVO> importExcel(@RequestParam("file") MultipartFile file,
@RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception {
List<CustomerImportExcelVO> list = ExcelUtils.read(file, CustomerImportExcelVO.class);
......
package cn.iocoder.yudao.module.visit.controller.admin.info;
import cn.iocoder.yudao.framework.idempotent.core.annotation.Idempotent;
import com.fhs.common.utils.StringUtil;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
......@@ -42,6 +43,7 @@ public class InfoController {
@PostMapping("/create")
@Operation(summary = "创建客户拜访记录")
@PreAuthorize("@ss.hasPermission('visit:info:create')")
@Idempotent(timeout = 10, message = "重复请求,请稍后重试")
public CommonResult<Long> createInfo(@Valid @RequestBody InfoSaveReqVO createReqVO) {
return success(infoService.createInfo(createReqVO));
}
......@@ -49,6 +51,7 @@ public class InfoController {
@PutMapping("/update")
@Operation(summary = "更新客户拜访记录")
@PreAuthorize("@ss.hasPermission('visit:info:update')")
@Idempotent(timeout = 10, message = "重复请求,请稍后重试")
public CommonResult<Boolean> updateInfo(@Valid @RequestBody InfoSaveReqVO updateReqVO) {
infoService.updateInfo(updateReqVO);
return success(true);
......@@ -58,6 +61,7 @@ public class InfoController {
@Operation(summary = "删除客户拜访记录")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('visit:info:delete')")
@Idempotent(timeout = 10, message = "重复请求,请稍后重试")
public CommonResult<Boolean> deleteInfo(@RequestParam("id") Long id) {
infoService.deleteInfo(id);
return success(true);
......
package cn.iocoder.yudao.module.visit.controller.admin.product;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.idempotent.core.annotation.Idempotent;
import cn.iocoder.yudao.module.system.enums.common.SexEnum;
import io.swagger.v3.oas.annotations.Parameters;
import org.springframework.web.bind.annotation.*;
......@@ -46,6 +47,7 @@ public class ProductController {
@PostMapping("/create")
@Operation(summary = "创建产品")
@PreAuthorize("@ss.hasPermission('visit:product:create')")
@Idempotent(timeout = 10, message = "重复请求,请稍后重试")
public CommonResult<Long> createProduct(@Valid @RequestBody ProductSaveReqVO createReqVO) {
return success(productService.createProduct(createReqVO));
}
......@@ -53,6 +55,7 @@ public class ProductController {
@PutMapping("/update")
@Operation(summary = "更新产品")
@PreAuthorize("@ss.hasPermission('visit:product:update')")
@Idempotent(timeout = 10, message = "重复请求,请稍后重试")
public CommonResult<Boolean> updateProduct(@Valid @RequestBody ProductSaveReqVO updateReqVO) {
productService.updateProduct(updateReqVO);
return success(true);
......@@ -62,6 +65,7 @@ public class ProductController {
@Operation(summary = "删除产品")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('visit:product:delete')")
@Idempotent(timeout = 10, message = "重复请求,请稍后重试")
public CommonResult<Boolean> deleteProduct(@RequestParam("id") Long id) {
productService.deleteProduct(id);
return success(true);
......@@ -129,6 +133,7 @@ public class ProductController {
@Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true")
})
@PreAuthorize("@ss.hasPermission('visit:product:import')")
@Idempotent(timeout = 10, message = "重复请求,请稍后重试")
public CommonResult<ProductImportRespVO> importExcel(@RequestParam("file") MultipartFile file,
@RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception {
List<ProductImportExcelVO> list = ExcelUtils.read(file, ProductImportExcelVO.class);
......
......@@ -5,6 +5,7 @@ import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.visit.dal.dataobject.customerinfo.CustomerInfoDO;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.visit.controller.admin.customerinfo.vo.*;
......@@ -18,38 +19,56 @@ import cn.iocoder.yudao.module.visit.controller.admin.customerinfo.vo.*;
public interface CustomerInfoMapper extends BaseMapperX<CustomerInfoDO> {
default PageResult<CustomerInfoDO> selectPage(CustomerInfoPageReqVO reqVO) {
Long companyId = SecurityFrameworkUtils.getLoginUserDeptId();
return selectPage(reqVO, new LambdaQueryWrapperX<CustomerInfoDO>()
.likeIfPresent(CustomerInfoDO::getCustomerName, reqVO.getCustomerName())
.eqIfPresent(CustomerInfoDO::getContact, reqVO.getContact())
.likeIfPresent(CustomerInfoDO::getCompanyName, reqVO.getCompanyName())
.eqIfPresent(CustomerInfoDO::getCustomerType, reqVO.getCustomerType())
.eqIfPresent(CustomerInfoDO::getCityCode, reqVO.getCityCode())
.eqIfPresent(CustomerInfoDO::getCompanyId,companyId)
.betweenIfPresent(CustomerInfoDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(CustomerInfoDO::getId));
}
default PageResult<CustomerInfoDO> selectHomePage(CustomerInfoPageReqVO reqVO) {
Long companyId = SecurityFrameworkUtils.getLoginUserDeptId();
return selectPage(reqVO, new LambdaQueryWrapperX<CustomerInfoDO>()
.eqIfPresent(CustomerInfoDO::getCustomerName, reqVO.getCustomerName())
.eqIfPresent(CustomerInfoDO::getContact, reqVO.getContact())
.eqIfPresent(CustomerInfoDO::getCompanyName, reqVO.getCompanyName())
.eqIfPresent(CustomerInfoDO::getCustomerType, reqVO.getCustomerType())
.eqIfPresent(CustomerInfoDO::getCityCode, reqVO.getCityCode())
.eqIfPresent(CustomerInfoDO::getCompanyId,companyId)
.betweenIfPresent(CustomerInfoDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(CustomerInfoDO::getId));
}
//根据公司名称查询客户信息(验证是否唯一使用)
default CustomerInfoDO selectByCompanyName(String companyName){
return selectOne(CustomerInfoDO::getCompanyName, companyName);
Long companyId = SecurityFrameworkUtils.getLoginUserDeptId();
return selectOne(new LambdaQueryWrapperX<CustomerInfoDO>()
.eq(CustomerInfoDO::getCompanyName, companyName)
.eqIfPresent(CustomerInfoDO::getCompanyId, companyId)
);
}
// 根据公司名称或手机号查询(根据任一条件带出符合条件的列表)
default List<CustomerInfoDO> selectListByCompanyName(String companyName) {
Long companyId = SecurityFrameworkUtils.getLoginUserDeptId();
return selectList(new LambdaQueryWrapperX<CustomerInfoDO>()
.eqIfPresent(CustomerInfoDO::getCompanyId, companyId)
.likeIfPresent(CustomerInfoDO::getCompanyName, companyName));
}
default List<CustomerInfoDO> selectListByContact(String contact) {
Long companyId = SecurityFrameworkUtils.getLoginUserDeptId();
return selectList(new LambdaQueryWrapperX<CustomerInfoDO>()
.eqIfPresent(CustomerInfoDO::getCompanyId, companyId)
.likeIfPresent(CustomerInfoDO::getContact, contact));
}
default List<CustomerInfoDO> selectList(Long companyId){
return selectList(new LambdaQueryWrapperX<CustomerInfoDO>()
.eqIfPresent(CustomerInfoDO::getCompanyId, companyId));
}
}
\ No newline at end of file
......@@ -5,6 +5,7 @@ import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.visit.dal.dataobject.info.InfoDO;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.visit.controller.admin.info.vo.*;
......@@ -18,6 +19,7 @@ import cn.iocoder.yudao.module.visit.controller.admin.info.vo.*;
public interface InfoMapper extends BaseMapperX<InfoDO> {
default PageResult<InfoDO> selectPage(InfoPageReqVO reqVO) {
Long companyId = SecurityFrameworkUtils.getLoginUserDeptId();
return selectPage(reqVO, new LambdaQueryWrapperX<InfoDO>()
.likeIfPresent(InfoDO::getCustomerName, reqVO.getCustomerName())
.eqIfPresent(InfoDO::getContact, reqVO.getContact())
......@@ -27,10 +29,12 @@ public interface InfoMapper extends BaseMapperX<InfoDO> {
.eqIfPresent(InfoDO::getVisitProductIds, reqVO.getVisitProductIds())
.eqIfPresent(InfoDO::getVisitMethod, reqVO.getVisitMethod())
.eqIfPresent(InfoDO::getVisitType, reqVO.getVisitType())
.eqIfPresent(InfoDO::getCompanyId,companyId)
.betweenIfPresent(InfoDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(InfoDO::getId));
}
default PageResult<InfoDO> selectHomePage(InfoPageReqVO reqVO) {
Long companyId = SecurityFrameworkUtils.getLoginUserDeptId();
return selectPage(reqVO, new LambdaQueryWrapperX<InfoDO>()
.eqIfPresent(InfoDO::getCustomerName, reqVO.getCustomerName())
.eqIfPresent(InfoDO::getContact, reqVO.getContact())
......@@ -40,12 +44,15 @@ public interface InfoMapper extends BaseMapperX<InfoDO> {
.eqIfPresent(InfoDO::getVisitProductIds, reqVO.getVisitProductIds())
.eqIfPresent(InfoDO::getVisitMethod, reqVO.getVisitMethod())
.eqIfPresent(InfoDO::getVisitType, reqVO.getVisitType())
.eqIfPresent(InfoDO::getCompanyId,companyId)
.betweenIfPresent(InfoDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(InfoDO::getId));
}
default List<InfoDO> selectByCompanyName(String companyName) {
Long companyId = SecurityFrameworkUtils.getLoginUserDeptId();
return selectList(new LambdaQueryWrapperX<InfoDO>()
.eqIfPresent(InfoDO::getCompanyId,companyId)
.eq(InfoDO::getCompanyName, companyName));
}
}
\ No newline at end of file
......@@ -5,7 +5,9 @@ import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.visit.dal.dataobject.product.ProductDO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.visit.controller.admin.product.vo.*;
......@@ -18,7 +20,14 @@ import cn.iocoder.yudao.module.visit.controller.admin.product.vo.*;
public interface ProductMapper extends BaseMapperX<ProductDO> {
default ProductDO selectByProductParam(String productName, String specification, String packageName) {
return selectOne(ProductDO::getProductName, productName, ProductDO::getSpecification, specification, ProductDO::getPackageName, packageName);
Long companyId = SecurityFrameworkUtils.getLoginUserDeptId();
return selectOne(new LambdaQueryWrapperX<ProductDO>()
.eqIfPresent(ProductDO::getProductName, productName)
.eqIfPresent(ProductDO::getSpecification, specification)
.eqIfPresent(ProductDO::getPackageName, packageName)
.eqIfPresent(ProductDO::getCompanyId, companyId)
);
}
default PageResult<ProductDO> selectPage(ProductPageReqVO reqVO) {
......@@ -27,8 +36,14 @@ public interface ProductMapper extends BaseMapperX<ProductDO> {
.eqIfPresent(ProductDO::getPackageName, reqVO.getPackageName())
.eqIfPresent(ProductDO::getSpecification, reqVO.getSpecification())
.eqIfPresent(ProductDO::getStatus, reqVO.getStatus())
.eqIfPresent(ProductDO::getCompanyId, reqVO.getCompanyId())
.betweenIfPresent(ProductDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(ProductDO::getId));
}
default List<ProductDO> selectByIds(List<String> list, Long companyId){
return selectList(new LambdaQueryWrapperX<ProductDO>()
.eqIfPresent(ProductDO::getCompanyId, companyId)
.inIfPresent(ProductDO::getId, list));
}
}
\ No newline at end of file
......@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.visit.service.customerinfo;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.infra.service.file.FileService;
import cn.iocoder.yudao.module.visit.controller.admin.product.vo.ProductPageReqVO;
import cn.iocoder.yudao.module.visit.dal.dataobject.product.ProductDO;
......@@ -132,7 +133,8 @@ public class CustomerInfoServiceImpl implements CustomerInfoService {
@Override
public List<CustomerInfoDO> getAllCustomerInfo() {
return customerInfoMapper.selectList();
Long companyId = SecurityFrameworkUtils.getLoginUserDeptId();
return customerInfoMapper.selectList(companyId);
}
@Override
......
......@@ -78,8 +78,18 @@ public class HomeServiceImpl implements HomeService {
PageResult<InfoDO> infoDOPageResult = infoMapper.selectHomePage(infoPageReqVO);//精准查询
//客户拜访总次数
homeFirstRespVO.setVisitCount(String.valueOf(infoDOPageResult.getTotal()));
homeFirstRespVO.setSykfcs(String.valueOf(infoDOPageResult.getList().stream().filter(infoDO -> infoDO.getVisitType() == 0).count()));
homeFirstRespVO.setYlkfcs(String.valueOf(infoDOPageResult.getList().stream().filter(infoDO -> infoDO.getVisitType() == 1).count()));
List<InfoDO> list = Optional.ofNullable(infoDOPageResult.getList())
.orElse(Collections.emptyList());
homeFirstRespVO.setSykfcs(String.valueOf(
list.stream()
.filter(infoDO -> Integer.valueOf(0).equals(infoDO.getVisitType()))
.count()));
homeFirstRespVO.setYlkfcs(String.valueOf(
list.stream()
.filter(infoDO -> Integer.valueOf(1).equals(infoDO.getVisitType()))
.count()));
return homeFirstRespVO;
}
......@@ -215,6 +225,7 @@ public class HomeServiceImpl implements HomeService {
// 2.分组计数:Map<customerType字典值, 数量>
Map<Integer, Long> typeCountMap = records.stream()
.filter(info -> info.getVisitMethod() != null) // ✅ null 保护
.collect(Collectors.groupingBy(InfoDO::getVisitMethod, Collectors.counting()));
// 3. 加载字典并转换为 Map
......@@ -252,6 +263,7 @@ public class HomeServiceImpl implements HomeService {
// 2.分组计数:Map<customerType字典值, 数量>
Map<String, Long> typeCountMap = records.stream()
.filter(record -> record.getDepartment() != null)
.collect(Collectors.groupingBy(InfoDO::getDepartment, Collectors.counting()));
// 3. 加载字典并转换为 Map
......@@ -289,6 +301,7 @@ public class HomeServiceImpl implements HomeService {
// 2.分组计数:Map<customerType字典值, 数量>
Map<Integer, Long> typeCountMap = records.stream()
.filter(info -> info.getVisitType() != null) // ✅ null 保护
.collect(Collectors.groupingBy(InfoDO::getVisitType, Collectors.counting()));
// 3. 加载字典并转换为 Map
......
......@@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.validation.ConstraintViolationException;
......@@ -77,6 +78,8 @@ public class ProductServiceImpl implements ProductService {
@Override
public PageResult<ProductDO> getProductPage(ProductPageReqVO pageReqVO) {
Long companyId = SecurityFrameworkUtils.getLoginUserDeptId();
pageReqVO.setCompanyId(companyId);
return productMapper.selectPage(pageReqVO);
}
......@@ -121,7 +124,8 @@ public class ProductServiceImpl implements ProductService {
String[] ids = productIds.split(",");
//3.判断数组长度
if (ids.length > 0) {
List<ProductDO> productDOS = productMapper.selectByIds(Arrays.asList(ids));
Long companyId = SecurityFrameworkUtils.getLoginUserDeptId();
List<ProductDO> productDOS = productMapper.selectByIds(Arrays.asList(ids), companyId);
return BeanUtils.toBean(productDOS, ProductSimpleReqVO.class);
}
return new ArrayList<>();
......@@ -133,6 +137,8 @@ public class ProductServiceImpl implements ProductService {
productPageReqVO.setProductName(productName);
productPageReqVO.setSpecification(specification);
productPageReqVO.setPackageName(packageName);
Long companyId = SecurityFrameworkUtils.getLoginUserDeptId();
productPageReqVO.setCompanyId(companyId);
PageResult<ProductDO> productDOPageResult = productMapper.selectPage(productPageReqVO);
if (productDOPageResult.getTotal() > 0) {
throw exception(PRODUCT_PRODUCT_EXISTS);
......
......@@ -9,6 +9,7 @@
<el-input
v-model="searchKey"
@blur="getEcharts"
@keyup.enter="getEcharts"
placeholder="请输入客户关键词"
clearable
class="filter-item"
......@@ -206,11 +207,12 @@ const homeInfoKhbffszbqk: Ref<any | null> = ref([])
const homeInfoKhbmzbqk: Ref<any | null> = ref([])
const homeInfoKhbflxzbqk: Ref<any | null> = ref([])
const homeInfoBfcplxzbqk: Ref<any | null> = ref([])
const homeInfoBfztjVal = ref('拜访统计')
const homeInfoBfztjVal = ref('拜访统计')
const homeInfoBfrtjVal = ref('拜访日统计')
// 获取图表数据
const getEcharts = async () => {
error.value = ''
if (loading.value) return; // ✅ 防止重复调用
loading.value = true
const params: any = {
......
<template>
<div class="visit-way-pie-chart">
<h3 class="chart-title">客户拜访方式占比情况</h3>
<h3 class="chart-title">{{props.tooltipTip}}</h3>
<chartsCard
:option="chartOption"
:width="width"
......@@ -84,7 +84,7 @@ const chartOption = computed(() => {
},
series: [
{
name: '客户拜访方式占比情况',
name: props.tooltipTip,
type: 'pie',
radius: ['40%', '70%'], // 环形图内外半径
center: ['35%', '50%'], // 图表中心位置,留出右侧图例空间
......
......@@ -101,6 +101,9 @@ import {defaultProps, handleTree} from '@/utils/tree'
import * as DeptApi from '@/api/system/dept'
import * as UserApi from '@/api/system/user'
import {FormRules} from 'element-plus'
import {getRefreshToken, getTenantId, setToken} from "@/utils/auth";
import axios from "axios";
import {config} from "@/config/axios/config";
defineOptions({ name: 'SystemUserForm' })
......@@ -169,7 +172,7 @@ const open = async (type: string, id?: number) => {
// postList.value = await PostApi.getSimplePostList()
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
const { base_url } = config
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
......@@ -186,6 +189,10 @@ const submitForm = async () => {
message.success(t('common.createSuccess'))
} else {
await UserApi.updateUser(data)
//更新成功后刷新一下token,因为需要更新用户新改变的deptId
const refreshTokenRes = await refreshToken()
// 2.1 刷新成功,则回放队列的请求 + 当前请求
setToken((await refreshTokenRes).data.data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
......@@ -195,6 +202,11 @@ const submitForm = async () => {
formLoading.value = false
}
}
//刷新token方法搬过来
const refreshToken = async () => {
axios.defaults.headers.common['tenant-id'] = getTenantId()
return await axios.post(base_url + '/system/auth/refresh-token?refreshToken=' + getRefreshToken())
}
/** 重置表单 */
const resetForm = () => {
......
......@@ -180,7 +180,7 @@ const formData = ref({
})
const formRules = reactive({
customerName: [{ required: true, message: '拜访人姓名不能为空', trigger: 'blur' }],
companyName: [{ required: true, message: '客户公司名称不能为空', trigger: 'blur' }],
companyName: [{ required: true, message: '客户公司名称不能为空', trigger: 'blur|change' }],
provinceName: [{ required: true, message: '省名称不能为空', trigger: 'blur' }],
cityName: [{ required: true, message: '市名称不能为空', trigger: 'blur' }],
areaName: [{ required: true, message: '区名称不能为空', trigger: 'blur' }],
......@@ -242,6 +242,7 @@ const loadAll = async () => {
latitude: item?.latitude || '',
locationImage: item?.locationImage || '',
customerStatus: item?.customerType??'',
department: item?.department || '',
}))
} catch (error) {
console.error('加载公司信息失败:', error)
......@@ -263,6 +264,7 @@ const handleSelect = (item: Record<string, any>) => {
formData.value.latitude = item.latitude;
formData.value.locationImage = item.locationImage;
formData.value.customerStatus = item.customerStatus;
formData.value.department = item.department;
restoreSelectedOptionsFromForm();
}
//===========================================选择产品相关操作=================================
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment