Browse Source

feat:新增车系树

master
tanzs 1 week ago
parent
commit
b7fdd763bd
21 changed files with 1495 additions and 24 deletions
  1. +298
    -0
      jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/controller/AppCarTreeController.java
  2. +73
    -0
      jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/entity/AppCarTree.java
  3. +35
    -0
      jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/mapper/AppCarTreeMapper.java
  4. +25
    -0
      jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/mapper/xml/AppCarTreeMapper.xml
  5. +74
    -0
      jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/service/IAppCarTreeService.java
  6. +219
    -0
      jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/service/impl/AppCarTreeServiceImpl.java
  7. +85
    -0
      jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/vue3/AppCarTree.api.ts
  8. +83
    -0
      jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/vue3/AppCarTree.data.ts
  9. +335
    -0
      jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/vue3/AppCarTreeList.vue
  10. +26
    -0
      jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/vue3/V20250219_1__menu_insert_AppCarTree.sql
  11. +70
    -0
      jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/vue3/components/AppCarTreeForm.vue
  12. +117
    -0
      jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/vue3/components/AppCarTreeModal.vue
  13. +1
    -1
      jeecg-module-demo/src/main/java/org/jeecg/modules/sysMiniapp/store/controller/AppStoreController.java
  14. +12
    -3
      jeecg-module-demo/src/main/java/org/jeecg/modules/sysMiniapp/store/entity/AppStore.java
  15. +1
    -1
      jeecg-module-demo/src/main/java/org/jeecg/modules/sysMiniapp/store/mapper/AppStoreMapper.java
  16. +1
    -1
      jeecg-module-demo/src/main/java/org/jeecg/modules/sysMiniapp/store/service/IAppStoreService.java
  17. +1
    -1
      jeecg-module-demo/src/main/java/org/jeecg/modules/sysMiniapp/store/service/impl/AppStoreServiceImpl.java
  18. +6
    -0
      jeecg-module-demo/src/main/java/org/jeecg/modules/sysMiniapp/store/uniapp/AppStoreForm.vue
  19. +19
    -4
      jeecg-module-demo/src/main/java/org/jeecg/modules/sysMiniapp/store/vue3/AppStore.data.ts
  20. +8
    -8
      jeecg-module-demo/src/main/java/org/jeecg/modules/sysMiniapp/store/vue3/V20250219_1__menu_insert_AppStore.sql
  21. +6
    -5
      jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/utils/BaiduOCRUtil.java

+ 298
- 0
jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/controller/AppCarTreeController.java View File

@ -0,0 +1,298 @@
package org.jeecg.modules.demo.car.controller;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.system.vo.SelectTreeModel;
import org.jeecg.modules.demo.car.entity.AppCarTree;
import org.jeecg.modules.demo.car.service.IAppCarTreeService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.jeecg.common.system.base.controller.JeecgController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSON;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.apache.shiro.authz.annotation.RequiresPermissions;
/**
* @Description: 汽车品牌
* @Author: jeecg-boot
* @Date: 2025-02-19
* @Version: V1.0
*/
@Api(tags="汽车品牌")
@RestController
@RequestMapping("/car/appCarTree")
@Slf4j
public class AppCarTreeController extends JeecgController<AppCarTree, IAppCarTreeService>{
@Autowired
private IAppCarTreeService appCarTreeService;
/**
* 分页列表查询
*
* @param appCarTree
* @param pageNo
* @param pageSize
* @param req
* @return
*/
//@AutoLog(value = "汽车品牌-分页列表查询")
@ApiOperation(value="汽车品牌-分页列表查询", notes="汽车品牌-分页列表查询")
@GetMapping(value = "/rootList")
public Result<IPage<AppCarTree>> queryPageList(AppCarTree appCarTree,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
String hasQuery = req.getParameter("hasQuery");
if(hasQuery != null && "true".equals(hasQuery)){
QueryWrapper<AppCarTree> queryWrapper = QueryGenerator.initQueryWrapper(appCarTree, req.getParameterMap());
List<AppCarTree> list = appCarTreeService.queryTreeListNoPage(queryWrapper);
IPage<AppCarTree> pageList = new Page<>(1, 10, list.size());
pageList.setRecords(list);
return Result.OK(pageList);
}else{
String parentId = appCarTree.getPid();
if (oConvertUtils.isEmpty(parentId)) {
parentId = "0";
}
appCarTree.setPid(null);
QueryWrapper<AppCarTree> queryWrapper = QueryGenerator.initQueryWrapper(appCarTree, req.getParameterMap());
// 使用 eq 防止模糊查询
queryWrapper.eq("pid", parentId);
Page<AppCarTree> page = new Page<AppCarTree>(pageNo, pageSize);
IPage<AppCarTree> pageList = appCarTreeService.page(page, queryWrapper);
return Result.OK(pageList);
}
}
/**
* vue3专用加载节点的子数据
*
* @param pid
* @return
*/
@RequestMapping(value = "/loadTreeChildren", method = RequestMethod.GET)
public Result<List<SelectTreeModel>> loadTreeChildren(@RequestParam(name = "pid") String pid) {
Result<List<SelectTreeModel>> result = new Result<>();
try {
List<SelectTreeModel> ls = appCarTreeService.queryListByPid(pid);
result.setResult(ls);
result.setSuccess(true);
} catch (Exception e) {
e.printStackTrace();
result.setMessage(e.getMessage());
result.setSuccess(false);
}
return result;
}
/**
* vue3专用加载一级节点/如果是同步 则所有数据
*
* @param async
* @param pcode
* @return
*/
@RequestMapping(value = "/loadTreeRoot", method = RequestMethod.GET)
public Result<List<SelectTreeModel>> loadTreeRoot(@RequestParam(name = "async") Boolean async, @RequestParam(name = "pcode") String pcode) {
Result<List<SelectTreeModel>> result = new Result<>();
try {
List<SelectTreeModel> ls = appCarTreeService.queryListByCode(pcode);
if (!async) {
loadAllChildren(ls);
}
result.setResult(ls);
result.setSuccess(true);
} catch (Exception e) {
e.printStackTrace();
result.setMessage(e.getMessage());
result.setSuccess(false);
}
return result;
}
/**
* vue3专用递归求子节点 同步加载用到
*
* @param ls
*/
private void loadAllChildren(List<SelectTreeModel> ls) {
for (SelectTreeModel tsm : ls) {
List<SelectTreeModel> temp = appCarTreeService.queryListByPid(tsm.getKey());
if (temp != null && temp.size() > 0) {
tsm.setChildren(temp);
loadAllChildren(temp);
}
}
}
/**
* 获取子数据
* @param appCarTree
* @param req
* @return
*/
//@AutoLog(value = "汽车品牌-获取子数据")
@ApiOperation(value="汽车品牌-获取子数据", notes="汽车品牌-获取子数据")
@GetMapping(value = "/childList")
public Result<IPage<AppCarTree>> queryPageList(AppCarTree appCarTree,HttpServletRequest req) {
QueryWrapper<AppCarTree> queryWrapper = QueryGenerator.initQueryWrapper(appCarTree, req.getParameterMap());
List<AppCarTree> list = appCarTreeService.list(queryWrapper);
IPage<AppCarTree> pageList = new Page<>(1, 10, list.size());
pageList.setRecords(list);
return Result.OK(pageList);
}
/**
* 批量查询子节点
* @param parentIds 父ID多个采用半角逗号分割
* @return 返回 IPage
* @param parentIds
* @return
*/
//@AutoLog(value = "汽车品牌-批量获取子数据")
@ApiOperation(value="汽车品牌-批量获取子数据", notes="汽车品牌-批量获取子数据")
@GetMapping("/getChildListBatch")
public Result getChildListBatch(@RequestParam("parentIds") String parentIds) {
try {
QueryWrapper<AppCarTree> queryWrapper = new QueryWrapper<>();
List<String> parentIdList = Arrays.asList(parentIds.split(","));
queryWrapper.in("pid", parentIdList);
List<AppCarTree> list = appCarTreeService.list(queryWrapper);
IPage<AppCarTree> pageList = new Page<>(1, 10, list.size());
pageList.setRecords(list);
return Result.OK(pageList);
} catch (Exception e) {
log.error(e.getMessage(), e);
return Result.error("批量查询子节点失败:" + e.getMessage());
}
}
/**
* 添加
*
* @param appCarTree
* @return
*/
@AutoLog(value = "汽车品牌-添加")
@ApiOperation(value="汽车品牌-添加", notes="汽车品牌-添加")
@RequiresPermissions("car:app_car_tree:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody AppCarTree appCarTree) {
appCarTreeService.addAppCarTree(appCarTree);
return Result.OK("添加成功!");
}
/**
* 编辑
*
* @param appCarTree
* @return
*/
@AutoLog(value = "汽车品牌-编辑")
@ApiOperation(value="汽车品牌-编辑", notes="汽车品牌-编辑")
@RequiresPermissions("car:app_car_tree:edit")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<String> edit(@RequestBody AppCarTree appCarTree) {
appCarTreeService.updateAppCarTree(appCarTree);
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
@AutoLog(value = "汽车品牌-通过id删除")
@ApiOperation(value="汽车品牌-通过id删除", notes="汽车品牌-通过id删除")
@RequiresPermissions("car:app_car_tree:delete")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
appCarTreeService.deleteAppCarTree(id);
return Result.OK("删除成功!");
}
/**
* 批量删除
*
* @param ids
* @return
*/
@AutoLog(value = "汽车品牌-批量删除")
@ApiOperation(value="汽车品牌-批量删除", notes="汽车品牌-批量删除")
@RequiresPermissions("car:app_car_tree:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.appCarTreeService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
/**
* 通过id查询
*
* @param id
* @return
*/
//@AutoLog(value = "汽车品牌-通过id查询")
@ApiOperation(value="汽车品牌-通过id查询", notes="汽车品牌-通过id查询")
@GetMapping(value = "/queryById")
public Result<AppCarTree> queryById(@RequestParam(name="id",required=true) String id) {
AppCarTree appCarTree = appCarTreeService.getById(id);
if(appCarTree==null) {
return Result.error("未找到对应数据");
}
return Result.OK(appCarTree);
}
/**
* 导出excel
*
* @param request
* @param appCarTree
*/
@RequiresPermissions("car:app_car_tree:exportXls")
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, AppCarTree appCarTree) {
return super.exportXls(request, appCarTree, AppCarTree.class, "汽车品牌");
}
/**
* 通过excel导入数据
*
* @param request
* @param response
* @return
*/
@RequiresPermissions("car:app_car_tree:importExcel")
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, AppCarTree.class);
}
}

+ 73
- 0
jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/entity/AppCarTree.java View File

@ -0,0 +1,73 @@
package org.jeecg.modules.demo.car.entity;
import java.io.Serializable;
import java.util.Date;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableLogic;
import org.jeecg.common.constant.ProvinceCityArea;
import org.jeecg.common.util.SpringContextUtils;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecg.common.aspect.annotation.Dict;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.UnsupportedEncodingException;
/**
* @Description: 汽车品牌
* @Author: jeecg-boot
* @Date: 2025-02-19
* @Version: V1.0
*/
@Data
@TableName("app_car_tree")
@ApiModel(value="app_car_tree对象", description="汽车品牌")
public class AppCarTree implements Serializable {
private static final long serialVersionUID = 1L;
/**主键*/
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "主键")
private java.lang.String id;
/**父级节点*/
@Excel(name = "父级节点", width = 15)
@ApiModelProperty(value = "父级节点")
private java.lang.String pid;
/**是否有子节点*/
@Excel(name = "是否有子节点", width = 15, dicCode = "yn")
@Dict(dicCode = "yn")
@ApiModelProperty(value = "是否有子节点")
private java.lang.String hasChild;
/**名称*/
@Excel(name = "名称", width = 15)
@ApiModelProperty(value = "名称")
private java.lang.String name;
/**描述*/
@Excel(name = "描述", width = 15)
@ApiModelProperty(value = "描述")
private java.lang.String description;
/**创建人*/
@ApiModelProperty(value = "创建人")
private java.lang.String createBy;
/**创建日期*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "创建日期")
private java.util.Date createTime;
/**更新人*/
@ApiModelProperty(value = "更新人")
private java.lang.String updateBy;
/**更新日期*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "更新日期")
private java.util.Date updateTime;
/**所属部门*/
@ApiModelProperty(value = "所属部门")
private java.lang.String sysOrgCode;
}

+ 35
- 0
jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/mapper/AppCarTreeMapper.java View File

@ -0,0 +1,35 @@
package org.jeecg.modules.demo.car.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.jeecg.common.system.vo.SelectTreeModel;
import org.jeecg.modules.demo.car.entity.AppCarTree;
import java.util.List;
import java.util.Map;
/**
* @Description: 汽车品牌
* @Author: jeecg-boot
* @Date: 2025-02-19
* @Version: V1.0
*/
public interface AppCarTreeMapper extends BaseMapper<AppCarTree> {
/**
* 编辑节点状态
* @param id
* @param status
*/
void updateTreeNodeStatus(@Param("id") String id,@Param("status") String status);
/**
* vue3专用根据父级ID查询树节点数据
*
* @param pid
* @param query
* @return
*/
List<SelectTreeModel> queryListByPid(@Param("pid") String pid, @Param("query") Map<String, String> query);
}

+ 25
- 0
jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/mapper/xml/AppCarTreeMapper.xml View File

@ -0,0 +1,25 @@
<?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="org.jeecg.modules.demo.car.mapper.AppCarTreeMapper">
<update id="updateTreeNodeStatus" parameterType="java.lang.String">
update app_car_tree set has_child = #{status} where id = #{id}
</update>
<!-- 【vue3专用】 -->
<select id="queryListByPid" parameterType="java.lang.Object" resultType="org.jeecg.common.system.vo.SelectTreeModel">
select
id as "key",
name as "title",
(case when has_child = '1' then 0 else 1 end) as isLeaf,
pid as parentId
from app_car_tree
where pid = #{pid}
<if test="query != null">
<foreach collection="query.entrySet()" item="value" index="key">
and ${key} = #{value}
</foreach>
</if>
</select>
</mapper>

+ 74
- 0
jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/service/IAppCarTreeService.java View File

@ -0,0 +1,74 @@
package org.jeecg.modules.demo.car.service;
import org.jeecg.common.system.vo.SelectTreeModel;
import org.jeecg.modules.demo.car.entity.AppCarTree;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.exception.JeecgBootException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import java.util.List;
/**
* @Description: 汽车品牌
* @Author: jeecg-boot
* @Date: 2025-02-19
* @Version: V1.0
*/
public interface IAppCarTreeService extends IService<AppCarTree> {
/**根节点父ID的值*/
public static final String ROOT_PID_VALUE = "0";
/**树节点有子节点状态值*/
public static final String HASCHILD = "1";
/**树节点无子节点状态值*/
public static final String NOCHILD = "0";
/**
* 新增节点
*
* @param appCarTree
*/
void addAppCarTree(AppCarTree appCarTree);
/**
* 修改节点
*
* @param appCarTree
* @throws JeecgBootException
*/
void updateAppCarTree(AppCarTree appCarTree) throws JeecgBootException;
/**
* 删除节点
*
* @param id
* @throws JeecgBootException
*/
void deleteAppCarTree(String id) throws JeecgBootException;
/**
* 查询所有数据无分页
*
* @param queryWrapper
* @return List<AppCarTree>
*/
List<AppCarTree> queryTreeListNoPage(QueryWrapper<AppCarTree> queryWrapper);
/**
* vue3专用根据父级编码加载分类字典的数据
*
* @param parentCode
* @return
*/
List<SelectTreeModel> queryListByCode(String parentCode);
/**
* vue3专用根据pid查询子节点集合
*
* @param pid
* @return
*/
List<SelectTreeModel> queryListByPid(String pid);
}

+ 219
- 0
jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/service/impl/AppCarTreeServiceImpl.java View File

@ -0,0 +1,219 @@
package org.jeecg.modules.demo.car.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.system.vo.SelectTreeModel;
import org.jeecg.modules.demo.car.entity.AppCarTree;
import org.jeecg.modules.demo.car.mapper.AppCarTreeMapper;
import org.jeecg.modules.demo.car.service.IAppCarTreeService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
/**
* @Description: 汽车品牌
* @Author: jeecg-boot
* @Date: 2025-02-19
* @Version: V1.0
*/
@Service
public class AppCarTreeServiceImpl extends ServiceImpl<AppCarTreeMapper, AppCarTree> implements IAppCarTreeService {
@Override
public void addAppCarTree(AppCarTree appCarTree) {
//新增时设置hasChild为0
appCarTree.setHasChild(IAppCarTreeService.NOCHILD);
if(oConvertUtils.isEmpty(appCarTree.getPid())){
appCarTree.setPid(IAppCarTreeService.ROOT_PID_VALUE);
}else{
//如果当前节点父ID不为空 则设置父节点的hasChildren 为1
AppCarTree parent = baseMapper.selectById(appCarTree.getPid());
if(parent!=null && !"1".equals(parent.getHasChild())){
parent.setHasChild("1");
baseMapper.updateById(parent);
}
}
baseMapper.insert(appCarTree);
}
@Override
public void updateAppCarTree(AppCarTree appCarTree) {
AppCarTree entity = this.getById(appCarTree.getId());
if(entity==null) {
throw new JeecgBootException("未找到对应实体");
}
String old_pid = entity.getPid();
String new_pid = appCarTree.getPid();
if(!old_pid.equals(new_pid)) {
updateOldParentNode(old_pid);
if(oConvertUtils.isEmpty(new_pid)){
appCarTree.setPid(IAppCarTreeService.ROOT_PID_VALUE);
}
if(!IAppCarTreeService.ROOT_PID_VALUE.equals(appCarTree.getPid())) {
baseMapper.updateTreeNodeStatus(appCarTree.getPid(), IAppCarTreeService.HASCHILD);
}
}
baseMapper.updateById(appCarTree);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteAppCarTree(String id) throws JeecgBootException {
//查询选中节点下所有子节点一并删除
id = this.queryTreeChildIds(id);
if(id.indexOf(",")>0) {
StringBuffer sb = new StringBuffer();
String[] idArr = id.split(",");
for (String idVal : idArr) {
if(idVal != null){
AppCarTree appCarTree = this.getById(idVal);
String pidVal = appCarTree.getPid();
//查询此节点上一级是否还有其他子节点
List<AppCarTree> dataList = baseMapper.selectList(new QueryWrapper<AppCarTree>().eq("pid", pidVal).notIn("id",Arrays.asList(idArr)));
boolean flag = (dataList == null || dataList.size() == 0) && !Arrays.asList(idArr).contains(pidVal) && !sb.toString().contains(pidVal);
if(flag){
//如果当前节点原本有子节点 现在木有了更新状态
sb.append(pidVal).append(",");
}
}
}
//批量删除节点
baseMapper.deleteBatchIds(Arrays.asList(idArr));
//修改已无子节点的标识
String[] pidArr = sb.toString().split(",");
for(String pid : pidArr){
this.updateOldParentNode(pid);
}
}else{
AppCarTree appCarTree = this.getById(id);
if(appCarTree==null) {
throw new JeecgBootException("未找到对应实体");
}
updateOldParentNode(appCarTree.getPid());
baseMapper.deleteById(id);
}
}
@Override
public List<AppCarTree> queryTreeListNoPage(QueryWrapper<AppCarTree> queryWrapper) {
List<AppCarTree> dataList = baseMapper.selectList(queryWrapper);
List<AppCarTree> mapList = new ArrayList<>();
for(AppCarTree data : dataList){
String pidVal = data.getPid();
//递归查询子节点的根节点
if(pidVal != null && !IAppCarTreeService.NOCHILD.equals(pidVal)){
AppCarTree rootVal = this.getTreeRoot(pidVal);
if(rootVal != null && !mapList.contains(rootVal)){
mapList.add(rootVal);
}
}else{
if(!mapList.contains(data)){
mapList.add(data);
}
}
}
return mapList;
}
@Override
public List<SelectTreeModel> queryListByCode(String parentCode) {
String pid = ROOT_PID_VALUE;
if (oConvertUtils.isNotEmpty(parentCode)) {
LambdaQueryWrapper<AppCarTree> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(AppCarTree::getPid, parentCode);
List<AppCarTree> list = baseMapper.selectList(queryWrapper);
if (list == null || list.size() == 0) {
throw new JeecgBootException("该编码【" + parentCode + "】不存在,请核实!");
}
if (list.size() > 1) {
throw new JeecgBootException("该编码【" + parentCode + "】存在多个,请核实!");
}
pid = list.get(0).getId();
}
return baseMapper.queryListByPid(pid, null);
}
@Override
public List<SelectTreeModel> queryListByPid(String pid) {
if (oConvertUtils.isEmpty(pid)) {
pid = ROOT_PID_VALUE;
}
return baseMapper.queryListByPid(pid, null);
}
/**
* 根据所传pid查询旧的父级节点的子节点并修改相应状态值
* @param pid
*/
private void updateOldParentNode(String pid) {
if(!IAppCarTreeService.ROOT_PID_VALUE.equals(pid)) {
Long count = baseMapper.selectCount(new QueryWrapper<AppCarTree>().eq("pid", pid));
if(count==null || count<=1) {
baseMapper.updateTreeNodeStatus(pid, IAppCarTreeService.NOCHILD);
}
}
}
/**
* 递归查询节点的根节点
* @param pidVal
* @return
*/
private AppCarTree getTreeRoot(String pidVal){
AppCarTree data = baseMapper.selectById(pidVal);
if(data != null && !IAppCarTreeService.ROOT_PID_VALUE.equals(data.getPid())){
return this.getTreeRoot(data.getPid());
}else{
return data;
}
}
/**
* 根据id查询所有子节点id
* @param ids
* @return
*/
private String queryTreeChildIds(String ids) {
//获取id数组
String[] idArr = ids.split(",");
StringBuffer sb = new StringBuffer();
for (String pidVal : idArr) {
if(pidVal != null){
if(!sb.toString().contains(pidVal)){
if(sb.toString().length() > 0){
sb.append(",");
}
sb.append(pidVal);
this.getTreeChildIds(pidVal,sb);
}
}
}
return sb.toString();
}
/**
* 递归查询所有子节点
* @param pidVal
* @param sb
* @return
*/
private StringBuffer getTreeChildIds(String pidVal,StringBuffer sb){
List<AppCarTree> dataList = baseMapper.selectList(new QueryWrapper<AppCarTree>().eq("pid", pidVal));
if(dataList != null && dataList.size()>0){
for(AppCarTree tree : dataList) {
if(!sb.toString().contains(tree.getId())){
sb.append(",").append(tree.getId());
}
this.getTreeChildIds(tree.getId(),sb);
}
}
return sb;
}
}

+ 85
- 0
jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/vue3/AppCarTree.api.ts View File

@ -0,0 +1,85 @@
import {defHttp} from "/@/utils/http/axios";
import { useMessage } from "/@/hooks/web/useMessage";
const { createConfirm } = useMessage();
enum Api {
list = '/car/appCarTree/rootList',
save='/car/appCarTree/add',
edit='/car/appCarTree/edit',
deleteAppCarTree = '/car/appCarTree/delete',
importExcel = '/car/appCarTree/importExcel',
exportXls = '/car/appCarTree/exportXls',
loadTreeData = '/car/appCarTree/loadTreeRoot',
getChildList = '/car/appCarTree/childList',
getChildListBatch = '/car/appCarTree/getChildListBatch',
}
/**
* api
* @param params
*/
export const getExportUrl = Api.exportXls;
/**
* api
* @param params
*/
export const getImportUrl = Api.importExcel;
/**
*
* @param params
*/
export const list = (params) =>
defHttp.get({url: Api.list, params});
/**
*
*/
export const deleteAppCarTree = (params,handleSuccess) => {
return defHttp.delete({url: Api.deleteAppCarTree, params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
/**
*
* @param params
*/
export const batchDeleteAppCarTree = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({url: Api.deleteAppCarTree, data: params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
});
}
/**
*
* @param params
*/
export const saveOrUpdateDict = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({url: url, params});
}
/**
*
* @param params
*/
export const loadTreeData = (params) =>
defHttp.get({url: Api.loadTreeData,params});
/**
*
* @param params
*/
export const getChildList = (params) =>
defHttp.get({url: Api.getChildList, params});
/**
*
* @param params
*/
export const getChildListBatch = (params) =>
defHttp.get({url: Api.getChildListBatch, params},{isTransformResponse:false});

+ 83
- 0
jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/vue3/AppCarTree.data.ts View File

@ -0,0 +1,83 @@
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
import { getWeekMonthQuarterYear } from '/@/utils';
//列表数据
export const columns: BasicColumn[] = [
{
title: '名称',
align: 'left',
dataIndex: 'name'
},
{
title: '描述',
align: 'center',
dataIndex: 'description'
},
];
//查询数据
export const searchFormSchema: FormSchema[] = [
{
label: "名称",
field: "name",
component: 'JInput',
},
{
label: "描述",
field: "description",
component: 'JInput',
},
];
//表单数据
export const formSchema: FormSchema[] = [
{
label: '父级节点',
field: 'pid',
component: 'JTreeSelect',
componentProps: {
dict: "app_car_tree,name,id",
pidField: "pid",
pidValue: "0",
hasChildField: "has_child",
},
},
{
label: '名称',
field: 'name',
component: 'Input',
dynamicRules: ({model,schema}) => {
return [
{ required: true, message: '请输入名称!'},
];
},
},
{
label: '描述',
field: 'description',
component: 'Input',
},
// TODO 主键隐藏字段,目前写死为ID
{
label: '',
field: 'id',
component: 'Input',
show: false
},
];
// 高级查询数据
export const superQuerySchema = {
name: {title: '名称',order: 1,view: 'text', type: 'string',},
description: {title: '描述',order: 2,view: 'text', type: 'string',},
};
/**
* formSchema
* @param param
*/
export function getBpmFormSchema(_formData): FormSchema[]{
// 默认和原始表单保持一致 如果流程中配置了权限数据,这里需要单独处理formSchema
return formSchema;
}

+ 335
- 0
jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/vue3/AppCarTreeList.vue View File

@ -0,0 +1,335 @@
<template>
<div>
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection" :expandedRowKeys="expandedRowKeys" @expand="handleExpand" @fetch-success="onFetchSuccess">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" v-auth="'car:app_car_tree:add'" @click="handleCreate" preIcon="ant-design:plus-outlined"> 新增</a-button>
<a-button type="primary" v-auth="'car:app_car_tree:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
<j-upload-button type="primary" v-auth="'car:app_car_tree:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
<a-dropdown v-if="selectedRowKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined"></Icon>
删除
</a-menu-item>
</a-menu>
</template>
<a-button v-auth="'car:app_car_tree:deleteBatch'">批量操作
<Icon icon="ant-design:down-outlined"></Icon>
</a-button>
</a-dropdown>
<!-- 高级查询 -->
<super-query :config="superQueryConfig" @search="handleSuperQuery" />
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
</template>
<!--字段回显插槽-->
<template v-slot:bodyCell="{ column, record, index, text }">
</template>
</BasicTable>
<!--字典弹窗-->
<AppCarTreeModal @register="registerModal" @success="handleSuccess"/>
</div>
</template>
<script lang="ts" name="car-appCarTree" setup>
//ts
import {ref, reactive, computed, unref, toRaw, nextTick} from 'vue';
import {BasicTable, TableAction} from '/@/components/Table';
import {useModal} from '/@/components/Modal';
import { useListPage } from '/@/hooks/system/useListPage'
import AppCarTreeModal from './components/AppCarTreeModal.vue';
import {columns, searchFormSchema, superQuerySchema} from './AppCarTree.data';
import { downloadFile } from '/@/utils/common/renderUtils';
import {list, deleteAppCarTree, batchDeleteAppCarTree, getExportUrl,getImportUrl, getChildList,getChildListBatch} from './AppCarTree.api';
const queryParam = reactive<any>({});
const expandedRowKeys = ref([]);
//model
const [registerModal, {openModal}] = useModal();
//table
const { prefixCls,tableContext,onExportXls,onImportXls } = useListPage({
tableProps:{
api: list,
title: '汽车品牌',
columns,
canResize:false,
isTreeTable: true,
formConfig: {
//labelWidth: 120,
schemas: searchFormSchema,
autoSubmitOnEnter:true,
showAdvancedButton:true,
fieldMapToNumber: [
],
fieldMapToTime: [
],
},
actionColumn: {
width: 240,
fixed:'right'
},
beforeFetch: (params) => {
params.hasQuery = "true";
return Object.assign(params, queryParam);
},
},
exportConfig: {
name:"汽车品牌",
url: getExportUrl,
params: queryParam,
},
importConfig: {
url: getImportUrl,
success: importSuccess
},
})
const [registerTable, {reload, collapseAll, updateTableDataRecord, findTableDataRecord,getDataSource},{ rowSelection, selectedRowKeys }] = tableContext
//
const superQueryConfig = reactive(superQuerySchema);
/**
* 高级查询事件
*/
function handleSuperQuery(params) {
Object.keys(params).map((k) => {
queryParam[k] = params[k];
});
reload();
}
/**
* 新增事件
*/
function handleCreate() {
openModal(true, {
isUpdate: false,
});
}
/**
* 编辑事件
*/
async function handleEdit(record) {
openModal(true, {
record,
isUpdate: true,
});
}
/**
* 详情
*/
async function handleDetail(record) {
openModal(true, {
record,
isUpdate: true,
hideFooter: true,
});
}
/**
* 删除事件
*/
async function handleDelete(record) {
await deleteAppCarTree({id: record.id}, importSuccess);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
const ids = selectedRowKeys.value.filter(item => !item.includes('loadChild'))
await batchDeleteAppCarTree({id: ids}, importSuccess);
}
/**
* 导入
*/
function importSuccess() {
(selectedRowKeys.value = []) && reload();
}
/**
* 添加下级
*/
function handleAddSub(record) {
openModal(true, {
record,
isUpdate: false,
});
}
/**
* 成功回调
*/
async function handleSuccess({isUpdate, values, expandedArr, changeParent}) {
if (isUpdate) {
if (changeParent) {
reload();
} else {
let data = await list({ id: values.id, pageSize: 1, pageNo: 1, pid: values['pid'] });
if (data && data.records && data.records.length > 0) {
//
updateTableDataRecord(values.id, data.records[0]);
}else{
updateTableDataRecord(values.id, values);
}
}
} else {
if(!values['id'] || !values['pid']){
//
reload();
}else{
//
expandedRowKeys.value = [];
for (let key of unref(expandedArr)) {
await expandTreeNode(key)
}
}
}
}
/**
* 接口请求成功后回调
*/
function onFetchSuccess(result) {
getDataByResult(result.items)&&loadDataByExpandedRows();
}
/**
* 根据已展开的行查询数据用于保存后刷新时异步加载子级的数据
*/
async function loadDataByExpandedRows() {
if (unref(expandedRowKeys).length > 0) {
const res = await getChildListBatch({ parentIds: unref(expandedRowKeys).join(',')});
if (res.success && res.result.records.length>0) {
//
let records = res.result.records
const listMap = new Map();
for (let item of records) {
let pid = item['pid'];
if (unref(expandedRowKeys).includes(pid)) {
let mapList = listMap.get(pid);
if (mapList == null) {
mapList = [];
}
mapList.push(item);
listMap.set(pid, mapList);
}
}
let childrenMap = listMap;
let fn = (list) => {
if(list) {
list.forEach(data => {
if (unref(expandedRowKeys).includes(data.id)) {
data.children = getDataByResult(childrenMap.get(data.id))
fn(data.children)
}
})
}
};
fn(getDataSource())
}
}
}
/**
* 处理数据集
*/
function getDataByResult(result){
if(result && result.length>0){
return result.map(item=>{
//
if(item["hasChild"]=='1'){
let loadChild = { id: item.id+'_loadChild', name: 'loading...', isLoading: true }
item.children = [loadChild]
}
return item
})
}
}
/**
*树节点展开合并
* */
async function handleExpand(expanded, record) {
// (expanded)(children)(isLoading)
if (expanded) {
expandedRowKeys.value.push(record.id)
if (record.children.length > 0 && !!record.children[0].isLoading) {
let result = await getChildList({pid: record.id});
result=result.records?result.records:result;
if (result && result.length > 0) {
record.children = getDataByResult(result);
} else {
record.children = null
record.hasChild = '0'
}
}
} else {
let keyIndex = expandedRowKeys.value.indexOf(record.id)
if (keyIndex >= 0) {
expandedRowKeys.value.splice(keyIndex, 1);
}
}
}
/**
*操作表格后处理树节点展开合并
* */
async function expandTreeNode(key) {
let record = findTableDataRecord(key)
expandedRowKeys.value.push(key);
let result = await getChildList({pid: key});
if (result && result.length > 0) {
record.children = getDataByResult(result);
} else {
record.children = null
record.hasChild = '0'
}
updateTableDataRecord(key, record);
}
/**
* 操作栏
*/
function getTableAction(record) {
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
auth: 'car:app_car_tree:edit'
},
{
label: '添加下级',
onClick: handleAddSub.bind(null, {pid: record.id}),
}
]
}
/**
* 下拉操作栏
*/
function getDropDownAction(record){
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
}, {
label: '删除',
popConfirm: {
title: '确定删除吗?',
confirm: handleDelete.bind(null, record),
placement: 'topLeft'
},
auth: 'car:app_car_tree:delete'
}
]
}
</script>
<style lang="less" scoped>
:deep(.ant-picker),:deep(.ant-input-number){
width: 100%;
}
</style>

+ 26
- 0
jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/vue3/V20250219_1__menu_insert_AppCarTree.sql View File

@ -0,0 +1,26 @@
-- 注意:该页面对应的前台目录为views/car文件夹下
-- 如果你想更改到其他目录,请修改sql中component字段对应的值
INSERT INTO sys_permission(id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive, hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external)
VALUES ('2025021909297880500', NULL, '汽车品牌', '/car/appCarTreeList', 'miniapp/car/AppCarTreeList', NULL, NULL, 0, NULL, '1', 0.00, 0, NULL, 1, 0, 0, 0, 0, NULL, '1', 0, 0, 'admin', '2025-02-19 21:29:50', NULL, NULL, 0);
-- 权限控制sql
-- 新增
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025021909297880501', '2025021909297880500', '添加汽车品牌', NULL, NULL, 0, NULL, NULL, 2, 'car:app_car_tree:add', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-02-19 21:29:50', NULL, NULL, 0, 0, '1', 0);
-- 编辑
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025021909297880502', '2025021909297880500', '编辑汽车品牌', NULL, NULL, 0, NULL, NULL, 2, 'car:app_car_tree:edit', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-02-19 21:29:50', NULL, NULL, 0, 0, '1', 0);
-- 删除
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025021909297880503', '2025021909297880500', '删除汽车品牌', NULL, NULL, 0, NULL, NULL, 2, 'car:app_car_tree:delete', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-02-19 21:29:50', NULL, NULL, 0, 0, '1', 0);
-- 批量删除
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025021909297880504', '2025021909297880500', '批量删除汽车品牌', NULL, NULL, 0, NULL, NULL, 2, 'car:app_car_tree:deleteBatch', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-02-19 21:29:50', NULL, NULL, 0, 0, '1', 0);
-- 导出excel
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025021909297880505', '2025021909297880500', '导出excel_汽车品牌', NULL, NULL, 0, NULL, NULL, 2, 'car:app_car_tree:exportXls', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-02-19 21:29:50', NULL, NULL, 0, 0, '1', 0);
-- 导入excel
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025021909297880506', '2025021909297880500', '导入excel_汽车品牌', NULL, NULL, 0, NULL, NULL, 2, 'car:app_car_tree:importExcel', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-02-19 21:29:50', NULL, NULL, 0, 0, '1', 0);

+ 70
- 0
jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/vue3/components/AppCarTreeForm.vue View File

@ -0,0 +1,70 @@
<template>
<div style="min-height: 400px">
<BasicForm @register="registerForm"></BasicForm>
<div style="width: 100%;text-align: center" v-if="!formDisabled">
<a-button @click="submitForm" pre-icon="ant-design:check" type="primary"> </a-button>
</div>
</div>
</template>
<script lang="ts">
import {BasicForm, useForm} from '/@/components/Form/index';
import {computed, defineComponent} from 'vue';
import {defHttp} from '/@/utils/http/axios';
import { propTypes } from '/@/utils/propTypes';
import {getBpmFormSchema} from '../AppCarTree.data';
import {saveOrUpdateDict} from '../AppCarTree.api';
export default defineComponent({
name: "AppCarTreeForm",
components:{
BasicForm
},
props:{
formData: propTypes.object.def({}),
formBpm: propTypes.bool.def(true),
},
setup(props){
const [registerForm, { setFieldsValue, setProps, getFieldsValue }] = useForm({
labelWidth: 150,
schemas: getBpmFormSchema(props.formData),
showActionButtonGroup: false,
baseColProps: {span: 24},
});
const formDisabled = computed(()=>{
if(props.formData.disabled === false){
return false;
}
return true;
});
let formData = {};
const queryByIdUrl = '/car/appCarTree/queryById';
async function initFormData(){
let params = {id: props.formData.dataId};
const data = await defHttp.get({url: queryByIdUrl, params});
formData = {...data}
//
await setFieldsValue(formData);
//
await setProps({disabled: formDisabled.value})
}
async function submitForm() {
let data = getFieldsValue();
let params = Object.assign({}, formData, data);
console.log('表单数据', params)
await saveOrUpdateDict(params, true)
}
initFormData();
return {
registerForm,
formDisabled,
submitForm,
}
}
});
</script>

+ 117
- 0
jeecg-module-demo/src/main/java/org/jeecg/modules/demo/car/vue3/components/AppCarTreeModal.vue View File

@ -0,0 +1,117 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :width="800" :title="getTitle" @ok="handleSubmit">
<BasicForm @register="registerForm" name="AppCarTreeForm" />
</BasicModal>
</template>
<script lang="ts" setup>
import {ref, computed, unref} from 'vue';
import {BasicModal, useModalInner} from '/@/components/Modal';
import {BasicForm, useForm} from '/@/components/Form';
import {formSchema} from '../AppCarTree.data';
import {loadTreeData, saveOrUpdateDict} from '../AppCarTree.api';
// emit
const emit = defineEmits(['register', 'success']);
const isUpdate = ref(true);
const isDetail = ref(false);
const expandedRowKeys = ref([]);
const treeData = ref([]);
//
let model:Nullable<Recordable> = null;
//
const [registerForm, { setProps,resetFields, setFieldsValue, validate, updateSchema, scrollToField }] = useForm({
schemas: formSchema,
showActionButtonGroup: false,
baseColProps: {span: 24},
labelCol: {
xs: { span: 24 },
sm: { span: 4 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 18 },
},
});
//
const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
//
await resetFields();
expandedRowKeys.value = [];
setModalProps({confirmLoading: false, minHeight: 80 ,showOkBtn: !!!data?.hideFooter});
isUpdate.value = !!data?.isUpdate;
isDetail.value = !!data?.showFooter;
if (data?.record) {
model = data.record;
//
await setFieldsValue({
...data.record,
});
} else {
model = null;
}
//
treeData.value = await loadTreeData({'async': false,'pcode':''});
//
setProps({ disabled: !!data?.hideFooter })
});
//
const getTitle = computed(() => (!unref(isUpdate) ? '新增' : !unref(isDetail) ? '详情' : '编辑'));
/**
* 根据pid获取展开的节点
* @param pid
* @param arr
*/
function getExpandKeysByPid(pid,arr){
if(pid && arr && arr.length>0){
for(let i=0;i<arr.length;i++){
if(arr[i].key==pid && unref(expandedRowKeys).indexOf(pid)<0){
expandedRowKeys.value.push(arr[i].key);
getExpandKeysByPid(arr[i]['parentId'],unref(treeData))
}else{
getExpandKeysByPid(pid,arr[i].children)
}
}
}
}
//
async function handleSubmit() {
try {
let values = await validate();
setModalProps({confirmLoading: true});
//
await saveOrUpdateDict(values, isUpdate.value);
//
closeModal();
//
await getExpandKeysByPid(values['pid'],unref(treeData))
//(isUpdate:;values:;expandedArr:)
emit('success', {
isUpdate: unref(isUpdate),
values: {...values},
expandedArr: unref(expandedRowKeys).reverse(),
//
changeParent: model != null && (model['pid'] != values['pid']),
});
} catch ({ errorFields }) {
if (errorFields) {
const firstField = errorFields[0];
if (firstField) {
scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
}
}
return Promise.reject(errorFields);
} finally {
setModalProps({confirmLoading: false});
}
}
</script>
<style lang="less" scoped>
/** 时间和数字输入框样式 */
:deep(.ant-input-number) {
width: 100%;
}
:deep(.ant-calendar-picker) {
width: 100%;
}
</style>

+ 1
- 1
jeecg-module-demo/src/main/java/org/jeecg/modules/sysMiniapp/store/controller/AppStoreController.java View File

@ -28,7 +28,7 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
/**
* @Description: 门店管理
* @Author: jeecg-boot
* @Date: 2025-02-16
* @Date: 2025-02-19
* @Version: V1.0
*/
@Api(tags="门店管理")


+ 12
- 3
jeecg-module-demo/src/main/java/org/jeecg/modules/sysMiniapp/store/entity/AppStore.java View File

@ -1,10 +1,15 @@
package org.jeecg.modules.sysMiniapp.store.entity;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableLogic;
import org.jeecg.common.constant.ProvinceCityArea;
import org.jeecg.common.util.SpringContextUtils;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
@ -18,7 +23,7 @@ import lombok.experimental.Accessors;
/**
* @Description: 门店管理
* @Author: jeecg-boot
* @Date: 2025-02-16
* @Date: 2025-02-19
* @Version: V1.0
*/
@Data
@ -30,7 +35,7 @@ public class AppStore implements Serializable {
private static final long serialVersionUID = 1L;
/**主键*/
@TableId(type = IdType.AUTO)
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "主键")
private java.lang.Integer id;
/**门店名称*/
@ -42,6 +47,10 @@ public class AppStore implements Serializable {
@Dict(dicCode = "dict_item_status")
@ApiModelProperty(value = "状态")
private java.lang.Integer status;
/**地址*/
@Excel(name = "地址", width = 15)
@ApiModelProperty(value = "地址")
private java.lang.String address;
/**备注*/
@Excel(name = "备注", width = 15)
@ApiModelProperty(value = "备注")


+ 1
- 1
jeecg-module-demo/src/main/java/org/jeecg/modules/sysMiniapp/store/mapper/AppStoreMapper.java View File

@ -6,7 +6,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @Description: 门店管理
* @Author: jeecg-boot
* @Date: 2025-02-16
* @Date: 2025-02-19
* @Version: V1.0
*/
public interface AppStoreMapper extends BaseMapper<AppStore> {


+ 1
- 1
jeecg-module-demo/src/main/java/org/jeecg/modules/sysMiniapp/store/service/IAppStoreService.java View File

@ -6,7 +6,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
/**
* @Description: 门店管理
* @Author: jeecg-boot
* @Date: 2025-02-16
* @Date: 2025-02-19
* @Version: V1.0
*/
public interface IAppStoreService extends IService<AppStore> {


+ 1
- 1
jeecg-module-demo/src/main/java/org/jeecg/modules/sysMiniapp/store/service/impl/AppStoreServiceImpl.java View File

@ -10,7 +10,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
/**
* @Description: 门店管理
* @Author: jeecg-boot
* @Date: 2025-02-16
* @Date: 2025-02-19
* @Version: V1.0
*/
@Service


+ 6
- 0
jeecg-module-demo/src/main/java/org/jeecg/modules/sysMiniapp/store/uniapp/AppStoreForm.vue View File

@ -20,6 +20,12 @@
<input type="number" placeholder="请输入状态" v-model="model.status"/>
</view>
</view>
<view class="cu-form-group">
<view class="flex align-center">
<view class="title"><text space="ensp">地址</text></view>
<input placeholder="请输入地址" v-model="model.address"/>
</view>
</view>
<view class="cu-form-group">
<view class="flex align-center">
<view class="title"><text space="ensp">备注</text></view>


+ 19
- 4
jeecg-module-demo/src/main/java/org/jeecg/modules/sysMiniapp/store/vue3/AppStore.data.ts View File

@ -16,9 +16,9 @@ export const columns: BasicColumn[] = [
dataIndex: 'status_dictText'
},
{
title: '备注',
title: '地址',
align:"center",
dataIndex: 'remark'
dataIndex: 'address'
},
{
title: '创建日期',
@ -42,6 +42,11 @@ export const searchFormSchema: FormSchema[] = [
},
//colProps: {span: 6},
},
{
label: "地址",
field: "address",
component: 'JInput',
},
];
//表单数据
export const formSchema: FormSchema[] = [
@ -70,6 +75,16 @@ export const formSchema: FormSchema[] = [
];
},
},
{
label: '地址',
field: 'address',
component: 'Input',
dynamicRules: ({model,schema}) => {
return [
{ required: true, message: '请输入地址!'},
];
},
},
{
label: '备注',
field: 'remark',
@ -88,8 +103,8 @@ export const formSchema: FormSchema[] = [
export const superQuerySchema = {
storeName: {title: '门店名称',order: 0,view: 'text', type: 'string',},
status: {title: '状态',order: 1,view: 'number', type: 'number',dictCode: 'dict_item_status',},
remark: {title: '备注',order: 2,view: 'text', type: 'string',},
createTime: {title: '创建日期',order: 3,view: 'datetime', type: 'string',},
address: {title: '地址',order: 2,view: 'text', type: 'string',},
createTime: {title: '创建日期',order: 4,view: 'datetime', type: 'string',},
};
/**


jeecg-module-demo/src/main/java/org/jeecg/modules/sysMiniapp/store/vue3/V20250216_1__menu_insert_AppStore.sql → jeecg-module-demo/src/main/java/org/jeecg/modules/sysMiniapp/store/vue3/V20250219_1__menu_insert_AppStore.sql View File

@ -2,25 +2,25 @@
-- 如果你想更改到其他目录,请修改sql中component字段对应的值
INSERT INTO sys_permission(id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive, hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external)
VALUES ('2025021602224080490', NULL, '门店管理', '/app/appStoreList', 'miniapp/store/AppStoreList', NULL, NULL, 0, NULL, '1', 0.00, 0, NULL, 1, 0, 0, 0, 0, NULL, '1', 0, 0, 'admin', '2025-02-16 14:22:49', NULL, NULL, 0);
INSERT INTO sys_permission(id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive, hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external)
VALUES ('2025021909084040110', NULL, '门店管理', '/store/appStoreList', 'store/AppStoreList', NULL, NULL, 0, NULL, '1', 0.00, 0, NULL, 1, 0, 0, 0, 0, NULL, '1', 0, 0, 'admin', '2025-02-19 21:08:11', NULL, NULL, 0);
-- 权限控制sql
-- 新增
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025021602224080491', '2025021602224080490', '添加门店管理', NULL, NULL, 0, NULL, NULL, 2, 'store:app_store:add', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-02-16 14:22:49', NULL, NULL, 0, 0, '1', 0);
VALUES ('2025021909084040111', '2025021909084040110', '添加门店管理', NULL, NULL, 0, NULL, NULL, 2, 'store:app_store:add', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-02-19 21:08:11', NULL, NULL, 0, 0, '1', 0);
-- 编辑
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025021602224080492', '2025021602224080490', '编辑门店管理', NULL, NULL, 0, NULL, NULL, 2, 'store:app_store:edit', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-02-16 14:22:49', NULL, NULL, 0, 0, '1', 0);
VALUES ('2025021909084040112', '2025021909084040110', '编辑门店管理', NULL, NULL, 0, NULL, NULL, 2, 'store:app_store:edit', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-02-19 21:08:11', NULL, NULL, 0, 0, '1', 0);
-- 删除
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025021602224080493', '2025021602224080490', '删除门店管理', NULL, NULL, 0, NULL, NULL, 2, 'store:app_store:delete', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-02-16 14:22:49', NULL, NULL, 0, 0, '1', 0);
VALUES ('2025021909084040113', '2025021909084040110', '删除门店管理', NULL, NULL, 0, NULL, NULL, 2, 'store:app_store:delete', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-02-19 21:08:11', NULL, NULL, 0, 0, '1', 0);
-- 批量删除
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025021602224080494', '2025021602224080490', '批量删除门店管理', NULL, NULL, 0, NULL, NULL, 2, 'store:app_store:deleteBatch', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-02-16 14:22:49', NULL, NULL, 0, 0, '1', 0);
VALUES ('2025021909084040114', '2025021909084040110', '批量删除门店管理', NULL, NULL, 0, NULL, NULL, 2, 'store:app_store:deleteBatch', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-02-19 21:08:11', NULL, NULL, 0, 0, '1', 0);
-- 导出excel
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025021602224080495', '2025021602224080490', '导出excel_门店管理', NULL, NULL, 0, NULL, NULL, 2, 'store:app_store:exportXls', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-02-16 14:22:49', NULL, NULL, 0, 0, '1', 0);
VALUES ('2025021909084040115', '2025021909084040110', '导出excel_门店管理', NULL, NULL, 0, NULL, NULL, 2, 'store:app_store:exportXls', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-02-19 21:08:11', NULL, NULL, 0, 0, '1', 0);
-- 导入excel
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025021602224080496', '2025021602224080490', '导入excel_门店管理', NULL, NULL, 0, NULL, NULL, 2, 'store:app_store:importExcel', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-02-16 14:22:49', NULL, NULL, 0, 0, '1', 0);
VALUES ('2025021909084040116', '2025021909084040110', '导入excel_门店管理', NULL, NULL, 0, NULL, NULL, 2, 'store:app_store:importExcel', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-02-19 21:08:11', NULL, NULL, 0, 0, '1', 0);

+ 6
- 5
jeecg-module-miniapp/src/main/java/org/jeecg/modules/miniapp/utils/BaiduOCRUtil.java View File

@ -2,6 +2,7 @@ package org.jeecg.modules.miniapp.utils;
import cn.hutool.core.codec.Base64;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
@ -19,8 +20,8 @@ import java.nio.file.Files;
@Slf4j
public class BaiduOCRUtil {
private static final String API_KEY = "ILgowCd9vTRSAEPRPhVvn0Oy"; // API Key
private static final String SECRET_KEY = "pqRPRjUaHvpgupAiPw7YtHaoj2GnE74S"; // Secret Key
private static final String API_KEY = "DtvxZu6pHU7dVzxavJUnLWuQ"; // API Key
private static final String SECRET_KEY = "BqwTCWaTLbICQWTPWcX0DDlLk1zD0nQR"; // Secret Key
private static final String ACCESS_TOKEN_URL = "https://aip.baidubce.com/oauth/2.0/token";
@ -120,7 +121,7 @@ public class BaiduOCRUtil {
private static String makePostRequest(String apiUrl, String accessToken, JSONObject params) {
String url = apiUrl + "?access_token=" + accessToken;
log.info("百度 POST 请求的 URL:" + url);
// log.info("百度 POST 请求的参数:" + params.toString());
log.info("百度 POST 请求的参数:" + params.toString());
String response = HttpRequest.post(url)
.body(jsonToQueryString(params),"application/x-www-form-urlencoded")
.header("Content-Type", "application/x-www-form-urlencoded")
@ -153,8 +154,8 @@ public class BaiduOCRUtil {
*/
public static void main(String[] args) throws IOException {
// 示例调用身份证识别API图片URL
String idCardResultUrl = recognizeIdCardWithImage("/Users/tanzs/Pictures/cert/font.jpg","front",true);
// String idCardResultUrl = recognizeIdCardWithImage("https://jf.sh.189.cn/minio/gov-miniapp/order_pdf/font.jpg","front",false);
// String idCardResultUrl = recognizeIdCardWithImage("/Users/tanzs/Pictures/cert/font.jpg","front",true);
String idCardResultUrl = recognizeIdCardWithImage("https://jf.sh.189.cn/minio/gov-miniapp/order_pdf/font.jpg","front",false);
System.out.println("身份证识别结果: " + idCardResultUrl);
// 示例调用营业执照识别API图片URL


Loading…
Cancel
Save