From b057df883dc79e7866ee37299286ec0c5dc3f056 Mon Sep 17 00:00:00 2001
From: yanderong <307678080@qq.com>
Date: 星期三, 17 六月 2026 20:20:55 +0800
Subject: [PATCH] feat: 新增出行卡管理相关功能

---
 ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TravelCardPackage.java                   |  130 +++++++++
 ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/TravelCardPackageMapper.java               |   15 +
 ManagementYKDTravel/guns-admin/src/test/sql/t_travel_card.sql                                                                 |   28 ++
 ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/travelcard/TravelCardStatusEnum.java     |   17 +
 ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/general/TTravelCardController.java  |  132 +++++++++
 ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ITravelCardPackageService.java         |   32 ++
 ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TravelCardPackage.xml              |   26 +
 ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TravelCard.java                          |  187 +++++++++++++
 ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TravelCardServiceImpl.java        |   95 ++++++
 ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/TravelCardMapper.java                      |   17 +
 ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TravelCardPackageServiceImpl.java |   57 ++++
 ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ITravelCardService.java                |   34 ++
 ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TravelCard.xml                     |   13 
 13 files changed, 783 insertions(+), 0 deletions(-)

diff --git a/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/travelcard/TravelCardStatusEnum.java b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/travelcard/TravelCardStatusEnum.java
new file mode 100644
index 0000000..53028f6
--- /dev/null
+++ b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/core/common/constant/travelcard/TravelCardStatusEnum.java
@@ -0,0 +1,17 @@
+package com.stylefeng.guns.core.common.constant.travelcard;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum TravelCardStatusEnum {
+
+    UN_RECHARGE(1, "未充值"),
+
+    RECHARGED(2, "已充值");
+
+    private final Integer code;
+
+    private final String desc;
+}
diff --git a/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/general/TTravelCardController.java b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/general/TTravelCardController.java
new file mode 100644
index 0000000..ae83eb6
--- /dev/null
+++ b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/general/TTravelCardController.java
@@ -0,0 +1,132 @@
+package com.stylefeng.guns.modular.system.controller.general;
+
+import com.baomidou.mybatisplus.plugins.Page;
+import com.stylefeng.guns.core.base.controller.BaseController;
+import com.stylefeng.guns.core.common.constant.factory.PageFactory;
+import com.stylefeng.guns.core.util.DateUtil;
+import com.stylefeng.guns.core.util.SinataUtil;
+import com.stylefeng.guns.modular.system.model.*;
+import com.stylefeng.guns.modular.system.service.*;
+import com.stylefeng.guns.modular.system.util.ExcelExportUtil;
+import com.stylefeng.guns.modular.system.util.ResultUtil;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.*;
+
+/**
+ * 出行卡管理控制器
+ *
+ * @author sky
+ * @since 2026-06-17 15:47:58
+ */
+@Slf4j
+@AllArgsConstructor
+@Controller
+@RequestMapping("/travelCard")
+public class TTravelCardController extends BaseController {
+    
+    private final String PREFIX = "/system/tTravelCard/";
+
+    private final ITravelCardService travelCardService;
+
+    private final ITravelCardPackageService travelCardPackageService;
+
+    /**
+     * 跳转到用户管理首页
+     */
+    @RequestMapping("")
+    public String index() {
+        return PREFIX + "tTravelCard.html";
+    }
+
+    /**
+     * 跳转到添加页面
+     */
+    @RequestMapping("/tTravelCardAdd")
+    public String showAddCarInsurance(){
+        return PREFIX + "tTravelCardAdd.html";
+    }
+
+
+    /**
+     * 获取出行卡包,管理列表
+     */
+    @RequestMapping(value = "/list")
+    @ResponseBody
+    public Object list(String name) {
+        Page<Map<String, Object>> page = new PageFactory<Map<String, Object>>().defaultPage();
+        page.setRecords(travelCardPackageService.getTravelCardPackageList(page, name));
+        return super.packForBT(page);
+    }
+
+    /**
+     * 添加出行卡包
+     */
+    @ResponseBody
+    @RequestMapping(value = "/saveTravelCard", method = RequestMethod.POST)
+    public ResultUtil<Integer> saveTravelCard(TravelCardPackage travelCardPackage){
+        Integer id = travelCardPackageService.saveTravelCard(travelCardPackage);
+        return ResultUtil.success(id);
+    }
+
+    /**
+     *  导出出行卡信息
+     */
+    @RequestMapping(value = "/outTravelCard")
+    public void outTravelCard(HttpServletRequest request, HttpServletResponse response, Integer packageId) {
+        List<Map<String, Object>> listMap = travelCardService.getTravelCardByPackageId(packageId);
+
+        // 表格数据【封装】
+        List<List<String>> dataList = new ArrayList<>();
+
+        //第一行显示【封装】
+        List<String> twoList = new ArrayList<String>();
+        twoList.add("总计:");
+        twoList.add(listMap.size() +"条");
+        dataList.add(twoList);
+
+        // 列【封装】
+        List<String> shellList = new ArrayList<String>();
+        shellList.add("卡号");
+        shellList.add("卡密码");
+        shellList.add("卡金额");
+        dataList.add(shellList);
+
+        for (Map<String,Object> object : listMap){
+            // 详细数据列【封装】
+            shellList = new ArrayList<String>();
+
+            if(SinataUtil.isNotEmpty(object.get("cardNo"))){
+                shellList.add(object.get("cardNo").toString());
+            }else{
+                shellList.add("-");
+            }
+            if(SinataUtil.isNotEmpty(object.get("cardPassword"))){
+                shellList.add(object.get("cardPassword").toString());
+            }else{
+                shellList.add("-");
+            }
+            if(SinataUtil.isNotEmpty(object.get("amount"))){
+                shellList.add(object.get("amount").toString());
+            }else{
+                shellList.add("-");
+            }
+            dataList.add(shellList);
+        }
+        try {
+            // 调用工具类进行导出
+            ExcelExportUtil.easySheet("出行卡信息导出记录"+DateUtil.formatDate(new Date(), "YYYYMMddHHmmss"), "=出行卡信息导出记录", dataList,request, response);
+        } catch (Exception e) {
+            log.error("出行卡导出异常:", e);
+        }
+    }
+
+
+
+
+}
diff --git a/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/TravelCardMapper.java b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/TravelCardMapper.java
new file mode 100644
index 0000000..1dd72e8
--- /dev/null
+++ b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/TravelCardMapper.java
@@ -0,0 +1,17 @@
+package com.stylefeng.guns.modular.system.dao;
+
+import com.baomidou.mybatisplus.mapper.BaseMapper;
+import com.stylefeng.guns.modular.system.model.TravelCard;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+
+public interface TravelCardMapper extends BaseMapper<TravelCard> {
+
+    String getMaxCardNo();
+
+    List<Map<String, Object>> getTravelCardByPackageId(@Param("packageId") Integer packageId);
+
+}
diff --git a/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/TravelCardPackageMapper.java b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/TravelCardPackageMapper.java
new file mode 100644
index 0000000..c5259cf
--- /dev/null
+++ b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/TravelCardPackageMapper.java
@@ -0,0 +1,15 @@
+package com.stylefeng.guns.modular.system.dao;
+
+import com.baomidou.mybatisplus.mapper.BaseMapper;
+import com.baomidou.mybatisplus.plugins.Page;
+import com.stylefeng.guns.modular.system.model.TravelCardPackage;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+
+public interface TravelCardPackageMapper extends BaseMapper<TravelCardPackage> {
+
+    List<Map<String, Object>> getTravelCardPackageList(@Param("page") Page<Map<String, Object>> page, @Param("name") String name);
+}
diff --git a/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TravelCard.xml b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TravelCard.xml
new file mode 100644
index 0000000..a6ce3ac
--- /dev/null
+++ b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TravelCard.xml
@@ -0,0 +1,13 @@
+<?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.stylefeng.guns.modular.system.dao.TravelCardMapper">
+
+    <select id="getMaxCardNo" resultType="java.lang.String">
+        select max(cardNo) from t_travel_card
+    </select>
+
+    <select id="getTravelCardByPackageId" resultType="java.util.Map">
+        select * from t_travel_card c where c.packageId = #{packageId}
+    </select>
+
+</mapper>
\ No newline at end of file
diff --git a/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TravelCardPackage.xml b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TravelCardPackage.xml
new file mode 100644
index 0000000..7fb531b
--- /dev/null
+++ b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TravelCardPackage.xml
@@ -0,0 +1,26 @@
+<?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.stylefeng.guns.modular.system.dao.TravelCardPackageMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.stylefeng.guns.modular.system.model.TravelCardPackage">
+        <id column="id" property="id" />
+        <result column="name" property="name" />
+        <result column="amount" property="amount" />
+        <result column="total" property="total" />
+        <result column="operator" property="operator" />
+        <result column="insertTime" property="insertTime" />
+        <result column="updateTime" property="updateTime" />
+    </resultMap>
+
+    <select id="getTravelCardPackageList" resultType="java.util.Map" parameterType="com.baomidou.mybatisplus.plugins.Page">
+        SELECT * FROM t_travel_card_package as c
+        <where>
+            <if test="name != null and name != ''">
+                and c.name = #{name}
+            </if>
+        </where>
+        order by c.id desc
+    </select>
+
+</mapper>
\ No newline at end of file
diff --git a/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TravelCard.java b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TravelCard.java
new file mode 100644
index 0000000..1e9a2b6
--- /dev/null
+++ b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TravelCard.java
@@ -0,0 +1,187 @@
+package com.stylefeng.guns.modular.system.model;
+
+import com.baomidou.mybatisplus.activerecord.Model;
+import com.baomidou.mybatisplus.annotations.TableId;
+import com.baomidou.mybatisplus.annotations.TableName;
+import com.baomidou.mybatisplus.enums.IdType;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * <p>
+ *  出行卡包
+ * </p>
+ */
+@TableName("t_travel_card")
+public class TravelCard extends Model<TravelCard> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 卡包ID
+     */
+    private Integer packageId;
+
+    /**
+     * 卡号
+     */
+    private String cardNo;
+
+    /**
+     * 卡密码
+     */
+    private String cardPassword;
+
+    /**
+     * 卡金额
+     */
+    private BigDecimal amount;
+
+    /**
+     * 状态:1未充值,2已充值
+     */
+    private Integer status;
+
+    /**
+     * 充值用户ID
+     */
+    private Integer rechargeUserId;
+
+    /**
+     * 充值用户手机号
+     */
+    private String rechargeUserPhone;
+
+    /**
+     * 充值金额
+     */
+    private BigDecimal rechargeAmount;
+
+    /**
+     * 充值时间
+     */
+    private Date rechargeTime;
+
+    /**
+     * 创建时间
+     */
+    private Date insertTime;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public Integer getPackageId() {
+        return packageId;
+    }
+
+    public void setPackageId(Integer packageId) {
+        this.packageId = packageId;
+    }
+
+    public String getCardNo() {
+        return cardNo;
+    }
+
+    public void setCardNo(String cardNo) {
+        this.cardNo = cardNo;
+    }
+
+    public String getCardPassword() {
+        return cardPassword;
+    }
+
+    public void setCardPassword(String cardPassword) {
+        this.cardPassword = cardPassword;
+    }
+
+    public BigDecimal getAmount() {
+        return amount;
+    }
+
+    public void setAmount(BigDecimal amount) {
+        this.amount = amount;
+    }
+
+    public Integer getStatus() {
+        return status;
+    }
+
+    public void setStatus(Integer status) {
+        this.status = status;
+    }
+
+    public Integer getRechargeUserId() {
+        return rechargeUserId;
+    }
+
+    public void setRechargeUserId(Integer rechargeUserId) {
+        this.rechargeUserId = rechargeUserId;
+    }
+
+    public String getRechargeUserPhone() {
+        return rechargeUserPhone;
+    }
+
+    public void setRechargeUserPhone(String rechargeUserPhone) {
+        this.rechargeUserPhone = rechargeUserPhone;
+    }
+
+    public BigDecimal getRechargeAmount() {
+        return rechargeAmount;
+    }
+
+    public void setRechargeAmount(BigDecimal rechargeAmount) {
+        this.rechargeAmount = rechargeAmount;
+    }
+
+    public Date getRechargeTime() {
+        return rechargeTime;
+    }
+
+    public void setRechargeTime(Date rechargeTime) {
+        this.rechargeTime = rechargeTime;
+    }
+
+    public Date getInsertTime() {
+        return insertTime;
+    }
+
+    public void setInsertTime(Date insertTime) {
+        this.insertTime = insertTime;
+    }
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+    @Override
+    public String toString() {
+        return "TravelCard{" +
+                "id=" + id +
+                ", packageId=" + packageId +
+                ", cardNo='" + cardNo + '\'' +
+                ", cardPassword='" + cardPassword + '\'' +
+                ", amount=" + amount +
+                ", status=" + status +
+                ", rechargeUserId=" + rechargeUserId +
+                ", rechargeUserPhone='" + rechargeUserPhone + '\'' +
+                ", rechargeAmount=" + rechargeAmount +
+                ", rechargeTime=" + rechargeTime +
+                ", insertTime=" + insertTime +
+                '}';
+    }
+}
diff --git a/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TravelCardPackage.java b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TravelCardPackage.java
new file mode 100644
index 0000000..6a1591c
--- /dev/null
+++ b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TravelCardPackage.java
@@ -0,0 +1,130 @@
+package com.stylefeng.guns.modular.system.model;
+
+import com.baomidou.mybatisplus.activerecord.Model;
+import com.baomidou.mybatisplus.annotations.TableId;
+import com.baomidou.mybatisplus.annotations.TableName;
+import com.baomidou.mybatisplus.enums.IdType;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * <p>
+ *  出行卡包
+ * </p>
+ */
+@TableName("t_travel_card_package")
+public class TravelCardPackage extends Model<TravelCardPackage> {
+
+    private static final long serialVersionUID = 1L;
+    /**
+     * 主键id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 卡包名称
+     */
+    private String name;
+
+    /**
+     * 金额
+     */
+    private BigDecimal amount;
+
+    /**
+     * 数量
+     */
+    private Integer total;
+
+    /**
+     * 操作人
+     */
+    private Integer operator;
+
+    /**
+     * 创建时间
+     */
+    private Date insertTime;
+
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public BigDecimal getAmount() {
+        return amount;
+    }
+
+    public void setAmount(BigDecimal amount) {
+        this.amount = amount;
+    }
+
+    public Integer getTotal() {
+        return total;
+    }
+
+    public void setTotal(Integer total) {
+        this.total = total;
+    }
+
+    public Integer getOperator() {
+        return operator;
+    }
+
+    public void setOperator(Integer operator) {
+        this.operator = operator;
+    }
+
+    public Date getInsertTime() {
+        return insertTime;
+    }
+
+    public void setInsertTime(Date insertTime) {
+        this.insertTime = insertTime;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+    @Override
+    public String toString() {
+        return "TravelCardPackage{" +
+                "id=" + id +
+                ", name='" + name + '\'' +
+                ", amount=" + amount +
+                ", total=" + total +
+                ", operator=" + operator +
+                ", insertTime=" + insertTime +
+                ", updateTime=" + updateTime +
+                '}';
+    }
+}
diff --git a/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ITravelCardPackageService.java b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ITravelCardPackageService.java
new file mode 100644
index 0000000..a77ce9a
--- /dev/null
+++ b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ITravelCardPackageService.java
@@ -0,0 +1,32 @@
+package com.stylefeng.guns.modular.system.service;
+
+import com.baomidou.mybatisplus.plugins.Page;
+import com.baomidou.mybatisplus.service.IService;
+import com.stylefeng.guns.modular.system.model.TravelCardPackage;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ *     出行卡包服务
+ * </p>
+ */
+public interface ITravelCardPackageService extends IService<TravelCardPackage> {
+
+
+    /**
+     * 获取出行卡包列表
+     * @param page 分页
+     * @param name 卡包名称
+     * @return 列表数据
+     */
+    List<Map<String, Object>> getTravelCardPackageList(Page<Map<String, Object>> page, String name);
+
+    /**
+     * 保存出行卡包
+     *
+     * @param travelCardPackage 卡包信息
+     */
+    Integer saveTravelCard(TravelCardPackage travelCardPackage);
+}
diff --git a/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ITravelCardService.java b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ITravelCardService.java
new file mode 100644
index 0000000..707020c
--- /dev/null
+++ b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ITravelCardService.java
@@ -0,0 +1,34 @@
+package com.stylefeng.guns.modular.system.service;
+
+import com.baomidou.mybatisplus.service.IService;
+import com.stylefeng.guns.modular.system.model.TravelCard;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ *     出行卡服务
+ * </p>
+ */
+public interface ITravelCardService extends IService<TravelCard> {
+
+
+    /**
+     * 生成出行卡
+     *
+     * @param packageId 卡包ID
+     * @param amount 卡金额
+     * @param total 卡数量
+     */
+     boolean generateTravelCard(Integer packageId, BigDecimal amount, Integer total);
+
+    /**
+     * 根据卡包查询出行卡
+     *
+     * @param packageId 卡包ID
+     * @return 出行卡列表
+     */
+    List<Map<String, Object>> getTravelCardByPackageId(Integer packageId);
+}
diff --git a/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TravelCardPackageServiceImpl.java b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TravelCardPackageServiceImpl.java
new file mode 100644
index 0000000..f514eb4
--- /dev/null
+++ b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TravelCardPackageServiceImpl.java
@@ -0,0 +1,57 @@
+package com.stylefeng.guns.modular.system.service.impl;
+
+import com.baomidou.mybatisplus.plugins.Page;
+import com.baomidou.mybatisplus.service.impl.ServiceImpl;
+import com.stylefeng.guns.modular.system.dao.TravelCardPackageMapper;
+import com.stylefeng.guns.modular.system.model.TravelCardPackage;
+import com.stylefeng.guns.modular.system.service.ITravelCardPackageService;
+import com.stylefeng.guns.modular.system.service.ITravelCardService;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * <p>
+ *     出行卡包,服务实现类
+ * </p>
+ * @author Lux
+ * @version 1.0.0
+ * @since 2026/6/17 18:21
+ */
+@Slf4j
+@Service
+@AllArgsConstructor
+public class TravelCardPackageServiceImpl extends ServiceImpl<TravelCardPackageMapper, TravelCardPackage> implements ITravelCardPackageService {
+
+    private final ITravelCardService travelCardService;
+
+    /**
+     * 获取出行卡包列表
+     * @param page 分页
+     * @param name 卡包名称
+     * @return 列表数据
+     */
+   public List<Map<String, Object>> getTravelCardPackageList(Page<Map<String, Object>> page, String name) {
+       return this.baseMapper.getTravelCardPackageList(page, name);
+    }
+
+    /**
+     * 保存出行卡包
+     *
+     * @param travelCardPackage 卡包信息
+     */
+    @Transactional
+    public Integer saveTravelCard(TravelCardPackage travelCardPackage) {
+        Optional.ofNullable(travelCardPackage).orElseThrow(() -> new RuntimeException("保存出行卡包数据不能为空!"));
+        this.baseMapper.insert(travelCardPackage);
+        // 生成出行卡
+        boolean flag = travelCardService.generateTravelCard(travelCardPackage.getId(), travelCardPackage.getAmount(), travelCardPackage.getTotal());
+        log.info("出行卡包保存,生成出行卡结果:{}", flag);
+        return travelCardPackage.getId();
+    }
+}
diff --git a/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TravelCardServiceImpl.java b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TravelCardServiceImpl.java
new file mode 100644
index 0000000..6741a7f
--- /dev/null
+++ b/ManagementYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TravelCardServiceImpl.java
@@ -0,0 +1,95 @@
+package com.stylefeng.guns.modular.system.service.impl;
+
+import com.baomidou.mybatisplus.service.impl.ServiceImpl;
+import com.stylefeng.guns.core.common.constant.travelcard.TravelCardStatusEnum;
+import com.stylefeng.guns.modular.system.dao.TravelCardMapper;
+import com.stylefeng.guns.modular.system.model.TravelCard;
+import com.stylefeng.guns.modular.system.service.ITravelCardService;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.security.SecureRandom;
+import java.util.*;
+
+/**
+ * <p>
+ *    出行卡,服务实现类
+ * </p>
+ * @author Lux
+ * @version 1.0.0
+ * @since 2026/6/17 18:21
+ */
+@Slf4j
+@Service
+@AllArgsConstructor
+public class TravelCardServiceImpl extends ServiceImpl<TravelCardMapper, TravelCard> implements ITravelCardService {
+
+    private static final char[] PASSWORD_CHARS = {'A','B','C','D','E','F','G','H', 'J','K','M','N','P','Q','R','S', 'T','U','V','W','X','Y','Z'};
+    private static final SecureRandom RANDOM = new SecureRandom();
+
+    /**
+     * 生成出行卡
+     *
+     * @param packageId 卡包ID
+     * @param amount 卡金额
+     * @param total 卡数量
+     */
+    public boolean generateTravelCard(Integer packageId, BigDecimal amount, Integer total) {
+        if(Objects.isNull(packageId)) {
+            log.error("生成出行卡-卡包ID为空,则不执行生成逻辑!");
+            return false;
+        }
+        if(Objects.isNull(total) || Objects.isNull(amount)) {
+            log.error("生成出行卡-金额或数量为空,则不执行生成逻辑!");
+            return false;
+        }
+        // 1、查询当前最大卡号
+        String maxCardNo = this.baseMapper.getMaxCardNo();
+        int startNo;
+        // 第一批卡从011001开始
+        if (StringUtils.isBlank(maxCardNo)) {
+            startNo = 11001;
+        } else {
+            startNo = Integer.parseInt(maxCardNo) + 1;
+        }
+        // 2、生成卡信息
+        List<TravelCard> dataList = new ArrayList<>(total);
+        Date now = new Date();
+        for (int i = 0; i < total; i++) {
+            TravelCard card = new TravelCard();
+            card.setPackageId(packageId);
+            String cardNo = String.format("%06d", startNo + i);
+            card.setCardNo(cardNo);    // 卡号
+            card.setCardPassword(generatePassword());  // 密码
+            card.setAmount(amount); // 金额
+            card.setStatus(TravelCardStatusEnum.UN_RECHARGE.getCode());   // 未充值
+            card.setInsertTime(now);
+            dataList.add(card);
+        }
+        return true;
+    }
+
+    /**
+     * 生成6位密码
+     */
+    private String generatePassword() {
+        StringBuilder sb = new StringBuilder(6);
+        for (int i = 0; i < 6; i++) {
+            sb.append(PASSWORD_CHARS[RANDOM.nextInt(PASSWORD_CHARS.length)]);
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 根据卡包查询出行卡
+     *
+     * @param packageId 卡包ID
+     * @return 出行卡列表
+     */
+    public List<Map<String, Object>> getTravelCardByPackageId(Integer packageId) {
+        return this.baseMapper.getTravelCardByPackageId(packageId);
+    }
+}
diff --git a/ManagementYKDTravel/guns-admin/src/test/sql/t_travel_card.sql b/ManagementYKDTravel/guns-admin/src/test/sql/t_travel_card.sql
new file mode 100644
index 0000000..51b3aa1
--- /dev/null
+++ b/ManagementYKDTravel/guns-admin/src/test/sql/t_travel_card.sql
@@ -0,0 +1,28 @@
+
+CREATE TABLE IF NOT EXISTS `t_travel_card_package` (
+   `id` int NOT NULL AUTO_INCREMENT COMMENT '主键id',
+   `name`  varchar(255) NULL COMMENT '卡包名称',
+    `amount` decimal(10,2) NULL COMMENT '金额',
+    `total` int NULL COMMENT '数量',
+    `operator` int NULL COMMENT '操作人',
+    `insertTime` datetime DEFAULT NULL COMMENT '创建时间',
+    `updateTime` datetime DEFAULT NULL COMMENT '更新时间',
+    PRIMARY KEY (`id`)
+    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='出行卡包';
+
+
+CREATE TABLE IF NOT EXISTS `t_travel_card` (
+   `id` int NOT NULL AUTO_INCREMENT COMMENT '主键id',
+   `packageId` int NULL COMMENT '卡包ID',
+   `cardNo`  varchar(50) NULL COMMENT '卡号',
+    `cardPassword`  varchar(50) NULL COMMENT '卡密码',
+    `amount` decimal(10,2) NULL COMMENT '卡金额',
+    `status` int NULL COMMENT '状态:1未充值,2已充值',
+    `rechargeUserId` int NULL COMMENT '充值用户ID',
+    `rechargeUserPhone`  varchar(50) NULL COMMENT '充值用户手机号',
+    `rechargeAmount` decimal(10,2) NULL COMMENT '充值金额',
+    `rechargeTime` datetime DEFAULT NULL COMMENT '充值时间',
+    `insertTime` datetime DEFAULT NULL COMMENT '创建时间',
+    PRIMARY KEY (`id`),
+    UNIQUE KEY `uk_card_no` (`cardNo`)
+    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='出行卡';
\ No newline at end of file

--
Gitblit v1.7.1