Commit 650d423b authored by 法拉51246's avatar 法拉51246

后端接口全部出完

parent 882f447d
......@@ -32,14 +32,15 @@ public class DefaultDBFieldHandler implements MetaObjectHandler {
baseDO.setUpdateTime(current);
}
Long userId = WebFrameworkUtils.getLoginUserId();
// Long userId = WebFrameworkUtils.getLoginUserId();
String userName = WebFrameworkUtils.getLoginUserName();
// 当前登录用户不为空,创建人为空,则当前登录用户为创建人
if (Objects.nonNull(userId) && Objects.isNull(baseDO.getCreator())) {
baseDO.setCreator(userId.toString());
if (Objects.nonNull(userName) && Objects.isNull(baseDO.getCreator())) {
baseDO.setCreator(userName);
}
// 当前登录用户不为空,更新人为空,则当前登录用户为更新人
if (Objects.nonNull(userId) && Objects.isNull(baseDO.getUpdater())) {
baseDO.setUpdater(userId.toString());
if (Objects.nonNull(userName) && Objects.isNull(baseDO.getUpdater())) {
baseDO.setUpdater(userName);
}
}
}
......
......@@ -15,6 +15,8 @@ import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.Objects;
import java.util.Optional;
/**
* 安全服务工具类
......@@ -127,6 +129,11 @@ public class SecurityFrameworkUtils {
// 额外设置到 request 中,用于 ApiAccessLogFilter 可以获取到用户编号;
// 原因是,Spring Security 的 Filter 在 ApiAccessLogFilter 后面,在它记录访问日志时,线上上下文已经没有用户编号等信息
WebFrameworkUtils.setLoginUserId(request, loginUser.getId());
String nickname = Optional.ofNullable(loginUser.getInfo())
.map(info -> info.get("nickname"))
.orElse("未知");
WebFrameworkUtils.setLoginUserName(request, nickname);
WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType());
}
......
......@@ -20,6 +20,7 @@ import javax.servlet.http.HttpServletRequest;
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_TYPE = "login_user_type";
private static final String REQUEST_ATTRIBUTE_COMMON_RESULT = "common_result";
......@@ -68,6 +69,16 @@ public class WebFrameworkUtils {
request.setAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_ID, userId);
}
/**
* 登录用户的用户名
*
* @param request 登录用户
* @param nickname 用户
*/
public static void setLoginUserName(ServletRequest request, String nickname) {
request.setAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_NAME, nickname);
}
/**
* 设置用户类型
*
......@@ -91,6 +102,12 @@ public class WebFrameworkUtils {
}
return (Long) request.getAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_ID);
}
public static String getLoginUserName(HttpServletRequest request) {
if (request == null) {
return null;
}
return request.getAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_NAME).toString();
}
/**
* 获得当前用户的类型
......@@ -127,6 +144,10 @@ public class WebFrameworkUtils {
HttpServletRequest request = getRequest();
return getLoginUserId(request);
}
public static String getLoginUserName() {
HttpServletRequest request = getRequest();
return getLoginUserName(request);
}
public static Integer getTerminal() {
HttpServletRequest request = getRequest();
......
......@@ -147,10 +147,10 @@ public class UserController {
public void importTemplate(HttpServletResponse response) throws IOException {
// 手动创建导出 demo
List<UserImportExcelVO> list = Arrays.asList(
UserImportExcelVO.builder().username("falao").deptId(1L).email("666666@qq.com").mobile("15601691300")
.nickname("模板用户1").status(CommonStatusEnum.ENABLE.getStatus()).sex(SexEnum.MALE.getSex()).build(),
UserImportExcelVO.builder().username("fala").deptId(2L).email("666666@qq.com").mobile("15601701300")
.nickname("模板用户2").status(CommonStatusEnum.DISABLE.getStatus()).sex(SexEnum.FEMALE.getSex()).build()
UserImportExcelVO.builder().username("zhangsan").deptId(1L).email("666666@qq.com").mobile("15601691300")
.nickname("张三").status(CommonStatusEnum.ENABLE.getStatus()).build(),
UserImportExcelVO.builder().username("lisi").deptId(2L).email("666666@qq.com").mobile("15601701300")
.nickname("李四").status(CommonStatusEnum.DISABLE.getStatus()).build()
);
// 输出
ExcelUtils.write(response, "用户导入模板.xls", "用户列表", UserImportExcelVO.class, list);
......
......@@ -23,7 +23,7 @@ public class UserImportExcelVO {
@ExcelProperty("登录名称")
private String username;
@ExcelProperty("用户名称")
@ExcelProperty("真实姓名")
private String nickname;
@ExcelProperty("部门编号")
......@@ -35,10 +35,6 @@ public class UserImportExcelVO {
@ExcelProperty("手机号码")
private String mobile;
@ExcelProperty(value = "用户性别", converter = DictConvert.class)
@DictFormat(DictTypeConstants.USER_SEX)
private Integer sex;
@ExcelProperty(value = "账号状态", converter = DictConvert.class)
@DictFormat(DictTypeConstants.COMMON_STATUS)
private Integer status;
......
......@@ -50,6 +50,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.system.enums.LogRecordConstants.*;
import static net.sf.jsqlparser.util.validation.metadata.NamedObject.user;
/**
* 后台用户 Service 实现类
......@@ -110,7 +111,10 @@ public class AdminUserServiceImpl implements AdminUserService {
userPostMapper.insertBatch(convertList(user.getPostIds(),
postId -> new UserPostDO().setUserId(user.getId()).setPostId(postId)));
}
// 2.3 默认都给一个id159业务员角色
Set<Long> roles = new HashSet<>();
roles.add(159L);
permissionService.assignUserRole(user.getId(), roles);
// 3. 记录操作日志上下文
LogRecordContext.putVariable("user", user);
return user.getId();
......@@ -482,8 +486,13 @@ public class AdminUserServiceImpl implements AdminUserService {
// 2.2.1 判断如果不存在,在进行插入
AdminUserDO existUser = userMapper.selectByUsername(importUser.getUsername());
if (existUser == null) {
userMapper.insert(BeanUtils.toBean(importUser, AdminUserDO.class)
.setPassword(encodePassword(initPassword)).setPostIds(new HashSet<>())); // 设置默认密码及空岗位编号数组
AdminUserDO adminUserDO = BeanUtils.toBean(importUser, AdminUserDO.class)
.setPassword(encodePassword(initPassword)).setPostIds(new HashSet<>());
userMapper.insert(adminUserDO); // 设置默认密码及空岗位编号数组
//插入成功后,给该用户一个默认的业务员角色
Set<Long> roles = new HashSet<>();
roles.add(159L);
permissionService.assignUserRole(adminUserDO.getId(), roles);
respVO.getCreateUsernames().add(importUser.getUsername());
return;
}
......
......@@ -51,6 +51,12 @@
<version>2.4.2-jdk8-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-system-biz</artifactId>
<version>2.4.2-jdk8-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
package cn.iocoder.yudao.module.visit.controller.admin.customerinfo;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
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;
import cn.iocoder.yudao.module.visit.service.product.ProductService;
import com.fhs.common.utils.StringUtil;
import io.swagger.v3.oas.annotations.Parameters;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
......@@ -31,6 +35,7 @@ import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
import cn.iocoder.yudao.module.visit.controller.admin.customerinfo.vo.*;
import cn.iocoder.yudao.module.visit.dal.dataobject.customerinfo.CustomerInfoDO;
import cn.iocoder.yudao.module.visit.service.customerinfo.CustomerInfoService;
import org.springframework.web.multipart.MultipartFile;
@Tag(name = "管理后台 - 客户信息")
@RestController
......@@ -130,5 +135,31 @@ public class CustomerInfoController {
}
@GetMapping("/get-import-template")
@Operation(summary = "获得导入客户信息模板")
public void importTemplate(HttpServletResponse response) throws IOException {
// 手动创建导出 demo
List<CustomerImportExcelVO> list = Collections.singletonList(
CustomerImportExcelVO.builder().customerName("张三").companyName("xxx有限公司").contact("13678944321")
.customerType(0).department("0").build()
);
// 输出
ExcelUtils.write(response, "客户信息导入模板.xls", "客户信息列表", CustomerImportExcelVO.class, list);
}
@PostMapping("/import")
@Operation(summary = "导入客户信息")
@Parameters({
@Parameter(name = "file", description = "Excel 文件", required = true),
@Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true")
})
@PreAuthorize("@ss.hasPermission('visit:customer-info:import')")
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);
return success(customerInfoService.importCustomerList(list, updateSupport));
}
}
\ No newline at end of file
package cn.iocoder.yudao.module.visit.controller.admin.customerinfo.vo;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.math.BigDecimal;
/**
* 用户 Excel 导入 VO
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = false) // 设置 chain = false,避免用户导入有问题
public class CustomerImportExcelVO {
@ExcelProperty("客户姓名")
private String customerName;
@ExcelProperty("联系方式")
@Pattern(regexp = "^$|^\\d{11}$", message = "联系方式必须是11位数字")
private String contact;
@ExcelProperty("公司名称")
private String companyName;
@ExcelProperty(value = "性质等级", converter = DictConvert.class)
@DictFormat("customer_type")
private Integer customerType;
@ExcelProperty(value = "客户部门", converter = DictConvert.class)
@DictFormat("customer_dept")
private String department;
}
package cn.iocoder.yudao.module.visit.controller.admin.customerinfo.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Schema(description = "管理后台 - 客户信息导入 Response VO")
@Data
@Builder
public class CustomerImportRespVO {
@Schema(description = "创建成功的公司名称数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<String> createCompanyNames;
@Schema(description = "更新成功的公司名称数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<String> updateCompanyNames;
@Schema(description = "导入失败的公司名称用户集合,key 为公司名称,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED)
private Map<String, String> failureCompanyNames;
}
package cn.iocoder.yudao.module.visit.controller.admin.home;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.visit.controller.admin.home.vo.*;
import cn.iocoder.yudao.module.visit.service.customerinfo.CustomerInfoService;
import cn.iocoder.yudao.module.visit.service.home.HomeService;
import cn.iocoder.yudao.module.visit.service.product.ProductService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 首页信息")
@RestController
@RequestMapping("/visit/home")
@Validated
public class HomeController {
@Resource
private CustomerInfoService customerInfoService;
@Resource
private ProductService productService;
@Resource
private HomeService homeService;
@GetMapping("/getHomeInfoFirst")
@Operation(summary = "获得首页第一排信息")
public CommonResult<HomeFirstRespVO> getHomeInfoFirst(@Valid HomeReqVO reqVO) {
HomeFirstRespVO data = homeService.getHomeInfoFirst(reqVO);
return success(data);
}
@GetMapping("/getHomeInfoBfztj")
@Operation(summary = "获得首页拜访周统计")
public CommonResult<HomeBfztjRespVO> getHomeInfoBfztj(@Valid HomeReqVO reqVO) {
HomeBfztjRespVO data = homeService.getHomeInfoBfztj(reqVO);
return success(data);
}
@GetMapping("/getHomeInfoKhxzdjzbqk")
@Operation(summary = "获得首页客户性质等级占比情况")
public CommonResult<HomeKhxzdjzbqkRespVO> getHomeInfoKhxzdjzbqk(@Valid HomeReqVO reqVO) {
HomeKhxzdjzbqkRespVO data = homeService.getHomeInfoKhxzdjzbqk(reqVO);
return success(data);
}
@GetMapping("/getHomeInfoBfrjfbqk")
@Operation(summary = "获得首页拜访人均分布情况")
public CommonResult<HomeBfrjfbqkRespVO> getHomeInfoBfrjfbqk(@Valid HomeReqVO reqVO) {
HomeBfrjfbqkRespVO data = homeService.getHomeInfoBfrjfbqk(reqVO);
return success(data);
}
@GetMapping("/getHomeInfoKhbffszbqk")
@Operation(summary = "获得首页客户拜访方式占比情况")
public CommonResult<HomeKhxzdjzbqkRespVO> getHomeInfoKhbffszbqk(@Valid HomeReqVO reqVO) {
HomeKhxzdjzbqkRespVO data = homeService.getHomeInfoKhbffszbqk(reqVO);
return success(data);
}
@GetMapping("/getHomeInfoKhbmzbqk")
@Operation(summary = "获得首页客户部门占比情况")
public CommonResult<HomeKhxzdjzbqkRespVO> getHomeInfoKhbmzbqk(@Valid HomeReqVO reqVO) {
HomeKhxzdjzbqkRespVO data = homeService.getHomeInfoKhbmzbqk(reqVO);
return success(data);
}
@GetMapping("/getHomeInfoKhbflxzbqk")
@Operation(summary = "获得首页客户拜访类型占比情况")
public CommonResult<HomeKhxzdjzbqkRespVO> getHomeInfoKhbflxzbqk(@Valid HomeReqVO reqVO) {
HomeKhxzdjzbqkRespVO data = homeService.getHomeInfoKhbflxzbqk(reqVO);
return success(data);
}
@GetMapping("/getHomeInfoBfcplxzbqk")
@Operation(summary = "获得首页拜访产品类型占比情况")
public CommonResult<HomeBfrjfbqkRespVO> getHomeInfoBfcplxzbqk(@Valid HomeReqVO reqVO) {
HomeBfrjfbqkRespVO data = homeService.getHomeInfoBfcplxzbqk(reqVO);
return success(data);
}
@GetMapping("/getHomeInfoBfrtj")
@Operation(summary = "获得首页拜访日统计")
public CommonResult<HomeBfrtjRespVO> getHomeInfoBfrtj(@Valid HomeReqVO reqVO) {
HomeBfrtjRespVO data = homeService.getHomeInfoBfrtj(reqVO);
return success(data);
}
}
\ No newline at end of file
package cn.iocoder.yudao.module.visit.controller.admin.home.vo;
import lombok.Data;
import java.util.List;
@Data
public class HomeBfrjfbqkRespVO {
private List<String> names; // xAxis,比如 ["张三", "李四", "王五"]
private List<Integer> values; // series,比如 [78, 65, 41]
}
package cn.iocoder.yudao.module.visit.controller.admin.home.vo;
import lombok.Data;
import java.util.List;
@Data
public class HomeBfrtjRespVO {
private List<String> dates; // xAxis,如 ["4月01日", "4月02日", ...]
private List<Integer> counts; // yAxis,对应每一天的拜访次数
}
package cn.iocoder.yudao.module.visit.controller.admin.home.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Data
@Schema(description = "首页拜访周统计数据响应 VO")
public class HomeBfztjRespVO {
@Schema(description = "周标签")
private List<String> weeks; // 如:["WEEK1", "WEEK2", ..., "WEEKN"]
@Schema(description = "拜访次数")
private List<Integer> visitCounts; // 每周对应次数,如:[10, 25, 12, 3]
@Schema(description = "总周数")
private Integer totalWeeks;
}
package cn.iocoder.yudao.module.visit.controller.admin.home.vo;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.visit.controller.admin.product.vo.ProductSimpleReqVO;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 首页第一行 Response VO")
@Data
public class HomeFirstRespVO {
@Schema(description = "拜访客户数量")
private String bfkhsl;
@Schema(description = "商业客户数量")
private String sykhsl;
@Schema(description = "医疗客户数量")
private String ylkhsl;
@Schema(description = "客户拜访总次数")
private String visitCount;
@Schema(description = "商业拜访次数")
private String sykfcs;
@Schema(description = "医疗拜访次数")
private String ylkfcs;
@Schema(description = "业务员数量")
private String ywysl;
}
\ No newline at end of file
package cn.iocoder.yudao.module.visit.controller.admin.home.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Data
public class HomeKhxzdjzbqkRespVO {
@Schema(description = "总拜访次数")
private Integer total;
@Schema(description = "按客户类型分类的统计数据")
private List<TypeCountItem> list;
@Data
public static class TypeCountItem {
@Schema(description = "客户类型标签(字典值)")
private String name;
@Schema(description = "拜访数量")
private Integer value;
}
}
package cn.iocoder.yudao.module.visit.controller.admin.home.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 首页数据 request VO")
@Data
@ToString(callSuper = true)
public class HomeReqVO {
@Schema(description = "公司名称")
private String companyName;
@Schema(description = "查询时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] searchTime;
}
\ No newline at end of file
......@@ -85,12 +85,12 @@ public class InfoRespVO {
private String visitProductNames;
@Schema(description = "拜访方式(字典)")
@ExcelProperty(value = "拜访方式(字典)", converter = DictConvert.class)
@ExcelProperty(value = "拜访方式", converter = DictConvert.class)
@DictFormat("visit_method") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
private Integer visitMethod;
@Schema(description = "拜访类型(字典)", example = "2")
@ExcelProperty(value = "拜访类型(字典)", converter = DictConvert.class)
@ExcelProperty(value = "拜访类型", converter = DictConvert.class)
@DictFormat("visit_type") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
private Integer visitType;
......@@ -109,6 +109,10 @@ public class InfoRespVO {
@Schema(description = "服务记录图片URL列表(JSON数组)")
private String serviceImages;
@Schema(description = "业务经理")
@ExcelProperty("业务经理")
private String creator;
}
\ No newline at end of file
......@@ -128,7 +128,7 @@ public class ProductController {
@Parameter(name = "file", description = "Excel 文件", required = true),
@Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true")
})
@PreAuthorize("@ss.hasPermission('system:product:import')")
@PreAuthorize("@ss.hasPermission('visit:product:import')")
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);
......
......@@ -27,6 +27,16 @@ public interface CustomerInfoMapper extends BaseMapperX<CustomerInfoDO> {
.betweenIfPresent(CustomerInfoDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(CustomerInfoDO::getId));
}
default PageResult<CustomerInfoDO> selectHomePage(CustomerInfoPageReqVO reqVO) {
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())
.betweenIfPresent(CustomerInfoDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(CustomerInfoDO::getId));
}
//根据公司名称查询客户信息(验证是否唯一使用)
default CustomerInfoDO selectByCompanyName(String companyName){
......
......@@ -30,6 +30,19 @@ public interface InfoMapper extends BaseMapperX<InfoDO> {
.betweenIfPresent(InfoDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(InfoDO::getId));
}
default PageResult<InfoDO> selectHomePage(InfoPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<InfoDO>()
.eqIfPresent(InfoDO::getCustomerName, reqVO.getCustomerName())
.eqIfPresent(InfoDO::getContact, reqVO.getContact())
.eqIfPresent(InfoDO::getCompanyName, reqVO.getCompanyName())
.betweenIfPresent(InfoDO::getVisitDate, reqVO.getVisitDate())
.eqIfPresent(InfoDO::getCustomerStatus, reqVO.getCustomerStatus())
.eqIfPresent(InfoDO::getVisitProductIds, reqVO.getVisitProductIds())
.eqIfPresent(InfoDO::getVisitMethod, reqVO.getVisitMethod())
.eqIfPresent(InfoDO::getVisitType, reqVO.getVisitType())
.betweenIfPresent(InfoDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(InfoDO::getId));
}
default List<InfoDO> selectByCompanyName(String companyName) {
return selectList(new LambdaQueryWrapperX<InfoDO>()
......
......@@ -11,12 +11,14 @@ public interface ErrorCodeConstants {
// ========== 产品 ==========
ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1001000001, "产品不存在");
ErrorCode PRODUCT_IMPORT_LIST_IS_EMPTY = new ErrorCode(1001000002, "导入产品数据不能为空!");
ErrorCode PRODUCT_PRODUCT_EXISTS = new ErrorCode(1001000002, "导入产品已存在!");
ErrorCode PRODUCT_IMPORT_LIST_IS_EMPTY = new ErrorCode(1001000003, "导入产品数据不能为空!");
// ========== 客户信息 ==========
ErrorCode CUSTOMER_INFO_NOT_EXISTS = new ErrorCode(1002000001, "客户信息不存在");
ErrorCode CUSTOMER_INFO_COMPANY_NAME_DUPLICATE = new ErrorCode(1002000002, "该公司名称已存在");
ErrorCode CUSTOMER_INFO_IMPORT_LIST_IS_EMPTY = new ErrorCode(1002000003, "导入客户数据不能为空!");
ErrorCode CUSTOMER_INFO_EXISTS = new ErrorCode(1002000004, "导入客户数据已存在!");
// ========== 客户拜访记录 ==========
......
......@@ -57,4 +57,6 @@ public interface CustomerInfoService {
List<CustomerInfoDO> getAllCustomerInfo();
CustomerImportRespVO importCustomerList(List<CustomerImportExcelVO> list, Boolean updateSupport);
}
\ No newline at end of file
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.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;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
......@@ -131,4 +135,42 @@ public class CustomerInfoServiceImpl implements CustomerInfoService {
return customerInfoMapper.selectList();
}
@Override
public CustomerImportRespVO importCustomerList(List<CustomerImportExcelVO> list, Boolean updateSupport) {
// 1 参数校验
if (CollUtil.isEmpty(list)) {
throw exception(CUSTOMER_INFO_IMPORT_LIST_IS_EMPTY);
}
// 2. 遍历,逐个创建 or 更新
CustomerImportRespVO respVO = CustomerImportRespVO.builder().createCompanyNames(new ArrayList<>())
.updateCompanyNames(new ArrayList<>()).failureCompanyNames(new LinkedHashMap<>()).build();
list.forEach(importCompany -> {
// 2.1.1 校验,判断是否有不符合的原因
try {
validateCompanyUnique(importCompany.getCompanyName());
} catch (ServiceException ex) {
respVO.getFailureCompanyNames().put(importCompany.getCompanyName(), ex.getMessage());
return;
}
// 2.2.1 判断如果不存在,在进行插入
CustomerInfoDO existCompany = customerInfoMapper.selectByCompanyName(importCompany.getCompanyName());
if (existCompany == null) {
customerInfoMapper.insert(BeanUtils.toBean(importCompany, CustomerInfoDO.class));
respVO.getCreateCompanyNames().add(importCompany.getCompanyName());
}
});
return respVO;
}
private void validateCompanyUnique(String companyName) {
CustomerInfoPageReqVO customerPageReqVO = new CustomerInfoPageReqVO();
customerPageReqVO.setCompanyName(companyName);
PageResult<CustomerInfoDO> customerInfoDOPageResult = customerInfoMapper.selectPage(customerPageReqVO);
if (customerInfoDOPageResult.getTotal() > 0) {
throw exception(CUSTOMER_INFO_EXISTS);
}
}
}
\ No newline at end of file
package cn.iocoder.yudao.module.visit.service.home;
import cn.iocoder.yudao.module.visit.controller.admin.home.vo.*;
import javax.validation.Valid;
/**
* 主页 Service 接口
*
* @author 超级管理员
*/
public interface HomeService {
HomeFirstRespVO getHomeInfoFirst(HomeReqVO reqVO);
HomeBfztjRespVO getHomeInfoBfztj(HomeReqVO reqVO);
HomeKhxzdjzbqkRespVO getHomeInfoKhxzdjzbqk(@Valid HomeReqVO reqVO);
HomeBfrjfbqkRespVO getHomeInfoBfrjfbqk(@Valid HomeReqVO reqVO);
HomeKhxzdjzbqkRespVO getHomeInfoKhbffszbqk(@Valid HomeReqVO reqVO);
HomeKhxzdjzbqkRespVO getHomeInfoKhbmzbqk(@Valid HomeReqVO reqVO);
HomeKhxzdjzbqkRespVO getHomeInfoKhbflxzbqk(@Valid HomeReqVO reqVO);
HomeBfrjfbqkRespVO getHomeInfoBfcplxzbqk(@Valid HomeReqVO reqVO);
HomeBfrtjRespVO getHomeInfoBfrtj(@Valid HomeReqVO reqVO);
}
\ No newline at end of file
package cn.iocoder.yudao.module.visit.service.home;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.visit.controller.admin.customerinfo.vo.CustomerInfoPageReqVO;
import cn.iocoder.yudao.module.visit.controller.admin.home.vo.*;
import cn.iocoder.yudao.module.visit.controller.admin.info.vo.InfoPageReqVO;
import cn.iocoder.yudao.module.visit.dal.dataobject.customerinfo.CustomerInfoDO;
import cn.iocoder.yudao.module.visit.dal.dataobject.info.InfoDO;
import cn.iocoder.yudao.module.visit.dal.dataobject.product.ProductDO;
import cn.iocoder.yudao.module.visit.dal.mysql.customerinfo.CustomerInfoMapper;
import cn.iocoder.yudao.module.visit.dal.mysql.info.InfoMapper;
import cn.iocoder.yudao.module.visit.dal.mysql.product.ProductMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 主页 Service 实现类
*
* @author 超级管理员
*/
@Service
@Validated
public class HomeServiceImpl implements HomeService {
@Resource
private CustomerInfoMapper customerInfoMapper;
@Resource
private InfoMapper infoMapper;
@Resource
private ProductMapper productMapper;
@Resource
private AdminUserMapper userMapper;
@Resource
private DictDataApi dictDataApi;
//首页第一排数据
@Override
public HomeFirstRespVO getHomeInfoFirst(HomeReqVO reqVO) {
HomeFirstRespVO homeFirstRespVO = new HomeFirstRespVO();
//业务员数量(不按时间)
List<AdminUserDO> userDOS = userMapper.selectList();
homeFirstRespVO.setYwysl(String.valueOf(userDOS.size()));
//按创建时间查这段时间的客户数量
CustomerInfoPageReqVO customerInfoPageReqVO = new CustomerInfoPageReqVO();
customerInfoPageReqVO.setCreateTime(reqVO.getSearchTime());
customerInfoPageReqVO.setPageSize(-1);//不分页
customerInfoPageReqVO.setCompanyName(reqVO.getCompanyName());
PageResult<CustomerInfoDO> customerInfoDOPageResult = customerInfoMapper.selectHomePage(customerInfoPageReqVO);//精准查询
//拜访客户总数量
homeFirstRespVO.setBfkhsl(String.valueOf(customerInfoDOPageResult.getTotal()));
//商业客户数量
String sykhsl = customerInfoDOPageResult.getList().stream().filter(customerInfoDO -> customerInfoDO.getCustomerType() == 0).count() + "";
//医疗客户数量
String ylkhsl = customerInfoDOPageResult.getList().stream().filter(customerInfoDO -> customerInfoDO.getCustomerType() == 1).count() + "";
homeFirstRespVO.setSykhsl(sykhsl);
homeFirstRespVO.setYlkhsl(ylkhsl);
//按拜访时间查这段时间的拜访次数
InfoPageReqVO infoPageReqVO = new InfoPageReqVO();
infoPageReqVO.setVisitDate(reqVO.getSearchTime());
infoPageReqVO.setPageSize(-1);//不分页
infoPageReqVO.setCompanyName(reqVO.getCompanyName());
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()));
return homeFirstRespVO;
}
//拜访周统计
@Override
public HomeBfztjRespVO getHomeInfoBfztj(HomeReqVO reqVO) {
LocalDateTime start = reqVO.getSearchTime()[0];
LocalDateTime end = reqVO.getSearchTime()[1];
// 对齐到每周一
start = start.with(DayOfWeek.MONDAY);
List<String> weeks = new ArrayList<>();
List<Integer> counts = new ArrayList<>();
for (int i = 0; i < 10; i++) {
LocalDateTime weekStart = start.plusWeeks(i);
LocalDateTime weekEnd = weekStart.plusDays(6).with(LocalTime.MAX);
LocalDateTime[] week = new LocalDateTime[]{weekStart, weekEnd};
if (weekStart.isAfter(end)) break;
int count = 0;//拜访次数
InfoPageReqVO infoPageReqVO = new InfoPageReqVO();
infoPageReqVO.setVisitDate(week);
infoPageReqVO.setPageSize(-1);//不分页
infoPageReqVO.setCompanyName(reqVO.getCompanyName());
PageResult<InfoDO> infoDOPageResult = infoMapper.selectHomePage(infoPageReqVO);//精准查询
weeks.add("WEEK" + (i + 1));
counts.add(count);
}
HomeBfztjRespVO vo = new HomeBfztjRespVO();
vo.setWeeks(weeks);
vo.setVisitCounts(counts);
vo.setTotalWeeks(weeks.size());
return vo;
}
//客户性质等级占比情况
@Override
public HomeKhxzdjzbqkRespVO getHomeInfoKhxzdjzbqk(HomeReqVO reqVO) {
//1.先查出所有的客户信息
InfoPageReqVO infoPageReqVO = new InfoPageReqVO();
infoPageReqVO.setPageSize(-1);
infoPageReqVO.setVisitDate(reqVO.getSearchTime());
infoPageReqVO.setCompanyName(reqVO.getCompanyName());
PageResult<InfoDO> infoDOPageResult = infoMapper.selectHomePage(infoPageReqVO);
List<InfoDO> records = infoDOPageResult.getList();
// 2.分组计数:Map<customerType字典值, 数量>
Map<Integer, Long> typeCountMap = records.stream()
.collect(Collectors.groupingBy(InfoDO::getCustomerStatus, Collectors.counting()));
// 3. 加载字典并转换为 Map
List<DictDataRespDTO> dictList = dictDataApi.getDictDataList("customer_type");
Map<String, String> dictMap = dictList.stream()
.collect(Collectors.toMap(DictDataRespDTO::getValue, DictDataRespDTO::getLabel));
// 4. 组装返回列表
List<HomeKhxzdjzbqkRespVO.TypeCountItem> list = typeCountMap.entrySet().stream()
.map(entry -> {
HomeKhxzdjzbqkRespVO.TypeCountItem item = new HomeKhxzdjzbqkRespVO.TypeCountItem();
item.setName(dictMap.getOrDefault(entry.getKey().toString(), "未知"));
item.setValue(entry.getValue().intValue());
return item;
})
.collect(Collectors.toList());
// 5. 返回结果
HomeKhxzdjzbqkRespVO respVO = new HomeKhxzdjzbqkRespVO();
respVO.setList(list);
respVO.setTotal(records.size());
return respVO;
}
//拜访人均分布情况
@Override
public HomeBfrjfbqkRespVO getHomeInfoBfrjfbqk(HomeReqVO reqVO) {
//1.先查出所有的拜访记录
InfoPageReqVO infoPageReqVO = new InfoPageReqVO();
infoPageReqVO.setPageSize(-1);
infoPageReqVO.setVisitDate(reqVO.getSearchTime());
infoPageReqVO.setCompanyName(reqVO.getCompanyName());
PageResult<InfoDO> infoDOPageResult = infoMapper.selectHomePage(infoPageReqVO);
List<InfoDO> records = infoDOPageResult.getList();
// 按业务员分组计数
Map<String, Long> countMap = records.stream()
.filter(r -> StringUtils.isNotBlank(r.getCreator()))
.collect(Collectors.groupingBy(InfoDO::getCreator, Collectors.counting()));
// 倒序排序,取前10
List<Map.Entry<String, Long>> top10 = countMap.entrySet().stream()
.sorted(Map.Entry.<String, Long>comparingByValue().reversed())
.limit(10)
.collect(Collectors.toList());
// 拆分为两个数组
List<String> names = top10.stream().map(Map.Entry::getKey).collect(Collectors.toList());
List<Integer> values = top10.stream().map(e -> e.getValue().intValue()).collect(Collectors.toList());
HomeBfrjfbqkRespVO respVO = new HomeBfrjfbqkRespVO();
respVO.setNames(names);
respVO.setValues(values);
return respVO;
}
// 客户拜访方式分布情况
@Override
public HomeKhxzdjzbqkRespVO getHomeInfoKhbffszbqk(HomeReqVO reqVO) {
//1.先查出所有的客户信息
InfoPageReqVO infoPageReqVO = new InfoPageReqVO();
infoPageReqVO.setPageSize(-1);
infoPageReqVO.setVisitDate(reqVO.getSearchTime());
infoPageReqVO.setCompanyName(reqVO.getCompanyName());
PageResult<InfoDO> infoDOPageResult = infoMapper.selectHomePage(infoPageReqVO);
List<InfoDO> records = infoDOPageResult.getList();
// 2.分组计数:Map<customerType字典值, 数量>
Map<Integer, Long> typeCountMap = records.stream()
.collect(Collectors.groupingBy(InfoDO::getVisitMethod, Collectors.counting()));
// 3. 加载字典并转换为 Map
List<DictDataRespDTO> dictList = dictDataApi.getDictDataList("visit_method");
Map<String, String> dictMap = dictList.stream()
.collect(Collectors.toMap(DictDataRespDTO::getValue, DictDataRespDTO::getLabel));
// 4. 组装返回列表
List<HomeKhxzdjzbqkRespVO.TypeCountItem> list = typeCountMap.entrySet().stream()
.map(entry -> {
HomeKhxzdjzbqkRespVO.TypeCountItem item = new HomeKhxzdjzbqkRespVO.TypeCountItem();
item.setName(dictMap.getOrDefault(entry.getKey().toString(), "未知"));
item.setValue(entry.getValue().intValue());
return item;
})
.collect(Collectors.toList());
// 5. 返回结果
HomeKhxzdjzbqkRespVO respVO = new HomeKhxzdjzbqkRespVO();
respVO.setList(list);
respVO.setTotal(records.size());
return respVO;
}
// 客户部门分布情况
@Override
public HomeKhxzdjzbqkRespVO getHomeInfoKhbmzbqk(HomeReqVO reqVO) {
//1.先查出所有的客户信息
InfoPageReqVO infoPageReqVO = new InfoPageReqVO();
infoPageReqVO.setPageSize(-1);
infoPageReqVO.setVisitDate(reqVO.getSearchTime());
infoPageReqVO.setCompanyName(reqVO.getCompanyName());
PageResult<InfoDO> infoDOPageResult = infoMapper.selectHomePage(infoPageReqVO);
List<InfoDO> records = infoDOPageResult.getList();
// 2.分组计数:Map<customerType字典值, 数量>
Map<String, Long> typeCountMap = records.stream()
.collect(Collectors.groupingBy(InfoDO::getDepartment, Collectors.counting()));
// 3. 加载字典并转换为 Map
List<DictDataRespDTO> dictList = dictDataApi.getDictDataList("customer_dept");
Map<String, String> dictMap = dictList.stream()
.collect(Collectors.toMap(DictDataRespDTO::getValue, DictDataRespDTO::getLabel));
// 4. 组装返回列表
List<HomeKhxzdjzbqkRespVO.TypeCountItem> list = typeCountMap.entrySet().stream()
.map(entry -> {
HomeKhxzdjzbqkRespVO.TypeCountItem item = new HomeKhxzdjzbqkRespVO.TypeCountItem();
item.setName(dictMap.getOrDefault(entry.getKey().toString(), "未知"));
item.setValue(entry.getValue().intValue());
return item;
})
.collect(Collectors.toList());
// 5. 返回结果
HomeKhxzdjzbqkRespVO respVO = new HomeKhxzdjzbqkRespVO();
respVO.setList(list);
respVO.setTotal(records.size());
return respVO;
}
// 客户拜访类型分布情况
@Override
public HomeKhxzdjzbqkRespVO getHomeInfoKhbflxzbqk(HomeReqVO reqVO) {
//1.先查出所有的客户信息
InfoPageReqVO infoPageReqVO = new InfoPageReqVO();
infoPageReqVO.setPageSize(-1);
infoPageReqVO.setVisitDate(reqVO.getSearchTime());
infoPageReqVO.setCompanyName(reqVO.getCompanyName());
PageResult<InfoDO> infoDOPageResult = infoMapper.selectHomePage(infoPageReqVO);
List<InfoDO> records = infoDOPageResult.getList();
// 2.分组计数:Map<customerType字典值, 数量>
Map<Integer, Long> typeCountMap = records.stream()
.collect(Collectors.groupingBy(InfoDO::getVisitType, Collectors.counting()));
// 3. 加载字典并转换为 Map
List<DictDataRespDTO> dictList = dictDataApi.getDictDataList("visit_type");
Map<String, String> dictMap = dictList.stream()
.collect(Collectors.toMap(DictDataRespDTO::getValue, DictDataRespDTO::getLabel));
// 4. 组装返回列表
List<HomeKhxzdjzbqkRespVO.TypeCountItem> list = typeCountMap.entrySet().stream()
.map(entry -> {
HomeKhxzdjzbqkRespVO.TypeCountItem item = new HomeKhxzdjzbqkRespVO.TypeCountItem();
item.setName(dictMap.getOrDefault(entry.getKey().toString(), "未知"));
item.setValue(entry.getValue().intValue());
return item;
})
.collect(Collectors.toList());
// 5. 返回结果
HomeKhxzdjzbqkRespVO respVO = new HomeKhxzdjzbqkRespVO();
respVO.setList(list);
respVO.setTotal(records.size());
return respVO;
}
@Override
public HomeBfrjfbqkRespVO getHomeInfoBfcplxzbqk(HomeReqVO reqVO) {
//1.先查出所有的客户信息
InfoPageReqVO infoPageReqVO = new InfoPageReqVO();
infoPageReqVO.setPageSize(-1);
infoPageReqVO.setVisitDate(reqVO.getSearchTime());
infoPageReqVO.setCompanyName(reqVO.getCompanyName());
PageResult<InfoDO> infoDOPageResult = infoMapper.selectHomePage(infoPageReqVO);
List<InfoDO> records = infoDOPageResult.getList();
// 2. 收集所有产品 ID
Set<Long> productIdSet = records.stream()
.flatMap(r -> {
String ids = r.getVisitProductIds();
if (StringUtils.isBlank(ids)) return Stream.empty();
return Arrays.stream(ids.split(","))
.map(String::trim)
.filter(StringUtils::isNotBlank)
.map(Long::valueOf);
})
.collect(Collectors.toSet());
// 3. 查询产品信息(id => 名称-规格)
List<ProductDO> productList = productMapper.selectBatchIds(productIdSet);
Map<Long, String> productMap = productList.stream()
.collect(Collectors.toMap(
ProductDO::getId,
p -> p.getProductName() + "-" + p.getSpecification()
));
// 4. 遍历所有拜访记录统计产品使用次数
Map<String, Integer> statMap = new HashMap<>();
for (InfoDO record : records) {
if (StringUtils.isBlank(record.getVisitProductIds())) continue;
for (String pidStr : record.getVisitProductIds().split(",")) {
Long pid = NumberUtils.toLong(pidStr.trim(), -1);
if (!productMap.containsKey(pid)) continue;
String key = productMap.get(pid);
statMap.merge(key, 1, Integer::sum);
}
}
// 5. 排序取前 N(如 top10)
List<Map.Entry<String, Integer>> topList = statMap.entrySet().stream()
.sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
.limit(10)
.collect(Collectors.toList());
List<String> names = topList.stream().map(Map.Entry::getKey).collect(Collectors.toList());
List<Integer> values = topList.stream().map(Map.Entry::getValue).collect(Collectors.toList());
// 6. 构建返回结果
HomeBfrjfbqkRespVO vo = new HomeBfrjfbqkRespVO();
vo.setNames(names);
vo.setValues(values);
return vo;
}
@Override
public HomeBfrtjRespVO getHomeInfoBfrtj(HomeReqVO reqVO) {
//1.先查出所有的客户信息
InfoPageReqVO infoPageReqVO = new InfoPageReqVO();
infoPageReqVO.setPageSize(-1);
infoPageReqVO.setVisitDate(reqVO.getSearchTime());
infoPageReqVO.setCompanyName(reqVO.getCompanyName());
PageResult<InfoDO> infoDOPageResult = infoMapper.selectHomePage(infoPageReqVO);
List<InfoDO> records = infoDOPageResult.getList();
// 2. 按日期(yyyy-MM-dd)分组计数
Map<LocalDate, Long> dateCountMap = records.stream()
.collect(Collectors.groupingBy(
r -> r.getVisitDate().toLocalDate(),
Collectors.counting()
));
// 3. 排序(从晚到早)+ 限制最多31天
List<Map.Entry<LocalDate, Long>> sorted = dateCountMap.entrySet().stream()
.sorted(Map.Entry.<LocalDate, Long>comparingByKey().reversed())
.limit(31)
.sorted(Map.Entry.comparingByKey()) // 前端从左到右看,从早到晚排列
.collect(Collectors.toList());
// 4. 构造 VO
List<String> dates = sorted.stream()
.map(e -> formatDate(e.getKey())) // 4月01日
.collect(Collectors.toList());
List<Integer> counts = sorted.stream()
.map(e -> e.getValue().intValue())
.collect(Collectors.toList());
HomeBfrtjRespVO vo = new HomeBfrtjRespVO();
vo.setDates(dates);
vo.setCounts(counts);
return vo;
}
// 工具方法:格式化为 4月01日
private String formatDate(LocalDate date) {
return date.getMonthValue() + "月" + String.format("%02d", date.getDayOfMonth()) + "日";
}
}
\ No newline at end of file
......@@ -69,4 +69,10 @@ export const CustomerInfoApi = {
exportCustomerInfo: async (params) => {
return await request.download({ url: `/visit/customer-info/export-excel`, params })
},
// 下载客户信息导入模板
importProductTemplate: async () => {
return await request.download({ url: '/visit/customer-info/get-import-template' })
}
}
......@@ -66,6 +66,7 @@
</template>
</el-table-column>
<el-table-column prop="sort" label="排序" />
<el-table-column prop="id" label="部门编号" />
<el-table-column prop="status" label="状态">
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
......
<template>
<Dialog v-model="dialogVisible" title="客户信息导入" width="400">
<el-upload
ref="uploadRef"
v-model:file-list="fileList"
:action="importUrl + '?updateSupport=' + updateSupport"
:auto-upload="false"
:disabled="formLoading"
:headers="uploadHeaders"
:limit="1"
:on-error="submitFormError"
:on-exceed="handleExceed"
:on-success="submitFormSuccess"
accept=".xlsx, .xls"
drag
>
<Icon icon="ep:upload" />
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<template #tip>
<div class="el-upload__tip text-center">
<span>仅允许导入 xls、xlsx 格式文件。</span>
<el-link
:underline="false"
style="font-size: 12px; vertical-align: baseline"
type="primary"
@click="importTemplate"
>
下载模板
</el-link>
</div>
</template>
</el-upload>
<template #footer>
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</template>
</Dialog>
</template>
<script lang="ts" setup>
import {getAccessToken, getTenantId} from '@/utils/auth'
import download from '@/utils/download'
import {CustomerInfoApi} from "@/api/visit/customerinfo";
defineOptions({ name: 'CustomerImportForm' })
const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) // 弹窗的是否展示
const formLoading = ref(false) // 表单的加载中
const uploadRef = ref()
const importUrl =
import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/visit/customer-info/import'
const uploadHeaders = ref() // 上传 Header 头
const fileList = ref([]) // 文件列表
const updateSupport = ref(0) // 是否更新已经存在的用户数据
/** 打开弹窗 */
const open = () => {
dialogVisible.value = true
updateSupport.value = 0
fileList.value = []
resetForm()
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */
const submitForm = async () => {
if (fileList.value.length == 0) {
message.error('请上传文件')
return
}
// 提交请求
uploadHeaders.value = {
Authorization: 'Bearer ' + getAccessToken(),
'tenant-id': getTenantId()
}
formLoading.value = true
uploadRef.value!.submit()
}
/** 文件上传成功 */
const emits = defineEmits(['success'])
const submitFormSuccess = (response: any) => {
if (response.code !== 0) {
message.error(response.msg)
formLoading.value = false
return
}
// 拼接提示语
const data = response.data
let text = '上传成功数量:' + data.createCompanyNames.length + ';'
for (let companyName of data.createCompanyNames) {
text += '< ' + companyName + ' >'
}
// text += '更新成功数量:' + data.updateProductNames.length + ';'
// for (const productName of data.updateProductNames) {
// text += '< ' + productName + ' >'
// }
text += '上传失败数量:' + Object.keys(data.failureCompanyNames).length + ';'
for (const companyName in data.failureCompanyNames) {
text += '< ' + companyName + ': ' + data.failureCompanyNames[companyName] + ' >'
}
message.alert(text)
formLoading.value = false
dialogVisible.value = false
// 发送操作成功的事件
emits('success')
}
/** 上传错误提示 */
const submitFormError = (): void => {
message.error('上传失败,请您重新上传!')
formLoading.value = false
}
/** 重置表单 */
const resetForm = async (): Promise<void> => {
// 重置上传状态和文件
formLoading.value = false
await nextTick()
uploadRef.value?.clearFiles()
}
/** 文件数超出提示 */
const handleExceed = (): void => {
message.error('最多只能上传一个文件!')
}
/** 下载模板操作 */
const importTemplate = async () => {
const res = await CustomerInfoApi.importProductTemplate()
download.excel(res, '客户信息导入模版.xls')
}
</script>
......@@ -72,6 +72,14 @@
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="warning"
plain
@click="handleImport"
v-hasPermi="['visit:customer-info:import']"
>
<Icon icon="ep:upload" /> 导入
</el-button>
<el-button
type="success"
plain
......@@ -159,17 +167,20 @@
<CustomerInfoForm ref="formRef" @success="getList" />
<!-- 打印弹窗 -->
<VisitPrint ref="visitPrintRef" :data="selectedData" />
<!-- 客户信息导入对话框 -->
<CustomerImportForm ref="importFormRef" @success="getList" />
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import {DICT_TYPE, getIntDictOptions} from '@/utils/dict'
import {dateFormatter} from '@/utils/formatTime'
import download from '@/utils/download'
import { CustomerInfoApi, CustomerInfoVO } from '@/api/visit/customerinfo'
import {CustomerInfoApi, CustomerInfoVO} from '@/api/visit/customerinfo'
import CustomerInfoForm from './CustomerInfoForm.vue'
import ProductList from "@/views/visit/util/ProductList.vue";
import { useRouter } from 'vue-router'
import {useRouter} from 'vue-router'
import {InfoApi, InfoPrintVO} from "@/api/visit/info";
import CustomerImportForm from "@/views/visit/customerinfo/CustomerImportForm.vue";
/** 客户信息 列表 */
......@@ -195,6 +206,14 @@ const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中
const multipleSelection = ref([]) //存储多选内容
/** 产品导入 */
const importFormRef = ref()
const handleImport = () => {
importFormRef.value.open()
}
const visitPrintRef = ref()
// 模拟获取详情数据的方法(你应该调 InfoApi.getInfoListByIds 或类似接口)
......
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