feat: add card statistics and vin management
| New file |
| | |
| | | # 任务耗时统计 |
| | | |
| | | > 自 2026-08-05 起,项目所有任务耗时统一记录到此 Markdown 表格(原 `doc/开发任务耗时统计.xlsx` 仅作历史备份)。 |
| | | > 缺失精确时间戳时标记为「估算」或「未记录」。 |
| | | |
| | | | 开始时间 | 结束时间 | 耗时(秒) | 用户原始任务描述 | 生成修改方案 | 任务内容 | 修改文件 | 测试结果 | 备注 | |
| | | |---|---|---|---|---|---|---|---|---| |
| | | | 2026-08-31(估算) | 2026-08-31(估算) | 约 600(估算) | 复制一个相同功能的接口只用于内部调用;giveVip1 删除 @RequiresPermissions,不需要加 @InnerAuth | 删除 giveVip1 上的 @RequiresPermissions,不加 @InnerAuth;giveVip 保持权限校验;网关白名单外无 token 请求 401;提示持有合法 token 的外部请求可直接调用该接口的风险 | 删除 giveVip1(/user/give/vip1)的权限注解,使其可供内部 Feign 调用(微信/支付宝会员回调链路放行) | ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppUserController.java | mvn -pl ruoyi-service/ruoyi-account -am compile 通过;lint 0 错误 | 待部署后实测微信购买会员 vip_end_time 更新;管理后台 giveVip 不受影响 | |
| | | | 2026-08-31 17:04:00(估算) | 2026-08-31 17:05:00(估算) | 约 60(估算) | 推送服务端代码 | 先检查改动,编译订单服务,通过后提交并推送;排除未跟踪的 `doc/` 目录 | 提交并推送刷卡充电订单查询接口服务端改动,提交号 `ec2cbf74`,推送至 `origin/2.3` | `ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/query/CardChargingOrderQuery.java`;`ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TCardChargingOrderController.java`;`ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TCardChargingOrderMapper.java`;`ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TCardChargingOrderService.java`;`ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TCardChargingOrderServiceImpl.java`;`ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TCardChargingOrderMapper.xml` | `mvn -pl ruoyi-service/ruoyi-order -am compile -DskipTests` 通过;`git diff --check` 通过;远程分支校验通过 | 工作区仍有未跟踪 `doc/` 目录,未纳入本次提交 | |
| | | | 2026-08-31 17:20:00(估算) | 2026-08-31 17:21:00(估算) | 约 60(估算) | 修复刷卡订单汇总 SQL 语法错误 | 将代理层无法正确解析的 `TIMESTAMPDIFF(SECOND, ...)` 替换为 `UNIX_TIMESTAMP` 时间戳差值,保持 `time` 字段秒数语义不变 | 修复 `TCardChargingOrderMapper.xml` 汇总查询中的充电时长统计 SQL | `ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TCardChargingOrderMapper.xml` | `mvn -pl ruoyi-service/ruoyi-order -am compile -DskipTests` 通过;`git diff --check` 通过;运行时 Mapper 资源已确认使用 `UNIX_TIMESTAMP`;IDE 诊断 0 条 | 未执行真实数据库接口验证;本次未提交未推送 | |
| | | | 2026-09-01 10:33:38 | 2026-09-01(结束时间待推送后补记) | 未记录 | 推送代码 | 是:回归验证通过后分别提交并普通推送服务端 `2.3` 与管理后台 `dev_2.3`,不使用强制推送 | 提交并推送当前两个仓库的卡片收支明细、刷卡订单统计、VIN 管理及相关路由权限改动 | 服务端 20 个业务/SQL 文件;管理后台 12 个页面、路由和权限文件 | 服务端 Maven clean test、前端 `tsc`、Jest 11 套件/42 用例、生产构建、UTF-8 检查及两仓库 `git diff --cached --check` 已通过;推送结果待完成 | 当前服务端 `doc/` 仍未纳入暂存,待补记最终耗时后提交;构建仅有既存警告 | |
| New file |
| | |
| | | package com.ruoyi.account.api.dto; |
| | | |
| | | import com.ruoyi.common.core.annotation.Excel; |
| | | import lombok.Data; |
| | | import java.io.Serializable; |
| | | |
| | | @Data |
| | | public class VinManagementExcelDTO implements Serializable { |
| | | private static final long serialVersionUID = 1L; |
| | | @Excel(name = "VIN码", width = 24, prompt = "必填,最多64个字符") private String vin; |
| | | @Excel(name = "车牌号", width = 16) private String plateNumber; |
| | | @Excel(name = "手机号", width = 16) private String phone; |
| | | @Excel(name = "所属公司", width = 24) private String companyName; |
| | | @Excel(name = "备注", width = 30) private String remark; |
| | | @Excel(name = "启用状态", width = 14, readConverterExp = "1=启用,2=禁用", combo = {"启用", "禁用"}) private String status; |
| | | } |
| New file |
| | |
| | | package com.ruoyi.account.api.dto; |
| | | |
| | | import com.ruoyi.common.core.web.page.BasePage; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class VinManagementQueryDTO extends BasePage { |
| | | private String vin; |
| | | private String plateNumber; |
| | | private String phone; |
| | | private Integer status; |
| | | } |
| New file |
| | |
| | | package com.ruoyi.account.api.dto; |
| | | |
| | | import lombok.Data; |
| | | import java.io.Serializable; |
| | | |
| | | @Data |
| | | public class VinManagementSaveDTO implements Serializable { |
| | | private static final long serialVersionUID = 1L; |
| | | private Long id; |
| | | private String vin; |
| | | private String plateNumber; |
| | | private String phone; |
| | | private String companyName; |
| | | private String remark; |
| | | private Integer status; |
| | | } |
| New file |
| | |
| | | package com.ruoyi.account.api.model; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableLogic; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.ruoyi.common.core.annotation.Excel; |
| | | import lombok.Data; |
| | | import java.io.Serializable; |
| | | import java.time.LocalDateTime; |
| | | |
| | | @Data |
| | | @TableName("t_vin_management") |
| | | public class TVinManagement implements Serializable { |
| | | private static final long serialVersionUID = 1L; |
| | | @TableId(value = "id", type = IdType.AUTO) private Long id; |
| | | @Excel(name = "VIN码", width = 24) private String vin; |
| | | @Excel(name = "车牌号", width = 16) private String plateNumber; |
| | | @Excel(name = "手机号", width = 16) private String phone; |
| | | @Excel(name = "所属公司", width = 24) private String companyName; |
| | | @Excel(name = "备注", width = 30) private String remark; |
| | | @Excel(name = "启用状态", readConverterExp = "1=启用,2=禁用") private Integer status; |
| | | @TableLogic(value = "0", delval = "2") private Integer delFlag; |
| | | private LocalDateTime createTime; |
| | | private Long createBy; |
| | | private LocalDateTime updateTime; |
| | | private Long updateBy; |
| | | } |
| New file |
| | |
| | | package com.ruoyi.order.api.query; |
| | | |
| | | import com.ruoyi.common.core.web.page.BasePage; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @ApiModel(value = "CardBalanceDetailQuery卡片收支明细查询对象") |
| | | public class CardBalanceDetailQuery extends BasePage { |
| | | |
| | | @ApiModelProperty("卡号") |
| | | private String cardNo; |
| | | |
| | | @ApiModelProperty("订单编号") |
| | | private String code; |
| | | |
| | | @ApiModelProperty("收支类型:1收入,2支出") |
| | | private Integer incomeType; |
| | | |
| | | @ApiModelProperty("操作内容:1充值,2充电扣款,3退款") |
| | | private Integer operationType; |
| | | |
| | | @ApiModelProperty("操作时间范围的开始时间") |
| | | private String operationTime1; |
| | | |
| | | @ApiModelProperty("操作时间范围的结束时间") |
| | | private String operationTime2; |
| | | |
| | | @ApiModelProperty("站点ids(权限过滤,前端忽略)") |
| | | private List<Integer> siteIds; |
| | | } |
| New file |
| | |
| | | package com.ruoyi.order.api.vo; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | |
| | | @Data |
| | | @ApiModel(value = "CardBalanceDetailVO卡片收支明细") |
| | | public class CardBalanceDetailVO { |
| | | |
| | | @ApiModelProperty("流水唯一标识") |
| | | private String id; |
| | | |
| | | @ApiModelProperty("刷卡订单ID") |
| | | private Long orderId; |
| | | |
| | | @ApiModelProperty("卡号") |
| | | private String cardNo; |
| | | |
| | | @ApiModelProperty("订单关联手机号") |
| | | private String phone; |
| | | |
| | | @ApiModelProperty("订单编号") |
| | | private String code; |
| | | |
| | | @ApiModelProperty("收支类型:1收入,2支出") |
| | | private Integer incomeType; |
| | | |
| | | @ApiModelProperty("操作内容:1充值,2充电扣款,3退款") |
| | | private Integer operationType; |
| | | |
| | | @ApiModelProperty("金额") |
| | | private BigDecimal amount; |
| | | |
| | | @ApiModelProperty("备注") |
| | | private String remark; |
| | | |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @ApiModelProperty("操作时间") |
| | | private LocalDateTime operationTime; |
| | | } |
| New file |
| | |
| | | package com.ruoyi.account.controller; |
| | | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.ruoyi.account.api.dto.VinManagementExcelDTO; |
| | | import com.ruoyi.account.api.dto.VinManagementQueryDTO; |
| | | import com.ruoyi.account.api.dto.VinManagementSaveDTO; |
| | | import com.ruoyi.account.service.TVinManagementService; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.core.utils.poi.ExcelUtil; |
| | | import com.ruoyi.common.core.web.controller.BaseController; |
| | | import com.ruoyi.common.security.annotation.Logical; |
| | | import com.ruoyi.common.security.annotation.RequiresPermissions; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.util.List; |
| | | |
| | | @RestController |
| | | @RequestMapping("/t-vin-management") |
| | | public class TVinManagementController extends BaseController { |
| | | @Autowired private TVinManagementService service; |
| | | @RequiresPermissions(value = "/vinManagement/list", logical = Logical.OR) |
| | | @PostMapping("/page") public R<IPage<?>> page(@RequestBody VinManagementQueryDTO query) { return R.ok(service.selectPageList(query)); } |
| | | @RequiresPermissions(value = "/vinManagement/add", logical = Logical.OR) |
| | | @PostMapping public R<Boolean> add(@RequestBody VinManagementSaveDTO dto) { return R.ok(service.saveVin(dto)); } |
| | | @RequiresPermissions(value = "/vinManagement/edit", logical = Logical.OR) |
| | | @PutMapping public R<Boolean> edit(@RequestBody VinManagementSaveDTO dto) { return R.ok(service.updateVin(dto)); } |
| | | @RequiresPermissions(value = "/vinManagement/delete", logical = Logical.OR) |
| | | @DeleteMapping public R<Boolean> delete(@RequestBody List<Long> ids) { return R.ok(service.deleteVins(ids)); } |
| | | @RequiresPermissions(value = "/vinManagement/status", logical = Logical.OR) |
| | | @PutMapping("/status") public R<Boolean> status(@RequestBody VinManagementSaveDTO dto) { return R.ok(service.updateStatus(dto.getId(), dto.getStatus())); } |
| | | @RequiresPermissions(value = "/vinManagement/export", logical = Logical.OR) |
| | | @PutMapping("/export") public void export(HttpServletResponse response, @RequestBody VinManagementQueryDTO query) { new ExcelUtil<>(VinManagementExcelDTO.class).exportExcel(response, service.selectExportList(query), "VIN码数据"); } |
| | | @RequiresPermissions(value = "/vinManagement/import", logical = Logical.OR) |
| | | @GetMapping("/import-template") public void template(HttpServletResponse response) { new ExcelUtil<>(VinManagementExcelDTO.class).importTemplateExcel(response, "VIN码导入模板"); } |
| | | @RequiresPermissions(value = "/vinManagement/import", logical = Logical.OR) |
| | | @PostMapping("/import") public R<String> importData(@RequestPart("file") MultipartFile file) throws Exception { List<VinManagementExcelDTO> items = new ExcelUtil<>(VinManagementExcelDTO.class).importExcel(file.getInputStream()); return R.ok(service.importVins(items)); } |
| | | } |
| New file |
| | |
| | | package com.ruoyi.account.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.account.api.dto.VinManagementExcelDTO; |
| | | import com.ruoyi.account.api.dto.VinManagementQueryDTO; |
| | | import com.ruoyi.account.api.model.TVinManagement; |
| | | import org.apache.ibatis.annotations.Param; |
| | | import java.util.List; |
| | | |
| | | public interface TVinManagementMapper extends BaseMapper<TVinManagement> { |
| | | IPage<TVinManagement> selectPageList(Page<TVinManagement> page, @Param("query") VinManagementQueryDTO query); |
| | | List<VinManagementExcelDTO> selectExportList(@Param("query") VinManagementQueryDTO query); |
| | | int countByVin(@Param("vin") String vin, @Param("excludeId") Long excludeId); |
| | | } |
| New file |
| | |
| | | package com.ruoyi.account.service; |
| | | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.account.api.dto.VinManagementExcelDTO; |
| | | import com.ruoyi.account.api.dto.VinManagementQueryDTO; |
| | | import com.ruoyi.account.api.dto.VinManagementSaveDTO; |
| | | import com.ruoyi.account.api.model.TVinManagement; |
| | | import java.util.List; |
| | | |
| | | public interface TVinManagementService extends IService<TVinManagement> { |
| | | IPage<TVinManagement> selectPageList(VinManagementQueryDTO query); |
| | | boolean saveVin(VinManagementSaveDTO dto); |
| | | boolean updateVin(VinManagementSaveDTO dto); |
| | | boolean deleteVins(List<Long> ids); |
| | | boolean updateStatus(Long id, Integer status); |
| | | List<VinManagementExcelDTO> selectExportList(VinManagementQueryDTO query); |
| | | String importVins(List<VinManagementExcelDTO> items); |
| | | } |
| New file |
| | |
| | | package com.ruoyi.account.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.account.api.dto.VinManagementExcelDTO; |
| | | import com.ruoyi.account.api.dto.VinManagementQueryDTO; |
| | | import com.ruoyi.account.api.dto.VinManagementSaveDTO; |
| | | import com.ruoyi.account.api.model.TVinManagement; |
| | | import com.ruoyi.account.mapper.TVinManagementMapper; |
| | | import com.ruoyi.account.service.TVinManagementService; |
| | | import com.ruoyi.common.core.exception.ServiceException; |
| | | import com.ruoyi.common.core.utils.StringUtils; |
| | | import com.ruoyi.common.security.utils.SecurityUtils; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import java.time.LocalDateTime; |
| | | import java.util.ArrayList; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | |
| | | @Service |
| | | public class TVinManagementServiceImpl extends ServiceImpl<TVinManagementMapper, TVinManagement> implements TVinManagementService { |
| | | private static final int ENABLED = 1; |
| | | private static final int DISABLED = 2; |
| | | |
| | | @Override public IPage<TVinManagement> selectPageList(VinManagementQueryDTO query) { |
| | | VinManagementQueryDTO safe = query == null ? new VinManagementQueryDTO() : query; |
| | | long page = safe.getPageCurr() == null || safe.getPageCurr() < 1 ? 1 : safe.getPageCurr(); |
| | | long size = safe.getPageSize() == null || safe.getPageSize() < 1 ? 10 : safe.getPageSize(); |
| | | return baseMapper.selectPageList(new Page<>(page, size), safe); |
| | | } |
| | | @Override public boolean saveVin(VinManagementSaveDTO dto) { validate(dto, false); TVinManagement item = from(dto); item.setDelFlag(0); item.setCreateTime(LocalDateTime.now()); item.setCreateBy(SecurityUtils.getUserId()); return save(item); } |
| | | @Override public boolean updateVin(VinManagementSaveDTO dto) { validate(dto, true); if (getById(dto.getId()) == null) throw new ServiceException("VIN码不存在或已删除"); TVinManagement item = from(dto); item.setId(dto.getId()); item.setUpdateTime(LocalDateTime.now()); item.setUpdateBy(SecurityUtils.getUserId()); return updateById(item); } |
| | | @Override public boolean deleteVins(List<Long> ids) { if (ids == null || ids.isEmpty()) throw new ServiceException("请选择需要删除的VIN码"); List<Long> distinct = new ArrayList<>(new HashSet<>(ids)); if (listByIds(distinct).size() != distinct.size()) throw new ServiceException("部分VIN码不存在或已删除"); return removeByIds(distinct); } |
| | | @Override public boolean updateStatus(Long id, Integer status) { if (id == null || !validStatus(status)) throw new ServiceException("VIN码状态参数错误"); if (getById(id) == null) throw new ServiceException("VIN码不存在或已删除"); TVinManagement item = new TVinManagement(); item.setId(id); item.setStatus(status); item.setUpdateTime(LocalDateTime.now()); item.setUpdateBy(SecurityUtils.getUserId()); return updateById(item); } |
| | | @Override public List<VinManagementExcelDTO> selectExportList(VinManagementQueryDTO query) { return baseMapper.selectExportList(query == null ? new VinManagementQueryDTO() : query); } |
| | | @Override @Transactional(rollbackFor = Exception.class) public String importVins(List<VinManagementExcelDTO> items) { if (items == null || items.isEmpty()) throw new ServiceException("导入数据不能为空"); Set<String> vins = new HashSet<>(); int row = 1; for (VinManagementExcelDTO item : items) { row++; if (item == null || StringUtils.isEmpty(item.getVin())) throw new ServiceException("第" + row + "行VIN码不能为空"); String vin = item.getVin().trim(); if (vin.length() > 64) throw new ServiceException("第" + row + "行VIN码不能超过64个字符"); if (!vins.add(vin) || baseMapper.countByVin(vin, null) > 0) throw new ServiceException("第" + row + "行VIN码已存在或重复"); parseStatus(item.getStatus(), row); } Long userId = SecurityUtils.getUserId(); LocalDateTime now = LocalDateTime.now(); for (VinManagementExcelDTO item : items) { TVinManagement v = new TVinManagement(); v.setVin(item.getVin().trim()); v.setPlateNumber(trim(item.getPlateNumber())); v.setPhone(trim(item.getPhone())); v.setCompanyName(trim(item.getCompanyName())); v.setRemark(trim(item.getRemark())); v.setStatus(parseStatus(item.getStatus(), 0)); v.setDelFlag(0); v.setCreateBy(userId); v.setCreateTime(now); save(v); } return "成功导入" + items.size() + "条VIN码数据"; } |
| | | private void validate(VinManagementSaveDTO dto, boolean update) { if (dto == null || StringUtils.isEmpty(dto.getVin())) throw new ServiceException("VIN码不能为空"); if (update && dto.getId() == null) throw new ServiceException("VIN码ID不能为空"); String vin = dto.getVin().trim(); if (vin.length() > 64) throw new ServiceException("VIN码不能超过64个字符"); if (!validStatus(dto.getStatus() == null ? ENABLED : dto.getStatus())) throw new ServiceException("VIN码状态参数错误"); if (baseMapper.countByVin(vin, dto.getId()) > 0) throw new ServiceException("VIN码已存在"); } |
| | | private TVinManagement from(VinManagementSaveDTO d) { TVinManagement v = new TVinManagement(); v.setVin(d.getVin().trim()); v.setPlateNumber(trim(d.getPlateNumber())); v.setPhone(trim(d.getPhone())); v.setCompanyName(trim(d.getCompanyName())); v.setRemark(trim(d.getRemark())); v.setStatus(d.getStatus() == null ? ENABLED : d.getStatus()); return v; } |
| | | private String trim(String value) { return value == null ? null : value.trim(); } |
| | | private boolean validStatus(Integer status) { return status != null && (status == ENABLED || status == DISABLED); } |
| | | private Integer parseStatus(String value, int row) { if (StringUtils.isEmpty(value) || "1".equals(value.trim()) || "启用".equals(value.trim())) return ENABLED; if ("2".equals(value.trim()) || "禁用".equals(value.trim())) return DISABLED; throw new ServiceException((row > 0 ? "第" + row + "行" : "") + "启用状态错误"); } |
| | | } |
| New file |
| | |
| | | <?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.ruoyi.account.mapper.TVinManagementMapper"> |
| | | <select id="selectPageList" resultType="com.ruoyi.account.api.model.TVinManagement"> |
| | | SELECT id, vin, plate_number, phone, company_name, remark, status, del_flag, create_time, create_by, update_time, update_by |
| | | FROM t_vin_management WHERE del_flag = 0 |
| | | <if test="query != null and query.vin != null and query.vin != ''">AND vin LIKE CONCAT('%', #{query.vin}, '%')</if> |
| | | <if test="query != null and query.plateNumber != null and query.plateNumber != ''">AND plate_number LIKE CONCAT('%', #{query.plateNumber}, '%')</if> |
| | | <if test="query != null and query.phone != null and query.phone != ''">AND phone LIKE CONCAT('%', #{query.phone}, '%')</if> |
| | | <if test="query != null and query.status != null">AND status = #{query.status}</if> |
| | | ORDER BY create_time DESC, id DESC |
| | | </select> |
| | | <select id="selectExportList" resultType="com.ruoyi.account.api.dto.VinManagementExcelDTO"> |
| | | SELECT vin, plate_number AS plateNumber, phone, company_name AS companyName, remark, status |
| | | FROM t_vin_management WHERE del_flag = 0 |
| | | <if test="query != null and query.vin != null and query.vin != ''">AND vin LIKE CONCAT('%', #{query.vin}, '%')</if> |
| | | <if test="query != null and query.plateNumber != null and query.plateNumber != ''">AND plate_number LIKE CONCAT('%', #{query.plateNumber}, '%')</if> |
| | | <if test="query != null and query.phone != null and query.phone != ''">AND phone LIKE CONCAT('%', #{query.phone}, '%')</if> |
| | | <if test="query != null and query.status != null">AND status = #{query.status}</if> |
| | | ORDER BY create_time DESC, id DESC |
| | | </select> |
| | | <select id="countByVin" resultType="int">SELECT COUNT(1) FROM t_vin_management WHERE vin = #{vin}<if test="excludeId != null"> AND id != #{excludeId}</if></select> |
| | | </mapper> |
| | |
| | | import com.ruoyi.common.log.enums.BusinessType; |
| | | import com.ruoyi.common.security.annotation.Logical; |
| | | import com.ruoyi.common.security.annotation.RequiresPermissions; |
| | | import com.ruoyi.order.api.query.CardBalanceDetailQuery; |
| | | import com.ruoyi.order.api.query.CardChargingOrderQuery; |
| | | import com.ruoyi.order.api.vo.CardBalanceDetailVO; |
| | | import com.ruoyi.order.api.vo.ChargingOrderVO; |
| | | import com.ruoyi.order.export.CardBalanceDetailExport; |
| | | import com.ruoyi.order.export.CardChargingOrderExport; |
| | | import com.ruoyi.order.service.TCardChargingOrderService; |
| | | import io.swagger.annotations.Api; |
| | |
| | | List<Map<String, Object>> list = cardChargingOrderService.accountingStrategyList(chargingOrderId); |
| | | return R.ok(Collections.singletonMap("list", list)); |
| | | } |
| | | |
| | | @RequiresPermissions("/chargingCardBalanceDetail/list") |
| | | @GetMapping("/balance-detail/list") |
| | | @ApiOperation("卡片收支明细列表") |
| | | public R<PageInfo<CardBalanceDetailVO>> balanceDetailList(CardBalanceDetailQuery query) { |
| | | return R.ok(cardChargingOrderService.balanceDetailPage(query)); |
| | | } |
| | | |
| | | @RequiresPermissions("/chargingCardBalanceDetail/list") |
| | | @GetMapping("/balance-detail/summary") |
| | | @ApiOperation("卡片收支明细汇总") |
| | | public R<Map<String, Object>> balanceDetailSummary(CardBalanceDetailQuery query) { |
| | | return R.ok(cardChargingOrderService.balanceDetailSummary(query)); |
| | | } |
| | | |
| | | @RequiresPermissions("/chargingCardBalanceDetail/export") |
| | | @PutMapping("/balance-detail/export") |
| | | @ApiOperation("卡片收支明细导出") |
| | | @Log(title = "卡片收支明细导出", businessType = BusinessType.EXPORT) |
| | | public void balanceDetailExport(@RequestBody CardBalanceDetailQuery query) { |
| | | List<CardBalanceDetailVO> list = cardChargingOrderService.balanceDetailExport(query); |
| | | List<CardBalanceDetailExport> exports = new ArrayList<>(); |
| | | for (int i = 0; i < list.size(); i++) { |
| | | CardBalanceDetailVO detail = list.get(i); |
| | | CardBalanceDetailExport export = new CardBalanceDetailExport(); |
| | | BeanUtils.copyProperties(detail, export); |
| | | export.setSequence(i + 1); |
| | | export.setOperationTime(formatTime(detail.getOperationTime())); |
| | | exports.add(export); |
| | | } |
| | | Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), CardBalanceDetailExport.class, exports); |
| | | writeWorkbook(workbook, "卡片收支明细导出.xls"); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.ruoyi.order.export; |
| | | |
| | | import cn.afterturn.easypoi.excel.annotation.Excel; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | import java.math.BigDecimal; |
| | | |
| | | @Data |
| | | public class CardBalanceDetailExport implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @Excel(name = "序号", width = 10) |
| | | private Integer sequence; |
| | | |
| | | @Excel(name = "卡号", width = 22) |
| | | private String cardNo; |
| | | |
| | | @Excel(name = "关联手机号", width = 18) |
| | | private String phone; |
| | | |
| | | @Excel(name = "收支类型", width = 12, replace = {"收入_1", "支出_2"}) |
| | | private Integer incomeType; |
| | | |
| | | @Excel(name = "操作内容", width = 16, replace = {"充值_1", "充电扣款_2", "退款_3"}) |
| | | private Integer operationType; |
| | | |
| | | @Excel(name = "金额", width = 14, numFormat = "0.00") |
| | | private BigDecimal amount; |
| | | |
| | | @Excel(name = "订单编号", width = 28) |
| | | private String code; |
| | | |
| | | @Excel(name = "备注", width = 30) |
| | | private String remark; |
| | | |
| | | @Excel(name = "操作时间", width = 22) |
| | | private String operationTime; |
| | | } |
| | |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.order.api.model.TCardChargingOrder; |
| | | import com.ruoyi.order.api.query.CardBalanceDetailQuery; |
| | | import com.ruoyi.order.api.query.CardChargingOrderQuery; |
| | | import com.ruoyi.order.api.vo.CardBalanceDetailVO; |
| | | import com.ruoyi.order.api.vo.ChargingOrderVO; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | |
| | | |
| | | List<Map<String, Object>> accountingStrategyList(@Param("chargingOrderId") Long chargingOrderId); |
| | | |
| | | List<CardBalanceDetailVO> balanceDetailList(@Param("query") CardBalanceDetailQuery query, |
| | | @Param("offset") long offset, |
| | | @Param("pageSize") long pageSize); |
| | | |
| | | long balanceDetailCount(@Param("query") CardBalanceDetailQuery query); |
| | | |
| | | Map<String, Object> balanceDetailSummary(@Param("query") CardBalanceDetailQuery query); |
| | | |
| | | List<Map<String, Object>> shareIncomeByOrderIds(@Param("orderIds") List<Long> orderIds); |
| | | |
| | | Map<String, Object> shareIncomeSummaryByOrderIds(@Param("orderIds") List<Long> orderIds); |
| | |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.order.api.model.TCardChargingOrder; |
| | | import com.ruoyi.order.api.query.CardBalanceDetailQuery; |
| | | import com.ruoyi.order.api.query.CardChargingOrderQuery; |
| | | import com.ruoyi.order.api.vo.CardBalanceDetailVO; |
| | | import com.ruoyi.order.api.vo.ChargingOrderVO; |
| | | |
| | | import java.util.List; |
| | |
| | | List<Map<String, Object>> balanceIncomeDetail(CardChargingOrderQuery query); |
| | | |
| | | List<Map<String, Object>> accountingStrategyList(Long chargingOrderId); |
| | | |
| | | PageInfo<CardBalanceDetailVO> balanceDetailPage(CardBalanceDetailQuery query); |
| | | |
| | | Map<String, Object> balanceDetailSummary(CardBalanceDetailQuery query); |
| | | |
| | | List<CardBalanceDetailVO> balanceDetailExport(CardBalanceDetailQuery query); |
| | | } |
| | |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.ruoyi.common.security.service.TokenService; |
| | | import com.ruoyi.order.api.model.TCardChargingOrder; |
| | | import com.ruoyi.order.api.query.CardBalanceDetailQuery; |
| | | import com.ruoyi.order.api.query.CardChargingOrderQuery; |
| | | import com.ruoyi.order.api.vo.CardBalanceDetailVO; |
| | | import com.ruoyi.order.api.vo.ChargingOrderVO; |
| | | import com.ruoyi.order.mapper.TCardChargingOrderMapper; |
| | | import com.ruoyi.order.service.TCardChargingOrderService; |
| | |
| | | return baseMapper.accountingStrategyList(chargingOrderId); |
| | | } |
| | | |
| | | @Override |
| | | public PageInfo<CardBalanceDetailVO> balanceDetailPage(CardBalanceDetailQuery query) { |
| | | int pageCurr = query.getPageCurr() == null || query.getPageCurr() < 1 ? 1 : query.getPageCurr(); |
| | | int pageSize = query.getPageSize() == null || query.getPageSize() < 1 ? 50 : query.getPageSize(); |
| | | setAuthSiteIds(query); |
| | | PageInfo<CardBalanceDetailVO> pageInfo = new PageInfo<>(pageCurr, pageSize); |
| | | long total = baseMapper.balanceDetailCount(query); |
| | | pageInfo.setTotal(total); |
| | | if (total == 0) { |
| | | pageInfo.setRecords(Collections.emptyList()); |
| | | return pageInfo; |
| | | } |
| | | long offset = (long) (pageCurr - 1) * pageSize; |
| | | List<CardBalanceDetailVO> list = baseMapper.balanceDetailList(query, offset, pageSize); |
| | | pageInfo.setRecords(list); |
| | | return pageInfo; |
| | | } |
| | | |
| | | @Override |
| | | public Map<String, Object> balanceDetailSummary(CardBalanceDetailQuery query) { |
| | | setAuthSiteIds(query); |
| | | Map<String, Object> result = baseMapper.balanceDetailSummary(query); |
| | | if (result == null) { |
| | | result = new HashMap<>(); |
| | | } |
| | | result.putIfAbsent("orderCount", 0); |
| | | result.putIfAbsent("incomeAmount", BigDecimal.ZERO); |
| | | result.putIfAbsent("expenseAmount", BigDecimal.ZERO); |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | public List<CardBalanceDetailVO> balanceDetailExport(CardBalanceDetailQuery query) { |
| | | setAuthSiteIds(query); |
| | | long total = baseMapper.balanceDetailCount(query); |
| | | if (total == 0) { |
| | | return new ArrayList<>(); |
| | | } |
| | | List<CardBalanceDetailVO> result = new ArrayList<>(); |
| | | int batchSize = 5000; |
| | | for (long offset = 0; offset < total; offset += batchSize) { |
| | | List<CardBalanceDetailVO> batch = baseMapper.balanceDetailList(query, offset, batchSize); |
| | | if (batch == null || batch.isEmpty()) { |
| | | break; |
| | | } |
| | | result.addAll(batch); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | private void setAuthSiteIds(CardChargingOrderQuery query) { |
| | | List<Integer> siteIds = new ArrayList<>(); |
| | | if (query.getSiteId() != null) { |
| | |
| | | query.setSiteIds(siteIds); |
| | | } |
| | | |
| | | private void setAuthSiteIds(CardBalanceDetailQuery query) { |
| | | List<Integer> siteIds = new ArrayList<>(); |
| | | Long userId = tokenService.getLoginUser().getUserid(); |
| | | if (userId != null) { |
| | | siteIds = Optional.ofNullable(siteClient.getSiteListByUserId(userId).getData()).orElse(Collections.emptyList()) |
| | | .stream().map(GetSiteListDTO::getId).collect(Collectors.toList()); |
| | | } |
| | | if (siteIds.isEmpty()) { |
| | | siteIds.add(-1); |
| | | } |
| | | query.setSiteIds(siteIds); |
| | | } |
| | | |
| | | private void fillPageExtra(List<ChargingOrderVO> list) { |
| | | if (list == null || list.isEmpty()) { |
| | | return; |
| | |
| | | ORDER BY balancePayAmount DESC |
| | | </select> |
| | | |
| | | <sql id="balanceDetailUnion"> |
| | | SELECT CONCAT('R-', o.id) AS id, |
| | | o.id AS orderId, |
| | | o.phone AS phone, |
| | | o.card_no AS cardNo, |
| | | o.code AS code, |
| | | 1 AS incomeType, |
| | | 1 AS operationType, |
| | | o.recharge_amount AS amount, |
| | | '刷卡订单充值' AS remark, |
| | | COALESCE(o.pay_time, o.create_time) AS operationTime |
| | | FROM t_card_charging_order o |
| | | WHERE o.del_flag = 0 |
| | | AND o.recharge_payment_status = 2 |
| | | AND IFNULL(o.recharge_amount, 0) > 0 |
| | | UNION ALL |
| | | SELECT CONCAT('P-', o.id) AS id, |
| | | o.id AS orderId, |
| | | o.phone AS phone, |
| | | o.card_no AS cardNo, |
| | | o.code AS code, |
| | | 2 AS incomeType, |
| | | 2 AS operationType, |
| | | o.balance_pay_amount AS amount, |
| | | '充电余额扣款' AS remark, |
| | | COALESCE(o.pay_time, o.end_time, o.create_time) AS operationTime |
| | | FROM t_card_charging_order o |
| | | WHERE o.del_flag = 0 |
| | | AND IFNULL(o.balance_pay_amount, 0) > 0 |
| | | UNION ALL |
| | | SELECT CONCAT('F-', r.id) AS id, |
| | | o.id AS orderId, |
| | | o.phone AS phone, |
| | | o.card_no AS cardNo, |
| | | o.code AS code, |
| | | 1 AS incomeType, |
| | | 3 AS operationType, |
| | | r.balance_refund_amount AS amount, |
| | | COALESCE(r.refund_remark, r.refund_reason, r.refund_content, '余额退款') AS remark, |
| | | COALESCE(r.refund_time, r.create_time) AS operationTime |
| | | FROM t_card_charging_order_refund r |
| | | INNER JOIN t_card_charging_order o ON o.id = r.charging_order_id |
| | | WHERE r.del_flag = 0 |
| | | AND o.del_flag = 0 |
| | | AND r.refund_status = 2 |
| | | AND IFNULL(r.balance_refund_amount, 0) > 0 |
| | | </sql> |
| | | |
| | | <sql id="balanceDetailCondition"> |
| | | <where> |
| | | <if test="query.siteIds != null and query.siteIds.size() > 0"> |
| | | AND o.site_id IN |
| | | <foreach collection="query.siteIds" item="siteId" open="(" separator="," close=")"> |
| | | #{siteId} |
| | | </foreach> |
| | | </if> |
| | | <if test="query.cardNo != null and query.cardNo != ''"> |
| | | AND d.cardNo LIKE CONCAT('%', #{query.cardNo}, '%') |
| | | </if> |
| | | <if test="query.code != null and query.code != ''"> |
| | | AND d.code LIKE CONCAT('%', #{query.code}, '%') |
| | | </if> |
| | | <if test="query.incomeType != null"> |
| | | AND d.incomeType = #{query.incomeType} |
| | | </if> |
| | | <if test="query.operationType != null"> |
| | | AND d.operationType = #{query.operationType} |
| | | </if> |
| | | <if test="query.operationTime1 != null and query.operationTime1 != ''"> |
| | | AND d.operationTime >= #{query.operationTime1} |
| | | </if> |
| | | <if test="query.operationTime2 != null and query.operationTime2 != ''"> |
| | | AND d.operationTime <= #{query.operationTime2} |
| | | </if> |
| | | </where> |
| | | </sql> |
| | | |
| | | <select id="balanceDetailList" resultType="com.ruoyi.order.api.vo.CardBalanceDetailVO"> |
| | | SELECT d.* |
| | | FROM (<include refid="balanceDetailUnion"/>) d |
| | | INNER JOIN t_card_charging_order o ON o.id = d.orderId |
| | | <include refid="balanceDetailCondition"/> |
| | | ORDER BY d.operationTime DESC, d.id DESC |
| | | LIMIT #{offset}, #{pageSize} |
| | | </select> |
| | | |
| | | <select id="balanceDetailCount" resultType="long"> |
| | | SELECT COUNT(1) |
| | | FROM (<include refid="balanceDetailUnion"/>) d |
| | | INNER JOIN t_card_charging_order o ON o.id = d.orderId |
| | | <include refid="balanceDetailCondition"/> |
| | | </select> |
| | | |
| | | <select id="balanceDetailSummary" resultType="java.util.LinkedHashMap"> |
| | | SELECT COUNT(DISTINCT d.orderId) AS orderCount, |
| | | IFNULL(SUM(CASE WHEN d.incomeType = 1 THEN d.amount ELSE 0 END), 0) AS incomeAmount, |
| | | IFNULL(SUM(CASE WHEN d.incomeType = 2 THEN d.amount ELSE 0 END), 0) AS expenseAmount |
| | | FROM (<include refid="balanceDetailUnion"/>) d |
| | | INNER JOIN t_card_charging_order o ON o.id = d.orderId |
| | | <include refid="balanceDetailCondition"/> |
| | | </select> |
| | | |
| | | <select id="accountingStrategyList" resultType="java.util.LinkedHashMap"> |
| | | SELECT id, |
| | | charging_order_id AS chargingOrderId, |
| New file |
| | |
| | | -- Card balance detail menu and button permissions. |
| | | -- Chinese text is encoded as UTF-8 hex literals to avoid PowerShell/mysql.exe encoding issues. |
| | | |
| | | SET @card_parent_id := ( |
| | | SELECT menu_id |
| | | FROM sys_menu |
| | | WHERE perms = '/chargingCard/list' AND parent_id = 0 |
| | | ORDER BY menu_id |
| | | LIMIT 1 |
| | | ); |
| | | |
| | | INSERT INTO sys_menu ( |
| | | menu_name, parent_id, order_num, path, component, query, is_frame, is_cache, |
| | | menu_type, visible, status, perms, icon, create_by, create_time, remark |
| | | ) |
| | | SELECT |
| | | CONVERT(0xE58DA1E78987E694B6E694AFE6988EE7BB86 USING utf8mb4), |
| | | @card_parent_id, 4, 'balanceDetail', 'card/balanceDetail', NULL, 1, 0, |
| | | 'C', '0', 0, '/chargingCardBalanceDetail/list', '#', 'admin', NOW(), |
| | | CONVERT(0xE58DA1E78987E694B6E694AFE6988EE7BB86E88F9CE58D95 USING utf8mb4) |
| | | WHERE @card_parent_id IS NOT NULL |
| | | AND NOT EXISTS ( |
| | | SELECT 1 FROM sys_menu WHERE perms = '/chargingCardBalanceDetail/list' |
| | | ); |
| | | |
| | | SET @balance_detail_menu_id := ( |
| | | SELECT menu_id |
| | | FROM sys_menu |
| | | WHERE perms = '/chargingCardBalanceDetail/list' |
| | | ORDER BY menu_id |
| | | LIMIT 1 |
| | | ); |
| | | |
| | | INSERT INTO sys_menu ( |
| | | menu_name, parent_id, order_num, path, component, query, is_frame, is_cache, |
| | | menu_type, visible, status, perms, icon, create_by, create_time, remark |
| | | ) |
| | | SELECT |
| | | CONVERT(0xE5AFBCE587BA USING utf8mb4), |
| | | @balance_detail_menu_id, 1, '#', NULL, NULL, 1, 0, |
| | | 'F', '0', 0, '/chargingCardBalanceDetail/export', '#', 'admin', NOW(), |
| | | CONVERT(0xE58DA1E78987E694B6E694AFE6988EE7BB86E5AFBCE587BAE68C89E992AE USING utf8mb4) |
| | | WHERE @balance_detail_menu_id IS NOT NULL |
| | | AND NOT EXISTS ( |
| | | SELECT 1 FROM sys_menu WHERE perms = '/chargingCardBalanceDetail/export' |
| | | ); |
| | | |
| | | INSERT IGNORE INTO sys_role_menu (role_id, menu_id) |
| | | SELECT DISTINCT role_id, @balance_detail_menu_id |
| | | FROM sys_role_menu |
| | | WHERE menu_id = @card_parent_id |
| | | AND @balance_detail_menu_id IS NOT NULL; |
| | | |
| | | SET @balance_detail_export_id := ( |
| | | SELECT menu_id |
| | | FROM sys_menu |
| | | WHERE perms = '/chargingCardBalanceDetail/export' |
| | | ORDER BY menu_id |
| | | LIMIT 1 |
| | | ); |
| | | |
| | | INSERT IGNORE INTO sys_role_menu (role_id, menu_id) |
| | | SELECT DISTINCT role_id, @balance_detail_export_id |
| | | FROM sys_role_menu |
| | | WHERE menu_id = @card_parent_id |
| | | AND @balance_detail_export_id IS NOT NULL; |
| New file |
| | |
| | | -- 卡片管理-刷卡订单统计菜单及超级管理员授权(幂等) |
| | | USE charging_pile_other; |
| | | |
| | | INSERT INTO sys_menu |
| | | (menu_name, parent_id, order_num, path, component, query, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) |
| | | SELECT CONVERT(0xE588B7E58DA1E8AEA2E7BB9FE8AEA1 USING utf8mb4), parent.menu_id, 3, 'cardOrderStatistics', 'order/cardOrderStatistics/index', '', 1, 0, 'C', '0', '0', '/cardOrderStatistics', 'transaction', 'admin', NOW(), '', NULL, '刷卡订单统计' |
| | | FROM sys_menu parent |
| | | WHERE parent.path = 'card' |
| | | AND parent.menu_type = 'M' |
| | | AND NOT EXISTS (SELECT 1 FROM sys_menu WHERE perms = '/cardOrderStatistics'); |
| | | |
| | | INSERT INTO sys_role_menu (role_id, menu_id) |
| | | SELECT 1, menu.menu_id |
| | | FROM sys_menu menu |
| | | WHERE menu.perms = '/cardOrderStatistics' |
| | | AND NOT EXISTS (SELECT 1 FROM sys_role_menu role_menu WHERE role_menu.role_id = 1 AND role_menu.menu_id = menu.menu_id); |
| New file |
| | |
| | | -- VIN码管理业务表及菜单权限,使用 UTF-8 执行。 |
| | | USE charging_pile_account; |
| | | CREATE TABLE IF NOT EXISTS t_vin_management ( |
| | | id BIGINT NOT NULL AUTO_INCREMENT, |
| | | vin VARCHAR(64) NOT NULL, |
| | | plate_number VARCHAR(32) DEFAULT NULL, |
| | | phone VARCHAR(32) DEFAULT NULL, |
| | | company_name VARCHAR(128) DEFAULT NULL, |
| | | remark VARCHAR(255) DEFAULT NULL, |
| | | status TINYINT NOT NULL DEFAULT 1, |
| | | del_flag TINYINT NOT NULL DEFAULT 0, |
| | | create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| | | create_by BIGINT DEFAULT NULL, |
| | | update_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, |
| | | update_by BIGINT DEFAULT NULL, |
| | | PRIMARY KEY (id), UNIQUE KEY uk_vin (vin), KEY idx_vin_status_del (status, del_flag) |
| | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='VIN码管理'; |
| | | USE charging_pile_other; |
| | | INSERT INTO sys_menu (menu_name,parent_id,order_num,path,component,menu_type,visible,status,perms,icon,create_by,create_time,remark) |
| | | SELECT 'VIN码管理',0,11,'/vinManagement',NULL,'M','0',0,'/vinManagement','car','admin',NOW(),'VIN码管理父级菜单' |
| | | WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE parent_id=0 AND path='/vinManagement'); |
| | | SET @vin_parent := (SELECT menu_id FROM sys_menu WHERE parent_id=0 AND path='/vinManagement' ORDER BY menu_id LIMIT 1); |
| | | INSERT INTO sys_menu (menu_name,parent_id,order_num,path,component,menu_type,visible,status,perms,icon,create_by,create_time,remark) |
| | | SELECT 'VIN码管理',@vin_parent,1,'list','vin','C','0',0,'/vinManagement/list','car','admin',NOW(),'VIN码管理列表' |
| | | WHERE @vin_parent IS NOT NULL AND NOT EXISTS (SELECT 1 FROM sys_menu WHERE parent_id=@vin_parent AND path='list'); |
| | | SET @vin_menu := (SELECT menu_id FROM sys_menu WHERE parent_id=@vin_parent AND path='list' ORDER BY menu_id LIMIT 1); |
| | | INSERT INTO sys_menu (menu_name,parent_id,order_num,path,component,menu_type,visible,status,perms,icon,create_by,create_time,remark) |
| | | SELECT '新增',@vin_menu,1,'#',NULL,'F','0',0,'/vinManagement/add','', 'admin',NOW(),'VIN新增' |
| | | WHERE @vin_menu IS NOT NULL AND NOT EXISTS (SELECT 1 FROM sys_menu WHERE parent_id=@vin_menu AND perms='/vinManagement/add'); |
| | | INSERT INTO sys_menu (menu_name,parent_id,order_num,path,component,menu_type,visible,status,perms,icon,create_by,create_time,remark) |
| | | SELECT '编辑',@vin_menu,2,'#',NULL,'F','0',0,'/vinManagement/edit','', 'admin',NOW(),'VIN编辑' |
| | | WHERE @vin_menu IS NOT NULL AND NOT EXISTS (SELECT 1 FROM sys_menu WHERE parent_id=@vin_menu AND perms='/vinManagement/edit'); |
| | | INSERT INTO sys_menu (menu_name,parent_id,order_num,path,component,menu_type,visible,status,perms,icon,create_by,create_time,remark) |
| | | SELECT '删除',@vin_menu,3,'#',NULL,'F','0',0,'/vinManagement/delete','', 'admin',NOW(),'VIN删除' |
| | | WHERE @vin_menu IS NOT NULL AND NOT EXISTS (SELECT 1 FROM sys_menu WHERE parent_id=@vin_menu AND perms='/vinManagement/delete'); |
| | | INSERT INTO sys_menu (menu_name,parent_id,order_num,path,component,menu_type,visible,status,perms,icon,create_by,create_time,remark) |
| | | SELECT '启停',@vin_menu,4,'#',NULL,'F','0',0,'/vinManagement/status','', 'admin',NOW(),'VIN启停' |
| | | WHERE @vin_menu IS NOT NULL AND NOT EXISTS (SELECT 1 FROM sys_menu WHERE parent_id=@vin_menu AND perms='/vinManagement/status'); |
| | | INSERT INTO sys_menu (menu_name,parent_id,order_num,path,component,menu_type,visible,status,perms,icon,create_by,create_time,remark) |
| | | SELECT '导入',@vin_menu,5,'#',NULL,'F','0',0,'/vinManagement/import','', 'admin',NOW(),'VIN导入' |
| | | WHERE @vin_menu IS NOT NULL AND NOT EXISTS (SELECT 1 FROM sys_menu WHERE parent_id=@vin_menu AND perms='/vinManagement/import'); |
| | | INSERT INTO sys_menu (menu_name,parent_id,order_num,path,component,menu_type,visible,status,perms,icon,create_by,create_time,remark) |
| | | SELECT '导出',@vin_menu,6,'#',NULL,'F','0',0,'/vinManagement/export','', 'admin',NOW(),'VIN导出' |
| | | WHERE @vin_menu IS NOT NULL AND NOT EXISTS (SELECT 1 FROM sys_menu WHERE parent_id=@vin_menu AND perms='/vinManagement/export'); |
| | | INSERT IGNORE INTO sys_role_menu (role_id,menu_id) SELECT 1,menu_id FROM sys_menu WHERE menu_id IN (@vin_parent,@vin_menu) OR parent_id=@vin_menu; |