保安 公安 注册

This commit is contained in:
luozhun 2024-08-30 17:03:25 +08:00
parent 5b28b5a10d
commit 5a563b8625
67 changed files with 2767 additions and 80 deletions

View File

@ -1,5 +1,6 @@
package com.changhu.common.db.enums; package com.changhu.common.db.enums;
import com.baomidou.mybatisplus.annotation.IEnum;
import com.changhu.common.db.BaseEnum; import com.changhu.common.db.BaseEnum;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
@ -11,7 +12,7 @@ import lombok.Getter;
*/ */
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public enum CheckStatus implements BaseEnum<Integer> { public enum CheckStatus implements BaseEnum<Integer>, IEnum<Integer> {
checked(0, "已审核"), checked(0, "已审核"),
unChecked(1, "未审核"), unChecked(1, "未审核"),

View File

@ -0,0 +1,131 @@
package com.changhu.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import com.changhu.common.annotation.IsExtData;
import com.changhu.common.annotation.JsonBody;
import com.changhu.common.db.BaseEnum;
import com.changhu.common.pojo.model.JsonResult;
import com.changhu.common.pojo.vo.SelectNodeVo;
import com.changhu.common.pojo.vo.TreeNodeVo;
import com.changhu.pojo.params.PoliceUnitRegisterParams;
import com.changhu.pojo.params.SecurityUnitRegisterParams;
import com.changhu.service.AdministrativeDivisionService;
import com.changhu.service.CommonService;
import com.changhu.support.minio.service.MinioService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author 20252
* @createTime 2024/8/30 下午2:16
* @desc CommonController...
*/
@Tag(name = "公共接口")
@RequestMapping("/common")
@JsonBody
public class CommonController {
@Autowired
private CommonService commonService;
@Autowired
private MinioService minioService;
@Autowired
private AdministrativeDivisionService administrativeDivisionService;
private static final Map<String, List<SelectNodeVo<?>>> enumsResult = new HashMap<>();
@Operation(summary = "行政区划树")
@GetMapping("/administrativeDivisionTree")
public List<TreeNodeVo<String>> AdministrativeDivisionTree(@Schema(description = "等级") @RequestParam(defaultValue = "4") Integer level) {
return administrativeDivisionService.tree(level);
}
@Operation(summary = "保安单位注册")
@PostMapping("/securityUnitRegister")
public JsonResult<Void> securityUnitRegister(@RequestBody @Valid SecurityUnitRegisterParams params) {
return commonService.securityUnitRegister(params);
}
@Operation(summary = "公安单位注册")
@PostMapping("/policeUnitRegister")
public JsonResult<Void> policeUnitRegister(@RequestBody @Valid PoliceUnitRegisterParams params) {
return commonService.policeUnitRegister(params);
}
@Operation(summary = "获取临时上传地址")
@GetMapping("/getResignedObjectUrl")
public String getResignedObjectUrl(@RequestParam @Schema(description = "bucketName") String bucketName,
@RequestParam @Schema(description = "对象地址") String objectName) {
return minioService.getResignedObjectUrl(bucketName, objectName);
}
@GetMapping("/enums")
public Map<String, List<SelectNodeVo<?>>> enums() {
return enumsResult;
}
@SuppressWarnings("unchecked")
@PostConstruct
public void initEnums() {
Set<Class<?>> classes = ClassUtil.scanPackageBySuper("com.changhu.common.db.enums", BaseEnum.class);
for (Class<?> aClass : classes) {
if (BaseEnum.class.isAssignableFrom(aClass)) {
enumsResult.put(aClass.getSimpleName(), listSelectNodes((Class<? extends BaseEnum<?>>) aClass));
}
}
}
public static <T extends BaseEnum<?>> List<SelectNodeVo<?>> listSelectNodes(Class<T> enumType) {
if (enumType == null) {
return null;
}
Field[] fields = ReflectUtil.getFields(enumType);
List<String> extras = new ArrayList<>();
for (Field field : fields) {
IsExtData annotation = field.getAnnotation(IsExtData.class);
if (ObjectUtil.isNotNull(annotation)) {
extras.add(field.getName());
}
}
T[] enumConstants = enumType.getEnumConstants();
if (enumConstants == null) {
return null;
}
return Stream.of(enumConstants).map(v -> {
SelectNodeVo<Object> vo = new SelectNodeVo<>();
vo.setValue(v.getValue());
vo.setLabel(v.getLabel());
if (CollUtil.isNotEmpty(extras)) {
Dict map = Dict.create();
for (String extra : extras) {
map.put(extra, ReflectUtil.getFieldValue(v, extra));
}
vo.setExtData(map);
}
return vo;
}).collect(Collectors.toList());
}
}

View File

@ -0,0 +1,26 @@
package com.changhu.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.changhu.common.pojo.vo.TreeNodeVo;
import com.changhu.pojo.entity.AdministrativeDivision;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* administrative_division (全国行政区划表(2023/12/04)) 固化类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Mapper
public interface AdministrativeDivisionMapper extends BaseMapper<AdministrativeDivision> {
/**
* 树列表
*
* @param level 等级
* @return 结果
*/
List<TreeNodeVo<String>> treeList(@Param("level") Integer level);
}

View File

@ -0,0 +1,39 @@
package com.changhu.module.management.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.changhu.common.annotation.JsonBody;
import com.changhu.common.utils.JavaClassToTsUtil;
import com.changhu.module.management.pojo.queryParams.PoliceUnitPagerQueryParams;
import com.changhu.module.management.pojo.vo.PoliceUnitPagerVo;
import com.changhu.module.management.service.PoliceUnitService;
import com.changhu.support.mybatisplus.pojo.params.PageParams;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author 20252
* @createTime 2024/8/30 下午3:45
* @desc PoliceUnitController...
*/
@Tag(name = "单位-公安")
@JsonBody
@RequestMapping("/policeUnit")
public class PoliceUnitController {
@Autowired
private PoliceUnitService policeUnitService;
@Operation(summary = "分页查询")
@PostMapping("/pager")
public Page<PoliceUnitPagerVo> pager(@RequestBody PageParams<PoliceUnitPagerQueryParams, PoliceUnitPagerVo> queryParams) {
return policeUnitService.pager(queryParams);
}
public static void main(String[] args) {
System.out.println(JavaClassToTsUtil.parse(PoliceUnitPagerVo.class));
}
}

View File

@ -0,0 +1,42 @@
package com.changhu.module.management.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.changhu.common.annotation.JsonBody;
import com.changhu.module.management.pojo.params.SecurityUnitSaveOrUpdateParams;
import com.changhu.module.management.pojo.queryParams.SecurityUnitPagerQueryParams;
import com.changhu.module.management.pojo.vo.SecurityUnitPagerVo;
import com.changhu.module.management.service.SecurityUnitService;
import com.changhu.support.mybatisplus.pojo.params.PageParams;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author 20252
* @createTime 2024/8/30 上午10:46
* @desc SecurityUnitController...
*/
@Tag(name = "单位-保安")
@JsonBody
@RequestMapping("/securityUnit")
public class SecurityUnitController {
@Autowired
private SecurityUnitService securityUnitService;
@Operation(summary = "分页查询")
@PostMapping("/pager")
public Page<SecurityUnitPagerVo> pager(@RequestBody PageParams<SecurityUnitPagerQueryParams, SecurityUnitPagerVo> queryParams) {
return securityUnitService.pager(queryParams);
}
@Operation(summary = "新增或修改")
@PostMapping("/saveOrUpdate")
public void saveOrUpdate(@RequestBody @Valid SecurityUnitSaveOrUpdateParams params) {
securityUnitService.saveOrUpdate(params);
}
}

View File

@ -1,57 +0,0 @@
package com.changhu.module.management.controller;
import com.changhu.common.db.enums.IsOrNot;
import com.changhu.common.db.enums.DeleteFlag;
import java.time.LocalDateTime;
import com.changhu.common.db.enums.IsEnable;
import com.changhu.common.db.enums.Sex;
import com.changhu.common.annotation.JsonBody;
import com.changhu.module.management.pojo.entity.ManagementPoliceUnitUser;
import lombok.Data;
import org.springframework.web.bind.annotation.*;
/**
* @author 20252
* @createTime 2024/8/28 下午4:02
* @desc TestController...
*/
@JsonBody
@RequestMapping("/test")
public class TestController {
@GetMapping("/get")
public ManagementPoliceUnitUser get() {
ManagementPoliceUnitUser managementPoliceUnitUser = new ManagementPoliceUnitUser();
managementPoliceUnitUser.setPoliceUnitId(0L);
managementPoliceUnitUser.setName("");
managementPoliceUnitUser.setSex(Sex.MAN);
managementPoliceUnitUser.setTelephone("");
managementPoliceUnitUser.setSalt("");
managementPoliceUnitUser.setPassword("");
managementPoliceUnitUser.setIsEnable(IsEnable.TRUE);
managementPoliceUnitUser.setIsAdmin(IsOrNot.IS);
managementPoliceUnitUser.setSnowFlakeId(0L);
managementPoliceUnitUser.setCreateBy(0L);
managementPoliceUnitUser.setCreateTime(LocalDateTime.now());
managementPoliceUnitUser.setUpdateBy(0L);
managementPoliceUnitUser.setUpdateTime(LocalDateTime.now());
managementPoliceUnitUser.setDeleteFlag(0);
return managementPoliceUnitUser;
}
@PostMapping("/de")
public void test(@RequestBody P p) {
System.out.println(p);
}
@Data
class P {
private String name;
private DeleteFlag deleteFlag;
}
}

View File

@ -0,0 +1,28 @@
package com.changhu.module.management.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.changhu.module.management.pojo.entity.PoliceUnit;
import com.changhu.module.management.pojo.queryParams.PoliceUnitPagerQueryParams;
import com.changhu.module.management.pojo.vo.PoliceUnitPagerVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* police_unit (公安单位) 固化类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Mapper
public interface PoliceUnitMapper extends BaseMapper<PoliceUnit> {
/**
* 分页查询
*
* @param page 分页参数
* @param params 查询参数
* @return 结果
*/
Page<PoliceUnitPagerVo> pager(@Param("page") Page<PoliceUnitPagerVo> page,
@Param("params") PoliceUnitPagerQueryParams params);
}

View File

@ -0,0 +1,31 @@
package com.changhu.module.management.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.changhu.module.management.pojo.entity.SecurityUnit;
import com.changhu.module.management.pojo.queryParams.SecurityUnitPagerQueryParams;
import com.changhu.module.management.pojo.vo.SecurityUnitPagerVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* security_unit (保安单位) 固化类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Mapper
public interface SecurityUnitMapper extends BaseMapper<SecurityUnit> {
/**
* 分页查询
*
* @param page 分页对象
* @param params 查询参数
* @return 结果
*/
Page<SecurityUnitPagerVo> pager(@Param("page") Page<SecurityUnitPagerVo> page,
@Param("params") SecurityUnitPagerQueryParams params);
}

View File

@ -0,0 +1,88 @@
package com.changhu.module.management.pojo.entity;
import java.io.Serial;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.extension.handlers.Fastjson2TypeHandler;
import com.changhu.common.db.enums.CheckStatus;
import com.changhu.common.db.enums.IsEnable;
import com.changhu.module.management.pojo.model.ContactPersonInfo;
import com.changhu.support.mybatisplus.pojo.entity.BaseEntity;
import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import lombok.EqualsAndHashCode;
import com.baomidou.mybatisplus.annotation.TableName;
/**
* 公安单位 实体类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
@EqualsAndHashCode(callSuper = true)
@TableName(autoResultMap = true)
public class PoliceUnit extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 名称
*/
private String name;
/**
* 代码
*/
private String code;
/**
*
*/
private String province;
/**
*
*/
private String city;
/**
* /
*/
private String districts;
/**
* 街道
*/
private String street;
/**
* 详细地址
*/
private String address;
/**
* 联系人
*/
@TableField(typeHandler = Fastjson2TypeHandler.class)
private ContactPersonInfo contactPersonInfo;
/**
* 是否启用
*/
private IsEnable isEnable;
/**
* 审核状态
*/
private CheckStatus checkStatus;
}

View File

@ -0,0 +1,98 @@
package com.changhu.module.management.pojo.entity;
import java.io.Serial;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.extension.handlers.Fastjson2TypeHandler;
import com.changhu.common.db.enums.CheckStatus;
import com.changhu.common.db.enums.IsEnable;
import com.changhu.module.management.pojo.model.LegalPersonInfo;
import com.changhu.support.mybatisplus.pojo.entity.BaseEntity;
import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import lombok.EqualsAndHashCode;
import com.baomidou.mybatisplus.annotation.TableName;
/**
* 保安单位 实体类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
@EqualsAndHashCode(callSuper = true)
@TableName(autoResultMap = true)
public class SecurityUnit extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 名称
*/
private String name;
/**
* 统一社会编码
*/
private String socialCode;
/**
* 营业执照
*/
private String businessLicense;
/**
* 法人信息
*/
@TableField(typeHandler = Fastjson2TypeHandler.class)
private LegalPersonInfo legalPersonInfo;
/**
*
*/
private String province;
/**
*
*/
private String city;
/**
* /
*/
private String districts;
/**
* 街道
*/
private String street;
/**
* 详细地址
*/
private String address;
/**
* 公司性质
*/
private String nature;
/**
* 是否启用
*/
private IsEnable isEnable;
/**
* 审核状态
*/
private CheckStatus checkStatus;
}

View File

@ -0,0 +1,22 @@
package com.changhu.module.management.pojo.model;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
/**
* @author 20252
* @createTime 2024/8/30 下午3:43
* @desc ContactPersonInfo...
*/
@Data
public class ContactPersonInfo {
@NotBlank(message = "名字不能为空")
@Schema(description = "名字")
private String name;
@NotBlank(message = "手机号不能为空")
@Schema(description = "手机号")
private String telephone;
}

View File

@ -0,0 +1,20 @@
package com.changhu.module.management.pojo.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* @author 20252
* @createTime 2024/8/30 上午11:01
* @desc 法人信息
*/
@Data
public class LegalPersonInfo {
@Schema(description = "名字")
private String name;
@Schema(description = "电话")
private String telephone;
}

View File

@ -0,0 +1,56 @@
package com.changhu.module.management.pojo.params;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.extension.handlers.Fastjson2TypeHandler;
import com.changhu.common.db.enums.CheckStatus;
import com.changhu.common.db.enums.IsEnable;
import com.changhu.common.validator.annotation.IsMobile;
import com.changhu.module.management.pojo.model.LegalPersonInfo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import java.util.List;
/**
* @author 20252
* @createTime 2024/8/30 下午3:07
* @desc SecurityUnitSaveOrUpdateParams...
*/
@Data
public class SecurityUnitSaveOrUpdateParams {
@Schema(description = "id")
private Long snowFlakeId;
@NotBlank(message = "名字不能为空")
@Schema(description = "名称")
private String name;
@NotBlank(message = "社会编码不能为空")
@Schema(description = "社会编码")
private String socialCode;
@NotBlank(message = "营业执照不能为空")
@Schema(description = "营业执照")
private String businessLicense;
@NotBlank(message = "法人信息不能为空")
@Schema(description = "法人信息")
private LegalPersonInfo legalPersonInfo;
@NotBlank(message = "公司性质不能为空")
@Schema(description = "性质")
private String nature;
@NotEmpty(message = "行政区划不能为空")
@Schema(description = "行政区划编码")
private List<String> administrativeDivisionCodes;
@NotBlank(message = "详细地址不能为空")
@Schema(description = "详细地址")
private String address;
@Schema(description = "是否启用")
private IsEnable isEnable;
}

View File

@ -0,0 +1,32 @@
package com.changhu.module.management.pojo.queryParams;
import com.changhu.common.db.enums.CheckStatus;
import com.changhu.common.db.enums.IsEnable;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
/**
* @author 20252
* @createTime 2024/8/30 下午3:55
* @desc PoliceUnitPagerQueryParams...
*/
@Data
public class PoliceUnitPagerQueryParams {
@Schema(description = "名称")
private String name;
@Schema(description = "代码")
private String code;
@Schema(description = "行政区划")
private List<String> administrativeDivisionCodes;
@Schema(description = "是否启用")
private IsEnable isEnable;
@Schema(description = "审核状态")
private CheckStatus checkStatus;
}

View File

@ -0,0 +1,27 @@
package com.changhu.module.management.pojo.queryParams;
import com.changhu.common.db.enums.CheckStatus;
import com.changhu.common.db.enums.IsEnable;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
/**
* @author 20252
* @createTime 2024/8/30 上午11:03
* @desc SecurityUnitPagerQueryParams...
*/
@Data
public class SecurityUnitPagerQueryParams {
@Schema(description = "名称")
private String name;
@Schema(description = "社会编码")
private String socialCode;
@Schema(description = "行政区划编码")
private List<String> administrativeDivisionCodes;
@Schema(description = "是否启用")
private IsEnable isEnable;
@Schema(description = "审核状态")
private CheckStatus checkStatus;
}

View File

@ -0,0 +1,60 @@
package com.changhu.module.management.pojo.vo;
import com.changhu.common.db.enums.CheckStatus;
import com.changhu.common.db.enums.IsEnable;
import com.changhu.module.management.pojo.model.ContactPersonInfo;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDateTime;
/**
* @author 20252
* @createTime 2024/8/30 下午3:55
* @desc PoliceUnitPagerVo...
*/
public class PoliceUnitPagerVo {
@Schema(description = "id")
private Long snowFlakeId;
@Schema(description = "名称")
private String name;
@Schema(description = "代码")
private String code;
@Schema(description = "省编码")
private String province;
@Schema(description = "省名字")
private String provinceName;
@Schema(description = "市编码")
private String city;
@Schema(description = "市名字")
private String cityName;
@Schema(description = "区/县编码")
private String districts;
@Schema(description = "区/县名字")
private String districtsName;
@Schema(description = "街道编码")
private String street;
@Schema(description = "街道编码")
private String streetName;
@Schema(description = "详细地址")
private String address;
@Schema(description = "联系人")
private ContactPersonInfo contactPersonInfo;
@Schema(description = "是否启用")
private IsEnable isEnable;
@Schema(description = "审核状态")
private CheckStatus checkStatus;
@Schema(description = "创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,67 @@
package com.changhu.module.management.pojo.vo;
import com.changhu.common.db.enums.CheckStatus;
import com.changhu.common.db.enums.IsEnable;
import com.changhu.module.management.pojo.model.LegalPersonInfo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* @author 20252
* @createTime 2024/8/30 上午10:50
* @desc SecurityUnitPagerVo...
*/
@Data
public class SecurityUnitPagerVo {
@Schema(description = "雪花id")
private Long snowFlakeId;
@Schema(description = "名称")
private String name;
@Schema(description = "社会编码")
private String socialCode;
@Schema(description = "营业执照")
private String businessLicense;
@Schema(description = "法人信息")
private LegalPersonInfo legalPersonInfo;
@Schema(description = "省编码")
private String province;
@Schema(description = "省名字")
private String provinceName;
@Schema(description = "市编码")
private String city;
@Schema(description = "市名字")
private String cityName;
@Schema(description = "区/县编码")
private String districts;
@Schema(description = "区/县名字")
private String districtsName;
@Schema(description = "街道编码")
private String street;
@Schema(description = "街道编码")
private String streetName;
@Schema(description = "详细地址")
private String address;
@Schema(description = "公司性质")
private String nature;
@Schema(description = "是否启用")
private IsEnable isEnable;
@Schema(description = "审核状态")
private CheckStatus checkStatus;
@Schema(description = "创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,24 @@
package com.changhu.module.management.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.changhu.module.management.pojo.entity.PoliceUnit;
import com.changhu.module.management.pojo.queryParams.PoliceUnitPagerQueryParams;
import com.changhu.module.management.pojo.vo.PoliceUnitPagerVo;
import com.changhu.support.mybatisplus.pojo.params.PageParams;
/**
* police_unit (公安单位) 服务类
* author: luozhun
* desc 由groovy脚本自动生成
*/
public interface PoliceUnitService extends IService<PoliceUnit> {
/**
* 分页查询
*
* @param queryParams 查询参数
* @return 结果
*/
Page<PoliceUnitPagerVo> pager(PageParams<PoliceUnitPagerQueryParams, PoliceUnitPagerVo> queryParams);
}

View File

@ -0,0 +1,32 @@
package com.changhu.module.management.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.changhu.module.management.pojo.entity.SecurityUnit;
import com.changhu.module.management.pojo.params.SecurityUnitSaveOrUpdateParams;
import com.changhu.module.management.pojo.queryParams.SecurityUnitPagerQueryParams;
import com.changhu.module.management.pojo.vo.SecurityUnitPagerVo;
import com.changhu.support.mybatisplus.pojo.params.PageParams;
/**
* security_unit (保安单位) 服务类
* author: luozhun
* desc 由groovy脚本自动生成
*/
public interface SecurityUnitService extends IService<SecurityUnit> {
/**
* 分页查询
*
* @param queryParams 查询参数
* @return 结果
*/
Page<SecurityUnitPagerVo> pager(PageParams<SecurityUnitPagerQueryParams, SecurityUnitPagerVo> queryParams);
/**
* 新增或修改保安单位
*
* @param params 参数
*/
void saveOrUpdate(SecurityUnitSaveOrUpdateParams params);
}

View File

@ -0,0 +1,25 @@
package com.changhu.module.management.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.changhu.module.management.mapper.PoliceUnitMapper;
import com.changhu.module.management.pojo.entity.PoliceUnit;
import com.changhu.module.management.pojo.queryParams.PoliceUnitPagerQueryParams;
import com.changhu.module.management.pojo.vo.PoliceUnitPagerVo;
import com.changhu.module.management.service.PoliceUnitService;
import com.changhu.support.mybatisplus.pojo.params.PageParams;
import org.springframework.stereotype.Service;
/**
* police_unit (公安单位) 服务实现类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Service
public class PoliceUnitServiceImpl extends ServiceImpl<PoliceUnitMapper, PoliceUnit> implements PoliceUnitService {
@Override
public Page<PoliceUnitPagerVo> pager(PageParams<PoliceUnitPagerQueryParams, PoliceUnitPagerVo> queryParams) {
return baseMapper.pager(queryParams.getPage(), queryParams.getParams());
}
}

View File

@ -0,0 +1,87 @@
package com.changhu.module.management.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.changhu.common.utils.JavaClassToTsUtil;
import com.changhu.module.management.pojo.model.LegalPersonInfo;
import com.changhu.module.management.pojo.params.SecurityUnitSaveOrUpdateParams;
import com.google.common.collect.Lists;
import com.changhu.common.db.enums.IsEnable;
import com.changhu.common.db.enums.CheckStatus;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.changhu.module.management.mapper.SecurityUnitMapper;
import com.changhu.module.management.pojo.entity.SecurityUnit;
import com.changhu.module.management.pojo.queryParams.SecurityUnitPagerQueryParams;
import com.changhu.module.management.pojo.vo.SecurityUnitPagerVo;
import com.changhu.module.management.service.SecurityUnitService;
import com.changhu.support.mybatisplus.pojo.params.PageParams;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
/**
* security_unit (保安单位) 服务实现类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Service
public class SecurityUnitServiceImpl extends ServiceImpl<SecurityUnitMapper, SecurityUnit> implements SecurityUnitService {
@Override
public Page<SecurityUnitPagerVo> pager(PageParams<SecurityUnitPagerQueryParams, SecurityUnitPagerVo> queryParams) {
Page<SecurityUnitPagerVo> page = queryParams.getPage();
SecurityUnitPagerQueryParams params = queryParams.getParams();
LambdaQueryWrapper<SecurityUnit> wrapper = Wrappers.<SecurityUnit>lambdaQuery()
.like(StrUtil.isNotEmpty(params.getName()), SecurityUnit::getName, params.getName())
.like(StrUtil.isNotEmpty(params.getSocialCode()), SecurityUnit::getSocialCode, params.getSocialCode());
if (params.getCheckStatus() != null) {
wrapper.eq(SecurityUnit::getCheckStatus, params.getCheckStatus().getValue());
}
if (params.getIsEnable() != null) {
wrapper.eq(SecurityUnit::getIsEnable, params.getIsEnable().getValue());
}
List<String> administrativeDivisionCodes = params.getAdministrativeDivisionCodes();
if (administrativeDivisionCodes != null) {
wrapper.eq(!administrativeDivisionCodes.isEmpty(), SecurityUnit::getProvince, administrativeDivisionCodes.get(0));
wrapper.eq(administrativeDivisionCodes.size() >= 2, SecurityUnit::getCity, administrativeDivisionCodes.get(1));
wrapper.eq(administrativeDivisionCodes.size() >= 3, SecurityUnit::getDistricts, administrativeDivisionCodes.get(2));
wrapper.eq(administrativeDivisionCodes.size() >= 4, SecurityUnit::getStreet, administrativeDivisionCodes.get(3));
}
return baseMapper.pager(page, params);
}
@Override
public void saveOrUpdate(SecurityUnitSaveOrUpdateParams params) {
SecurityUnit securityUnit = BeanUtil.copyProperties(params, SecurityUnit.class);
Optional.ofNullable(params.getAdministrativeDivisionCodes())
.ifPresent(codes -> {
if (!codes.isEmpty()) {
securityUnit.setProvince(codes.get(0));
}
if (codes.size() >= 2) {
securityUnit.setCity(codes.get(1));
}
if (codes.size() >= 3) {
securityUnit.setCity(codes.get(2));
}
if (codes.size() >= 4) {
securityUnit.setCity(codes.get(3));
}
});
this.saveOrUpdate(securityUnit);
}
public static void main(String[] args) {
String parse = JavaClassToTsUtil.parse(SecurityUnitPagerQueryParams.class);
System.out.println(parse);
}
}

View File

@ -0,0 +1,57 @@
package com.changhu.pojo.entity;
import java.io.Serial;
import java.io.Serializable;
import com.changhu.support.mybatisplus.pojo.entity.BaseEntity;
import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import lombok.EqualsAndHashCode;
import com.baomidou.mybatisplus.annotation.TableName;
/**
* 全国行政区划表(2023/12/04) 实体类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
@EqualsAndHashCode(callSuper = true)
@TableName(autoResultMap = true)
public class AdministrativeDivision extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 区划名称
*/
private String name;
/**
* 区划编码
*/
private String code;
/**
* 上级行政区划编码
*/
private String parentCode;
/**
* 区划级别: 1:/自治区/直辖市 2:市级 3:/县级 4:街道级
*/
private Integer level;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,35 @@
package com.changhu.pojo.params;
import com.changhu.module.management.pojo.model.ContactPersonInfo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import java.util.List;
/**
* @author 20252
* @createTime 2024/8/30 下午4:47
* @desc PoliceUnitRegisterParams...
*/
@Data
public class PoliceUnitRegisterParams {
@NotBlank(message = "单位名称不能为空")
@Schema(description = "单位名称")
private String name;
@NotBlank(message = "单位代码不能为空")
@Schema(description = "单位代码")
private String code;
@NotEmpty(message = "行政区划不能为空")
@Schema(description = "行政区划")
private List<String> administrativeDivisionCodes;
@Schema(description = "详细地址")
private String address;
@Schema(description = "联系人")
private ContactPersonInfo contactPersonInfo;
}

View File

@ -0,0 +1,49 @@
package com.changhu.pojo.params;
import com.changhu.module.management.pojo.model.LegalPersonInfo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.List;
/**
* @author 20252
* @createTime 2024/8/30 下午3:16
* @desc SecurityUnitRegisterParams...
*/
@Data
public class SecurityUnitRegisterParams {
@Schema(description = "id")
private Long snowFlakeId;
@NotBlank(message = "名字不能为空")
@Schema(description = "名称")
private String name;
@NotBlank(message = "社会编码不能为空")
@Schema(description = "社会编码")
private String socialCode;
@NotBlank(message = "营业执照不能为空")
@Schema(description = "营业执照")
private String businessLicense;
@Schema(description = "法人信息")
private LegalPersonInfo legalPersonInfo;
@NotBlank(message = "公司性质不能为空")
@Schema(description = "性质")
private String nature;
@NotEmpty(message = "行政区划不能为空")
@Schema(description = "行政区划编码")
private List<String> administrativeDivisionCodes;
@NotBlank(message = "详细地址不能为空")
@Schema(description = "详细地址")
private String address;
}

View File

@ -0,0 +1,23 @@
package com.changhu.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.changhu.common.pojo.vo.TreeNodeVo;
import com.changhu.pojo.entity.AdministrativeDivision;
import java.util.List;
/**
* administrative_division (全国行政区划表(2023/12/04)) 服务类
* author: luozhun
* desc 由groovy脚本自动生成
*/
public interface AdministrativeDivisionService extends IService<AdministrativeDivision> {
/**
* 全国行政区划树
*
* @param level 需要几级数据
* @return 全国行政区划树
*/
List<TreeNodeVo<String>> tree(Integer level);
}

View File

@ -0,0 +1,27 @@
package com.changhu.service;
import com.changhu.common.pojo.model.JsonResult;
import com.changhu.pojo.params.PoliceUnitRegisterParams;
import com.changhu.pojo.params.SecurityUnitRegisterParams;
/**
* @author 20252
* @createTime 2024/8/30 下午3:18
* @desc CommonService...
*/
public interface CommonService {
/**
* 保安单位注册
*
* @param params 注册参数
*/
JsonResult<Void> securityUnitRegister(SecurityUnitRegisterParams params);
/**
* 公安单位注册
*
* @param params 注册参数
*/
JsonResult<Void> policeUnitRegister(PoliceUnitRegisterParams params);
}

View File

@ -0,0 +1,25 @@
package com.changhu.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.changhu.common.pojo.vo.TreeNodeVo;
import com.changhu.mapper.AdministrativeDivisionMapper;
import com.changhu.pojo.entity.AdministrativeDivision;
import com.changhu.service.AdministrativeDivisionService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* administrative_division (全国行政区划表(2023/12/04)) 服务实现类
* author: luozhun
* desc 由groovy脚本自动生成
*/
@Service
public class AdministrativeDivisionServiceImpl extends ServiceImpl<AdministrativeDivisionMapper, AdministrativeDivision> implements AdministrativeDivisionService {
@Override
public List<TreeNodeVo<String>> tree(Integer level) {
List<TreeNodeVo<String>> treeNodeVos = baseMapper.treeList(level);
return TreeNodeVo.buildTree(treeNodeVos, "0");
}
}

View File

@ -0,0 +1,97 @@
package com.changhu.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.changhu.common.enums.ResultCode;
import com.changhu.common.exception.MessageException;
import com.changhu.common.pojo.model.JsonResult;
import com.changhu.module.management.mapper.PoliceUnitMapper;
import com.changhu.module.management.mapper.SecurityUnitMapper;
import com.changhu.module.management.pojo.entity.PoliceUnit;
import com.changhu.module.management.pojo.entity.SecurityUnit;
import com.changhu.pojo.params.PoliceUnitRegisterParams;
import com.changhu.pojo.params.SecurityUnitRegisterParams;
import com.changhu.service.CommonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Optional;
/**
* @author 20252
* @createTime 2024/8/30 下午3:18
* @desc CommonServiceImpl...
*/
@Service
public class CommonServiceImpl implements CommonService {
@Autowired
private SecurityUnitMapper securityUnitMapper;
@Autowired
private PoliceUnitMapper policeUnitMapper;
@Override
public JsonResult<Void> securityUnitRegister(SecurityUnitRegisterParams params) {
//先查看该社会编码是否存在
boolean exists = securityUnitMapper.exists(Wrappers.<SecurityUnit>lambdaQuery().eq(SecurityUnit::getSocialCode, params.getSocialCode()));
if (exists) {
throw new MessageException("该单位已存在或已提交申请!");
}
SecurityUnit securityUnit = BeanUtil.copyProperties(params, SecurityUnit.class);
Optional.ofNullable(params.getAdministrativeDivisionCodes())
.ifPresent(codes -> {
if (!codes.isEmpty()) {
securityUnit.setProvince(codes.get(0));
}
if (codes.size() >= 2) {
securityUnit.setCity(codes.get(1));
}
if (codes.size() >= 3) {
securityUnit.setDistricts(codes.get(2));
}
if (codes.size() >= 4) {
securityUnit.setStreet(codes.get(3));
}
});
int i = securityUnitMapper.insert(securityUnit);
if (i <= 0) {
throw new MessageException(ResultCode.ERROR);
}
return JsonResult.successMsg("申请已提交,请等待审核");
}
@Override
public JsonResult<Void> policeUnitRegister(PoliceUnitRegisterParams params) {
//先查看该公安单位是否存在
boolean exists = policeUnitMapper.exists(Wrappers.<PoliceUnit>lambdaQuery().eq(PoliceUnit::getCode, params.getCode()));
if (exists) {
throw new MessageException("该单位已存在或已提交申请!");
}
PoliceUnit policeUnit = BeanUtil.copyProperties(params, PoliceUnit.class);
Optional.ofNullable(params.getAdministrativeDivisionCodes())
.ifPresent(codes -> {
if (!codes.isEmpty()) {
policeUnit.setProvince(codes.get(0));
}
if (codes.size() >= 2) {
policeUnit.setCity(codes.get(1));
}
if (codes.size() >= 3) {
policeUnit.setDistricts(codes.get(2));
}
if (codes.size() >= 4) {
policeUnit.setStreet(codes.get(3));
}
});
int i = policeUnitMapper.insert(policeUnit);
if (i <= 0) {
throw new MessageException(ResultCode.ERROR);
}
return JsonResult.successMsg("申请已提交,请等待审核");
}
}

View File

@ -17,7 +17,7 @@ import org.springframework.context.annotation.Configuration;
public class Knefe4jConfig { public class Knefe4jConfig {
@Value("spring.application.name") @Value("${spring.application.name}")
private String applicationName; private String applicationName;
@Bean @Bean

View File

@ -116,10 +116,10 @@ logging:
config: classpath:conf/log4j2.xml config: classpath:conf/log4j2.xml
minio: minio:
url: http://172.10.10.238:9000 url: http://118.253.177.137:9000
accessKey: admin accessKey: admin
secretKey: lonsung301 secretKey: lonsung301
bucketName: management-dev bucketName: police-security-dev
sa-token: sa-token:
# token 名称(同时也是 cookie 名称) # token 名称(同时也是 cookie 名称)

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.changhu.mapper.AdministrativeDivisionMapper">
<select id="treeList" resultType="com.changhu.common.pojo.vo.TreeNodeVo">
select
code as 'value',
name as 'label',
parent_code as 'parentValue'
from
administrative_division
where delete_flag = 0
<if test="level!=null">and level &lt;= #{level}</if>
order by code
</select>
</mapper>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.changhu.module.management.mapper.PoliceUnitMapper">
<select id="pager" resultType="com.changhu.module.management.pojo.vo.PoliceUnitPagerVo">
select *
from police_unit
where delete_flag = 0
<if test="params.name!=null and params.name!=''">and name like concat('%',#{params.name},'%')</if>
<if test="params.code!=null and params.code!=''">and code like concat('%',#{params.code},'%')</if>
<if test="params.administrativeDivisionCodes!=null">
<if test="params.administrativeDivisionCodes.size>=1">
and province = #{params.administrativeDivisionCodes[0]}
</if>
<if test="params.administrativeDivisionCodes.size>=2">
and city = #{params.administrativeDivisionCodes[1]}
</if>
<if test="params.administrativeDivisionCodes.size>=3">
and districts = #{params.administrativeDivisionCodes[2]}
</if>
<if test="params.administrativeDivisionCodes.size>=4">
and street = #{params.administrativeDivisionCodes[3]}
</if>
order by create_time desc
</if>
<if test="params.isEnable!=null">and is_enable = #{params.isEnable.value}</if>
<if test="params.checkStatus!=null">and check_status = #{params.checkStatus.value}</if>
</select>
</mapper>

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.changhu.module.management.mapper.SecurityUnitMapper">
<select id="pager" resultType="com.changhu.module.management.pojo.vo.SecurityUnitPagerVo">
select
*
from security_unit
where
delete_flag = 0
<if test="params.name!=null and params.name!=''">
and name like concat('%',#{params.name},'%')
</if>
<if test="params.socialCode!=null and params.socialCode!=''">
and socialCode like concat('%',#{params.socialCode},'%')
</if>
<if test="params.administrativeDivisionCodes!=null">
<if test="params.administrativeDivisionCodes.size>=1">
and province = #{params.administrativeDivisionCodes[0]}
</if>
<if test="params.administrativeDivisionCodes.size>=2">
and city = #{params.administrativeDivisionCodes[1]}
</if>
<if test="params.administrativeDivisionCodes.size>=3">
and districts = #{params.administrativeDivisionCodes[2]}
</if>
<if test="params.administrativeDivisionCodes.size>=4">
and street = #{params.administrativeDivisionCodes[3]}
</if>
order by create_time desc
</if>
<if test="params.isEnable!=null">and is_enable = #{params.isEnable.value}</if>
<if test="params.checkStatus!=null">and check_status = #{params.checkStatus.value}</if>
</select>
</mapper>

View File

@ -9,3 +9,7 @@ VITE_APP_PROXY_URL=http://localhost:8765
# rsa 公钥 # rsa 公钥
VITE_APP_RSA_PUBLIC_KEY=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJps/EXxxSpEM1Ix4R0NWIOBciHCr7P7coDT8tNKfelgR7txcJOqHCO/MIWe7T04aHQTcpQxqx9hMca7dbqz8TZpz9jvLzE/6ZonVKxHsoFnNlHMp1/CPAJ9f6D9wYicum2KltJkmQ0g//D9W2zPCYoGOmSRFcZx/KEBa4EM53jQIDAQAB VITE_APP_RSA_PUBLIC_KEY=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJps/EXxxSpEM1Ix4R0NWIOBciHCr7P7coDT8tNKfelgR7txcJOqHCO/MIWe7T04aHQTcpQxqx9hMca7dbqz8TZpz9jvLzE/6ZonVKxHsoFnNlHMp1/CPAJ9f6D9wYicum2KltJkmQ0g//D9W2zPCYoGOmSRFcZx/KEBa4EM53jQIDAQAB
# minio
VITE_APP_MINIO_URL=http://118.253.177.137:9000
VITE_APP_MINIO_BUCKET=police-security-dev

View File

@ -6,3 +6,7 @@ VITE_DROP_CONSOLE=true
# axios # axios
VITE_APP_BASE_API=/api VITE_APP_BASE_API=/api
VITE_APP_PROXY_URL=https://172.10.10.238:8765 VITE_APP_PROXY_URL=https://172.10.10.238:8765
# minio
VITE_APP_MINIO_URL=http://118.253.177.137:9000
VITE_APP_MINIO_BUCKET=police-security-dev

View File

@ -23,3 +23,7 @@ dist-ssr
*.njsproj *.njsproj
*.sln *.sln
*.sw? *.sw?
components.d.ts
package-lock.json
yarn.lock

View File

@ -13,13 +13,17 @@
"ant-design-vue": "^4.2.3", "ant-design-vue": "^4.2.3",
"axios": "^1.7.5", "axios": "^1.7.5",
"jsencrypt": "^3.3.2", "jsencrypt": "^3.3.2",
"lodash-es": "^4.17.21",
"pinia": "^2.2.2", "pinia": "^2.2.2",
"pinia-plugin-persistedstate": "^3.2.0", "pinia-plugin-persistedstate": "^3.2.0",
"sass": "^1.77.8", "sass": "^1.77.8",
"vue": "^3.4.37", "vue": "^3.4.37",
"vue-router": "4" "vue-component-type-helpers": "^2.1.2",
"vue-router": "4",
"vue-uuid": "^3.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/lodash-es": "^4.17.8",
"@types/node": "^22.5.1", "@types/node": "^22.5.1",
"@vitejs/plugin-vue": "^5.1.2", "@vitejs/plugin-vue": "^5.1.2",
"@vitejs/plugin-vue-jsx": "^4.0.1", "@vitejs/plugin-vue-jsx": "^4.0.1",

View File

@ -0,0 +1,206 @@
<template>
<a-form
ref="formProMaxRef"
v-bind="props"
:model="modelValue"
>
<a-row :gutter="props.gutter">
<a-col
v-for="(item,field) in props.formItemOptions as FormProMaxItemOptions<T>"
:key="field"
v-bind="getResponsive(item)"
>
<a-form-item
:name="field"
v-bind="item"
:label="undefined"
>
<template v-slot:label>
{{ item.label }}
<template v-if="item.remarkRender">
<a-popover :title="item.label" :content="item.remarkRender()">
<QuestionCircleOutlined class="margin-left-xs" style="color: red"/>
</a-popover>
</template>
</template>
<!-- 自定义组件 -->
<!-- ant design vue 组件 -->
<a-input
v-if="item.type==='input'"
v-model:value="modelValue[field]"
style="width: 100%"
v-bind="item.componentsProps"
:placeholder="getPlaceholder(item)"
:allowClear="item.componentsProps?.allowClear ?? true"
/>
<a-input-password
v-else-if="item.type==='inputPassword'"
v-model:value="modelValue[field]"
style="width: 100%"
v-bind="item.componentsProps"
:placeholder="getPlaceholder(item)"
:allowClear="item.componentsProps?.allowClear ?? true"
/>
<a-input-number
v-else-if="item.type==='inputNumber'"
v-model:value="modelValue[field]"
style="width: 100%"
v-bind="item.componentsProps"
:placeholder="getPlaceholder(item)"
/>
<a-textarea
v-else-if="item.type==='inputTextArea'"
v-model:value="modelValue[field]"
style="width: 100%"
v-bind="item.componentsProps"
:placeholder="getPlaceholder(item)"
:allowClear="item.componentsProps?.allowClear ?? true"
/>
<a-radio-group
v-else-if="item.type==='radioGroup'"
v-model:value="modelValue[field]"
style="width: 100%"
v-bind="item.componentsProps"
:options="item.options"
/>
<a-checkbox-group
v-else-if="item.type==='checkboxGroup'"
v-model:value="modelValue[field]"
style="width: 100%"
v-bind="item.componentsProps"
:options="item.options"
/>
<a-select
v-else-if="item.type==='select'"
v-model:value="modelValue[field]"
style="width: 100%"
v-bind="item.componentsProps"
:placeholder="getPlaceholder(item)"
:allowClear="item.componentsProps?.allowClear ?? true"
:options="item.options"
/>
<a-tree-select
v-else-if="item.type==='treeSelect'"
style="width: 100%"
v-model:value="modelValue[field]"
v-bind="item.componentsProps"
:placeholder="getPlaceholder(item)"
:allowClear="item.componentsProps?.allowClear ?? true"
:tree-data="item.options"
/>
<a-cascader
v-else-if="item.type ==='cascader'"
style="width: 100%"
v-model:value="modelValue[field]"
v-bind="item.componentsProps"
:placeholder="getPlaceholder(item)"
:allowClear="item.componentsProps?.allowClear ?? true"
:options="item.options"
/>
<a-range-picker
v-else-if="item.type ==='rangePicker'"
style="width: 100%"
v-model:value="modelValue[field]"
v-bind="item.componentsProps"
:placeholder="item.componentsProps?.placeholder ?? ['开始日期', '结束日期']"
:allowClear="item.componentsProps?.allowClear ?? true"
/>
<a-date-picker
v-else-if="item.type ==='datePicker'"
style="width: 100%"
v-model:value="modelValue[field]"
v-bind="item.componentsProps"
:placeholder="item.componentsProps?.placeholder ?? '请选择日期'"
:allowClear="item.componentsProps?.allowClear ?? true"
/>
<a-time-range-picker
v-else-if="item.type ==='timeRangePicker'"
style="width: 100%"
v-model:value="modelValue[field]"
v-bind="item.componentsProps"
:placeholder="item.componentsProps?.placeholder ?? ['开始时间', '结束时间']"
:allowClear="item.componentsProps?.allowClear ?? true"
/>
<a-time-picker
v-else-if="item.type ==='timePicker'"
style="width: 100%"
v-model:value="modelValue[field]"
v-bind="item.componentsProps"
:placeholder="getPlaceholder(item)"
:allowClear="item.componentsProps?.allowClear ?? true"
/>
<template v-else-if="item.type==='custom'">
<component :is="item.customRender"/>
</template>
</a-form-item>
</a-col>
</a-row>
<slot name="formOperation"></slot>
</a-form>
</template>
<script setup lang="ts" generic="T extends Record<string,any>">
import {FormInstance} from "ant-design-vue";
import {ref} from "vue";
import {FormExpose} from "ant-design-vue/es/form/Form";
import {QuestionCircleOutlined} from '@ant-design/icons-vue'
import {FormProMaxItemOptions, FormProMaxItemProps, FormProMaxProps} from "@/types/components/form/index.ts";
const modelValue = defineModel<T>('value', {
default: {}
})
const props = withDefaults(defineProps<FormProMaxProps<T>>(), {
grid: () => {
return {
span: 24
}
},
gutter: 10,
labelCol: () => {
return {
style: {
width: '100px'
}
}
},
wrapperCol: () => {
return {
span: 18
}
},
labelAlign: "left",
colon: undefined,
disabled: undefined,
hideRequiredMark: undefined,
labelWrap: undefined,
scrollToFirstError: undefined,
validateOnRuleChange: undefined
})
const formProMaxRef = ref<FormInstance>(null!)
const getResponsive = (item: FormProMaxItemProps): Grid => {
//span
if (item.grid) return item.grid.span ? {span: item.grid.span} : {...item.grid};
return {...props.grid}
}
//: =formItem=label
const getPlaceholder = (item: FormProMaxItemProps) => item.componentsProps?.placeholder ?? item.placeholder ?? (item.type.includes('input') ? `请输入${item.label}` : `请选择${item.label}`)
defineExpose<FormExpose>({
validate: (nameList, options) => formProMaxRef.value?.validate(nameList, options),
resetFields: (name) => formProMaxRef.value?.resetFields(name),
clearValidate: () => formProMaxRef.value?.clearValidate(),
getFieldsValue: (nameList) => formProMaxRef.value?.getFieldsValue(nameList),
scrollToField: (name, options) => formProMaxRef.value?.scrollToField(name, options),
validateFields: (nameList, options) => formProMaxRef.value?.validateFields(nameList, options)
})
</script>
<style scoped>
</style>

View File

@ -0,0 +1,20 @@
<template>
<i v-if="type==='class'" :class="[`iconfont ${fontClass}`]" :style="{fontSize:`${size}px`}"/>
<svg v-else-if="type === 'svg'" :style="{width:`${size}px`,height:`${size}px`}">
<use :href="`#${fontClass}`"/>
</svg>
</template>
<script setup lang="ts">
import {IconFontProps} from "@/types/components/iconfont/IconFont";
withDefaults(defineProps<IconFontProps>(), {
size: 25,
type: "svg"
});
</script>
<style scoped lang="scss">
</style>

View File

@ -12,6 +12,7 @@
<div v-else class="logo flex-center"> <div v-else class="logo flex-center">
<img src="@/assets/vue.svg" title="超级后台" alt="xx"> <img src="@/assets/vue.svg" title="超级后台" alt="xx">
</div> </div>
<SystemMenus/>
</a-layout-sider> </a-layout-sider>
<a-layout> <a-layout>
<a-layout-header <a-layout-header
@ -37,6 +38,7 @@
<script setup lang="ts"> <script setup lang="ts">
import {ref} from "vue"; import {ref} from "vue";
import LayoutHeader from "@/components/layout/header/LayoutHeader.vue"; import LayoutHeader from "@/components/layout/header/LayoutHeader.vue";
import SystemMenus from "@/components/layout/SystemMenus.vue";
const collapsed = ref<boolean>(false); const collapsed = ref<boolean>(false);

View File

@ -0,0 +1,47 @@
<template>
<template v-for="item in menuList">
<a-sub-menu
v-if="item.type === 'dir'"
:key="item.path"
>
<template #icon>
<icon-font :font-class="item.icon"/>
</template>
<template #title>
<span class="margin-left-xs">{{ item.title }}</span>
</template>
<menu-item :menu-list="item.children"/>
</a-sub-menu>
<a-menu-item
v-else
:key="item.path as any"
@click="router.push(item.path)"
>
<template #icon>
<icon-font :font-class="item.icon"/>
</template>
<span class="margin-left-xs">{{ item.title }}</span>
</a-menu-item>
</template>
</template>
<script setup lang="ts">
import {SystemMenu} from "@/types/config";
import {useRouter} from "vue-router";
import IconFont from "@/components/iconfont/IconFont.vue";
const router = useRouter()
withDefaults(defineProps<{
menuList?: SystemMenu[]
}>(), {
menuList: (): SystemMenu[] => {
return [];
}
})
</script>
<style scoped lang="scss">
</style>

View File

@ -0,0 +1,29 @@
<template>
<a-menu
:selectedKeys="activeMenus"
mode="inline"
:inline-collapsed="false"
class="system-menus"
>
<menu-item :menu-list="SYSTEM_MENUS"/>
</a-menu>
</template>
<script setup lang="ts">
import {computed} from "vue";
import {useRoute} from "vue-router";
import {SYSTEM_MENUS} from "@/config";
import MenuItem from "@/components/layout/MenuItem.vue";
const route = useRoute()
const activeMenus = computed(() => [route.path]);
</script>
<style scoped lang="scss">
.system-menus {
height: calc(100% - 100px);
overflow-y: auto;
}
</style>

View File

@ -0,0 +1,223 @@
<template>
<div class="table-pro-content">
<div class="card padding" v-if="props.searchFormOptions">
<FormProMax
ref="searchFormRef"
:form-item-options="props.searchFormOptions"
v-model:value="searchParams"
v-bind="props.searchFormProps"
>
<template v-slot:formOperation>
<a-space class="margin-right flex-end">
<a-button type="primary" @click="search">
<search-outlined/>
搜索
</a-button>
<a-button danger @click="resetFormAndTable">
<rollback-outlined/>
重置
</a-button>
</a-space>
</template>
</FormProMax>
</div>
<div class="card padding margin-top-xs">
<div class="flex-justify-between">
<slot name="tableHeader" :selectKeys="selectKeys" :selectRows="selectRows"></slot>
<div></div>
<slot name="tableHeaderRight" :selectKeys="selectKeys" :selectRows="selectRows"></slot>
<a-space>
<template v-if="!props.searchFormOptions">
<a-tooltip>
<template #title>刷新数据</template>
<a-button shape="circle" @click="requestGetTableData">
<ReloadOutlined/>
</a-button>
</a-tooltip>
</template>
<template v-if="props.isPrinter">
<a-tooltip>
<template #title>打印数据</template>
<a-button shape="circle">
<PrinterOutlined/>
</a-button>
</a-tooltip>
</template>
</a-space>
</div>
<a-table
class="margin-top"
v-bind="props"
:columns="tableColumns"
:row-selection="props.isSelection ? props.selectionProps ? props.selectionProps : defaultSelectProps : null"
:data-source="dataSource"
:loading="loading"
:pagination="false"
>
<template v-for="(_,key) in slots" v-slot:[key]="scope">
<slot v-if="!includes(['tableHeader','tableHeaderRight'],key)" :name="key" v-bind="scope"></slot>
</template>
</a-table>
<a-pagination
v-if="props.isPagination"
class="flex-end margin-top margin-right"
v-model:current="pageParams.current"
v-model:page-size="pageParams.size"
:total="pageParams.total"
v-bind="props.paginationProps"
@change="handleCurrentChange"
@showSizeChange="handleSizeChange"
/>
</div>
</div>
</template>
<script
setup
lang="ts"
generic="T extends BaseTableRowRecord = {},P extends { [key: string]: any } ={}"
>
import FormProMax from "@/components/form/FormProMax.vue";
import {PrinterOutlined, ReloadOutlined, RollbackOutlined, SearchOutlined} from "@ant-design/icons-vue";
import {computed, onMounted, Ref, ref} from "vue";
import {FormInstance} from "ant-design-vue";
import useTableProMax from "@/hooks/useTableProMax";
import {includes, isEmpty} from "lodash-es";
import {BaseTableRowRecord, TableProMaxProps, TableProMaxRowSelect, TableProMaxSlots} from "@/types/components/table";
const selectKeys = ref<string[]>([])
const selectRows = ref<T[]>([]) as Ref<T[]>
const defaultSelectProps: TableProMaxRowSelect<T> = {
type: "checkbox",
selectedRowKeys: selectKeys as any,
preserveSelectedRowKeys: true,
onSelect: (record, selected) => {
if (selected) {
selectKeys.value.push(record[props.rowKey] as string)
selectRows.value.push(record)
} else {
selectKeys.value.splice(selectKeys.value.findIndex(x => x === record[props.rowKey]));
selectRows.value.splice(selectRows.value.findIndex(r => r[props.rowKey] === record[props.rowKey]))
}
},
onChange: (selectedRowKeys, selectedRows) => {
selectKeys.value = selectedRowKeys as string[];
selectRows.value = selectedRows;
},
}
const clearSelect = () => {
selectKeys.value = [];
selectRows.value = [];
}
const props = withDefaults(defineProps<TableProMaxProps<T, P>>(), {
needIndex: true,
searchFormProps: () => {
return {
grid: {
xs: 24,
sm: 12,
md: 8,
lg: 6,
xl: 4
},
labelCol: undefined,
wrapperCol: undefined
}
},
rowKey: 'snowFlakeId',
requestAuto: true,
isPagination: true,
isSelection: false,
paginationProps: () => {
return {
showTotal: (total) => `${total}`,
showSizeChanger: true,
}
},
bordered: true,
showSorterTooltip: undefined,
showHeader: undefined,
expandFixed: undefined,
expandRowByClick: undefined,
defaultExpandAllRows: undefined,
showExpandColumn: undefined,
sticky: undefined
})
const slots = defineSlots<TableProMaxSlots<T>>()
const tableColumns = computed(() => {
let cols = props.columns;
if (!isEmpty(cols) && props.needIndex) {
if (!(cols?.[0].dataIndex === 'index')) {
cols?.unshift({
dataIndex: 'index',
width: 50,
title: '序号',
customRender: ({index}) => index + 1
})
}
}
return cols;
})
/**
* 表单实例
*/
const searchFormRef = ref<FormInstance>() as Ref<FormInstance>
/**
* 查询参数
*/
const searchParams = ref<P | Record<string, any>>(props.defaultSearchParams || {}) as Ref<P>
const {
loading,
dataSource,
pageParams,
search,
requestGetTableData,
handleSizeChange,
handleCurrentChange,
resetState
} = useTableProMax(props.requestApi,
searchFormRef,
searchParams,
props.isPagination,
props.dataCallback,
props.requestError
)
onMounted(() => props.requestAuto && requestGetTableData(true))
/**
* 重置表单并查询
*/
const resetFormAndTable = () => {
searchFormRef.value?.resetFields()
requestGetTableData()
}
defineExpose({
selectKeys,
selectRows,
requestGetTableData,
clearSelect,
resetTable: () => {
searchFormRef.value?.resetFields()
resetState();
}
})
</script>
<style scoped lang="scss">
.card {
box-sizing: border-box;
background-color: #ffffff;
border: 1px solid #e4e7ed;
border-radius: 6px;
box-shadow: 0 0 12px rgba(0, 0, 0, 0.05);
}
</style>

View File

@ -0,0 +1,96 @@
<template>
<div class="simpleUploadDiv">
<a-progress v-if="uploading" type="circle" :percent="percent"/>
<a-image
height="80%"
v-else
:src="minioBaseUrl+modelValue"
alt="avatar"/>
<a-button class="btn-success" @click="selectFile">{{ btnLabel }}</a-button>
<input id="myFileInput" type="file" style="display: none"/>
</div>
</template>
<script setup lang="ts">
import {message} from "ant-design-vue";
import {onMounted, onUnmounted, ref} from "vue";
import {generateSimpleObjectName, getResignedObjectUrl} from "@/utils/minioUtil";
import axios, {CancelTokenSource} from "axios";
import {convertFileSizeToStr} from "@/utils/index.ts";
const minioBaseUrl = __APP_ENV.VITE_APP_MINIO_URL
const modelValue = defineModel<string>('value')
const props = withDefaults(defineProps<{
parentDir?: string,
allowedExtensions?: string[],
maxSize?: number,
width?: string | number,
height?: string | number,
btnLabel?: string
}>(), {
parentDir: '',
allowedExtensions: () => ['jpg', 'jpeg', 'png', 'gif'],
maxSize: 1024 * 1024 * 4,
width: '150px',
height: '150px',
btnLabel: '选择图片'
})
const uploading = ref(false)
const percent = ref(0)
let cancelToken: CancelTokenSource | null = null
const selectFile = () => {
document.getElementById('myFileInput')?.click()
}
async function inputFileListener(this: HTMLInputElement) {
const selectedFile: File = this.files?.[0] as File;
const fileExtension = selectedFile.name?.split('.').pop().toLowerCase() as string;
if (!props.allowedExtensions.includes(fileExtension)) {
return message.error(`错误:不支持的文件格式,目前支持:【${props.allowedExtensions}`)
}
const isMax = selectedFile.size > props.maxSize;
if (isMax) {
return message.error(`文件大小超出限制,最大支持:【${convertFileSizeToStr(props.maxSize)}`);
}
cancelToken?.cancel();
percent.value = 0;
uploading.value = true;
const objectName = generateSimpleObjectName(selectedFile.name, props.parentDir)
const uploadUrl = await getResignedObjectUrl(__APP_ENV.VITE_APP_MINIO_BUCKET, objectName);
cancelToken = axios.CancelToken.source()
await axios.put(uploadUrl, selectedFile, {
cancelToken: cancelToken.token,
onUploadProgress: (progressEvent) => {
percent.value = (progressEvent.loaded / (progressEvent.total as number) * 100 | 0)
}
})
modelValue.value = '/' + __APP_ENV.VITE_APP_MINIO_BUCKET + objectName;
uploading.value = false;
}
onMounted(() => {
document.getElementById('myFileInput')?.addEventListener('change', inputFileListener);
})
onUnmounted(() => {
document.getElementById('myFileInput')?.removeEventListener('change', inputFileListener);
})
</script>
<style scoped lang="scss">
.simpleUploadDiv {
width: v-bind(width);
height: v-bind(height);
display: flex;
flex-direction: column;
}
</style>

View File

@ -0,0 +1,17 @@
import api from "@/axios";
type DictType =
'CheckStatus'
| 'DeleteFlag'
| 'IsEnable'
| 'IsOrNot'
| 'Sex'
export const initEnums = () => {
api.get<Record<DictType, SelectNodeVo<any>[]>>('/common/enums').then(resp => {
sessionStorage.setItem('dictMap', JSON.stringify(resp.data))
})
}
export const enumSelectNodes = <T>(enumType: DictType): SelectNodeVo<T>[] => JSON.parse(sessionStorage.getItem('dictMap') as string)?.[enumType] || []

View File

@ -1,2 +1,34 @@
import {SystemMenu} from "@/types/config";
export const CLIENT_TYPE = "MANAGEMENT_SUPER"; export const CLIENT_TYPE = "MANAGEMENT_SUPER";
export const ROUTER_WHITE_LIST: string[] = ['/login', '/test']; export const ROUTER_WHITE_LIST: string[] = ['/login', '/test'];
export const SYSTEM_MENUS: SystemMenu[] = [
{
title: '首页',
name: 'index',
path: '/index',
type: "menu",
component: () => import('@/views/index.vue')
}, {
title: '单位管理',
name: 'unitManage',
path: '/unitManage',
type: 'dir',
children: [
{
title: '公安单位',
name: 'policeUnit',
path: '/policeUnit',
type: 'menu',
component: () => import('@/views/unitManage/policeUnit/index.vue')
}, {
title: '保安单位',
name: 'securityUnit',
path: '/securityUnit',
type: 'menu',
component: () => import('@/views/unitManage/securityUnit/index.vue')
}
]
}
]

View File

@ -8,3 +8,56 @@ interface JsonResult<T> {
message: string; message: string;
data?: T; data?: T;
} }
/**
*
*/
class SelectNodeVo<T, E = Record<string, any>> {
value: T;
label: string;
options?: SelectNodeVo<T>[]
orderIndex?: number;
disabled?: boolean;
extData?: E
}
/**
*
*/
class TreeNodeVo<T, E = Record<string, any>> {
value: T;
parentValue: T;
label: string;
orderIndex?: number;
children?: TreeNodeVo<T>[]
extData?: E;
}
/**
*
*/
declare interface Grid {
//栅格占据的列数
span?: number;
//栅格左侧的间隔格数
offset?: number;
//栅格向右移动格数
push?: number;
//栅格向左移动格数
pull?: number;
//<768px 响应式栅格数或者栅格属性对象
xs?: number;
//≥768px 响应式栅格数或者栅格属性对象
sm?: number;
//≥992px 响应式栅格数或者栅格属性对象
md?: number;
//≥1200px 响应式栅格数或者栅格属性对象
lg?: number;
//≥1920px 响应式栅格数或者栅格属性对象
xl?: number;
}
interface BaseEnum<T> {
value: T;
label: string
}

View File

@ -0,0 +1,134 @@
import {ref, Ref} from "vue";
import {Page, PageParams, PageResult} from "@/types/hooks/useTableProMax.ts";
import {FormInstance} from "ant-design-vue";
import {BaseTableRowRecord, RequestApiType} from "@/types/components/table";
/**
*
* @param api
* @param searchFormRef
* @param searchParams
* @param isPageTable
* @param dataCallBack
* @param requestError
*/
export default <T extends BaseTableRowRecord, P extends Record<string, any> | PageParams<P>>(api: RequestApiType<T, P>,
searchFormRef: Ref<FormInstance>,
searchParams: Ref<P>,
isPageTable: boolean = true,
dataCallBack?: (data: T[]) => T[],
requestError?: (errorMsg: any) => void) => {
const dataSource = ref<T[]>([]) as Ref<T[]>;
const loading = ref<boolean>(false);
const pageParams = ref<Page>({
current: 1,
size: 10,
total: 0
})
/**
*
*/
const requestGetTableData = async (isInit: boolean = false) => {
try {
//校验表单
!isInit && await searchFormRef.value?.validate();
//组装参数
let totalSearchParams;
if (isPageTable) {
totalSearchParams = {
params: searchParams.value,
page: {
current: pageParams.value.current,
size: pageParams.value.size
}
} as PageParams<P>;
} else {
totalSearchParams = searchParams.value
}
loading.value = true;
const resp = await api(totalSearchParams as P);
let tableData: T[];
if (isPageTable) {
const {current, records, size, total} = resp.data as PageResult<T>;
isPageTable && updatePageParams({
current: parseInt(current),
size: parseInt(size),
total: parseInt(total)
});
tableData = records;
} else {
tableData = resp.data as T[]
}
dataCallBack && (tableData = dataCallBack(tableData));
dataSource.value = tableData;
} catch (error) {
requestError && requestError(error);
} finally {
loading.value = false;
}
}
/**
*
*/
const updatePageParams = (ps: Page) => Object.assign(pageParams.value, ps)
/**
* dataSource loading pageParams
*/
const resetState = () => {
dataSource.value = [];
loading.value = false;
pageParams.value = {
current: 1,
size: 10,
total: 0
}
}
/**
* requestGetTableData 1
* requestGetTableData
*/
const search = async () => {
pageParams.value.current = 1;
await requestGetTableData();
};
/**
* @description
* @param _
* @param {Number} size
*/
const handleSizeChange = async (_: number, size: number) => {
pageParams.value.current = 1;
pageParams.value.size = size;
await requestGetTableData();
};
/**
* @description
* @param current
*/
const handleCurrentChange = async (current: number) => {
pageParams.value.current = current;
await requestGetTableData();
};
return {
dataSource,
loading,
pageParams,
requestGetTableData,
search,
handleSizeChange,
handleCurrentChange,
resetState
};
}

View File

@ -10,6 +10,9 @@ import "@/assets/iconfont/iconfont.css";
import router from "@/router"; import router from "@/router";
// pinia stores // pinia stores
import pinia from "@/stores"; import pinia from "@/stores";
import {initEnums} from "@/config/dict.ts";
initEnums();
const vueApp = createApp(App); const vueApp = createApp(App);

View File

@ -1,4 +1,33 @@
import {RouteRecordRaw} from "vue-router"; import {RouteRecordRaw} from "vue-router";
import {SYSTEM_MENUS} from "@/config";
import {SystemMenu} from "@/types/config";
/**
*
*/
const extractMenuToRouter = (): RouteRecordRaw[] => {
const result: RouteRecordRaw[] = []
const traverse = (data: SystemMenu[]) => {
data.forEach(item => {
if (item.type === 'dir' && item.children && item.children.length > 0) {
traverse(item.children)
} else {
result.push({
path: item.path,
name: item.name,
meta: {
title: item.title
},
component: item.component
} as RouteRecordRaw)
}
})
}
traverse(SYSTEM_MENUS)
return result;
}
export const staticRouter: RouteRecordRaw[] = [ export const staticRouter: RouteRecordRaw[] = [
{ {
@ -15,19 +44,11 @@ export const staticRouter: RouteRecordRaw[] = [
path: '/layout', path: '/layout',
name: 'layout', name: 'layout',
redirect: '/index', redirect: '/index',
component: () => import("@/components/layout/layout.vue"), component: () => import("@/components/layout/Layout.vue"),
children: [ children: extractMenuToRouter()
{ }, {
path: '/index', path: '/test',
name: 'index', name: 'test',
meta: { component: () => import("@/views/test.vue"),
title: '首页',
icon: 'icon-shouye',
fixed: true,
isKeepAlive: false
}, },
component: () => import('@/views/index.vue')
}
]
}
] ]

View File

@ -0,0 +1,73 @@
import {
FormProps,
RangePicker,
Input,
InputNumber,
Textarea,
InputPassword,
RadioGroup,
Select,
TreeSelect,
Cascader,
CheckboxGroup,
DatePicker,
FormItem, TimeRangePicker, TimePicker,
} from "ant-design-vue";
import {Ref, UnwrapRef, VNode} from "vue";
import {ComponentProps} from "vue-component-type-helpers";
type FormProMaxItemType =
| 'custom'
| 'input'
| 'inputPassword'
| 'inputNumber'
| 'inputTextArea'
| 'radioGroup'
| 'select'
| 'selectIcon'
| 'selectUser'
| 'treeSelect'
| 'cascader'
| 'checkboxGroup'
| 'datePicker'
| 'rangePicker'
| 'timeRangePicker'
| 'timePicker';
interface FormProMaxItemCommonProps extends ComponentProps<typeof FormItem> {
label?: string,
grid?: Grid,
placeholder?: string,
remarkRender?: () => VNode | string,
customRender?: () => VNode;
options?: (SelectNodeVo<unknown> | TreeNodeVo<unknown>) [] | Ref<(SelectNodeVo<unknown> | TreeNodeVo<unknown>)[]>
}
export interface FormProMaxItemProps<T extends FormProMaxItemType = any, C = any> extends FormProMaxItemCommonProps {
type: T
componentsProps?: C
}
export type FormProMaxItemOptions<T> = {
[key in keyof T | string]:
FormProMaxItemProps<'custom', ComponentProps<Record<string, any>>>
| FormProMaxItemProps<'input', ComponentProps<typeof Input>>
| FormProMaxItemProps<'inputPassword', ComponentProps<typeof InputPassword>>
| FormProMaxItemProps<'inputNumber', ComponentProps<typeof InputNumber>>
| FormProMaxItemProps<'inputTextArea', ComponentProps<typeof Textarea>>
| FormProMaxItemProps<'radioGroup', ComponentProps<typeof RadioGroup>>
| FormProMaxItemProps<'select', ComponentProps<typeof Select>>
| FormProMaxItemProps<'treeSelect', ComponentProps<typeof TreeSelect>>
| FormProMaxItemProps<'cascader', ComponentProps<typeof Cascader>>
| FormProMaxItemProps<'checkboxGroup', ComponentProps<typeof CheckboxGroup>>
| FormProMaxItemProps<'datePicker', ComponentProps<typeof DatePicker>>
| FormProMaxItemProps<'rangePicker', ComponentProps<typeof RangePicker>>
| FormProMaxItemProps<'timeRangePicker', ComponentProps<typeof TimeRangePicker>>
| FormProMaxItemProps<'timePicker', ComponentProps<typeof TimePicker>>
}
export interface FormProMaxProps<T = {}> extends FormProps {
grid?: Grid
gutter?: number;
formItemOptions?: FormProMaxItemOptions<T> | Ref<FormProMaxItemOptions<T>> | UnwrapRef<FormProMaxItemOptions<T>>
}

View File

@ -0,0 +1,5 @@
export interface IconFontProps {
fontClass?: string,
size?: number,
type?: 'class' | 'svg'
}

View File

@ -0,0 +1,55 @@
import {PaginationProps, Table, TableProps} from "ant-design-vue";
import {TableRowSelection} from "ant-design-vue/lib/table/interface";
import {Ref, UnwrapRef} from "vue";
import {ColumnType} from "ant-design-vue/es/table/interface";
import {ComponentSlots} from "vue-component-type-helpers";
import {FormProMaxItemOptions, FormProMaxProps} from "@/types/components/form";
import {PageParams, PageResult} from "@/types/hooks/useTableProMax.ts";
export type TableProMaxColumnType<T extends BaseTableRowRecord> = Omit<ColumnType<T>, 'dataIndex'> & {
dataIndex: keyof T | string | string[] | number | number[];
}
export type TableProMaxProps<
T extends BaseTableRowRecord = {},
P extends { [key: string]: any } = {}
> = Partial<Omit<TableProps<T>, "dataSource" | 'pagination' | 'loading' | 'rowKey' | 'columns'>> & {
rowKey?: keyof T,
columns?: TableProMaxColumnType<T>[],
searchFormProps?: Omit<FormProMaxProps<P>, 'formItems'>
searchFormOptions?: FormProMaxItemOptions<P> | Ref<FormProMaxItemOptions<P>> | UnwrapRef<FormProMaxItemOptions<P>>,
defaultSearchParams?: { [key in keyof P | string]: any };
requestAuto?: boolean,
requestApi: RequestApiType<T, P>,
requestError?: (errorMsg: any) => void,
dataCallback?: (data: T[]) => T[],
isPagination?: boolean,
paginationProps?: TableProMaxPaginationProps,
isSelection?: boolean,
selectionProps?: TableProMaxRowSelect<T>,
isPrinter?: boolean,
needIndex?: boolean
}
export type TableProMaxSlots<T> = ComponentSlots<typeof Table> & {
tableHeader: (scope: { selectKeys: string[], selectRows: T[] }) => any,
tableHeaderRight: (scope: { selectKeys: string[], selectRows: T[] }) => any,
}
export type RequestApiType<T extends BaseTableRowRecord, P extends {
[key: string]: any
} = {}> = (params: P | PageParams<P>) => Promise<JsonResult<T[] | PageResult<T>>>;
export type TableProMaxPaginationProps = Partial<Omit<PaginationProps, "current" | "pageSize" | "total">>;
export type TableProMaxRowSelect<T extends BaseTableRowRecord> = TableRowSelection<T>;
export interface BaseTableRowRecord {
snowFlakeId?: string;
createUserName?: string;
createTime?: Date | string;
updateUserName?: string;
updateTime?: Date | string
}

View File

@ -0,0 +1,12 @@
import {RouteComponent} from "vue-router";
export interface SystemMenu {
type: 'dir' | 'menu';
title: string;
path: string;
name: string;
icon?: string;
component?: RouteComponent;
children?: SystemMenu[];
}

View File

@ -0,0 +1,26 @@
/**
*
*/
export interface Page {
current: number,
size: number,
total: number
}
/**
*
*/
export interface PageParams<T extends Record<string, any> = {}> {
params: T & { [key: string]: any },
page: Omit<Page, 'total'>
}
/**
*
*/
export interface PageResult<T> {
current: string,
records: T[],
size: string,
total: string
}

View File

@ -0,0 +1,48 @@
import {BaseTableRowRecord} from "@/types/components/table";
export interface PoliceUnitPagerQueryParams {
/** 名称 **/
name?: string;
/** 代码 **/
code?: string;
/** 行政区划 **/
administrativeDivisionCodes?: string[];
/** 是否启用 **/
isEnable?: BaseEnum<number>;
/** 审核状态 **/
checkStatus?: BaseEnum<number>;
}
export interface PoliceUnitPagerVo extends BaseTableRowRecord {
/** 名称 **/
name?: string;
/** 代码 **/
code?: string;
/** 省编码 **/
province?: string;
/** 省名字 **/
provinceName?: string;
/** 市编码 **/
city?: string;
/** 市名字 **/
cityName?: string;
/** 区/县编码 **/
districts?: string;
/** 区/县名字 **/
districtsName?: string;
/** 街道编码 **/
street?: string;
/** 街道编码 **/
streetName?: string;
/** 详细地址 **/
address?: string;
/** 联系人 **/
contactPersonInfo?: {
name: string;
telephone: string;
};
/** 是否启用 **/
isEnable?: BaseEnum<number>;
/** 审核状态 **/
checkStatus?: BaseEnum<number>;
}

View File

@ -0,0 +1,52 @@
import {BaseTableRowRecord} from "@/types/components/table";
export interface SecurityUnitPagerQueryParams {
/** 名称 **/
name?: string;
/** 社会编码 **/
socialCode?: string;
/** 行政区划编码 **/
administrativeDivisionCodes?: string[];
/** 是否启用 **/
isEnable?: number;
/** 审核状态 **/
checkStatus?: number;
}
export interface SecurityUnitPagerVo extends BaseTableRowRecord {
/** 名称 **/
name?: string;
/** 社会编码 **/
socialCode?: string;
/** 营业执照 **/
businessLicense?: string;
/** 法人信息 **/
legalPersonInfo?: {
name: string;
telephone: string;
};
/** 省编码 **/
province?: string;
/** 省名字 **/
provinceName?: string;
/** 市编码 **/
city?: string;
/** 市名字 **/
cityName?: string;
/** 区/县编码 **/
districts?: string;
/** 区/县名字 **/
districtsName?: string;
/** 街道编码 **/
street?: string;
/** 街道编码 **/
streetName?: string;
/** 详细地址 **/
address?: string;
/** 公司性质 **/
nature?: string;
/** 是否启用 **/
isEnable?: BaseEnum<number>;
/** 审核状态 **/
checkStatus?: BaseEnum<number>;
}

View File

@ -0,0 +1,17 @@
import {ceil, divide} from "lodash-es";
/**
*
* @param fileSizeInBytes
*/
export const convertFileSizeToStr = (fileSizeInBytes: number): string => {
if (fileSizeInBytes < 1024) {
return fileSizeInBytes + "B";
} else if (fileSizeInBytes < 1024 * 1024) {
return (ceil(divide(fileSizeInBytes, 1024), 2)) + "KB";
} else if (fileSizeInBytes < 1024 * 1024 * 1024) {
return (ceil(divide(fileSizeInBytes, (1024 * 1024)), 2)) + "MB";
} else {
return (ceil(divide(fileSizeInBytes, (1024 * 1024 * 1024)), 2)) + "GB";
}
}

View File

@ -0,0 +1,26 @@
import api from "@/axios";
import dayjs from "dayjs";
import {uuid} from "vue-uuid";
/**
*
* @param fileName
* @param parentDir
*/
export const generateSimpleObjectName = (fileName: string, parentDir?: String): string => {
let objectName = parentDir + dayjs().format('/YYYY/MM/DD/') + uuid.v4().replace(/-/g, '');
if (fileName && fileName.length > 0) {
objectName += fileName.substring(fileName.lastIndexOf('.'))
}
return objectName;
}
/**
* URL
*/
export const getResignedObjectUrl = async (bucketName: string, objectName: string): Promise<string> => {
return (await api.get<string>('/common/getResignedObjectUrl', {
bucketName,
objectName
})).data as string;
}

View File

@ -1,5 +1,7 @@
<template> <template>
<div>
index页面 index页面
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">

View File

@ -0,0 +1,17 @@
<template>
{{ url}}
<SingleImageFileUpload
v-model:value="url"
/>
</template>
<script setup lang="ts">
import SingleImageFileUpload from "@/components/upload/SingleImageFileUpload.vue";
import {ref} from "vue";
const url = ref<string>('')
</script>
<style scoped lang="scss">
</style>

View File

@ -0,0 +1,82 @@
<template>
<TableProMax
ref="tableRef"
:request-api="reqApi"
:columns="columns"
:searchFormOptions="searchFormOptions"
>
</TableProMax>
</template>
<script setup lang="ts">
import TableProMax from "@/components/table/TableProMax.vue";
import {ref} from "vue";
import {ComponentExposed} from "vue-component-type-helpers";
import {TableProMaxProps} from "@/types/components/table";
import {PoliceUnitPagerQueryParams, PoliceUnitPagerVo} from "@/types/views/unitManage/policeUnit.ts";
import api from "@/axios";
import {enumSelectNodes} from "@/config/dict.ts";
type TableProps = TableProMaxProps<PoliceUnitPagerVo, PoliceUnitPagerQueryParams>
const tableRef = ref<ComponentExposed<typeof TableProMax>>(null!)
const reqApi: TableProps['requestApi'] = (params) => api.post('/policeUnit/pager', params)
const columns: TableProps['columns'] = [
{
dataIndex: 'name',
title: '名称'
}, {
dataIndex: 'code',
title: '代码'
}, {
dataIndex: 'legalPersonInfo',
title: '联系人'
}, {
dataIndex: 'provinceName',
title: '行政区划',
customRender: ({record}) => [record.provinceName, record.cityName, record.districtsName, record.streetName].filter(Boolean).join('/')
}, {
dataIndex: 'isEnable',
title: '是否启用'
}, {
dataIndex: 'checkStatus',
title: '审核状态'
}, {
dataIndex: 'createTime',
title: '创建时间'
}
]
const searchFormOptions: TableProps["searchFormOptions"] = {
name: {
type: 'input',
label: '名称'
}, code: {
type: 'input',
label: '代码'
}, isEnable: {
type: 'select',
label: '是否启用',
options: [
{
value: null,
label: '全部'
}, ...enumSelectNodes('IsEnable')
]
}, checkStatus: {
type: 'select',
label: '审核状态',
options: [
{
value: null,
label: '全部'
}, ...enumSelectNodes('CheckStatus')
]
}
}
</script>
<style scoped lang="scss">
</style>

View File

@ -0,0 +1,89 @@
<template>
<TableProMax
ref="tableRef"
:request-api="reqApi"
:columns="columns"
:searchFormOptions="searchFormOptions"
>
</TableProMax>
</template>
<script setup lang="ts">
import TableProMax from "@/components/table/TableProMax.vue";
import {TableProMaxProps} from "@/types/components/table";
import {SecurityUnitPagerQueryParams, SecurityUnitPagerVo} from "@/types/views/unitManage/securityUnit.ts";
import api from "@/axios";
import {ref} from "vue";
import {ComponentExposed} from "vue-component-type-helpers";
import {enumSelectNodes} from "@/config/dict.ts";
type TableProps = TableProMaxProps<SecurityUnitPagerVo, SecurityUnitPagerQueryParams>
const tableRef = ref<ComponentExposed<typeof TableProMax>>(null!)
const reqApi: TableProps['requestApi'] = (params) => api.post('/securityUnit/pager', params)
const columns: TableProps['columns'] = [
{
dataIndex: 'name',
title: '名称'
}, {
dataIndex: 'socialCode',
title: '社会编码'
}, {
dataIndex: 'businessLicense',
title: '印业执照'
}, {
dataIndex: 'legalPersonInfo',
title: '法人信息'
}, {
dataIndex: 'provinceName',
title: '行政区划',
customRender: ({record}) => [record.provinceName, record.cityName, record.districtsName, record.streetName].filter(Boolean).join('/')
}, {
dataIndex: 'nature',
title: '性质'
}, {
dataIndex: 'isEnable',
title: '是否启用'
}, {
dataIndex: 'checkStatus',
title: '审核状态'
}, {
dataIndex: 'createTime',
title: '创建时间'
}
]
const searchFormOptions: TableProps["searchFormOptions"] = {
name: {
type: 'input',
label: '名称'
}, socialCode: {
type: 'input',
label: '社会编码'
}, isEnable: {
type: 'select',
label: '是否启用',
options: [
{
value: null,
label: '全部'
}, ...enumSelectNodes('IsEnable')
]
}, checkStatus: {
type: 'select',
label: '审核状态',
options: [
{
value: null,
label: '全部'
}, ...enumSelectNodes('CheckStatus')
]
}
}
</script>
<style scoped lang="scss">
</style>

View File

@ -0,0 +1,11 @@
<script setup lang="ts">
</script>
<template>
123
</template>
<style scoped lang="scss">
</style>

View File

@ -11,6 +11,10 @@ interface ImportMetaEnv {
readonly VITE_APP_BASE_API: string; readonly VITE_APP_BASE_API: string;
readonly VITE_APP_PROXY_URL: string; readonly VITE_APP_PROXY_URL: string;
// minio
readonly VITE_APP_MINIO_URL: string
readonly VITE_APP_MINIO_BUCKET: string
// RSA公钥 // RSA公钥
readonly VITE_APP_RSA_PUBLIC_KEY: string; readonly VITE_APP_RSA_PUBLIC_KEY: string;
} }

View File

@ -18,7 +18,7 @@
"jsx": "preserve", "jsx": "preserve",
"jsxImportSource": "vue", "jsxImportSource": "vue",
/* Linting */ /* Linting */
"strict": true, "strict": false,
"noUnusedLocals": true, "noUnusedLocals": true,
"noUnusedParameters": true, "noUnusedParameters": true,
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,

View File

@ -13,7 +13,7 @@
"moduleDetection": "force", "moduleDetection": "force",
"noEmit": true, "noEmit": true,
/* Linting */ /* Linting */
"strict": true, "strict": false,
"noUnusedLocals": true, "noUnusedLocals": true,
"noUnusedParameters": true, "noUnusedParameters": true,
"noFallthroughCasesInSwitch": true "noFallthroughCasesInSwitch": true