diff --git a/.idea/misc.xml b/.idea/misc.xml
index 639900d..e2044d1 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,6 +1,14 @@
-
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 7ddf35f..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/system/Enum/VideoTagEnum.java b/src/main/java/com/ruoyi/system/Enum/VideoTagEnum.java
new file mode 100644
index 0000000..607ff85
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/Enum/VideoTagEnum.java
@@ -0,0 +1,39 @@
+package com.ruoyi.system.Enum;
+
+/**
+ * @author: Larry
+ * @Date: 2023 /12 /06 / 15:23
+ * @Description:
+ */
+public enum VideoTagEnum {
+ ACTION(1, "鬼畜"),
+ COMEDY(2, "色情"),
+ DRAMA(3, "运动"),
+ ROMANCE(4, "火影忍者");
+
+ private int id;
+ private String type;
+
+ VideoTagEnum(int id, String type) {
+ this.id = id;
+ this.type = type;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public static VideoTagEnum getById(int id) {
+ for (VideoTagEnum tag : values()) {
+ if (tag.getId() == id) {
+ return tag;
+ }
+ }
+ throw new IllegalArgumentException("Invalid VideoTagEnum id: " + id);
+ }
+}
+
diff --git a/src/main/java/com/ruoyi/system/Interceptor/LoginInterceptor.java b/src/main/java/com/ruoyi/system/Interceptor/LoginInterceptor.java
new file mode 100644
index 0000000..b485bb3
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/Interceptor/LoginInterceptor.java
@@ -0,0 +1,40 @@
+package com.ruoyi.system.Interceptor;
+
+import com.zy.util.BaseContext;
+import com.zy.util.TokenUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author: Larry
+ * @Date: 2023 /11 /22 / 21:40
+ * @Description:
+ */
+@Slf4j
+@Component
+public class LoginInterceptor implements HandlerInterceptor {
+ @Resource
+ RedisTemplate redisTemplate;
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+ String token = request.getHeader("token");
+ log.info(token);
+ Long userId = TokenUtil.verifyToken(token);
+ if (userId > 0) {
+ BaseContext.setCurrentId(userId);
+ Date passTime = TokenUtil.getTokenExpirationTime(token);
+ log.info(passTime.toString());
+ redisTemplate.opsForValue().set("token"+userId,passTime.toString(),1, TimeUnit.HOURS);
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/Interceptor/RefreshTokenInterceptor.java b/src/main/java/com/ruoyi/system/Interceptor/RefreshTokenInterceptor.java
new file mode 100644
index 0000000..61955bb
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/Interceptor/RefreshTokenInterceptor.java
@@ -0,0 +1,32 @@
+package com.ruoyi.system.Interceptor;
+
+import com.zy.util.TokenUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @author: Larry
+ * @Date: 2023 /11 /23 / 8:40
+ * @Description:
+ */
+@Component
+@Slf4j
+public class RefreshTokenInterceptor implements HandlerInterceptor {
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+ String token = request.getHeader("token");
+ try {
+ Long id = TokenUtil.verifyToken(token);
+ TokenUtil.generateRefreshToken(id);
+ log.info("刷新成功");
+ return true ;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/adapter/port/package-info.java b/src/main/java/com/ruoyi/system/adapter/port/package-info.java
new file mode 100644
index 0000000..a67ae85
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/adapter/port/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * 实现对外部的api调用,类的名称为 XxxPort 接口定义在 domain 中
+ */
+package com.ruoyi.system.adapter.port;
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/system/adapter/repository/ActivityRepository.java b/src/main/java/com/ruoyi/system/adapter/repository/ActivityRepository.java
new file mode 100644
index 0000000..ad0ef0e
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/adapter/repository/ActivityRepository.java
@@ -0,0 +1,81 @@
+package com.ruoyi.system.adapter.repository;
+
+import cn.bugstack.domain.activity.adapter.repository.IActivityRepository;
+import cn.bugstack.domain.activity.model.valobj.GroupBuyActivityDiscountVO;
+import cn.bugstack.domain.activity.model.valobj.SkuVO;
+import cn.bugstack.infrastructure.dao.IGroupBuyActivityDao;
+import cn.bugstack.infrastructure.dao.IGroupBuyDiscountDao;
+import cn.bugstack.infrastructure.dao.ISkuDao;
+import cn.bugstack.infrastructure.dao.po.GroupBuyActivity;
+import cn.bugstack.infrastructure.dao.po.GroupBuyDiscount;
+import cn.bugstack.infrastructure.dao.po.Sku;
+import org.springframework.stereotype.Repository;
+
+import javax.annotation.Resource;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 活动仓储
+ * @create 2024-12-21 10:10
+ */
+@Repository
+public class ActivityRepository implements IActivityRepository {
+
+ @Resource
+ private IGroupBuyActivityDao groupBuyActivityDao;
+ @Resource
+ private IGroupBuyDiscountDao groupBuyDiscountDao;
+
+ @Resource
+ private ISkuDao skuDao;
+
+ @Override
+ public GroupBuyActivityDiscountVO queryGroupBuyActivityDiscountVO(String source, String channel) {
+ // 根据SC渠道值查询配置中最新的1个有效的活动
+ GroupBuyActivity groupBuyActivityReq = new GroupBuyActivity();
+ groupBuyActivityReq.setSource(source);
+ groupBuyActivityReq.setChannel(channel);
+ GroupBuyActivity groupBuyActivityRes = groupBuyActivityDao.queryValidGroupBuyActivity(groupBuyActivityReq);
+
+ String discountId = groupBuyActivityRes.getDiscountId();
+
+ GroupBuyDiscount groupBuyDiscountRes = groupBuyDiscountDao.queryGroupBuyActivityDiscountByDiscountId(discountId);
+ GroupBuyActivityDiscountVO.GroupBuyDiscount groupBuyDiscount = GroupBuyActivityDiscountVO.GroupBuyDiscount.builder()
+ .discountName(groupBuyDiscountRes.getDiscountName())
+ .discountDesc(groupBuyDiscountRes.getDiscountDesc())
+ .discountType(groupBuyDiscountRes.getDiscountType())
+ .marketPlan(groupBuyDiscountRes.getMarketPlan())
+ .marketExpr(groupBuyDiscountRes.getMarketExpr())
+ .tagId(groupBuyDiscountRes.getTagId())
+ .build();
+
+ return GroupBuyActivityDiscountVO.builder()
+ .activityId(groupBuyActivityRes.getActivityId())
+ .activityName(groupBuyActivityRes.getActivityName())
+ .source(groupBuyActivityRes.getSource())
+ .channel(groupBuyActivityRes.getChannel())
+ .goodsId(groupBuyActivityRes.getGoodsId())
+ .groupBuyDiscount(groupBuyDiscount)
+ .groupType(groupBuyActivityRes.getGroupType())
+ .takeLimitCount(groupBuyActivityRes.getTakeLimitCount())
+ .target(groupBuyActivityRes.getTarget())
+ .validTime(groupBuyActivityRes.getValidTime())
+ .status(groupBuyActivityRes.getStatus())
+ .startTime(groupBuyActivityRes.getStartTime())
+ .endTime(groupBuyActivityRes.getEndTime())
+ .tagId(groupBuyActivityRes.getTagId())
+ .tagScope(groupBuyActivityRes.getTagScope())
+ .build();
+ }
+
+ @Override
+ public SkuVO querySkuByGoodsId(String goodsId) {
+ Sku sku = skuDao.querySkuByGoodsId(goodsId);
+ return SkuVO.builder()
+ .goodsId(sku.getGoodsId())
+ .goodsName(sku.getGoodsName())
+ .originalPrice(sku.getOriginalPrice())
+ .build();
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/system/adapter/repository/package-info.java b/src/main/java/com/ruoyi/system/adapter/repository/package-info.java
new file mode 100644
index 0000000..537d212
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/adapter/repository/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * 仓储实现;用于实现 domain 中定义的仓储接口,如;IXxxRepository 在 Repository 中调用服务
+ */
+package com.ruoyi.system.adapter.repository;
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/system/ai/annotation/LogicStrategy.java b/src/main/java/com/ruoyi/system/ai/annotation/LogicStrategy.java
new file mode 100644
index 0000000..739e6a9
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/annotation/LogicStrategy.java
@@ -0,0 +1,18 @@
+package com.ruoyi.system.ai.annotation;
+import com.muta.ai.chain.DefaultChainFactory;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /01 / 0:10
+ * @Description: 规则过滤注解
+ */
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface LogicStrategy {
+ DefaultChainFactory.LogicModel logicMode();
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/chain/AbstractLogicChain.java b/src/main/java/com/ruoyi/system/ai/chain/AbstractLogicChain.java
new file mode 100644
index 0000000..008351a
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/chain/AbstractLogicChain.java
@@ -0,0 +1,30 @@
+package com.ruoyi.system.ai.chain;
+
+import com.muta.ai.domain.RuleLogicEntity;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 抽奖策略责任链,判断走那种抽奖策略。如;默认抽象、权重抽奖、黑名单抽奖
+ * @create 2024-01-20 09:37
+ */
+@Slf4j
+public abstract class AbstractLogicChain implements ILogicChain {
+
+ private ILogicChain next;
+
+ @Override
+ public ILogicChain next() {
+ return next;
+ }
+
+ @Override
+ public ILogicChain appendNext(ILogicChain next) {
+ this.next = next;
+ return next;
+ }
+
+ protected abstract String ruleModel();
+
+ public abstract RuleLogicEntity logic(UserAccountQuotaEntity userAccountQuotaEntity, MusicProcessAggregate chatProcessAggregate);
+}
diff --git a/src/main/java/com/ruoyi/system/ai/chain/BackListLogicChain.java b/src/main/java/com/ruoyi/system/ai/chain/BackListLogicChain.java
new file mode 100644
index 0000000..b7e148c
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/chain/BackListLogicChain.java
@@ -0,0 +1,36 @@
+package com.ruoyi.system.ai.chain;
+
+import com.muta.ai.annotation.LogicStrategy;
+import com.muta.ai.chain.MusicProcessAggregate;
+import com.muta.ai.domain.RuleLogicEntity;
+import com.muta.ai.chain.UserAccountQuotaEntity;
+import com.muta.ai.chain.DefaultChainFactory;
+import com.muta.ai.chain.AbstractLogicChain;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 黑名单责任链
+ * @create 2024-01-20 10:23
+ */
+@Slf4j
+@Component("rule_blacklist")
+@LogicStrategy(logicMode = DefaultChainFactory.LogicModel.RULE_BLACKLIST)
+public class BackListLogicChain extends AbstractLogicChain {
+
+ ;
+
+ @Override
+ protected String ruleModel() {
+ return DefaultChainFactory.LogicModel.RULE_BLACKLIST.getCode();
+ }
+
+
+ @Override
+ public RuleLogicEntity logic(UserAccountQuotaEntity userAccountQuotaEntity, MusicProcessAggregate chatProcessAggregate) {
+ return null;
+ }
+
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/chain/DefaultChainFactory.java b/src/main/java/com/ruoyi/system/ai/chain/DefaultChainFactory.java
new file mode 100644
index 0000000..dad19bd
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/chain/DefaultChainFactory.java
@@ -0,0 +1,70 @@
+package com.ruoyi.system.ai.chain;
+
+import com.muta.ai.annotation.LogicStrategy;
+import lombok.*;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 工厂
+ * @create 2024-01-20 10:54
+ */
+@Service
+public class DefaultChainFactory {
+ public Map> logicFilterMap = new ConcurrentHashMap<>();
+
+ public DefaultChainFactory(List> logicFilters) {
+ logicFilters.forEach(logic -> {
+ LogicStrategy strategy = AnnotationUtils.findAnnotation(logic.getClass(), LogicStrategy.class);
+ if (null != strategy) {
+ logicFilterMap.put(strategy.logicMode().getCode(), logic);
+ }
+ });
+ }
+
+ /**
+ * 通过策略ID,构建责任链
+ * @return LogicChain
+ */
+ public ILogicChain openLogicChain(Long test) {
+
+ List ruleModels = new ArrayList<>();
+ ruleModels.add(LogicModel.RULE_BLACKLIST.code);
+ ruleModels.add(LogicModel.RULE_WEIGHT.code);
+ ILogicChain current = logicFilterMap.get(LogicModel.RULE_BLACKLIST.getCode());
+ System.out.println(current+"current");
+ for (int i = 1; i < ruleModels.size(); i++) {
+ System.out.println(ruleModels.get(i));
+ ILogicChain nextChain = logicFilterMap.get(ruleModels.get(i));
+ System.out.println(nextChain);
+ current = current.appendNext(nextChain);
+ }
+ current.appendNext(logicFilterMap.get(LogicModel.RULE_DEFAULT.code));
+
+ return current;
+ }
+
+
+
+ @Getter
+ @AllArgsConstructor
+ public enum LogicModel {
+
+ RULE_DEFAULT("rule_default", "默认抽奖"),
+ RULE_BLACKLIST("rule_blacklist", "黑名单抽奖"),
+ RULE_WEIGHT("rule_weight", "权重规则"),
+ RULE_SENSITIVE_WORDS("rule_sensitive_words", "敏感词规则过滤"),
+ RULE_SING("rule_sing", "歌曲过滤"),
+ ;
+ private final String code;
+ private final String info;
+
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/chain/DefaultLogicChain.java b/src/main/java/com/ruoyi/system/ai/chain/DefaultLogicChain.java
new file mode 100644
index 0000000..9256eca
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/chain/DefaultLogicChain.java
@@ -0,0 +1,35 @@
+package com.ruoyi.system.ai.chain;
+
+import com.muta.ai.annotation.LogicStrategy;
+import com.muta.ai.chain.MusicProcessAggregate;
+import com.muta.ai.domain.RuleLogicEntity;
+import com.muta.ai.chain.UserAccountQuotaEntity;
+import com.muta.ai.chain.DefaultChainFactory;
+import com.muta.ai.chain.AbstractLogicChain;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 默认的责任链「作为最后一个链」
+ * @create 2024-01-20 10:06
+ */
+@Slf4j
+@Component("rule_default")
+@LogicStrategy(logicMode = DefaultChainFactory.LogicModel.RULE_DEFAULT)
+public class DefaultLogicChain extends AbstractLogicChain {
+
+
+ @Override
+ protected String ruleModel() {
+ return DefaultChainFactory.LogicModel.RULE_DEFAULT.getCode();
+ }
+
+ @Override
+ public RuleLogicEntity logic(UserAccountQuotaEntity userAccountQuotaEntity, MusicProcessAggregate chatProcessAggregate) {
+ System.out.println("测试注入");
+ return null;
+ }
+
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/chain/ILogicChain.java b/src/main/java/com/ruoyi/system/ai/chain/ILogicChain.java
new file mode 100644
index 0000000..e2ae8ae
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/chain/ILogicChain.java
@@ -0,0 +1,17 @@
+package com.ruoyi.system.ai.chain;
+
+import com.muta.ai.domain.RuleLogicEntity;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 抽奖策略规则责任链接口
+ * @create 2024-01-20 09:40
+ */
+public interface ILogicChain extends ILogicChainArmory, Cloneable {
+
+ /**
+ * 责任链接口
+ */
+ RuleLogicEntity logic(UserAccountQuotaEntity userAccountQuotaEntity, MusicProcessAggregate data);
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/chain/ILogicChainArmory.java b/src/main/java/com/ruoyi/system/ai/chain/ILogicChainArmory.java
new file mode 100644
index 0000000..12b1150
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/chain/ILogicChainArmory.java
@@ -0,0 +1,14 @@
+package com.ruoyi.system.ai.chain;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 责任链装配
+ * @create 2024-01-20 11:53
+ */
+public interface ILogicChainArmory {
+
+ ILogicChain next();
+
+ ILogicChain appendNext(ILogicChain next);
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/chain/MusicProcessAggregate.java b/src/main/java/com/ruoyi/system/ai/chain/MusicProcessAggregate.java
new file mode 100644
index 0000000..24988ed
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/chain/MusicProcessAggregate.java
@@ -0,0 +1,30 @@
+package com.ruoyi.system.ai.chain;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description
+ * @create 2023-07-22 21:09
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class MusicProcessAggregate {
+ /**
+ * 歌手ID
+ */
+ private Long singerId;
+ /**
+ * 音乐ID
+ */
+ private Integer musicId;
+ /** 提示词 */
+ private String prompt;
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/chain/RuleWeightLogicChain.java b/src/main/java/com/ruoyi/system/ai/chain/RuleWeightLogicChain.java
new file mode 100644
index 0000000..9ef25a8
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/chain/RuleWeightLogicChain.java
@@ -0,0 +1,40 @@
+package com.ruoyi.system.ai.chain;
+
+
+import com.muta.ai.annotation.LogicStrategy;
+import com.muta.ai.chain.MusicProcessAggregate;
+import com.muta.ai.domain.RuleLogicEntity;
+import com.muta.ai.chain.UserAccountQuotaEntity;
+import com.muta.ai.chain.DefaultChainFactory;
+import com.muta.ai.chain.AbstractLogicChain;
+import com.muta.system.service.IUserExtraService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 权重抽奖责任链
+ * @create 2024-01-20 10:38
+ */
+@Slf4j
+@Component("rule_UserAccountQuota")
+@LogicStrategy(logicMode = DefaultChainFactory.LogicModel.RULE_WEIGHT)
+public class RuleWeightLogicChain extends AbstractLogicChain {
+ @Resource
+ private IUserExtraService userExtraService;
+
+ @Override
+ protected String ruleModel() {
+ return DefaultChainFactory.LogicModel.RULE_WEIGHT.getCode();
+ }
+
+ @Override
+ public RuleLogicEntity logic(UserAccountQuotaEntity userAccountQuotaEntity, MusicProcessAggregate chatProcessAggregate) {
+ return null;
+ }
+
+
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/chain/UserAccountQuotaEntity.java b/src/main/java/com/ruoyi/system/ai/chain/UserAccountQuotaEntity.java
new file mode 100644
index 0000000..5b27984
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/chain/UserAccountQuotaEntity.java
@@ -0,0 +1,36 @@
+package com.ruoyi.system.ai.chain;
+
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 用户账户额度实体对象
+ * @create 2023-10-03 16:49
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class UserAccountQuotaEntity {
+ /**
+ * 用户ID
+ */
+ private Long userId;
+ /**
+ * 剩余额度
+ */
+ private Integer integral;
+ /**
+ * 会员等级
+ */
+ private Integer vipGrade;
+
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/config/ChatConfig.java b/src/main/java/com/ruoyi/system/ai/config/ChatConfig.java
new file mode 100644
index 0000000..86b1f32
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/config/ChatConfig.java
@@ -0,0 +1,24 @@
+package com.ruoyi.system.ai.config;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /11 / 14:18
+ * @Description:
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class ChatConfig {
+ private Long id;
+ private Long userId;
+ private float temperature;
+ private Integer maxToken;
+ private Integer n;
+ private float top;
+}
diff --git a/src/main/java/com/ruoyi/system/ai/config/CustomWordAllow.java b/src/main/java/com/ruoyi/system/ai/config/CustomWordAllow.java
new file mode 100644
index 0000000..f2da3f4
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/config/CustomWordAllow.java
@@ -0,0 +1,32 @@
+package com.ruoyi.system.ai.config;
+
+import com.github.houbb.sensitive.word.api.IWordAllow;
+import org.apache.commons.compress.utils.Lists;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 自定义敏感词白名单
+ *
+ * @author Larry
+ * @date 2024-05-18 15:07:01
+ */
+public class CustomWordAllow implements IWordAllow {
+
+ /**
+ * 允许的内容-返回的内容不被当做敏感词
+ *
+ * @return
+ */
+ @Override
+ public List allow() {
+ // 可以获取数据库数据或文件内容
+ List list = new ArrayList<>();
+ list.add("草");
+ list.add("小草");
+ list.add("");
+ return list;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/system/ai/config/CustomWordDeny.java b/src/main/java/com/ruoyi/system/ai/config/CustomWordDeny.java
new file mode 100644
index 0000000..54fc1f3
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/config/CustomWordDeny.java
@@ -0,0 +1,30 @@
+package com.ruoyi.system.ai.config;
+
+import com.github.houbb.sensitive.word.api.IWordDeny;
+import org.apache.commons.compress.utils.Lists;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 自定义敏感词黑名单
+ *
+ * @author Larry
+ * @date 2024-05-08 14:59:51
+ */
+public class CustomWordDeny implements IWordDeny {
+
+ /**
+ * 拒绝出现的数据-返回的内容被当做是敏感词
+ *
+ * @return
+ */
+ @Override
+ public List deny() {
+ // 可以获取数据库数据或文件内容
+ List list = new ArrayList<>();
+ list.add("测试");
+ return list;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/system/ai/config/LogicConfig.java b/src/main/java/com/ruoyi/system/ai/config/LogicConfig.java
new file mode 100644
index 0000000..b158dbf
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/config/LogicConfig.java
@@ -0,0 +1,70 @@
+package com.ruoyi.system.ai.config;//package com.muta.ai.config;
+//
+//import com.muta.ai.chain.UserAccountQuotaEntity;
+//import com.muta.ai.service.ILogicFilter;
+//import com.muta.ai.service.impl.SensitiveWordFilter;
+//import com.muta.ai.service.impl.TokenFilter;
+//import com.muta.ai.service.impl.UserQuotaFilter;
+//
+//import javax.annotation.PostConstruct;
+//import javax.annotation.Resource;
+//import java.util.Map;
+//import java.util.concurrent.ConcurrentHashMap;
+//
+///**
+// * @author: Larry
+// * @Date: 2024 /05 /09 / 20:35
+// * @Description:
+// */
+//public class LogicConfig {
+// public Map> logicFilterMap = new ConcurrentHashMap<>();
+// @Resource
+// private SensitiveWordFilter sensitiveWordFilter;
+// @Resource
+// private TokenFilter tokenFilter;
+// @Resource
+// private UserQuotaFilter userQuotaFilter;
+// @PostConstruct
+// private void init(){
+// logicFilterMap.put(LogicModel.SENSITIVE_WORD.code,sensitiveWordFilter);
+// logicFilterMap.put(LogicModel.MAX_TOKEN.code,tokenFilter);
+// logicFilterMap.put(LogicModel.USER_QUOTA.code, userQuotaFilter);
+//
+// }
+// public enum LogicModel {
+//
+// NULL("NULL", "放行不用过滤"),
+// MAX_TOKEN("TOKEN_LIMIT", "限制最大会话数"),
+// SENSITIVE_WORD("SENSITIVE_WORD", "敏感词过滤"),
+// USER_QUOTA("USER_QUOTA", "用户额度过滤"),
+//// MODEL_TYPE("MODEL_TYPE", "模型可用范围过滤"),
+//// ACCOUNT_STATUS("ACCOUNT_STATUS", "账户状态过滤"),
+//
+// ;
+//
+// private String code;
+// private String info;
+//
+// LogicModel(String code, String info) {
+// this.code = code;
+// this.info = info;
+// }
+//
+// public String getCode() {
+// return code;
+// }
+//
+// public void setCode(String code) {
+// this.code = code;
+// }
+//
+// public String getInfo() {
+// return info;
+// }
+//
+// public void setInfo(String info) {
+// this.info = info;
+// }
+// }
+//
+//}
diff --git a/src/main/java/com/ruoyi/system/ai/config/MessageMqConfig.java b/src/main/java/com/ruoyi/system/ai/config/MessageMqConfig.java
new file mode 100644
index 0000000..e8eda82
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/config/MessageMqConfig.java
@@ -0,0 +1,85 @@
+package com.ruoyi.system.ai.config;
+import lombok.Data;
+import org.springframework.amqp.core.Binding;
+import org.springframework.amqp.core.Exchange;
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.core.TopicExchange;
+import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
+import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Scope;
+
+import javax.annotation.Resource;
+
+/**
+ * @ClassName RabbitMQConfig
+ * @Author Larr
+ * @create 2024/5/12 15:23
+ */
+@Configuration
+@Data
+public class MessageMqConfig {
+ /**
+ * 交换机
+ */
+ @Value("${mqconfig.message_event_exchange}")
+ private String eventExchange;
+ /**
+ * 第⼀个队列延迟队列,
+ */
+
+ @Value("${mqconfig.message_queue}")
+ private String MessageQueue;
+ /**
+ * 第⼀个队列的路由key
+ * 进⼊队列的路由key
+ */
+
+ @Value("${mqconfig.message_routing_key}")
+ private String MessageRoutingKey;
+ /**
+ * 过期时间
+ */
+ @Value("${mqconfig.ttl}")
+ private Integer ttl;
+ @Bean
+ public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
+ RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
+ rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
+ return rabbitTemplate;
+ }
+
+ @Bean
+ public Exchange MessageEventExchange() {
+ return new TopicExchange(eventExchange, true, false);
+ }
+ @Bean
+ public Queue MessageQueue() {
+ return new Queue(MessageQueue, true, false, false);
+ }
+ @Bean
+ public Binding couponRelaseBinding() {
+ return new Binding(MessageQueue, Binding.DestinationType.QUEUE, eventExchange, MessageRoutingKey, null);
+ }
+
+
+
+ /**
+ * @Author Administrator
+ * 延迟队列
+ **/
+// @Bean
+// public Queue couponReleaseDelayQueue() {
+// Map args = new HashMap<>(3);
+// args.put("x-message-ttl", ttl);
+// args.put("x-dead-letter-routing-key", couponReleaseRoutingKey);
+// args.put("x-dead-letter-exchange", eventExchange);
+// return new Queue(couponReleaseDelayQueue, true, false, false, args);
+// }
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/config/SensitiveWordConfig.java b/src/main/java/com/ruoyi/system/ai/config/SensitiveWordConfig.java
new file mode 100644
index 0000000..e6ce8bb
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/config/SensitiveWordConfig.java
@@ -0,0 +1,30 @@
+package com.ruoyi.system.ai.config;
+
+import com.github.houbb.sensitive.word.bs.SensitiveWordBs;
+import com.github.houbb.sensitive.word.core.SensitiveWordHelper;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 敏感词过滤配置
+ *
+ * @author 一个肥鲇鱼
+ * @date 2023-09-08 14:28:45
+ */
+@Configuration
+public class SensitiveWordConfig {
+
+ /**
+ * 初始化引导类
+ *
+ * @return 初始化引导类
+ * @since 1.0.0
+ */
+ @Bean(value = "sensitiveWordBsBean")
+ public SensitiveWordBs sensitiveWordBs() {
+ System.out.println("测试");
+ // 设置系统默认敏感词
+ return SensitiveWordBs.newInstance().wordDeny(new CustomWordDeny()).wordAllow(new CustomWordAllow()).init();
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/system/ai/config/WebSocketConfiguration.java b/src/main/java/com/ruoyi/system/ai/config/WebSocketConfiguration.java
new file mode 100644
index 0000000..31cfd94
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/config/WebSocketConfiguration.java
@@ -0,0 +1,34 @@
+package com.ruoyi.system.ai.config;
+
+import org.springframework.boot.web.servlet.ServletContextInitializer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+import org.springframework.web.util.WebAppRootListener;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+
+/**
+ * @author Frankiefly
+ * 2024/3/23
+ */
+
+@Configuration
+public class WebSocketConfiguration implements ServletContextInitializer {
+
+ @Bean
+ public ServerEndpointExporter serverEndpointExporter(){
+ return new ServerEndpointExporter();
+ }
+
+ @Override
+ public void onStartup(ServletContext servletContext) throws ServletException {
+ servletContext.addListener(WebAppRootListener.class);
+ //这里设置了1024M的缓冲区
+ //Tomcat每次请求过来时在创建session时都会把这个webSocketContainer作为参数传进去所以对所有的session都生效了
+ servletContext.setInitParameter("org.apache.tomcat.websocket.textBufferSize","1024000");
+
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/config/server/Client.java b/src/main/java/com/ruoyi/system/ai/config/server/Client.java
new file mode 100644
index 0000000..6fb304d
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/config/server/Client.java
@@ -0,0 +1,524 @@
+package com.ruoyi.system.ai.config.server;
+
+import com.alibaba.fastjson.JSONObject;
+import com.google.gson.annotations.SerializedName;
+import com.google.gson.Gson;
+import com.muta.ai.domain.ChatCompletionMessage;
+import io.reactivex.BackpressureStrategy;
+import io.reactivex.Flowable;
+import netscape.javascript.JSObject;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Objects;
+
+public class Client {
+ private static final String DEFAULT_BASE_URL = "https://api.moonshot.cn/v1";
+
+ private static final String CHAT_COMPLETION_SUFFIX = "/chat/completions";
+ private static final String MODELS_SUFFIX = "/models";
+ private static final String FILES_SUFFIX = "/files";
+
+ private String baseUrl;
+ private String apiKey;
+
+ public Client(String apiKey) {
+ this(apiKey, DEFAULT_BASE_URL);
+ }
+
+ public Client(String apiKey, String baseUrl) {
+ this.apiKey = apiKey;
+ if (baseUrl.endsWith("/")) {
+ baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
+ }
+ this.baseUrl = baseUrl;
+ }
+
+ public String getChatCompletionUrl() {
+ return baseUrl + CHAT_COMPLETION_SUFFIX;
+ }
+
+ public String getModelsUrl() {
+ return baseUrl + MODELS_SUFFIX;
+ }
+
+ public String getFilesUrl() {
+ return baseUrl + FILES_SUFFIX;
+ }
+
+ public String getApiKey() {
+ return apiKey;
+ }
+
+ public ModelsList ListModels() throws IOException {
+ okhttp3.OkHttpClient client = new okhttp3.OkHttpClient();
+ okhttp3.Request request = new okhttp3.Request.Builder()
+ .url(getModelsUrl())
+ .addHeader("Authorization", "Bearer " + getApiKey())
+ .build();
+ try {
+ okhttp3.Response response = client.newCall(request).execute();
+ String body = response.body().string();
+ Gson gson = new Gson();
+ return gson.fromJson(body, ModelsList.class);
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw e;
+ }
+ }
+
+
+ public ChatCompletionResponse ChatCompletion(ChatCompletionRequest request) throws IOException {
+ request.stream = false;
+ okhttp3.OkHttpClient client = new okhttp3.OkHttpClient();
+ okhttp3.MediaType mediaType = okhttp3.MediaType.parse("application/json");
+ okhttp3.RequestBody body = okhttp3.RequestBody.create(mediaType, new Gson().toJson(request));
+ okhttp3.Request httpRequest = new okhttp3.Request.Builder()
+ .url(getChatCompletionUrl())
+ .addHeader("Authorization", "Bearer " + getApiKey())
+ .addHeader("Content-Type", "application/json")
+ .post(body)
+ .build();
+ try {
+ okhttp3.Response response = client.newCall(httpRequest).execute();
+ String responseBody = response.body().string();
+ System.out.println(responseBody);
+ Gson gson = new Gson();
+ return gson.fromJson(responseBody, ChatCompletionResponse.class);
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw e;
+ }
+ }
+
+ // return a stream of ChatCompletionStreamResponse
+ public Flowable ChatCompletionStream(ChatCompletionRequest request) throws IOException {
+ request.stream = true;
+ okhttp3.OkHttpClient client = new okhttp3.OkHttpClient();
+ okhttp3.MediaType mediaType = okhttp3.MediaType.parse("application/json");
+ okhttp3.RequestBody body = okhttp3.RequestBody.create(mediaType, new Gson().toJson(request));
+ okhttp3.Request httpRequest = new okhttp3.Request.Builder()
+ .url(getChatCompletionUrl())
+ .addHeader("Authorization", "Bearer " + getApiKey())
+ .addHeader("Content-Type", "application/json")
+ .post(body)
+ .build();
+ okhttp3.Response response = client.newCall(httpRequest).execute();
+ if (response.code() != 200) {
+ System.err.println(response);
+ throw new RuntimeException("Failed to start stream: " + response.body().string());
+ }
+
+ // get response body line by line
+ return Flowable.create(emitter -> {
+ okhttp3.ResponseBody responseBody = response.body();
+ if (responseBody == null) {
+ emitter.onError(new RuntimeException("Response body is null"));
+ return;
+ }
+ String line;
+ while ((line = responseBody.source().readUtf8Line()) != null) {
+ if (line.startsWith("data:")) {
+ line = line.substring(5);
+ line = line.trim();
+ }
+ if (Objects.equals(line, "[DONE]")) {
+ emitter.onComplete();
+ return;
+ }
+ line = line.trim();
+ if (line.isEmpty()) {
+ continue;
+ }
+ //System.out.println(line);
+ Gson gson = new Gson();
+ ChatCompletionStreamResponse streamResponse = gson.fromJson(line, ChatCompletionStreamResponse.class);
+ emitter.onNext(streamResponse);
+ }
+ emitter.onComplete();
+ }, BackpressureStrategy.BUFFER);
+ }
+}
+
+
+
+enum ChatMessageRole {
+ SYSTEM, USER, ASSISTANT;
+
+ public String value() {
+ return this.name().toLowerCase();
+ }
+}
+
+
+
+class ChatCompletionStreamChoiceDelta {
+ private String content;
+ private String role;
+
+ public String getContent() {
+ return content;
+ }
+
+ public String getRole() {
+ return role;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+ public void setRole(String role) {
+ this.role = role;
+ }
+
+ public ChatCompletionStreamChoiceDelta(String content, String role) {
+ this.content = content;
+ this.role = role;
+ }
+
+ @Override
+ public String toString() {
+ return "ChatCompletionStreamChoiceDelta{" +
+ "content='" + content + '\'' +
+ ", role='" + role + '\'' +
+ '}';
+ }
+}
+
+class Usage {
+ private int prompt_tokens;
+ private int completion_tokens;
+ private int total_tokens;
+
+ public int getPrompt_tokens() {
+ return prompt_tokens;
+ }
+
+ public void setPrompt_tokens(int prompt_tokens) {
+ this.prompt_tokens = prompt_tokens;
+ }
+
+ public int getCompletion_tokens() {
+ return completion_tokens;
+ }
+
+ public void setCompletion_tokens(int completion_tokens) {
+ this.completion_tokens = completion_tokens;
+ }
+
+ public int getTotal_tokens() {
+ return total_tokens;
+ }
+
+ public void setTotal_tokens(int total_tokens) {
+ this.total_tokens = total_tokens;
+ }
+
+ public Usage(int prompt_tokens, int completion_tokens, int total_tokens) {
+ this.prompt_tokens = prompt_tokens;
+ this.completion_tokens = completion_tokens;
+ this.total_tokens = total_tokens;
+ }
+
+ public Usage() {
+ }
+
+ @Override
+ public String toString() {
+ return "Usage{" +
+ "prompt_tokens=" + prompt_tokens +
+ ", completion_tokens=" + completion_tokens +
+ ", total_tokens=" + total_tokens +
+ '}';
+ }
+}
+
+class ChatCompletionStreamChoice {
+ private int index;
+ private ChatCompletionStreamChoiceDelta delta;
+
+ @SerializedName("finish_reason")
+ private String finishReason;
+ private Usage usage;
+
+ public int getIndex() {
+ return index;
+ }
+
+ public ChatCompletionStreamChoiceDelta getDelta() {
+ return delta;
+ }
+
+ public String getFinishReason() {
+ return finishReason;
+ }
+
+ public Usage getUsage() {
+ return usage;
+ }
+
+ public void setIndex(int index) {
+ this.index = index;
+ }
+
+ public void setDelta(ChatCompletionStreamChoiceDelta delta) {
+ this.delta = delta;
+ }
+
+ public void setFinishReason(String finishReason) {
+ this.finishReason = finishReason;
+ }
+
+ public void setUsage(Usage usage) {
+ this.usage = usage;
+ }
+
+ public ChatCompletionStreamChoice(int index, ChatCompletionStreamChoiceDelta delta, String finishReason, Usage usage) {
+ this.index = index;
+ this.delta = delta;
+ this.finishReason = finishReason;
+ this.usage = usage;
+ }
+
+ @Override
+ public String toString() {
+ return "ChatCompletionStreamChoice{" +
+ "index=" + index +
+ ", delta=" + delta +
+ ", finishReason='" + finishReason + '\'' +
+ ", usage=" + usage +
+ '}';
+ }
+}
+
+class ChatCompletionStreamResponse {
+ private String id;
+ private String object;
+ private long created;
+ private String model;
+ private List choices;
+
+ public String getId() {
+ return id;
+ }
+
+ public String getObject() {
+ return object;
+ }
+
+ public long getCreated() {
+ return created;
+ }
+
+ public String getModel() {
+ return model;
+ }
+
+ public List getChoices() {
+ return choices;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public void setObject(String object) {
+ this.object = object;
+ }
+
+ public void setCreated(long created) {
+ this.created = created;
+ }
+
+ @Override
+ public String toString() {
+ return "ChatCompletionStreamResponse{" +
+ "id='" + id + '\'' +
+ ", object='" + object + '\'' +
+ ", created=" + created +
+ ", model='" + model + '\'' +
+ ", choices=" + choices +
+ '}';
+ }
+}
+
+class ChatCompletionChoice {
+ private int index;
+ private ChatCompletionMessage message;
+
+ @SerializedName("finish_reason")
+ private String finishReason;
+
+ public int getIndex() {
+ return index;
+ }
+
+ public ChatCompletionMessage getMessage() {
+ return message;
+ }
+
+ public String getFinishReason() {
+ return finishReason;
+ }
+
+ public void setIndex(int index) {
+ this.index = index;
+ }
+
+ public void setMessage(ChatCompletionMessage message) {
+ this.message = message;
+ }
+
+ public void setFinishReason(String finishReason) {
+ this.finishReason = finishReason;
+ }
+
+}
+
+class ChatCompletionResponse {
+ private String id;
+ private String object;
+ private long created;
+ private String model;
+ private List choices;
+ private Usage usage;
+
+ public String getId() {
+ return id;
+ }
+
+ public String getObject() {
+ return object;
+ }
+
+ public long getCreated() {
+ return created;
+ }
+
+ public String getModel() {
+ return model;
+ }
+
+ public List getChoices() {
+ if (choices == null) {
+ return List.of();
+ }
+ return choices;
+ }
+}
+
+
+class ChatCompletionRequest {
+ public String model;
+ public List messages;
+
+ @SerializedName("max_tokens")
+ public int maxTokens;
+
+ @SerializedName("temperature")
+ public float temperature;
+ public float topP;
+
+ public Integer n;
+ public boolean stream;
+ public List stop;
+
+ @SerializedName("presence_penalty")
+ public float presencePenalty;
+
+ @SerializedName("frequency_penalty")
+ public float frequencyPenalty;
+
+ public String user;
+
+ public List getMessages() {
+ return messages;
+ }
+
+ public ChatCompletionRequest(String model, List messages, int maxTokens, float temperature, int n, float topP) {
+ this.model = model;
+ this.messages = messages;
+ this.maxTokens = maxTokens;
+ this.temperature = temperature;
+ this.n = n;
+ this.topP = topP;
+ }
+
+}
+
+class Model {
+ private String id;
+ private String object;
+
+ @SerializedName("owner_by")
+ private String ownedBy;
+ private String root;
+ private String parent;
+
+ public String getId() {
+ return id;
+ }
+
+ public String getObject() {
+ return object;
+ }
+
+ public String getOwnedBy() {
+ return ownedBy;
+ }
+
+ public String getRoot() {
+ return root;
+ }
+
+ public String getParent() {
+ return parent;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public void setObject(String object) {
+ this.object = object;
+ }
+
+ public void setOwnedBy(String ownedBy) {
+ this.ownedBy = ownedBy;
+ }
+
+ public void setRoot(String root) {
+ this.root = root;
+ }
+
+ public void setParent(String parent) {
+ this.parent = parent;
+ }
+
+ public Model(String id, String object, String ownedBy, String root, String parent) {
+ this.id = id;
+ this.object = object;
+ this.ownedBy = ownedBy;
+ this.root = root;
+ this.parent = parent;
+ }
+}
+
+class ModelsList {
+ private List data;
+
+ public List getData() {
+ return data;
+ }
+
+ public void setData(List data) {
+ this.data = data;
+ }
+
+ public ModelsList(List data) {
+ this.data = data;
+ }
+}
+
+
diff --git a/src/main/java/com/ruoyi/system/ai/config/server/WebSocketServer.java b/src/main/java/com/ruoyi/system/ai/config/server/WebSocketServer.java
new file mode 100644
index 0000000..3ef75b4
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/config/server/WebSocketServer.java
@@ -0,0 +1,187 @@
+package com.ruoyi.system.ai.config.server;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.muta.ai.chain.MusicProcessAggregate;
+import com.muta.ai.chain.UserAccountQuotaEntity;
+import com.muta.ai.config.ChatConfig;
+import com.muta.ai.domain.*;
+import com.muta.ai.enums.LogicCheckEnum;
+import com.muta.ai.service.IChatConfigService;
+import com.muta.ai.service.IMessageFileService;
+import com.muta.ai.service.impl.KimiChatService;
+import com.muta.common.utils.StringUtils;
+import org.json.JSONObject;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import javax.annotation.Resource;
+import javax.websocket.*;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+import java.io.IOException;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
+
+
+@Component
+@ServerEndpoint(value = "/chatgpt/{sid}")
+public class WebSocketServer {
+
+ private static IChatConfigService chatConfigService;
+
+ private static RedisTemplate redisTemplate;
+
+ private static KimiChatService kimiChatService;
+
+ private static IMessageFileService messageFileService;
+
+ @Resource
+ public void setChatConfigService(IChatConfigService chatConfigService) {
+ WebSocketServer.chatConfigService = chatConfigService;
+ }
+
+ @Resource
+ public void setMessageFileService(IMessageFileService messageFileService) {
+ WebSocketServer.messageFileService = messageFileService;
+ }
+
+ @Resource
+ public void setKimiChatService(KimiChatService kimiChatService) {
+ WebSocketServer.kimiChatService = kimiChatService;
+ }
+
+ @Resource
+ public void setChatgptService(RedisTemplate redisTemplate) {
+ WebSocketServer.redisTemplate = redisTemplate;
+ }
+
+ private static Map sessionMap = new HashMap<>();
+
+ @OnOpen
+ public void onOpen(Session session, @PathParam("sid") String sid) {
+ System.out.println("客户端: " + sid + "建立连接");
+ sessionMap.put(sid, session);
+ }
+
+ @OnMessage
+ public void onMessage(String jsonFrom, @PathParam("sid") String sid) throws Exception {
+ JSONObject jsonParse = new JSONObject(jsonFrom);
+
+ String url = jsonFrom.contains("\"url\"") ? jsonParse.getString("url") : null;
+ String content = jsonParse.getString("content");
+ String model = jsonParse.getString("model");
+
+ if (StringUtils.isNotEmpty(url)) {
+ content += " " + messageFileService.getContentByUrl(url);
+ }
+
+ Long userId = Long.valueOf(sid.split(":")[0]);
+
+ List history = redisTemplate.opsForSet().members(sid).stream().collect(Collectors.toList());
+ List messages = CollectionUtil.isEmpty(history) ? new ArrayList<>() : history;
+ messages.add(new ChatCompletionMessage(ChatMessageRole.USER.value(), content));
+
+ for (ChatCompletionMessage message : messages) {
+ System.out.println(message.toString());
+ }
+
+
+ MusicProcessAggregate chatProcessAggregate = kimiChatService.initChatData(userId, model, messages);
+ System.out.println(chatProcessAggregate.toString());
+ UserAccountQuotaEntity userAccountQuotaEntity = kimiChatService.initUserData(userId);
+ System.out.println(userAccountQuotaEntity.toString());
+ //
+ RuleLogicEntity logicRes = kimiChatService.doCheckLogic(chatProcessAggregate, userAccountQuotaEntity);
+ if(logicRes.getType().equals(LogicCheckEnum.REFUSE)){
+ sendToClient(sid, logicRes.getInfo());
+ }
+ else {
+ System.err.println(chatProcessAggregate.getKey());
+ Client client = new Client(chatProcessAggregate.getKey());
+ StringBuffer stringBuffer = new StringBuffer();
+
+ AtomicBoolean flag = new AtomicBoolean(true);
+ AtomicReference role = new AtomicReference<>();
+ ChatConfig config = chatConfigService.selectChatConfigById(userId);
+
+
+ try {
+
+ String finalContent = content;
+ client.ChatCompletionStream(new ChatCompletionRequest(
+ model,
+ messages,
+ userAccountQuotaEntity.getMaxToken(),
+ config.getTemperature(),
+ config.getN(),
+ config.getTop()
+ )).subscribe(
+ streamResponse -> {
+ if (streamResponse.getChoices().isEmpty()) {
+ return;
+ }
+ for (ChatCompletionStreamChoice choice : streamResponse.getChoices()) {
+ if (flag.getAndSet(false)) {
+ role.set(choice.getDelta().getRole());
+ }
+ String finishReason = choice.getFinishReason();
+ System.out.println(choice.getDelta().getContent());
+ stringBuffer.append(choice.getDelta().getContent());
+ if (finishReason != null) {
+ System.out.println(streamResponse);
+ System.out.println(sid);
+ MessageEntity messageEntity
+ = MessageEntity.builder()
+ .model(streamResponse.getModel())
+ .role(role.get())
+ .userId(userId)
+ .content(stringBuffer.toString())
+ .finishReason(finishReason)
+ .promptTokens(choice.getUsage().getPrompt_tokens())
+ .completionTokens(choice.getUsage().getCompletion_tokens())
+ .totalTokens(choice.getUsage().getTotal_tokens())
+ .sessionId(sid)
+ .build();
+
+ System.out.println(messageEntity.toString());
+ kimiChatService.PostRule(chatProcessAggregate,userAccountQuotaEntity, messageEntity);
+ continue;
+ }
+ sendToClient(sid, choice.getDelta().getContent());
+ }
+ },
+ error -> {
+ error.printStackTrace();
+ },
+ () -> {
+ System.out.println("complete");
+
+// redisTemplate.opsForSet().remove(sid);
+// Set members = redisTemplate.opsForSet().members(sid);
+// members.add(new ChatCompletionMessage(ChatMessageRole.USER.value(), finalContent));
+ redisTemplate.opsForSet().add(sid, new ChatCompletionMessage(ChatMessageRole.USER.value(), finalContent));
+ }
+ );
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @OnClose
+ public void onClose(@PathParam("sid") String sid){
+ System.out.println("连接断开: " + sid);
+ sessionMap.remove(sid);
+ }
+
+ public void sendToClient(String sid, String result){
+ Session session = sessionMap.get(sid);
+ try {
+ session.getBasicRemote().sendText(result);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
+
diff --git a/src/main/java/com/ruoyi/system/ai/domain/AiKey.java b/src/main/java/com/ruoyi/system/ai/domain/AiKey.java
new file mode 100644
index 0000000..4ead0f6
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/domain/AiKey.java
@@ -0,0 +1,50 @@
+package com.ruoyi.system.ai.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.muta.common.core.MutaBaseEntity;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class AiKey extends MutaBaseEntity {
+
+ /** 主键 */
+ @TableId(value = "id",type = IdType.AUTO)
+ private Long id;
+
+ /** key值 */
+ @TableField("`key`")
+ private String key;
+
+ /** 代理 */
+ @TableField("`host`")
+ private String host;
+
+ /** 可用模型 */
+ @TableField("`model_list`")
+ private String modelList;
+
+ /** ai类型 */
+ @TableField("`type`")
+ private Integer type;
+
+ /** 状态 */
+ @TableField("`status`")
+ private String status;
+
+ /** 额度 */
+ @TableField("`limit`")
+ private BigDecimal limit;
+ /** 用户id */
+ @TableField("`user_id`")
+ private Long userId;
+}
diff --git a/src/main/java/com/ruoyi/system/ai/domain/ChatCompletionMessage.java b/src/main/java/com/ruoyi/system/ai/domain/ChatCompletionMessage.java
new file mode 100644
index 0000000..05199ce
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/domain/ChatCompletionMessage.java
@@ -0,0 +1,40 @@
+package com.ruoyi.system.ai.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@Builder
+public class ChatCompletionMessage {
+ public String role;
+ public String name;
+ public String content;
+ public Boolean partial;
+
+ public ChatCompletionMessage(String role, String content) {
+ this.role = role;
+ this.content = content;
+ }
+
+ public ChatCompletionMessage(String role, String name, String content, Boolean partial) {
+ this.role = role;
+ this.name = name;
+ this.content = content;
+ this.partial = partial;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public Boolean getPartial() {
+ return partial;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/system/ai/domain/ChatConfig.java b/src/main/java/com/ruoyi/system/ai/domain/ChatConfig.java
new file mode 100644
index 0000000..b3428d9
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/domain/ChatConfig.java
@@ -0,0 +1,26 @@
+package com.ruoyi.system.ai.domain;//package com.muta.ai.domain;
+//
+//import com.baomidou.mybatisplus.annotation.TableName;
+//import lombok.AllArgsConstructor;
+//import lombok.Builder;
+//import lombok.Data;
+//import lombok.NoArgsConstructor;
+//
+///**
+// * @author: Larry
+// * @Date: 2024 /05 /11 / 14:18
+// * @Description:
+// */
+//@Data
+//@AllArgsConstructor
+//@NoArgsConstructor
+//@Builder
+//@TableName("chat_config")
+//public class ChatConfig {
+// private Long id;
+// private Long userId;
+// private float temperature;
+// private String maxToken;
+// private Integer n;
+// private float top;
+//}
diff --git a/src/main/java/com/ruoyi/system/ai/domain/MessageEntity.java b/src/main/java/com/ruoyi/system/ai/domain/MessageEntity.java
new file mode 100644
index 0000000..be9b29f
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/domain/MessageEntity.java
@@ -0,0 +1,46 @@
+package com.ruoyi.system.ai.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.muta.common.core.MutaBaseEntity;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /09 / 13:17
+ * @Description:
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class MessageEntity extends MutaBaseEntity {
+ @TableId(type = IdType.AUTO)
+ private Long id;
+ private Long userId;
+
+ private String content;
+
+ private String role;
+
+ private String model;
+
+ private String url;
+
+ private String finishReason;
+
+ private String sessionId;
+
+ private Integer promptTokens;
+
+ private Integer completionTokens;
+
+ private Integer totalTokens;
+
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/domain/MessageFile.java b/src/main/java/com/ruoyi/system/ai/domain/MessageFile.java
new file mode 100644
index 0000000..0a29a6b
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/domain/MessageFile.java
@@ -0,0 +1,55 @@
+package com.ruoyi.system.ai.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.muta.common.core.MutaBaseEntity;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author 马兰友
+ * @Date: 2024/05/17/14:57
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class MessageFile extends MutaBaseEntity {
+
+ /**
+ * 主键
+ */
+ @TableId(type = IdType.AUTO)
+ @JsonFormat(shape =JsonFormat.Shape.STRING)
+ private Long id;
+
+ /**
+ * 文件名(传进来时)
+ */
+ private String name;
+
+ /**
+ * 文件url,也就是阿里云存储的url
+ */
+ private String url;
+
+ /**
+ * 文件大小
+ */
+ private String size;
+
+ /**
+ * 解析后文件内容
+ */
+ private String analysisContent;
+
+ /**
+ * 对应的消息id
+ */
+ @JsonFormat(shape =JsonFormat.Shape.STRING)
+ private Long messageId;
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/domain/MessageSession.java b/src/main/java/com/ruoyi/system/ai/domain/MessageSession.java
new file mode 100644
index 0000000..a64f289
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/domain/MessageSession.java
@@ -0,0 +1,35 @@
+package com.ruoyi.system.ai.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.muta.common.core.MutaBaseEntity;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author 马兰友
+ * @Date: 2024/05/13/15:52
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class MessageSession extends MutaBaseEntity {
+
+ /**
+ * id
+ */
+ @TableId(type = IdType.AUTO)
+ @JsonFormat(shape =JsonFormat.Shape.STRING)
+ private Long id;
+
+ /**
+ * userId
+ */
+ @JsonFormat(shape =JsonFormat.Shape.STRING)
+ private Long userId;
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/domain/RuleLogicEntity.java b/src/main/java/com/ruoyi/system/ai/domain/RuleLogicEntity.java
new file mode 100644
index 0000000..909ca48
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/domain/RuleLogicEntity.java
@@ -0,0 +1,23 @@
+package com.ruoyi.system.ai.domain;
+import com.muta.ai.enums.LogicCheckEnum;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 规则校验结果实体
+ * @create 2023-09-16 17:02
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class RuleLogicEntity {
+
+ private LogicCheckEnum type;
+ private String info;
+ private T data;
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/domain/dto/MessageHistoryKimi.java b/src/main/java/com/ruoyi/system/ai/domain/dto/MessageHistoryKimi.java
new file mode 100644
index 0000000..a8ce10b
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/domain/dto/MessageHistoryKimi.java
@@ -0,0 +1,26 @@
+package com.ruoyi.system.ai.domain.dto;
+
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /10 / 18:41
+ * @Description:
+ */
+
+@NoArgsConstructor
+@Data
+@Builder
+public class MessageHistoryKimi {
+ private String role;
+
+ private String content;
+
+ public MessageHistoryKimi(String role, String content) {
+ this.role = role;
+ this.content = content;
+
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/ai/domain/dto/PostDTO.java b/src/main/java/com/ruoyi/system/ai/domain/dto/PostDTO.java
new file mode 100644
index 0000000..bf8ad38
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/domain/dto/PostDTO.java
@@ -0,0 +1,45 @@
+package com.ruoyi.system.ai.domain.dto;
+
+import com.muta.ai.domain.ChatCompletionMessage;
+import com.muta.ai.domain.MessageEntity;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /21 / 17:55
+ * @Description:
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class PostDTO {
+ private MessageEntity message;
+ /**
+ * 用户ID
+ */
+ private Long userId;
+ /**
+ * 所选模型
+ */
+ private String model;
+ /** 历史消息 */
+ private List messages;
+ /**
+ * 所用key
+ */
+ private String key;
+ /**
+ * 模型单位积分对应key
+ */
+ private Integer modelConsumer;
+ /**
+ * 上下文token数量
+ */
+ private Integer tokenNum;
+}
diff --git a/src/main/java/com/ruoyi/system/ai/domain/event/MessageEvent.java b/src/main/java/com/ruoyi/system/ai/domain/event/MessageEvent.java
new file mode 100644
index 0000000..b618ab2
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/domain/event/MessageEvent.java
@@ -0,0 +1,31 @@
+package com.ruoyi.system.ai.domain.event;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /15 / 17:44
+ * @Description:
+ */
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+@Builder
+public class MessageEvent implements Serializable {
+ private static final long serialVersionUID = 3349917261877342192L;
+ private Long userId;
+ private String finishReason;
+ private String promptTokens;
+ private String completionTokens;
+ private Integer totalTokens;
+ private String content;
+ private String role;
+ private String model;
+ private String username;
+ private Long sessionId;
+}
diff --git a/src/main/java/com/ruoyi/system/ai/enums/LogicCheckEnum.java b/src/main/java/com/ruoyi/system/ai/enums/LogicCheckEnum.java
new file mode 100644
index 0000000..0c3e7b4
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/enums/LogicCheckEnum.java
@@ -0,0 +1,22 @@
+package com.ruoyi.system.ai.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author Larry
+ * @description 逻辑校验类型,值对象
+ * @create 2024-05-06 17:04
+ */
+@Getter
+@AllArgsConstructor
+public enum LogicCheckEnum {
+
+ SUCCESS("0000", "校验通过"),
+ REFUSE("0001","校验拒绝"),
+ ;
+
+ private final String code;
+ private final String info;
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/enums/RoleEnum.java b/src/main/java/com/ruoyi/system/ai/enums/RoleEnum.java
new file mode 100644
index 0000000..d8ed2d5
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/enums/RoleEnum.java
@@ -0,0 +1,8 @@
+package com.ruoyi.system.ai.enums;
+
+
+public enum RoleEnum {
+ system,
+ user,
+ assistant;
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/system/ai/factory/DefaultLogicFactory.java b/src/main/java/com/ruoyi/system/ai/factory/DefaultLogicFactory.java
new file mode 100644
index 0000000..cf8d566
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/factory/DefaultLogicFactory.java
@@ -0,0 +1,35 @@
+package com.ruoyi.system.ai.factory;//package com.muta.ai.factory;
+//
+//
+//import com.muta.ai.annotation.LogicStrategy;
+//import com.muta.ai.config.LogicConfig;
+//import com.muta.ai.chain.UserAccountQuotaEntity;
+//import com.muta.ai.service.ILogicFilter;
+//import org.springframework.core.annotation.AnnotationUtils;
+//import org.springframework.stereotype.Service;
+//
+//import javax.annotation.PostConstruct;
+//import javax.annotation.Resource;
+//import java.util.List;
+//import java.util.Map;
+//import java.util.concurrent.ConcurrentHashMap;
+//
+///**
+// * @author Fuzhengwei bugstack.cn @小傅哥
+// * @description 规则工厂
+// * @create 2023-09-16 17:42
+// */
+//@Service
+//public class DefaultLogicFactory extends LogicConfig {
+//
+// //后期可加入参数,自动选择过滤器
+// public Map> openLogicFilter() {
+// return logicFilterMap;
+// }
+//
+//
+// /**
+// * 规则逻辑枚举
+// */
+//
+//}
diff --git a/src/main/java/com/ruoyi/system/ai/mapper/AiKeyMapper.java b/src/main/java/com/ruoyi/system/ai/mapper/AiKeyMapper.java
new file mode 100644
index 0000000..7c2a2b7
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/mapper/AiKeyMapper.java
@@ -0,0 +1,70 @@
+package com.ruoyi.system.ai.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.muta.ai.domain.AiKey;
+import com.muta.common.annotation.AutoFill;
+import com.muta.common.enums.BaseOperatorType;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+
+/**
+ * 【请填写功能名称】Mapper接口
+ *
+ * @author mutaai
+ * @date 2024-05-16
+ */
+@Mapper
+public interface AiKeyMapper extends BaseMapper {
+ /**
+ * 查询【请填写功能名称】
+ *
+ * @param id 【请填写功能名称】主键
+ * @return 【请填写功能名称】
+ */
+ public AiKey selectAiKeyById(Long id);
+
+ /**
+ * 查询【请填写功能名称】列表
+ *
+ * @return 【请填写功能名称】集合
+ */
+ public List selectAiKeyList();
+
+ /**
+ * 新增【请填写功能名称】
+ *
+ * @param aiKey 【请填写功能名称】
+ * @return 结果
+ */
+ @AutoFill(BaseOperatorType.INSERT)
+ public int insertAiKey(AiKey aiKey);
+
+ /**
+ * 修改【请填写功能名称】
+ *
+ * @param aiKey 【请填写功能名称】
+ * @return 结果
+ */
+ @AutoFill(BaseOperatorType.UPDATE)
+ public int updateAiKey(AiKey aiKey);
+
+ /**
+ * 删除【请填写功能名称】
+ *
+ * @param id 【请填写功能名称】主键
+ * @return 结果
+ */
+ public int deleteAiKeyById(Long id);
+
+ /**
+ * 批量删除【请填写功能名称】
+ *
+ * @param ids 需要删除的数据主键集合
+ * @return 结果
+ */
+ public int deleteAiKeyByIds(Long[] ids);
+
+ @Select("select `key`, host, model_list, type, status, `limit`, create_time, create_by, update_time, update_by, user_id, is_del from ai_key where is_del = 0 and user_id = #{userId}")
+ List list(Long userId);
+}
diff --git a/src/main/java/com/ruoyi/system/ai/mapper/ChatConfigMapper.java b/src/main/java/com/ruoyi/system/ai/mapper/ChatConfigMapper.java
new file mode 100644
index 0000000..0bd58df
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/mapper/ChatConfigMapper.java
@@ -0,0 +1,61 @@
+package com.ruoyi.system.ai.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.muta.ai.config.ChatConfig;
+
+/**
+ * 【请填写功能名称】Mapper接口
+ *
+ * @author mutaai
+ * @date 2024-05-13
+ */
+public interface ChatConfigMapper extends BaseMapper {
+ /**
+ * 查询【请填写功能名称】
+ *
+ * @param id 【请填写功能名称】主键
+ * @return 【请填写功能名称】
+ */
+ public ChatConfig selectChatConfigById(Long id);
+
+ /**
+ * 查询【请填写功能名称】列表
+ *
+ * @param chatConfig 【请填写功能名称】
+ * @return 【请填写功能名称】集合
+ */
+ public List selectChatConfigList(ChatConfig chatConfig);
+
+ /**
+ * 新增【请填写功能名称】
+ *
+ * @param chatConfig 【请填写功能名称】
+ * @return 结果
+ */
+ public int insertChatConfig(ChatConfig chatConfig);
+
+ /**
+ * 修改【请填写功能名称】
+ *
+ * @param chatConfig 【请填写功能名称】
+ * @return 结果
+ */
+ public int updateChatConfig(ChatConfig chatConfig);
+
+ /**
+ * 删除【请填写功能名称】
+ *
+ * @param id 【请填写功能名称】主键
+ * @return 结果
+ */
+ public int deleteChatConfigById(Long id);
+
+ /**
+ * 批量删除【请填写功能名称】
+ *
+ * @param ids 需要删除的数据主键集合
+ * @return 结果
+ */
+ public int deleteChatConfigByIds(Long[] ids);
+}
diff --git a/src/main/java/com/ruoyi/system/ai/mapper/MessageFileMapper.java b/src/main/java/com/ruoyi/system/ai/mapper/MessageFileMapper.java
new file mode 100644
index 0000000..615fe71
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/mapper/MessageFileMapper.java
@@ -0,0 +1,13 @@
+package com.ruoyi.system.ai.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.muta.ai.domain.MessageFile;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @author 马兰友
+ * @Date: 2024/05/17/15:16
+ */
+@Mapper
+public interface MessageFileMapper extends BaseMapper {
+}
diff --git a/src/main/java/com/ruoyi/system/ai/mapper/MessageMapper.java b/src/main/java/com/ruoyi/system/ai/mapper/MessageMapper.java
new file mode 100644
index 0000000..23f1ee4
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/mapper/MessageMapper.java
@@ -0,0 +1,20 @@
+package com.ruoyi.system.ai.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.muta.ai.domain.MessageEntity;
+import com.muta.common.core.domain.entity.SysUser;
+import com.muta.system.domain.Message;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /20 / 13:02
+ * @Description:
+ */
+@Mapper
+public interface MessageMapper extends BaseMapper {
+
+ List selectByFilter(SysUser sysUser);
+}
diff --git a/src/main/java/com/ruoyi/system/ai/mapper/MessageSessionMapper.java b/src/main/java/com/ruoyi/system/ai/mapper/MessageSessionMapper.java
new file mode 100644
index 0000000..15218d0
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/mapper/MessageSessionMapper.java
@@ -0,0 +1,16 @@
+package com.ruoyi.system.ai.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.muta.ai.domain.MessageSession;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @author 马兰友
+ * @Date: 2024/05/13/16:09
+ */
+@Mapper
+public interface MessageSessionMapper extends BaseMapper {
+
+
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/mq/listener/MessageListener.java b/src/main/java/com/ruoyi/system/ai/mq/listener/MessageListener.java
new file mode 100644
index 0000000..5c7d501
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/mq/listener/MessageListener.java
@@ -0,0 +1,39 @@
+package com.ruoyi.system.ai.mq.listener;//package com.muta.ai.mq.listener;
+//
+//import cn.hutool.json.JSONUtil;
+//import com.fasterxml.jackson.databind.ObjectMapper;
+//import com.muta.ai.domain.MessageEntity;
+//import com.muta.ai.domain.event.MessageEvent;
+//import com.muta.ai.service.IMessageService;
+//import com.muta.ai.service.impl.BaseChatService;
+//import com.rabbitmq.client.Channel;
+//import org.springframework.amqp.core.Message;
+//import org.springframework.amqp.rabbit.annotation.RabbitHandler;
+//import org.springframework.amqp.rabbit.annotation.RabbitListener;
+//import org.springframework.amqp.rabbit.core.RabbitTemplate;
+//import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
+//import org.springframework.amqp.support.converter.MessageConverter;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.stereotype.Component;
+//
+//import javax.annotation.Resource;
+//
+///**
+// * @author: Larry
+// * @Date: 2024 /05 /15 / 17:44
+// * @Description:
+// */
+//@Component
+//
+//public class MessageListener {
+// @Resource
+// private BaseChatService baseChatService;
+// @RabbitHandler
+// @RabbitListener(queues = "message.queue")
+// public void listenMessage(String message, Channel channel){
+// MessageEntity messageEntity = JSONUtil.toBean(message, MessageEntity.class);
+// System.out.println(messageEntity.getContent());
+// }
+//
+//}
diff --git a/src/main/java/com/ruoyi/system/ai/mq/producer/MessageSender.java b/src/main/java/com/ruoyi/system/ai/mq/producer/MessageSender.java
new file mode 100644
index 0000000..d680deb
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/mq/producer/MessageSender.java
@@ -0,0 +1,49 @@
+package com.ruoyi.system.ai.mq.producer;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.muta.ai.domain.MessageEntity;
+import com.muta.ai.domain.event.MessageEvent;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
+import org.springframework.amqp.support.converter.MessageConverter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /16 / 20:29
+ * @Description:
+ */
+
+@Component
+public class MessageSender {
+
+ @Value("${mqconfig.message_event_exchange}")
+ private String eventExchange;
+ /**
+ * 第⼀个队列延迟队列,
+ */
+
+ @Value("${mqconfig.message_queue}")
+ private String MessageQueue;
+ /**
+ * 第⼀个队列的路由key
+ * 进⼊队列的路由key
+ */
+
+ @Value("${mqconfig.message_routing_key}")
+ private String MessageRoutingKey;
+
+ @Resource
+ private RabbitTemplate rabbitTemplate;
+ public void addSyncMessage(MessageEntity message){
+ rabbitTemplate.convertAndSend(eventExchange,MessageRoutingKey,message);
+ }
+
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/service/HelloWorld.java b/src/main/java/com/ruoyi/system/ai/service/HelloWorld.java
new file mode 100644
index 0000000..fc6b961
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/HelloWorld.java
@@ -0,0 +1,563 @@
+package com.ruoyi.system.ai.service;//package com.muta.ai.service;
+//
+//import com.alibaba.fastjson.JSONObject;
+//import com.google.gson.annotations.SerializedName;
+//import com.google.gson.Gson;
+//import io.reactivex.BackpressureStrategy;
+//import io.reactivex.Flowable;
+//import netscape.javascript.JSObject;
+//
+//import java.io.IOException;
+//import java.util.List;
+//import java.util.Objects;
+//
+//
+//
+//enum ChatMessageRole {
+// SYSTEM, USER, ASSISTANT;
+//
+// public String value() {
+// return this.name().toLowerCase();
+// }
+//}
+//
+//class ChatCompletionMessage {
+// public String role;
+// public String name;
+// public String content;
+// public Boolean partial;
+//
+// public ChatCompletionMessage(String role, String content) {
+// this.role = role;
+// this.content = content;
+// }
+//
+// public ChatCompletionMessage(String role, String name, String content, Boolean partial) {
+// this.role = role;
+// this.name = name;
+// this.content = content;
+// this.partial = partial;
+// }
+//
+// public String getName() {
+// return name;
+// }
+//
+// public String getContent() {
+// return content;
+// }
+//
+// public Boolean getPartial() {
+// return partial;
+// }
+//}
+//
+//class ChatCompletionStreamChoiceDelta {
+// private String content;
+// private String role;
+//
+// public String getContent() {
+// return content;
+// }
+//
+// public String getRole() {
+// return role;
+// }
+//
+// public void setContent(String content) {
+// this.content = content;
+// }
+//
+// public void setRole(String role) {
+// this.role = role;
+// }
+//
+// public ChatCompletionStreamChoiceDelta(String content, String role) {
+// this.content = content;
+// this.role = role;
+// }
+//}
+//
+//class Usage {
+// private int promptTokens;
+// private int completionTokens;
+// private int totalTokens;
+//
+// public int getPromptTokens() {
+// return promptTokens;
+// }
+//
+// public int getCompletionTokens() {
+// return completionTokens;
+// }
+//
+// public int getTotalTokens() {
+// return totalTokens;
+// }
+//}
+//
+//class ChatCompletionStreamChoice {
+// private int index;
+// private ChatCompletionStreamChoiceDelta delta;
+//
+// @SerializedName("finish_reason")
+// private String finishReason;
+// private Usage usage;
+//
+// public int getIndex() {
+// return index;
+// }
+//
+// public ChatCompletionStreamChoiceDelta getDelta() {
+// return delta;
+// }
+//
+// public String getFinishReason() {
+// return finishReason;
+// }
+//
+// public Usage getUsage() {
+// return usage;
+// }
+//
+// public void setIndex(int index) {
+// this.index = index;
+// }
+//
+// public void setDelta(ChatCompletionStreamChoiceDelta delta) {
+// this.delta = delta;
+// }
+//
+// public void setFinishReason(String finishReason) {
+// this.finishReason = finishReason;
+// }
+//
+// public void setUsage(Usage usage) {
+// this.usage = usage;
+// }
+//
+// public ChatCompletionStreamChoice(int index, ChatCompletionStreamChoiceDelta delta, String finishReason, Usage usage) {
+// this.index = index;
+// this.delta = delta;
+// this.finishReason = finishReason;
+// this.usage = usage;
+// }
+//}
+//
+//class ChatCompletionStreamResponse {
+// private String id;
+// private String object;
+// private long created;
+// private String model;
+// private List choices;
+//
+// public String getId() {
+// return id;
+// }
+//
+// public String getObject() {
+// return object;
+// }
+//
+// public long getCreated() {
+// return created;
+// }
+//
+// public String getModel() {
+// return model;
+// }
+//
+// public List getChoices() {
+// return choices;
+// }
+//
+// public void setId(String id) {
+// this.id = id;
+// }
+//
+// public void setObject(String object) {
+// this.object = object;
+// }
+//
+// public void setCreated(long created) {
+// this.created = created;
+// }
+//}
+//
+//class ChatCompletionChoice {
+// private int index;
+// private ChatCompletionMessage message;
+//
+// @SerializedName("finish_reason")
+// private String finishReason;
+//
+// public int getIndex() {
+// return index;
+// }
+//
+// public ChatCompletionMessage getMessage() {
+// return message;
+// }
+//
+// public String getFinishReason() {
+// return finishReason;
+// }
+//
+// public void setIndex(int index) {
+// this.index = index;
+// }
+//
+// public void setMessage(ChatCompletionMessage message) {
+// this.message = message;
+// }
+//
+// public void setFinishReason(String finishReason) {
+// this.finishReason = finishReason;
+// }
+//
+//}
+//
+//class ChatCompletionResponse {
+// private String id;
+// private String object;
+// private long created;
+// private String model;
+// private List choices;
+// private Usage usage;
+//
+// public String getId() {
+// return id;
+// }
+//
+// public String getObject() {
+// return object;
+// }
+//
+// public long getCreated() {
+// return created;
+// }
+//
+// public String getModel() {
+// return model;
+// }
+//
+// public List getChoices() {
+// if (choices == null) {
+// return List.of();
+// }
+// return choices;
+// }
+//}
+//
+//
+//class ChatCompletionRequest {
+// public String model;
+// public List messages;
+//
+// @SerializedName("max_tokens")
+// public int maxTokens;
+//
+// @SerializedName("temperature")
+// public float temperature;
+// public float topP;
+//
+// public Integer n;
+// public boolean stream;
+// public List stop;
+//
+// @SerializedName("presence_penalty")
+// public float presencePenalty;
+//
+// @SerializedName("frequency_penalty")
+// public float frequencyPenalty;
+//
+// public String user;
+//
+// public List getMessages() {
+// return messages;
+// }
+//
+// public ChatCompletionRequest(String model, List messages, int maxTokens, float temperature, int n) {
+// this.model = model;
+// this.messages = messages;
+// this.maxTokens = maxTokens;
+// this.temperature = temperature;
+// this.n = n;
+// }
+//
+//}
+//
+//class Model {
+// private String id;
+// private String object;
+//
+// @SerializedName("owner_by")
+// private String ownedBy;
+// private String root;
+// private String parent;
+//
+// public String getId() {
+// return id;
+// }
+//
+// public String getObject() {
+// return object;
+// }
+//
+// public String getOwnedBy() {
+// return ownedBy;
+// }
+//
+// public String getRoot() {
+// return root;
+// }
+//
+// public String getParent() {
+// return parent;
+// }
+//
+// public void setId(String id) {
+// this.id = id;
+// }
+//
+// public void setObject(String object) {
+// this.object = object;
+// }
+//
+// public void setOwnedBy(String ownedBy) {
+// this.ownedBy = ownedBy;
+// }
+//
+// public void setRoot(String root) {
+// this.root = root;
+// }
+//
+// public void setParent(String parent) {
+// this.parent = parent;
+// }
+//
+// public Model(String id, String object, String ownedBy, String root, String parent) {
+// this.id = id;
+// this.object = object;
+// this.ownedBy = ownedBy;
+// this.root = root;
+// this.parent = parent;
+// }
+//}
+//
+//class ModelsList {
+// private List data;
+//
+// public List getData() {
+// return data;
+// }
+//
+// public void setData(List data) {
+// this.data = data;
+// }
+//
+// public ModelsList(List data) {
+// this.data = data;
+// }
+//}
+//
+//class Client {
+// private static final String DEFAULT_BASE_URL = "https://api.moonshot.cn/v1";
+//
+// private static final String CHAT_COMPLETION_SUFFIX = "/chat/completions";
+// private static final String MODELS_SUFFIX = "/models";
+// private static final String FILES_SUFFIX = "/files";
+//
+// private String baseUrl;
+// private String apiKey;
+//
+// public Client(String apiKey) {
+// this(apiKey, DEFAULT_BASE_URL);
+// }
+//
+// public Client(String apiKey, String baseUrl) {
+// this.apiKey = apiKey;
+// if (baseUrl.endsWith("/")) {
+// baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
+// }
+// this.baseUrl = baseUrl;
+// }
+//
+// public String getChatCompletionUrl() {
+// return baseUrl + CHAT_COMPLETION_SUFFIX;
+// }
+//
+// public String getModelsUrl() {
+// return baseUrl + MODELS_SUFFIX;
+// }
+//
+// public String getFilesUrl() {
+// return baseUrl + FILES_SUFFIX;
+// }
+//
+// public String getApiKey() {
+// return apiKey;
+// }
+//
+// public ModelsList ListModels() throws IOException {
+// okhttp3.OkHttpClient client = new okhttp3.OkHttpClient();
+// okhttp3.Request request = new okhttp3.Request.Builder()
+// .url(getModelsUrl())
+// .addHeader("Authorization", "Bearer " + getApiKey())
+// .build();
+// try {
+// okhttp3.Response response = client.newCall(request).execute();
+// String body = response.body().string();
+// Gson gson = new Gson();
+// return gson.fromJson(body, ModelsList.class);
+// } catch (java.io.IOException e) {
+// e.printStackTrace();
+// throw e;
+// }
+// }
+//
+//
+// public ChatCompletionResponse ChatCompletion(ChatCompletionRequest request) throws IOException {
+// request.stream = false;
+// okhttp3.OkHttpClient client = new okhttp3.OkHttpClient();
+// okhttp3.MediaType mediaType = okhttp3.MediaType.parse("application/json");
+// okhttp3.RequestBody body = okhttp3.RequestBody.create(mediaType, new Gson().toJson(request));
+// okhttp3.Request httpRequest = new okhttp3.Request.Builder()
+// .url(getChatCompletionUrl())
+// .addHeader("Authorization", "Bearer " + getApiKey())
+// .addHeader("Content-Type", "application/json")
+// .post(body)
+// .build();
+// try {
+// okhttp3.Response response = client.newCall(httpRequest).execute();
+// String responseBody = response.body().string();
+// System.out.println(responseBody);
+// Gson gson = new Gson();
+// return gson.fromJson(responseBody, ChatCompletionResponse.class);
+// } catch (java.io.IOException e) {
+// e.printStackTrace();
+// throw e;
+// }
+// }
+//
+// // return a stream of ChatCompletionStreamResponse
+// public Flowable ChatCompletionStream(ChatCompletionRequest request) throws IOException {
+// request.stream = true;
+// okhttp3.OkHttpClient client = new okhttp3.OkHttpClient();
+// okhttp3.MediaType mediaType = okhttp3.MediaType.parse("application/json");
+// okhttp3.RequestBody body = okhttp3.RequestBody.create(mediaType, new Gson().toJson(request));
+// okhttp3.Request httpRequest = new okhttp3.Request.Builder()
+// .url(getChatCompletionUrl())
+// .addHeader("Authorization", "Bearer " + getApiKey())
+// .addHeader("Content-Type", "application/json")
+// .post(body)
+// .build();
+// okhttp3.Response response = client.newCall(httpRequest).execute();
+// if (response.code() != 200) {
+// throw new RuntimeException("Failed to start stream: " + response.body().string());
+// }
+//
+// // get response body line by line
+// return Flowable.create(emitter -> {
+// okhttp3.ResponseBody responseBody = response.body();
+// if (responseBody == null) {
+// emitter.onError(new RuntimeException("Response body is null"));
+// return;
+// }
+// String line;
+// while ((line = responseBody.source().readUtf8Line()) != null) {
+// if (line.startsWith("data:")) {
+// line = line.substring(5);
+// line = line.trim();
+// }
+// if (Objects.equals(line, "[DONE]")) {
+// emitter.onComplete();
+// return;
+// }
+// line = line.trim();
+// if (line.isEmpty()) {
+// continue;
+// }
+// Gson gson = new Gson();
+// JSONObject json = gson.fromJson(line, JSONObject.class);
+// json.getJSONArray("choices").getJSONObject(0).getJSONObject("finish_reason");
+// ChatCompletionStreamResponse streamResponse = gson.fromJson(line, ChatCompletionStreamResponse.class);
+// emitter.onNext(streamResponse);
+// }
+// emitter.onComplete();
+// }, BackpressureStrategy.BUFFER);
+// }
+//}
+//
+//public class rld {
+// public static void main(String... args) {
+// String apiKey = System.getenv("MOONSHOT_API_KEY");
+// if (apiKey == null) {
+// System.out.println("Please set MOONSHOT_API_KEY env");
+// return;
+// }
+// Client client = new Client(apiKey);
+// try {
+// ModelsList models = client.ListModels();
+// for (Model model : models.getData()) {
+// System.out.println(model.getId());
+// }
+// } catch (IOException e) {
+// e.printStackTrace();
+// }
+//
+// final List messages = List.of(
+// new ChatCompletionMessage(ChatMessageRole.SYSTEM.value(),
+// "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一些涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"),
+// new ChatCompletionMessage(ChatMessageRole.USER.value(),
+// "你好,我叫李雷,1+1等于多少?")
+// );
+//
+//// try {
+//// ChatCompletionResponse response = client.ChatCompletion(new ChatCompletionRequest(
+//// "moonshot-v1-8k",
+//// messages,
+//// 50,
+//// 0.3f,
+//// 1
+//// ));
+//// for (ChatCompletionChoice choice : response.getChoices()) {
+//// System.out.println(choice.getMessage().getContent());
+//// }
+//// } catch (IOException e) {
+//// e.printStackTrace();
+//// }
+//AtomicR
+// try {
+// client.ChatCompletionStream(new ChatCompletionRequest(
+// "moonshot-v1-8k",
+// messages,
+// 50,
+// 0.3f,
+// 1
+// )).subscribe(
+// streamResponse -> {
+// if (streamResponse.getChoices().isEmpty()) {
+// return;
+// }
+// for (ChatCompletionStreamChoice choice : streamResponse.getChoices()) {
+// String finishReason = choice.getFinishReason();
+// if (finishReason != null) {
+// System.out.println("finish reason: " + finishReason);
+// continue;
+// }
+// System.out.println(choice.getDelta().getContent());
+// }
+// },
+// error -> {
+// error.printStackTrace();
+// },
+// () -> {
+// System.out.println("complete");
+// }
+// );
+// } catch (Exception e) {
+// e.printStackTrace();
+// }
+// }
+//}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/system/ai/service/IAiKeyService.java b/src/main/java/com/ruoyi/system/ai/service/IAiKeyService.java
new file mode 100644
index 0000000..937bc38
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/IAiKeyService.java
@@ -0,0 +1,87 @@
+package com.ruoyi.system.ai.service;
+
+import java.util.List;
+import com.muta.ai.domain.AiKey;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * 【请填写功能名称】Service接口
+ *
+ * @author mutaai
+ * @date 2024-05-16
+ */
+public interface IAiKeyService extends IService {
+ /**
+ * 查询【请填写功能名称】
+ *
+ * @param id 【请填写功能名称】主键
+ * @return 【请填写功能名称】
+ */
+ public AiKey selectAiKeyById(Long id);
+
+ /**
+ * 查询【请填写功能名称】列表
+ *
+ * @return 【请填写功能名称】集合
+ */
+ public List selectAiKeyList();
+
+ /**
+ * 新增【请填写功能名称】
+ *
+ * @param aiKey 【请填写功能名称】
+ * @return 结果
+ */
+ public int insertAiKey(AiKey aiKey);
+
+ /**
+ * 修改【请填写功能名称】
+ *
+ * @param aiKey 【请填写功能名称】
+ * @return 结果
+ */
+ public int updateAiKey(AiKey aiKey);
+
+ /**
+ * 批量删除【请填写功能名称】
+ *
+ * @param ids 需要删除的【请填写功能名称】主键集合
+ * @return 结果
+ */
+ public int deleteAiKeyByIds(Long[] ids);
+
+ /**
+ * 删除【请填写功能名称】信息
+ *
+ * @param id 【请填写功能名称】主键
+ * @return 结果
+ */
+ public int deleteAiKeyById(Long id);
+
+ /**
+ * 查询额度
+ *
+ * @param key
+ * @return
+ */
+ public String getLimitByKey(String key);
+
+ /**
+ * 判断key是否可用
+ * @param key
+ * @return
+ */
+ public Integer isAvailable(String key);
+
+ /**
+ * 通过id获得AiKey(String)
+ * @param
+ * @return
+ */
+ List getAiKeyStrById(Long userId);
+
+ /**
+ * 刷新Key额度
+ */
+ void updateKeyLimit();
+}
diff --git a/src/main/java/com/ruoyi/system/ai/service/IChatConfigService.java b/src/main/java/com/ruoyi/system/ai/service/IChatConfigService.java
new file mode 100644
index 0000000..9eb7cf1
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/IChatConfigService.java
@@ -0,0 +1,49 @@
+package com.ruoyi.system.ai.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.muta.ai.config.ChatConfig;
+
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Service接口
+ *
+ * @author mutaai
+ * @date 2024-05-13
+ */
+public interface IChatConfigService extends IService {
+ /**
+ * 查询【请填写功能名称】
+ *
+ * @param id 【请填写功能名称】主键
+ * @return 【请填写功能名称】
+ */
+ public ChatConfig selectChatConfigById(Long id);
+
+ /**
+ * 查询【请填写功能名称】列表
+ *
+ * @param chatConfig 【请填写功能名称】
+ * @return 【请填写功能名称】集合
+ */
+ public List selectChatConfigList(ChatConfig chatConfig);
+
+ /**
+ * 新增【请填写功能名称】
+ *
+ * @param chatConfig 【请填写功能名称】
+ * @return 结果
+ */
+ public int insertChatConfig(ChatConfig chatConfig);
+
+ /**
+ * 修改【请填写功能名称】
+ *
+ * @param chatConfig 【请填写功能名称】
+ * @return 结果
+ */
+ public int updateChatConfig(ChatConfig chatConfig);
+
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/service/IChatService.java b/src/main/java/com/ruoyi/system/ai/service/IChatService.java
new file mode 100644
index 0000000..e718f17
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/IChatService.java
@@ -0,0 +1,20 @@
+package com.ruoyi.system.ai.service;
+
+import com.muta.ai.domain.ChatCompletionMessage;
+import com.muta.ai.chain.MusicProcessAggregate;
+import com.muta.ai.chain.UserAccountQuotaEntity;
+
+import java.util.List;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /09 / 20:06
+ * @Description:
+ */
+public interface IChatService {
+
+
+
+ MusicProcessAggregate initChatData(Long userId, String model, List messages);
+ UserAccountQuotaEntity initUserData(Long userId);
+}
diff --git a/src/main/java/com/ruoyi/system/ai/service/IChatUploadService.java b/src/main/java/com/ruoyi/system/ai/service/IChatUploadService.java
new file mode 100644
index 0000000..9b46fe1
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/IChatUploadService.java
@@ -0,0 +1,13 @@
+package com.ruoyi.system.ai.service;
+
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /15 / 20:59
+ * @Description:
+ */
+public interface IChatUploadService {
+ String upload(MultipartFile file);
+ String analyzeFile(String path);
+}
diff --git a/src/main/java/com/ruoyi/system/ai/service/ILogicFilter.java b/src/main/java/com/ruoyi/system/ai/service/ILogicFilter.java
new file mode 100644
index 0000000..86fcc92
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/ILogicFilter.java
@@ -0,0 +1,16 @@
+package com.ruoyi.system.ai.service;
+
+
+import com.muta.ai.chain.MusicProcessAggregate;
+import com.muta.ai.domain.RuleLogicEntity;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 规则过滤接口
+ * @create 2023-09-16 16:59
+ */
+public interface ILogicFilter {
+
+ RuleLogicEntity filter(MusicProcessAggregate chatProcess, T data) throws Exception;
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/service/IMessageFileService.java b/src/main/java/com/ruoyi/system/ai/service/IMessageFileService.java
new file mode 100644
index 0000000..e192f58
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/IMessageFileService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.system.ai.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.muta.ai.domain.MessageFile;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * @author 马兰友
+ * @Date: 2024/05/17/15:15
+ */
+public interface IMessageFileService extends IService {
+ MessageFile upload(MultipartFile file) throws Exception;
+
+ //根据url获取文件解析信息
+ String getContentByUrl(String url);
+}
diff --git a/src/main/java/com/ruoyi/system/ai/service/IMessageService.java b/src/main/java/com/ruoyi/system/ai/service/IMessageService.java
new file mode 100644
index 0000000..c3eb27c
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/IMessageService.java
@@ -0,0 +1,19 @@
+package com.ruoyi.system.ai.service;
+
+import com.muta.ai.domain.MessageEntity;
+import com.muta.common.core.domain.entity.SysUser;
+import com.muta.system.domain.Message;
+
+import java.util.List;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /20 / 13:01
+ * @Description:
+ */
+public interface IMessageService {
+ //根据权限返回对应消息列表
+ List getList(SysUser sysUser);
+
+ void add(MessageEntity message);
+}
diff --git a/src/main/java/com/ruoyi/system/ai/service/IMessageSessionService.java b/src/main/java/com/ruoyi/system/ai/service/IMessageSessionService.java
new file mode 100644
index 0000000..bc3f456
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/IMessageSessionService.java
@@ -0,0 +1,11 @@
+package com.ruoyi.system.ai.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.muta.ai.domain.MessageSession;
+
+/**
+ * @author 马兰友
+ * @Date: 2024/05/13/16:07
+ */
+public interface IMessageSessionService extends IService {
+}
diff --git a/src/main/java/com/ruoyi/system/ai/service/IModelService.java b/src/main/java/com/ruoyi/system/ai/service/IModelService.java
new file mode 100644
index 0000000..286a0bb
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/IModelService.java
@@ -0,0 +1,7 @@
+package com.ruoyi.system.ai.service;
+
+import java.util.List;
+
+public interface IModelService {
+ List getModelList();
+}
diff --git a/src/main/java/com/ruoyi/system/ai/service/impl/AiKeyServiceImpl.java b/src/main/java/com/ruoyi/system/ai/service/impl/AiKeyServiceImpl.java
new file mode 100644
index 0000000..65b4873
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/impl/AiKeyServiceImpl.java
@@ -0,0 +1,163 @@
+package com.ruoyi.system.ai.service.impl;
+
+import com.alibaba.fastjson2.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.muta.ai.mapper.AiKeyMapper;
+import com.muta.ai.util.MoonshotAiUtils;
+import com.muta.common.utils.SecurityUtils;
+import org.apache.commons.lang3.ObjectUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+import com.muta.ai.domain.AiKey;
+import com.muta.ai.service.IAiKeyService;
+import org.web3j.crypto.MnemonicUtils;
+
+import java.math.BigDecimal;
+import java.security.Security;
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Service业务层处理
+ *
+ * @author mutaai
+ * @date 2024-05-16
+ */
+@Service
+public class AiKeyServiceImpl extends ServiceImpl implements IAiKeyService {
+ @Autowired
+ private AiKeyMapper aiKeyMapper;
+
+ /**
+ * 查询【请填写功能名称】
+ *
+ * @param id 【请填写功能名称】主键
+ * @return 【请填写功能名称】
+ */
+ @Override
+ public AiKey selectAiKeyById(Long id) {
+ return aiKeyMapper.selectAiKeyById(id);
+ }
+
+ /**
+ * 查询【请填写功能名称】列表
+ *
+ * @return 【请填写功能名称】
+ */
+ @Override
+ public List selectAiKeyList() {
+ return aiKeyMapper.selectAiKeyList();
+ }
+
+ /**
+ * 新增【请填写功能名称】
+ *
+ * @param aiKey 【请填写功能名称】
+ * @return 结果
+ */
+ @Override
+ public int insertAiKey(AiKey aiKey) {
+ String limit = getLimitByKey(aiKey.getKey());
+ aiKey.setLimit(new BigDecimal(limit));
+ aiKey.setUserId(SecurityUtils.getUserId());
+ return aiKeyMapper.insertAiKey(aiKey);
+ }
+
+ /**
+ * 修改【请填写功能名称】
+ *
+ * @param aiKey 【请填写功能名称】
+ * @return 结果
+ */
+ @Override
+ public int updateAiKey(AiKey aiKey) {
+ return aiKeyMapper.updateAiKey(aiKey);
+ }
+
+ /**
+ * 批量删除【请填写功能名称】
+ *
+ * @param ids 需要删除的【请填写功能名称】主键
+ * @return 结果
+ */
+ @Override
+ public int deleteAiKeyByIds(Long[] ids) {
+ return aiKeyMapper.deleteAiKeyByIds(ids);
+ }
+
+ /**
+ * 删除【请填写功能名称】信息
+ *
+ * @param id 【请填写功能名称】主键
+ * @return 结果
+ */
+ @Override
+ public int deleteAiKeyById(Long id) {
+ return aiKeyMapper.deleteAiKeyById(id);
+ }
+
+ /**
+ * 查询额度
+ *
+ * @param key
+ * @return
+ */
+ @Override
+ public String getLimitByKey(String key) {
+ String balance = MoonshotAiUtils.getBalanceByKey(key);
+ Object availableBalance = JSON.parseObject(balance)
+ .getJSONObject("data")
+ .get("available_balance");
+ return availableBalance.toString();
+ }
+
+ /**
+ * 判断key是否可用
+ * @param key
+ * @return
+ */
+ @Override
+ public Integer isAvailable(String key) {
+ if (ObjectUtils.isEmpty(key)) return 1;
+
+ // 0可用 1不可用
+ String response = MoonshotAiUtils.getBalanceByKey(key);
+ Object error = JSON.parseObject(response).get("error");
+ if (ObjectUtils.isEmpty(error)) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+
+ /**
+ * 通过user_id获得AiKey
+ * @param
+ * @return
+ */
+ @Override
+ public List getAiKeyStrById(Long userId) {
+ System.out.println(userId);
+ return aiKeyMapper.list(userId);
+ }
+
+ /**
+ * 刷新Key额度。
+ * 该方法不接受参数,也不返回任何值。
+ * 功能描述:获取当前用户ID,查询该用户所有的Key信息,并更新每个Key的额度。
+ */
+ @Override
+ public void updateKeyLimit() {
+ // 获取当前登录用户的ID
+ Long userId = SecurityUtils.getUserId();
+ // 构造查询条件,查询当前用户所有的Key
+ QueryWrapper wrapper = new QueryWrapper().eq("user_id", userId);
+ List aiKeyList = aiKeyMapper.selectList(wrapper);
+ // 遍历查询结果,更新每个Key的额度
+ aiKeyList.forEach(key -> {
+ key.setLimit(new BigDecimal(getLimitByKey(key.getKey())));
+ });
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/ai/service/impl/BaseChatService.java b/src/main/java/com/ruoyi/system/ai/service/impl/BaseChatService.java
new file mode 100644
index 0000000..71bdcd3
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/impl/BaseChatService.java
@@ -0,0 +1,75 @@
+package com.ruoyi.system.ai.service.impl;//package com.muta.ai.service.impl;
+//
+//import com.muta.ai.chain.MusicProcessAggregate;
+//import com.muta.ai.domain.MessageEntity;
+//import com.muta.ai.domain.RuleLogicEntity;
+//import com.muta.ai.chain.UserAccountQuotaEntity;
+//import com.muta.ai.enums.LogicCheckEnum;
+//import com.muta.ai.factory.DefaultLogicFactory;
+//import com.muta.ai.service.ILogicFilter;
+//import com.muta.ai.service.IMessageService;
+//import com.muta.common.constant.Constants;
+//import com.muta.common.core.domain.entity.UserExtra;
+//import com.muta.common.utils.SecurityUtils;
+//import com.muta.log.domain.IntegralLog;
+//import com.muta.log.service.impl.MessageIntegralLogServiceImpl;
+//import com.muta.system.mapper.UserExtraMapper;
+//import org.springframework.transaction.annotation.Transactional;
+//
+//import javax.annotation.Resource;
+//import java.util.Map;
+//
+///**
+// * @author: Larry
+// * @Date: 2024 /05 /09 / 16:05
+// * @Description: 前置过滤规则处理
+// */
+//public class BaseChatService {
+// @Resource
+// private DefaultLogicFactory logicFactory;
+// //后面可拓展为根据需要传入对应过滤器执行
+// @Resource
+// private UserExtraMapper userExtraMapper;
+// @Resource
+// private IMessageService messageService;
+// @Resource
+// private MessageIntegralLogServiceImpl messageIntegralLogService;
+// //前置过滤
+// protected RuleLogicEntity doCheckLogic(MusicProcessAggregate chatProcess, UserAccountQuotaEntity userAccountQuotaEntity) throws Exception {
+// //获得所有的拦截器
+// Map> logicFilterMap = logicFactory.openLogicFilter();
+// //定义返回结果
+// RuleLogicEntity entity = null;
+// //遍历所有拦截器,如果拦截则结束并返回,否则放行
+// for (ILogicFilter filter : logicFilterMap.values()) {
+// entity = filter.filter(chatProcess,userAccountQuotaEntity);
+// if(entity.getType().equals(LogicCheckEnum.REFUSE)){
+// return entity;
+// }
+// }
+// //全部方向后通过
+// return entity != null ? entity : RuleLogicEntity.builder()
+// .type(LogicCheckEnum.SUCCESS).data(chatProcess).build();
+//
+// }
+// //后置过滤
+// @Transactional
+// public void PostRule(MusicProcessAggregate chatProcess, UserAccountQuotaEntity userAccountQuotaEntity, MessageEntity message){
+// double result = chatProcess.getTokenNum() / (double) chatProcess.getModelConsumer();
+// Integer consumption = Math.toIntExact(Math.round(result));
+// //扣减积分
+// increaseIntegral(consumption,userAccountQuotaEntity.getUserId());
+// //新增积分记录
+// IntegralLog integralLog = IntegralLog.builder()
+// .value(consumption+"积分")
+// .build();
+// messageIntegralLogService.insertLog(integralLog);
+// //新增消息记录
+//// messageService.add(message);
+// }
+// private void increaseIntegral(Integer integral,Long userId){
+// userExtraMapper.IncreaseIntegralByUserId(integral,userId);
+// }
+//
+//
+//}
diff --git a/src/main/java/com/ruoyi/system/ai/service/impl/ChatConfigServiceImpl.java b/src/main/java/com/ruoyi/system/ai/service/impl/ChatConfigServiceImpl.java
new file mode 100644
index 0000000..d3d671d
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/impl/ChatConfigServiceImpl.java
@@ -0,0 +1,83 @@
+package com.ruoyi.system.ai.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import java.util.List;
+
+import com.muta.ai.config.ChatConfig;
+import com.muta.ai.mapper.ChatConfigMapper;
+import com.muta.ai.service.IChatConfigService;
+import com.muta.common.utils.SecurityUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+/**
+ * 【请填写功能名称】Service业务层处理
+ *
+ * @author mutaai
+ * @date 2024-05-13
+ */
+@Service
+public class ChatConfigServiceImpl extends ServiceImpl implements IChatConfigService {
+ @Resource
+ private ChatConfigMapper chatConfigMapper;
+
+ /**
+ * 查询【请填写功能名称】
+ *
+ * @param 【请填写功能名称】主键
+ * @return 【请填写功能名称】
+ */
+ @Override
+ public ChatConfig selectChatConfigById(Long userId) {
+ LambdaQueryWrapper chatConfigLambdaQueryWrapper = new LambdaQueryWrapper<>();
+ chatConfigLambdaQueryWrapper.eq(userId!=null,ChatConfig::getUserId, userId);
+ return chatConfigMapper.selectOne(chatConfigLambdaQueryWrapper);
+ }
+
+ /**
+ * 查询【请填写功能名称】列表
+ *
+ * @param chatConfig 【请填写功能名称】
+ * @return 【请填写功能名称】
+ */
+ @Override
+ public List selectChatConfigList(ChatConfig chatConfig) {
+ return chatConfigMapper.selectChatConfigList(chatConfig);
+ }
+
+ /**
+ * 新增【请填写功能名称】
+ *
+ * @param chatConfig 【请填写功能名称】
+ * @return 结果
+ */
+ @Override
+ public int insertChatConfig(ChatConfig chatConfig) {
+ return chatConfigMapper.insert(chatConfig);
+ }
+
+ /**
+ * 修改【请填写功能名称】
+ *
+ * @param chatConfig 【请填写功能名称】
+ * @return 结果
+ */
+ @Override
+ public int updateChatConfig(ChatConfig chatConfig) {
+ System.out.println(chatConfig.getUserId());
+ LambdaQueryWrapper chatConfigLambdaQueryWrapper = new LambdaQueryWrapper<>();
+ chatConfigLambdaQueryWrapper.eq(SecurityUtils.getUserId()!=null,ChatConfig::getUserId, SecurityUtils.getUserId());
+ return chatConfigMapper.update(chatConfig,chatConfigLambdaQueryWrapper);
+ }
+
+ /**
+ * 批量删除【请填写功能名称】
+ *
+ * @param ids 需要删除的【请填写功能名称】主键
+ * @return 结果
+ */
+
+}
diff --git a/src/main/java/com/ruoyi/system/ai/service/impl/KimiChatService.java b/src/main/java/com/ruoyi/system/ai/service/impl/KimiChatService.java
new file mode 100644
index 0000000..43ee9ba
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/impl/KimiChatService.java
@@ -0,0 +1,110 @@
+package com.ruoyi.system.ai.service.impl;//package com.muta.ai.service.impl;
+//
+//import com.alibaba.fastjson2.JSON;
+//import com.alibaba.fastjson2.JSONObject;
+//import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+//import com.muta.ai.config.ChatConfig;
+//
+//import com.muta.ai.domain.*;
+//import com.muta.ai.domain.dto.MessageHistoryKimi;
+//import com.muta.ai.service.IAiKeyService;
+//import com.muta.ai.service.IChatConfigService;
+//import com.muta.ai.service.IChatService;
+//import com.muta.ai.util.MoonshotAiUtils;
+//import com.muta.common.core.domain.entity.UserExtra;
+//import com.muta.system.mapper.UserExtraMapper;
+//import com.muta.system.service.ICommonSettingService;
+//import com.muta.system.service.impl.CommonSettingServiceImpl;
+//import org.springframework.stereotype.Service;
+//
+//import javax.annotation.Resource;
+//import java.math.BigDecimal;
+//import java.util.Comparator;
+//import java.util.List;
+//import java.util.Optional;
+//import java.util.stream.Collectors;
+//
+///**
+// * @author: Larry
+// * @Date: 2024 /05 /09 / 18:06
+// * @Description:
+// */
+//@SuppressWarnings("all")
+//@Service
+//public class KimiChatService extends BaseChatService implements IChatService {
+// @Resource
+// private IAiKeyService aiKeyService;
+// @Resource
+// private UserExtraMapper userExtraMapper;
+// @Resource
+// private IChatConfigService chatConfigService;
+// @Resource
+// private ICommonSettingService commonSettingService;
+//
+// @Override
+// public UserAccountQuotaEntity initUserData(Long userId) {
+// LambdaQueryWrapper userExtraLambdaQueryWrapper = new LambdaQueryWrapper<>();
+// userExtraLambdaQueryWrapper.eq(userId!=null,UserExtra::getUserId,userId);
+// UserExtra userExtra = userExtraMapper.selectOne(userExtraLambdaQueryWrapper);
+// ChatConfig config = chatConfigService.selectChatConfigById(userId);
+// return UserAccountQuotaEntity.builder()
+// .userId(userId)
+// .integral(userExtra.getIntegral())
+// .maxToken(config.getMaxToken())
+// .build();
+// }
+//
+// @Override
+// public MusicProcessAggregate initChatData(Long userId, String model, List messages) {
+// String key = LoadBalancingKey(userId);
+// Integer tokenNum = getTokenNum(model, messages);
+// return MusicProcessAggregate.builder()
+// .messages(messages)
+// .model(model)
+// .userId(userId)
+// .key(key)
+// .tokenNum(tokenNum)
+// .modelConsumer(commonSettingService.getRatioByName(model))
+// .build();
+// }
+//
+// private Integer getTokenNum(String model, List messages) {
+// List messageHistoryKimis = messages.stream().map(
+// chatCompletionMessage -> MessageHistoryKimi.builder()
+// .role(chatCompletionMessage.getRole())
+// .content(chatCompletionMessage.getContent())
+// .build()
+//).collect(Collectors.toList());
+// // 调用工具类方法,估算对话的令牌数量
+// String response = MoonshotAiUtils.estimateTokenCount(model, messageHistoryKimis);
+// JSONObject jsonObject = JSON.parseObject(response);
+// return jsonObject.getJSONObject("data").getInteger("total_tokens");
+// }
+//
+// @Override
+// public RuleLogicEntity doCheckLogic(MusicProcessAggregate chatProcess, UserAccountQuotaEntity userAccountQuotaEntity) throws Exception {
+// return super.doCheckLogic(chatProcess, userAccountQuotaEntity);
+// }
+//
+// @Override
+// public void PostRule(MusicProcessAggregate chatProcess, UserAccountQuotaEntity userAccountQuotaEntity, MessageEntity message) {
+// super.PostRule(chatProcess, userAccountQuotaEntity, message);
+// }
+//
+// private String LoadBalancingKey(Long userId) {
+// //找到该用户的最近代理
+// LambdaQueryWrapper userExtraMapperLambdaQueryWrapper = new LambdaQueryWrapper<>();
+// userExtraMapperLambdaQueryWrapper.eq(userId != null, UserExtra::getUserId, userId);
+// UserExtra extraInfo = userExtraMapper.selectOne(userExtraMapperLambdaQueryWrapper);
+// List aiKeyList = aiKeyService.getAiKeyStrById(extraInfo.getLowestId());
+// //找到下面额度最大的key,实现负载均衡
+// if (aiKeyList != null && !aiKeyList.isEmpty()) {
+// AiKey max = aiKeyList.stream()
+// .filter(aiKey -> aiKey.getKey() != null)
+// .max(Comparator.comparing(AiKey::getLimit))
+// .orElse(null);
+// return max.getKey();
+// }
+// return null;
+// }
+//}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/system/ai/service/impl/MessageFileServiceImpl.java b/src/main/java/com/ruoyi/system/ai/service/impl/MessageFileServiceImpl.java
new file mode 100644
index 0000000..abdce51
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/impl/MessageFileServiceImpl.java
@@ -0,0 +1,117 @@
+package com.ruoyi.system.ai.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.muta.ai.domain.MessageFile;
+import com.muta.ai.mapper.MessageFileMapper;
+import com.muta.ai.service.IMessageFileService;
+import com.muta.ai.util.DocumentReaderUtils;
+import com.muta.common.core.service.ISysFileService;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.stereotype.Service;
+import org.springframework.util.FileCopyUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * @author 马兰友
+ * @Date: 2024/05/17/15:15
+ */
+@Service
+public class MessageFileServiceImpl extends ServiceImpl implements IMessageFileService {
+
+ @Resource
+ private MessageFileMapper messageFileMapper;
+
+ @Resource
+ private ISysFileService aliOssServiceImpl;
+
+ @Resource
+ @Qualifier("asyncPoolTaskExecutor")
+ ThreadPoolTaskExecutor executor;
+
+
+ @Override
+ public MessageFile upload(MultipartFile file) throws Exception {
+ MessageFile messageFile = new MessageFile();
+ messageFile.setUrl(aliOssServiceImpl.uploadFile(file));
+ File tempFile = multipartFile2File(file);
+ messageFile.setAnalysisContent(DocumentReaderUtils.readDocument(tempFile));
+ if (tempFile.exists()) {
+ tempFile.delete();
+ }
+ messageFile.setName(file.getOriginalFilename());
+ messageFile.setSize(formatFileSize(file.getSize()));
+ messageFileMapper.insert(messageFile);
+
+ return messageFile;
+ }
+
+ @Override
+ public String getContentByUrl(String url) {
+ LambdaQueryWrapper lqw = new LambdaQueryWrapper<>();
+ lqw.eq(MessageFile::getUrl, url);
+ MessageFile messageFile = messageFileMapper.selectOne(lqw);
+ return messageFile.getAnalysisContent();
+ }
+
+ private CompletableFuture futureUpload(MultipartFile file){
+ return CompletableFuture.supplyAsync(() -> {
+ try {
+ MessageFile messageFile = new MessageFile();
+ messageFile.setUrl(aliOssServiceImpl.uploadFile(file));
+ File tempFile = multipartFile2File(file);
+ messageFile.setAnalysisContent(DocumentReaderUtils.readDocument(tempFile));
+ deleteTempFile(tempFile);
+ messageFile.setName(file.getOriginalFilename());
+ messageFile.setSize(formatFileSize(file.getSize()));
+ messageFileMapper.insert(messageFile);
+ return messageFile;
+ } catch (Exception e) {
+ // 根据需要处理异常,或者重新抛出
+ throw new RuntimeException(e);
+ }
+ }, executor); // 使用提供的线程池执行上传任务
+ }
+
+ private void deleteTempFile(File tempFile) throws IOException {
+ if (tempFile.exists()) {
+ boolean delete = tempFile.delete();
+ if (!delete) {
+ throw new IOException("Failed to delete temporary file: " + tempFile.getAbsolutePath());
+ }
+ }
+ }
+
+
+ public File multipartFile2File (MultipartFile multipartFile) throws IOException {
+ // 获取原始文件名
+ String originalFilename = multipartFile.getOriginalFilename();
+ // 获取文件扩展名
+ String fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
+ // 创建临时文件
+ File file = File.createTempFile("temp-" + UUID.randomUUID(), fileExtension);
+ System.err.println(file);
+ // 将MultipartFile对象的内容写入临时文件
+ multipartFile.transferTo(file);
+ return file;
+ }
+ public String formatFileSize(long bytes) {
+ double kilobytes = bytes / 1024.0;
+ double megabytes = kilobytes / 1024.0;
+
+ if (megabytes >= 1) {
+ return String.format("%.2f MB", megabytes);
+ } else {
+ return String.format("%.2f KB", kilobytes);
+ }
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/ai/service/impl/MessageServiceImpl.java b/src/main/java/com/ruoyi/system/ai/service/impl/MessageServiceImpl.java
new file mode 100644
index 0000000..2dfcff2
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/impl/MessageServiceImpl.java
@@ -0,0 +1,31 @@
+package com.ruoyi.system.ai.service.impl;
+
+import com.muta.ai.domain.MessageEntity;
+import com.muta.ai.mapper.MessageMapper;
+import com.muta.ai.service.IMessageService;
+import com.muta.common.core.domain.entity.SysUser;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /20 / 13:01
+ * @Description:
+ */
+@Service
+public class MessageServiceImpl implements IMessageService {
+ @Resource
+ private MessageMapper messageMapper;
+
+ @Override
+ public void add(MessageEntity message) {
+ messageMapper.insert(message);
+ }
+
+ @Override
+ public List getList(SysUser sysUser) {
+ return messageMapper.selectByFilter(sysUser);
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/ai/service/impl/MessageSessionServiceImpl.java b/src/main/java/com/ruoyi/system/ai/service/impl/MessageSessionServiceImpl.java
new file mode 100644
index 0000000..c84065d
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/impl/MessageSessionServiceImpl.java
@@ -0,0 +1,15 @@
+package com.ruoyi.system.ai.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.muta.ai.domain.MessageSession;
+import com.muta.ai.mapper.MessageSessionMapper;
+import com.muta.ai.service.IMessageSessionService;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author 马兰友
+ * @Date: 2024/05/13/16:07
+ */
+@Service
+public class MessageSessionServiceImpl extends ServiceImpl implements IMessageSessionService {
+}
diff --git a/src/main/java/com/ruoyi/system/ai/service/impl/ModelService.java b/src/main/java/com/ruoyi/system/ai/service/impl/ModelService.java
new file mode 100644
index 0000000..5e12768
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/impl/ModelService.java
@@ -0,0 +1,36 @@
+package com.ruoyi.system.ai.service.impl;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import com.muta.ai.service.IModelService;
+import com.muta.ai.util.MoonshotAiUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class ModelService implements IModelService {
+
+ /**
+ * 从MoonshotAiUtils工具类中获取模型列表的JSON字符串,解析并返回模型ID的列表
+ * @return 模型ID列表
+ */
+ @Override
+ public List getModelList() {
+ List models = new ArrayList<>();
+
+ // 获取模型列表的JSON字符串
+ String modelListJSON = MoonshotAiUtils.getModelList();
+ // 解析JSON字符串,获取模型数据数组
+ JSONArray data = JSON.parseObject(modelListJSON).getJSONArray("data");
+ // 遍历数据数组,提取模型ID并添加到列表中
+ data.forEach(item -> {
+ JSONObject model = (JSONObject) item;
+ models.add(model.getString("id"));
+ });
+ return models;
+ }
+}
+
diff --git a/src/main/java/com/ruoyi/system/ai/service/impl/SensitiveWordFilter.java b/src/main/java/com/ruoyi/system/ai/service/impl/SensitiveWordFilter.java
new file mode 100644
index 0000000..0ebbec7
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/impl/SensitiveWordFilter.java
@@ -0,0 +1,52 @@
+package com.ruoyi.system.ai.service.impl;//package com.muta.ai.service.impl;
+//
+//import com.github.houbb.sensitive.word.bs.SensitiveWordBs;
+//import com.github.houbb.sensitive.word.core.SensitiveWordHelper;
+//import com.muta.ai.annotation.LogicStrategy;
+//import com.muta.ai.domain.*;
+//import com.muta.ai.enums.LogicCheckEnum;
+//import com.muta.ai.factory.DefaultLogicFactory;
+//import com.muta.ai.service.ILogicFilter;
+//import com.muta.common.annotation.Log;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.beans.factory.annotation.Qualifier;
+//import org.springframework.stereotype.Component;
+//
+//import javax.annotation.Resource;
+//import java.util.List;
+//
+///**
+// * @author Larry
+// * @description 敏感词过滤
+// * @create 2024-05-10 17:39
+// */
+//@Slf4j
+//@Component
+//@LogicStrategy(logicMode = DefaultLogicFactory.LogicModel.SENSITIVE_WORD)
+//public class SensitiveWordFilter implements ILogicFilter {
+// @Resource
+// @Qualifier("sensitiveWordBsBean")
+// SensitiveWordBs sensitiveWordBs;
+// @Override
+// public RuleLogicEntity filter(MusicProcessAggregate chatProcess, UserAccountQuotaEntity data) throws Exception {
+// //只对当前的信息进行敏感词过滤
+// ChatCompletionMessage nowMessage = chatProcess.getMessages().get(chatProcess.getMessages().size() -1);
+// System.out.println();
+// //调用外部依赖进行敏感词查找
+// if (sensitiveWordBs.contains(nowMessage.getContent())) {
+// //如果有敏感词,返回相关结果
+// return RuleLogicEntity.builder()
+// .type(LogicCheckEnum.REFUSE)
+// .info("您的对话含有敏感词,请注意!")
+// .data(chatProcess).build();
+// }
+//
+// return RuleLogicEntity.builder()
+// .type(LogicCheckEnum.SUCCESS).data(chatProcess).build();
+// }
+//
+// public static void main(String[] args) {
+//
+//
+// }
+//}
diff --git a/src/main/java/com/ruoyi/system/ai/service/impl/TokenFilter.java b/src/main/java/com/ruoyi/system/ai/service/impl/TokenFilter.java
new file mode 100644
index 0000000..cb66880
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/impl/TokenFilter.java
@@ -0,0 +1,62 @@
+package com.ruoyi.system.ai.service.impl;//package com.muta.ai.service.impl;
+//
+//import com.alibaba.fastjson2.JSON;
+//import com.alibaba.fastjson2.JSONObject;
+//import com.muta.ai.annotation.LogicStrategy;
+//import com.muta.ai.domain.*;
+//import com.muta.ai.domain.dto.MessageHistoryKimi;
+//import com.muta.ai.enums.LogicCheckEnum;
+//import com.muta.ai.factory.DefaultLogicFactory;
+//import com.muta.ai.service.ILogicFilter;
+//import com.muta.ai.util.MoonshotAiUtils;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.stereotype.Component;
+//
+//import java.util.ArrayList;
+//import java.util.List;
+//import java.util.stream.Collectors;
+//
+///**
+// * 该类实现了ILogicFilter接口,用于过滤total_tokens。
+// * 通过评估对话中消息的令牌数量,决定是否继续处理或拒绝该对话。
+// */
+//@Slf4j
+//@LogicStrategy(logicMode = DefaultLogicFactory.LogicModel.MAX_TOKEN)
+//@Component
+//public class TokenFilter implements ILogicFilter {
+//
+// /**
+// * 过滤方法,检查对话的total_tokens数量是否超过限制。
+// * @param chatProcess
+// * @param data
+// * @return 如果超过限制,返回拒绝信息;否则返回成功。
+// * @throws Exception 如果过程中发生错误,抛出异常。
+// */
+//// List messageHistoryKimis = chatProcess.getMessages().stream().map(
+//// chatCompletionMessage -> MessageHistoryKimi.builder()
+//// .role(chatCompletionMessage.getRole())
+//// .content(chatCompletionMessage.getContent())
+//// .build()
+//// ).collect(Collectors.toList());
+//// // 调用工具类方法,估算对话的令牌数量
+//// String response = MoonshotAiUtils.estimateTokenCount(chatProcess.getModel(), messageHistoryKimis);
+//// JSONObject jsonObject = JSON.parseObject(response);
+//// Integer total_tokens = jsonObject.getJSONObject("data").getInteger("total_tokens");
+// @Override
+// public RuleLogicEntity filter(MusicProcessAggregate chatProcess, UserAccountQuotaEntity data) throws Exception {
+// // 检查数量是否超过配置的最大值
+// if (chatProcess.getTokenNum() > data.getMaxToken()) {
+// // 如果超过最大值,返回拒绝信息
+// return RuleLogicEntity.builder()
+// .type(LogicCheckEnum.REFUSE)
+// .info("您的对话所含token数超过限制!")
+// .data(chatProcess).build();
+// }
+//
+// // 如果未超过最大值,返回成功
+// return RuleLogicEntity.builder()
+// .type(LogicCheckEnum.SUCCESS)
+// .data(chatProcess).build();
+// }
+//}
+//
diff --git a/src/main/java/com/ruoyi/system/ai/service/impl/UserQuotaFilter.java b/src/main/java/com/ruoyi/system/ai/service/impl/UserQuotaFilter.java
new file mode 100644
index 0000000..0600280
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/service/impl/UserQuotaFilter.java
@@ -0,0 +1,46 @@
+package com.ruoyi.system.ai.service.impl;//package com.muta.ai.service.impl;
+//import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+//import com.muta.ai.annotation.LogicStrategy;
+//import com.muta.ai.chain.MusicProcessAggregate;
+//import com.muta.ai.domain.RuleLogicEntity;
+//import com.muta.ai.chain.UserAccountQuotaEntity;
+//import com.muta.ai.enums.LogicCheckEnum;
+//import com.muta.ai.factory.DefaultLogicFactory;
+//import com.muta.ai.service.ILogicFilter;
+//import com.muta.common.core.domain.entity.UserExtra;
+//import com.muta.system.mapper.UserExtraMapper;
+//import com.muta.system.service.ICommonSettingService;
+//import com.muta.system.service.impl.CommonSettingServiceImpl;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.stereotype.Component;
+//
+//import javax.annotation.Resource;
+//
+///**
+// * @author Fuzhengwei bugstack.cn @小傅哥
+// * @description 用户额度扣减规则过滤
+// * @create 2023-10-03 16:48
+// */
+//@Slf4j
+//@Component
+//@LogicStrategy(logicMode = DefaultLogicFactory.LogicModel.USER_QUOTA)
+//public class UserQuotaFilter implements ILogicFilter {
+// //调用基础业务查询积分
+// @Resource
+// private UserExtraMapper userExtraMapper;
+// @Override
+// public RuleLogicEntity filter(MusicProcessAggregate chatProcess, UserAccountQuotaEntity data) throws Exception {
+//
+// if(data.getIntegral()builder()
+// .info("积分不足,请及时充值")
+// .type(LogicCheckEnum.REFUSE)
+// .data(chatProcess).build();
+// }
+//
+// return RuleLogicEntity.builder()
+// .type(LogicCheckEnum.SUCCESS).data(chatProcess).build();
+// }
+//
+//
+//}
diff --git a/src/main/java/com/ruoyi/system/ai/util/DocumentReaderUtils.java b/src/main/java/com/ruoyi/system/ai/util/DocumentReaderUtils.java
new file mode 100644
index 0000000..23c1201
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/util/DocumentReaderUtils.java
@@ -0,0 +1,69 @@
+package com.ruoyi.system.ai.util;
+
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.text.PDFTextStripper;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.apache.poi.xwpf.usermodel.XWPFParagraph;
+
+import java.io.File;
+import java.nio.charset.StandardCharsets;
+import java.io.IOException;
+import java.util.List;
+
+public class DocumentReaderUtils {
+
+ public static String readDocument(File file) {
+
+ if(file.length()>200 *1024){
+ return "文件过大";
+ }
+ String content = "";
+ String extension = file.getName().substring(file.getName().lastIndexOf('.') + 1).toLowerCase();
+ System.out.println(extension);
+ try {
+ switch (extension) {
+ case "txt":
+ case "md":
+ case "csv":
+ case "markdown":
+ // 对于文本文件,可以直接读取内容
+ List lines = java.nio.file.Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
+ content = String.join("\n", lines);
+ break;
+ case "docx":
+ // 对于Word文档,使用Apache POI库
+ try (XWPFDocument docxDocument = new XWPFDocument(OPCPackage.open(file))) {
+ StringBuilder contentBuilder = new StringBuilder();
+ for (XWPFParagraph paragraph : docxDocument.getParagraphs()) {
+ contentBuilder.append(paragraph.getText()).append("\n");
+ }
+ content = contentBuilder.toString();
+ }
+ break;
+ case "pdf":
+ // 对于PDF文档,使用PDFBox库
+ try (PDDocument pdfDocument = PDDocument.load(file)) {
+ PDFTextStripper stripper = new PDFTextStripper();
+ content = stripper.getText(pdfDocument);
+ }
+ break;
+ // 可以根据需要添加更多文件类型和相应的处理逻辑
+ default:
+ content = "Unsupported file type";
+ }
+ } catch (IOException | InvalidFormatException e) {
+ content = "Error reading file: " + e.getMessage();
+ e.printStackTrace();
+ }
+
+ return content;
+ }
+
+ public static void main(String[] args) {
+ File file = new File("C:\\Users\\weizh\\Desktop\\packageIO.csv"); // 替换为实际文件路径
+ String documentContent = readDocument(file);
+ System.out.println(documentContent);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/system/ai/util/MoonshotAiUtils.java b/src/main/java/com/ruoyi/system/ai/util/MoonshotAiUtils.java
new file mode 100644
index 0000000..e183e70
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/ai/util/MoonshotAiUtils.java
@@ -0,0 +1,154 @@
+package com.ruoyi.system.ai.util;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.ContentType;
+import cn.hutool.http.Header;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.Method;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.muta.ai.domain.dto.MessageHistoryKimi;
+import lombok.NonNull;
+import lombok.SneakyThrows;
+import okhttp3.*;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.util.List;
+import java.util.Optional;
+
+
+public class MoonshotAiUtils {
+
+ private static final String API_KEY = "sk-SgNVCgBxkVPVHjINo708cqiuXPNMNKWdT2JORNkika6FOAht";
+ private static final String MODELS_URL = "https://api.moonshot.cn/v1/models";
+ private static final String FILES_URL = "https://api.moonshot.cn/v1/files";
+ private static final String ESTIMATE_TOKEN_COUNT_URL = "https://api.moonshot.cn/v1/tokenizers/estimate-token-count";
+ private static final String CHAT_COMPLETION_URL = "https://api.moonshot.cn/v1/chat/completions";
+
+ private static final String CHECK_BALANCE ="https://api.moonshot.cn/v1/users/me/balance";
+ public static String getModelList() {
+ return getCommonRequest(MODELS_URL)
+ .execute()
+ .body();
+ }
+ public static String getBalance() {
+ return getCommonRequest(CHECK_BALANCE)
+ .execute()
+ .body();
+ }
+ public static String getBalanceByKey(String key) {
+ return getCommonRequestByKey(CHECK_BALANCE, key)
+ .execute()
+ .body();
+ }
+
+ public static String uploadFile(@NonNull File file) {
+ return getCommonRequest(FILES_URL)
+ .method(Method.POST)
+ .header("purpose", "file-extract")
+ .form("file", file)
+ .execute()
+ .body();
+ }
+
+ public static String getFileList() {
+ return getCommonRequest(FILES_URL)
+ .execute()
+ .body();
+ }
+
+ public static String deleteFile(@NonNull String fileId) {
+ return getCommonRequest(FILES_URL + "/" + fileId)
+ .method(Method.DELETE)
+ .execute()
+ .body();
+ }
+
+ public static String getFileDetail(@NonNull String fileId) {
+ return getCommonRequest(FILES_URL + "/" + fileId)
+ .execute()
+ .body();
+ }
+
+ public static String getFileContent(@NonNull String fileId) {
+ return getCommonRequest(FILES_URL + "/" + fileId + "/content")
+ .execute()
+ .body();
+ }
+
+ public static String estimateTokenCount(@NonNull String model, @NonNull List messages) {
+ String requestBody = new JSONObject()
+ .putOpt("model", model)
+ .putOpt("messages", messages)
+ .toString();
+ return getCommonRequest(ESTIMATE_TOKEN_COUNT_URL)
+ .method(Method.POST)
+ .header(Header.CONTENT_TYPE, ContentType.JSON.getValue())
+ .body(requestBody)
+ .execute()
+ .body();
+ }
+
+ @SneakyThrows
+ public static void chat(@NonNull String model, @NonNull List messages) {
+ String requestBody = new JSONObject()
+ .putOpt("model", model)
+ .putOpt("messages", messages)
+ .putOpt("stream", true)
+ .toString();
+
+ Request okhttpRequest = new Request.Builder()
+ .url(CHAT_COMPLETION_URL)
+ .post(RequestBody.create(MediaType.get(ContentType.JSON.getValue()), requestBody))
+ .addHeader("Authorization", "Bearer " + API_KEY)
+ .build();
+ Call call = new OkHttpClient().newCall(okhttpRequest);
+ Response okhttpResponse = call.execute();
+ BufferedReader reader = new BufferedReader(okhttpResponse.body().charStream());
+ String line;
+ StringBuffer content = new StringBuffer();
+ while ((line = reader.readLine()) != null) {
+ if (StrUtil.isBlank(line)) {
+ continue;
+ }
+ if (JSONUtil.isTypeJSON(line)) {
+ Optional.of(JSONUtil.parseObj(line))
+ .map(x -> x.getJSONObject("error"))
+ .map(x -> x.getStr("message"))
+ .ifPresent(x -> System.out.println("error: " + x));
+ return;
+ }
+ line = StrUtil.replace(line, "data: ", StrUtil.EMPTY);
+ if (StrUtil.equals("[DONE]", line) || !JSONUtil.isTypeJSON(line)) {
+ System.out.println(content);
+ return;
+ }
+ Optional.of(JSONUtil.parseObj(line))
+ .map(x -> x.getJSONArray("choices"))
+ .filter(CollUtil::isNotEmpty)
+ .map(x -> (JSONObject) x.get(0))
+ .map(x -> x.getJSONObject("delta"))
+ .map(x -> x.getStr("content"))
+ .ifPresent(x ->{
+ System.out.println("rowData: " + x);
+ content.append(x);
+ } );
+ }
+
+ }
+
+ private static HttpRequest getCommonRequest(@NonNull String url) {
+ return HttpRequest.of(url).header(Header.AUTHORIZATION, "Bearer " + API_KEY);
+ }
+
+ private static HttpRequest getCommonRequestByKey(@NonNull String url, @NonNull String key) {
+ return HttpRequest.of(url).header(Header.AUTHORIZATION, "Bearer " + key);
+ }
+
+ public static void main(String[] args) {
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/system/aipay/AlipaySystemOauthToken.java b/src/main/java/com/ruoyi/system/aipay/AlipaySystemOauthToken.java
new file mode 100644
index 0000000..fc7e707
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/aipay/AlipaySystemOauthToken.java
@@ -0,0 +1,69 @@
+package com.ruoyi.system.aipay;
+
+import com.alipay.api.AlipayApiException;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.DefaultAlipayClient;
+import com.alipay.api.AlipayConfig;
+import com.alipay.api.request.AlipayUserInfoShareRequest;
+import com.alipay.api.response.AlipaySystemOauthTokenResponse;
+import com.alipay.api.request.AlipaySystemOauthTokenRequest;
+
+import com.alipay.api.FileItem;
+import com.alipay.api.response.AlipayUserInfoShareResponse;
+import com.muta.pay.config.AliPayConfig;
+
+import java.util.Base64;
+import java.util.ArrayList;
+import java.util.List;
+
+public class AlipaySystemOauthToken {
+
+ public static void main(String[] args) throws AlipayApiException {
+// AlipayClient alipayClient1 = AliPayConfig.getInstance();
+// AlipayUserInfoShareRequest request1 = new AlipayUserInfoShareRequest();
+// AlipayUserInfoShareResponse response1 = alipayClient1.execute(request1,accessToken);
+// if(response1.isSuccess()){
+// System.out.println("调用成功");
+// } else {
+// System.out.println("调用失败");
+// }
+ // 初始化SDK
+ AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
+
+ // 构造请求参数以调用接口
+ AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
+
+// // 设置刷新令牌
+// request.setRefreshToken("201208134b203fe6c11548bcabd8da5bb087a83b");
+//
+// // 设置授权码
+// request.setCode("4b203fe6c11548bcabd8da5bb087a83b");
+
+ // 设置授权方式
+ request.setGrantType("authorization_code");
+
+ AlipaySystemOauthTokenResponse response = alipayClient.execute(request);
+ System.out.println(response.getBody());
+
+ if (response.isSuccess()) {
+ System.out.println("调用成功");
+ } else {
+ System.out.println("调用失败");
+ // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
+ // String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
+ // System.out.println(diagnosisUrl);
+ }
+ }
+
+ private static AlipayConfig getAlipayConfig() {
+ AlipayConfig alipayConfig = new AlipayConfig();
+ alipayConfig.setServerUrl(AliPayConfig.PAY_GATEWAY);
+ alipayConfig.setAppId(AliPayConfig.APPID);
+ alipayConfig.setPrivateKey(AliPayConfig.APP_PRI_KEY);
+ alipayConfig.setFormat("json");
+ alipayConfig.setAlipayPublicKey(AliPayConfig.APP_PUB_KEY);
+ alipayConfig.setCharset("UTF-8");
+ alipayConfig.setSignType("RSA2");
+ return alipayConfig;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/system/aipay/TestLogin.java b/src/main/java/com/ruoyi/system/aipay/TestLogin.java
new file mode 100644
index 0000000..8334edf
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/aipay/TestLogin.java
@@ -0,0 +1,13 @@
+package com.ruoyi.system.aipay;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /08 /01 / 16:15
+ * @Description:
+ */
+public class TestLogin {
+
+ public void test(){
+
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/basics/domain/Kamil.java b/src/main/java/com/ruoyi/system/basics/domain/Kamil.java
new file mode 100644
index 0000000..eb7ef75
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/basics/domain/Kamil.java
@@ -0,0 +1,72 @@
+package com.ruoyi.system.basics.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.muta.common.core.MutaBaseEntity;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * @author 马兰友
+ * @Date: 2024/04/20/16:22
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class Kamil extends MutaBaseEntity {
+
+ /**
+ * id
+ */
+ @TableId(type = IdType.AUTO)
+ @JsonFormat(shape =JsonFormat.Shape.STRING)
+ private Long id;
+
+ /**
+ * 卡密被使用时使用者的ip
+ */
+ private String ip;
+
+ /**
+ * 使用者的id
+ */
+ @JsonFormat(shape =JsonFormat.Shape.STRING)
+ private Long userId;
+
+ /**
+ * 卡密
+ */
+ @TableField(value = "`key`")
+ private String key;
+
+ /**
+ * 值,若type是积分(0),该值为积分数
+ * 若type是会员(1),该值为会员天数
+ * 若type是svip(2),该值为svip天数
+ */
+ private Integer value;
+
+ /**
+ * 状态 0:有效 1:已使用
+ */
+ private Integer status;
+
+ /**
+ * 卡密类型 0:积分 1:会员 2:svip
+ */
+ private Integer type;
+
+ /**
+ * 截止日期 该字段只有自定义的卡密有值 批量生成的没有
+ */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date endTime;
+
+}
diff --git a/src/main/java/com/ruoyi/system/basics/domain/dto/KamilAddDTO.java b/src/main/java/com/ruoyi/system/basics/domain/dto/KamilAddDTO.java
new file mode 100644
index 0000000..89da413
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/basics/domain/dto/KamilAddDTO.java
@@ -0,0 +1,34 @@
+package com.ruoyi.system.basics.domain.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author 马兰友
+ * @Date: 2024/04/21/20:24
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class KamilAddDTO {
+
+ /**
+ * 卡密类型 0:积分 1:普通会员 2:超级会员
+ */
+ private Integer type;
+
+ /**
+ * 卡密的值 根据type不同 含义也有所不同
+ * type为0 表示积分的数量 type为1或2 表示天数
+ */
+ private Integer value;
+
+ /**
+ * 本次生成的卡密数量
+ */
+ private Integer quantity;
+
+}
diff --git a/src/main/java/com/ruoyi/system/basics/domain/dto/KamilConDefDTO.java b/src/main/java/com/ruoyi/system/basics/domain/dto/KamilConDefDTO.java
new file mode 100644
index 0000000..f371105
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/basics/domain/dto/KamilConDefDTO.java
@@ -0,0 +1,25 @@
+package com.ruoyi.system.basics.domain.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * @author 马兰友
+ * @Date: 2024/05/06/16:36
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class KamilConDefDTO {
+
+ private String key;
+ private Integer value;
+ private Integer type;
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date endTime;
+
+}
diff --git a/src/main/java/com/ruoyi/system/basics/factory/kamil/KamilConsumption.java b/src/main/java/com/ruoyi/system/basics/factory/kamil/KamilConsumption.java
new file mode 100644
index 0000000..0c8a9a1
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/basics/factory/kamil/KamilConsumption.java
@@ -0,0 +1,12 @@
+package com.ruoyi.system.basics.factory.kamil;
+
+import com.muta.basics.domain.Kamil;
+
+/**
+ * @author 马兰友
+ * @Date: 2024/04/22/19:45
+ */
+public interface KamilConsumption {
+
+ void consumption(Kamil kamil);
+}
diff --git a/src/main/java/com/ruoyi/system/basics/factory/kamil/KamilTypeFactory.java b/src/main/java/com/ruoyi/system/basics/factory/kamil/KamilTypeFactory.java
new file mode 100644
index 0000000..468d032
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/basics/factory/kamil/KamilTypeFactory.java
@@ -0,0 +1,37 @@
+package com.ruoyi.system.basics.factory.kamil;
+
+import com.muta.basics.factory.kamil.impl.SvipKamilConsumption;
+import com.muta.basics.factory.kamil.impl.VipKamilConsumption;
+import com.muta.basics.factory.kamil.impl.IntegrationKamilConsumption;
+import com.muta.basics.domain.Kamil;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author 马兰友
+ * @Date: 2024/04/22/18:31
+ */
+@Service
+public class KamilTypeFactory {
+ public Map kamilConsumptionMap = new ConcurrentHashMap<>();
+ @Resource
+ private IntegrationKamilConsumption integrationKamilConsumption;
+ @Resource
+ private VipKamilConsumption vipKamilConsumption;
+ @Resource
+ private SvipKamilConsumption svipKamilConsumption;
+ @PostConstruct
+ public void init() {
+ kamilConsumptionMap.put(0, integrationKamilConsumption);
+ kamilConsumptionMap.put(1, vipKamilConsumption);
+ kamilConsumptionMap.put(2, svipKamilConsumption);
+ }
+ public void consumption(Kamil kamil) {
+ KamilConsumption kamilConsumption = kamilConsumptionMap.get(kamil.getType());
+ kamilConsumption.consumption(kamil);
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/basics/factory/kamil/impl/IntegrationKamilConsumption.java b/src/main/java/com/ruoyi/system/basics/factory/kamil/impl/IntegrationKamilConsumption.java
new file mode 100644
index 0000000..1bce65d
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/basics/factory/kamil/impl/IntegrationKamilConsumption.java
@@ -0,0 +1,36 @@
+package com.ruoyi.system.basics.factory.kamil.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.muta.basics.factory.kamil.KamilConsumption;
+import com.muta.common.annotation.IntegralLogInsert;
+import com.muta.common.constant.OperationConstants;
+import com.muta.common.core.domain.entity.UserExtra;
+import com.muta.common.utils.SecurityUtils;
+import com.muta.basics.domain.Kamil;
+import com.muta.system.mapper.UserExtraMapper;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+/**
+ * @author 马兰友
+ * @Date: 2024/04/22/19:48
+ */
+@Service
+public class IntegrationKamilConsumption implements KamilConsumption {
+
+ @Resource
+ private UserExtraMapper userExtraMapper;
+
+ @Override
+ @IntegralLogInsert(operation = OperationConstants.Kamil)
+ public void consumption(Kamil kamil) {
+ LambdaQueryWrapper lqw = new LambdaQueryWrapper<>();
+ lqw.eq(UserExtra::getUserId, SecurityUtils.getUserId());
+ UserExtra userExtra = userExtraMapper.selectOne(lqw);
+ Integer value = kamil.getValue();
+ userExtra.setIntegral(userExtra.getIntegral() + value);
+ userExtraMapper.updateById(userExtra);
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/system/basics/factory/kamil/impl/SvipKamilConsumption.java b/src/main/java/com/ruoyi/system/basics/factory/kamil/impl/SvipKamilConsumption.java
new file mode 100644
index 0000000..d7f9882
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/basics/factory/kamil/impl/SvipKamilConsumption.java
@@ -0,0 +1,53 @@
+package com.ruoyi.system.basics.factory.kamil.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.muta.basics.factory.kamil.KamilConsumption;
+import com.muta.common.annotation.IntegralLogInsert;
+import com.muta.common.constant.OperationConstants;
+import com.muta.common.core.domain.entity.UserExtra;
+import com.muta.common.utils.SecurityUtils;
+import com.muta.basics.domain.Kamil;
+import com.muta.system.domain.Vip;
+import com.muta.system.mapper.UserExtraMapper;
+import com.muta.system.mapper.VipMapper;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * @author 马兰友
+ * @Date: 2024/04/22/19:49
+ */
+@Component
+public class SvipKamilConsumption implements KamilConsumption {
+
+ @Resource
+ private VipMapper vipMapper;
+
+ @Override
+ @IntegralLogInsert(operation = OperationConstants.Kamil)
+ public void consumption(Kamil kamil) {
+ LambdaQueryWrapper lqw = new LambdaQueryWrapper<>();
+ lqw.eq(Vip::getUserId, SecurityUtils.getUserId());
+ Vip vip = vipMapper.selectOne(lqw);
+ Integer value = kamil.getValue();
+ Date now = new Date();
+
+ Date svipExpireTime = vip.getSvipExpireTime();
+ Calendar calendar = Calendar.getInstance();
+ //首先判断用户当前是不是svip 若是则在截止日期后加上value天
+ if (null != svipExpireTime && svipExpireTime.after(now))
+ calendar.setTime(vip.getVipExpireTime());
+
+ else {
+ //若不是 则在从今天开始加上value天 作为截止日期 并更新开始时间为今日
+ calendar.setTime(now);
+ vip.setSvipBeginTime(now);
+ }
+ calendar.add(Calendar.DAY_OF_YEAR, value);
+ vip.setSvipExpireTime(calendar.getTime());
+ vipMapper.updateById(vip);
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/basics/factory/kamil/impl/VipKamilConsumption.java b/src/main/java/com/ruoyi/system/basics/factory/kamil/impl/VipKamilConsumption.java
new file mode 100644
index 0000000..68ecba5
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/basics/factory/kamil/impl/VipKamilConsumption.java
@@ -0,0 +1,53 @@
+package com.ruoyi.system.basics.factory.kamil.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.muta.basics.factory.kamil.KamilConsumption;
+import com.muta.common.annotation.IntegralLogInsert;
+import com.muta.common.constant.OperationConstants;
+import com.muta.common.core.domain.entity.UserExtra;
+import com.muta.common.utils.SecurityUtils;
+import com.muta.basics.domain.Kamil;
+import com.muta.system.domain.Vip;
+import com.muta.system.mapper.UserExtraMapper;
+import com.muta.system.mapper.VipMapper;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * @author 马兰友
+ * @Date: 2024/04/22/19:49
+ */
+@Service
+public class VipKamilConsumption implements KamilConsumption {
+
+ @Resource
+ private UserExtraMapper userExtraMapper;
+ @Resource
+ private VipMapper vipMapper;
+
+ @Override
+ @IntegralLogInsert(operation = OperationConstants.Kamil)
+ public void consumption(Kamil kamil) {
+ LambdaQueryWrapper lqw = new LambdaQueryWrapper<>();
+ lqw.eq(Vip::getUserId, SecurityUtils.getUserId());
+ Vip vip = vipMapper.selectOne(lqw);
+ Integer value = kamil.getValue();
+ Date now = new Date();
+ Date vipExpireTime = vip.getVipExpireTime();
+ Calendar expCalendar = Calendar.getInstance();
+ //首先判断用户当前是不是svip 若是则在截止日期后加上value天
+ if (null != vipExpireTime && vipExpireTime.after(now))
+ expCalendar.setTime(vip.getVipExpireTime());
+ else {
+ //若不是 则在从今天开始加上value天 作为截止日期 并更新开始日期为今日
+ expCalendar.setTime(now);
+ vip.setVipBeginTime(now);
+ }
+ expCalendar.add(Calendar.DAY_OF_YEAR, value);
+ vip.setVipExpireTime(expCalendar.getTime());
+ vipMapper.updateById(vip);
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/basics/mapper/KamilMapper.java b/src/main/java/com/ruoyi/system/basics/mapper/KamilMapper.java
new file mode 100644
index 0000000..d2c7b48
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/basics/mapper/KamilMapper.java
@@ -0,0 +1,64 @@
+package com.ruoyi.system.basics.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.muta.basics.domain.Kamil;
+
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Mapper接口
+ *
+ * @author mutaai
+ * @date 2024-04-21
+ */
+public interface KamilMapper extends BaseMapper {
+ /**
+ * 查询【请填写功能名称】
+ *
+ * @param id 【请填写功能名称】主键
+ * @return 【请填写功能名称】
+ */
+ public Kamil selectKamilById(String id);
+
+ /**
+ * 查询【请填写功能名称】列表
+ *
+ * @param kamil 【请填写功能名称】
+ * @return 【请填写功能名称】集合
+ */
+ public List selectKamilList(Kamil kamil);
+
+ /**
+ * 新增【请填写功能名称】
+ *
+ * @param kamil 【请填写功能名称】
+ * @return 结果
+ */
+ public int insertKamil(Kamil kamil);
+
+ /**
+ * 修改【请填写功能名称】
+ *
+ * @param kamil 【请填写功能名称】
+ * @return 结果
+ */
+ public int updateKamil(Kamil kamil);
+
+ /**
+ * 删除【请填写功能名称】
+ *
+ * @param id 【请填写功能名称】主键
+ * @return 结果
+ */
+ public int deleteKamilById(String id);
+
+ /**
+ * 批量删除【请填写功能名称】
+ *
+ * @param ids 需要删除的数据主键集合
+ * @return 结果
+ */
+ public int deleteKamilByIds(String[] ids);
+
+}
diff --git a/src/main/java/com/ruoyi/system/basics/service/IKamilService.java b/src/main/java/com/ruoyi/system/basics/service/IKamilService.java
new file mode 100644
index 0000000..527ee02
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/basics/service/IKamilService.java
@@ -0,0 +1,72 @@
+package com.ruoyi.system.basics.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.muta.common.core.domain.AjaxResult;
+import com.muta.basics.domain.Kamil;
+import com.muta.basics.domain.dto.KamilAddDTO;
+import com.muta.basics.domain.dto.KamilConDefDTO;
+
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Service接口
+ *
+ * @author mutaai
+ * @date 2024-04-21
+ */
+public interface IKamilService extends IService {
+ /**
+ * 查询【请填写功能名称】
+ *
+ * @param id 【请填写功能名称】主键
+ * @return 【请填写功能名称】
+ */
+ public Kamil selectKamilById(String id);
+
+ /**
+ * 查询【请填写功能名称】列表
+ *
+ * @param kamil 【请填写功能名称】
+ * @return 【请填写功能名称】集合
+ */
+ public List selectKamilList(Kamil kamil);
+
+ /**
+ * 新增【请填写功能名称】
+ *
+ * @param kamil 【请填写功能名称】
+ * @return 结果
+ */
+ public int insertKamil(Kamil kamil);
+
+ /**
+ * 修改【请填写功能名称】
+ *
+ * @param kamil 【请填写功能名称】
+ * @return 结果
+ */
+ public int updateKamil(Kamil kamil);
+
+ /**
+ * 批量删除【请填写功能名称】
+ *
+ * @param ids 需要删除的【请填写功能名称】主键集合
+ * @return 结果
+ */
+ public int deleteKamilByIds(String[] ids);
+
+ /**
+ * 删除【请填写功能名称】信息
+ *
+ * @param id 【请填写功能名称】主键
+ * @return 结果
+ */
+ public int deleteKamilById(String id);
+
+ void addBatch(KamilAddDTO kamilAddDTO);
+
+ AjaxResult use(String key);
+
+ AjaxResult conDef(KamilConDefDTO kamilConDefDTO);
+}
diff --git a/src/main/java/com/ruoyi/system/basics/service/impl/KamilServiceImpl.java b/src/main/java/com/ruoyi/system/basics/service/impl/KamilServiceImpl.java
new file mode 100644
index 0000000..ab168db
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/basics/service/impl/KamilServiceImpl.java
@@ -0,0 +1,190 @@
+package com.ruoyi.system.basics.service.impl;
+
+
+import cn.hutool.core.util.ObjUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.crypto.digest.MD5;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.muta.common.annotation.RepeatSubmit;
+import com.muta.common.core.domain.AjaxResult;
+import com.muta.common.utils.DateUtils;
+import com.muta.common.utils.SecurityUtils;
+import com.muta.basics.domain.dto.KamilConDefDTO;
+import com.muta.basics.factory.kamil.KamilTypeFactory;
+import com.muta.basics.domain.Kamil;
+import com.muta.basics.domain.dto.KamilAddDTO;
+import com.muta.basics.mapper.KamilMapper;
+import com.muta.basics.service.IKamilService;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.List;
+
+import static com.muta.common.constant.CacheConstants.KAMIL_KEY;
+
+
+/**
+ * 【请填写功能名称】Service业务层处理
+ *
+ * @author mutaai
+ * @date 2024-04-21
+ */
+@Service
+public class KamilServiceImpl extends ServiceImpl implements IKamilService {
+ @Resource
+ private KamilMapper kamilMapper;
+
+ @Resource
+ private KamilTypeFactory kamilTypeFactory;
+
+ @Resource
+ private StringRedisTemplate stringRedisTemplate;
+
+ /**
+ * 查询【请填写功能名称】
+ *
+ * @param id 【请填写功能名称】主键
+ * @return 【请填写功能名称】
+ */
+ @Override
+ public Kamil selectKamilById(String id) {
+ return kamilMapper.selectKamilById(id);
+ }
+
+ /**
+ * 查询【请填写功能名称】列表
+ *
+ * @param kamil 【请填写功能名称】
+ * @return 【请填写功能名称】
+ */
+ @Override
+ public List selectKamilList(Kamil kamil) {
+ return kamilMapper.selectList(new LambdaQueryWrapper<>());
+ }
+
+ /**
+ * 新增【请填写功能名称】
+ *
+ * @param kamil 【请填写功能名称】
+ * @return 结果
+ */
+ @Override
+ public int insertKamil(Kamil kamil) {
+ kamil.setCreateTime(DateUtils.getNowDate());
+ return kamilMapper.insertKamil(kamil);
+ }
+
+ /**
+ * 修改【请填写功能名称】
+ *
+ * @param kamil 【请填写功能名称】
+ * @return 结果
+ */
+ @Override
+ public int updateKamil(Kamil kamil) {
+ kamil.setUpdateTime(DateUtils.getNowDate());
+ return kamilMapper.updateKamil(kamil);
+ }
+
+ /**
+ * 批量删除【请填写功能名称】
+ *
+ * @param ids 需要删除的【请填写功能名称】主键
+ * @return 结果
+ */
+ @Override
+ public int deleteKamilByIds(String[] ids) {
+ return kamilMapper.deleteKamilByIds(ids);
+ }
+
+ /**
+ * 删除【请填写功能名称】信息
+ *
+ * @param id 【请填写功能名称】主键
+ * @return 结果
+ */
+ @Override
+ public int deleteKamilById(String id) {
+ return kamilMapper.deleteKamilById(id);
+ }
+
+ @Override
+ @Transactional
+ public void addBatch(KamilAddDTO kamilAddDTO) {
+ int n = kamilAddDTO.getQuantity();
+ Kamil kamil = new Kamil();
+ kamil.setType(kamilAddDTO.getType());
+ kamil.setValue(kamilAddDTO.getValue());
+ //生成n个卡密
+ for (int i = 0; i < n; i++) {
+ //卡密的key为对当前时间戳进行md5加密获得的32位字符串
+ kamil.setKey(MD5.create().digestHex(String.valueOf(System.currentTimeMillis())));
+ kamilMapper.insert(kamil);
+ }
+ }
+
+ @Override
+ @RepeatSubmit
+ public AjaxResult use(String key) {
+ Long userId = SecurityUtils.getUserId();
+ LambdaQueryWrapper lqw = new LambdaQueryWrapper<>();
+ lqw.eq(Kamil::getKey, key);
+ //根据用户输入的key查找卡密 对其存在与否以及状态进行判断
+ Kamil kamil = kamilMapper.selectOne(lqw);
+ System.out.println(kamil);
+ if (ObjUtil.isEmpty(kamil))
+ return AjaxResult.error("卡密不存在");
+ if (kamil.getEndTime() == null) {
+ if (kamil.getStatus() == 1)
+ return AjaxResult.error("卡密已被使用");
+ //校验通过 修改数据库卡密状态
+ kamil.setStatus(1);
+ kamil.setUserId(userId);
+ kamilMapper.updateById(kamil);
+ } else {
+ //是存在截止时间的自定义卡密
+ if (kamil.getEndTime().before(new Date())) {
+ //判断是否已过期
+ if (kamil.getStatus() == 0) {
+ //过期 且status为0 则将其status设置为1 并将该key从redis中删除
+ kamil.setStatus(1);
+ stringRedisTemplate.delete(KAMIL_KEY + key);
+ kamilMapper.updateById(kamil);
+ }
+ return AjaxResult.error("卡密已过期");
+ }
+ //该卡密未过期 判断该用户是否使用过 也就是判断以该卡密的key为 key的set列表中有没有该用户的userId 若有 则使用过
+ if (Boolean.TRUE.equals(stringRedisTemplate.opsForSet().isMember(KAMIL_KEY + key, userId.toString()))) {
+ return AjaxResult.error("您已使用过该卡密");
+ } else {
+ //没使用过该卡密 将用户id添加到set列表中
+ stringRedisTemplate.opsForSet().add(KAMIL_KEY + key, userId.toString());
+ }
+ }
+ //调用工厂 消耗卡密 为用户增加相应的值
+ kamilTypeFactory.consumption(kamil);
+ return AjaxResult.success();
+ }
+
+ @Override
+ public AjaxResult conDef(KamilConDefDTO kamilConDefDTO) {
+ Kamil kamil = new Kamil();
+ LambdaQueryWrapper lqw = new LambdaQueryWrapper<>();
+ lqw.eq(Kamil::getKey, kamilConDefDTO.getKey()); //构建查询条件 查询卡密的key是否被占用
+ if (ObjectUtil.isNotEmpty(kamilMapper.selectList(lqw))) {
+ return AjaxResult.error("卡密已存在"); //卡密已存在 返回错误信息 生成失败
+ };
+ //校验成功 将dto中的值拷贝到kamil对象中
+ kamil.setKey(kamilConDefDTO.getKey());
+ kamil.setValue(kamilConDefDTO.getValue());
+ kamil.setType(kamilConDefDTO.getType());
+ kamil.setEndTime(kamilConDefDTO.getEndTime());
+ //新增
+ kamilMapper.insert(kamil);
+ return AjaxResult.success();
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/dao/IGroupBuyActivityDao.java b/src/main/java/com/ruoyi/system/dao/IGroupBuyActivityDao.java
new file mode 100644
index 0000000..7bed518
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/dao/IGroupBuyActivityDao.java
@@ -0,0 +1,20 @@
+package com.ruoyi.system.dao;
+
+import cn.bugstack.infrastructure.dao.po.GroupBuyActivity;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 拼团活动Dao
+ * @create 2024-12-07 10:10
+ */
+@Mapper
+public interface IGroupBuyActivityDao {
+
+ List queryGroupBuyActivityList();
+
+ GroupBuyActivity queryValidGroupBuyActivity(GroupBuyActivity groupBuyActivityReq);
+
+}
diff --git a/src/main/java/com/ruoyi/system/dao/IGroupBuyDiscountDao.java b/src/main/java/com/ruoyi/system/dao/IGroupBuyDiscountDao.java
new file mode 100644
index 0000000..be6c258
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/dao/IGroupBuyDiscountDao.java
@@ -0,0 +1,20 @@
+package com.ruoyi.system.dao;
+
+import cn.bugstack.infrastructure.dao.po.GroupBuyDiscount;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 折扣配置Dao
+ * @create 2024-12-07 10:10
+ */
+@Mapper
+public interface IGroupBuyDiscountDao {
+
+ List queryGroupBuyDiscountList();
+
+ GroupBuyDiscount queryGroupBuyActivityDiscountByDiscountId(String discountId);
+
+}
diff --git a/src/main/java/com/ruoyi/system/dao/ISkuDao.java b/src/main/java/com/ruoyi/system/dao/ISkuDao.java
new file mode 100644
index 0000000..039509b
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/dao/ISkuDao.java
@@ -0,0 +1,16 @@
+package com.ruoyi.system.dao;
+
+import cn.bugstack.infrastructure.dao.po.Sku;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 商品查询
+ * @create 2024-12-21 10:48
+ */
+@Mapper
+public interface ISkuDao {
+
+ Sku querySkuByGoodsId(String goodsId);
+
+}
diff --git a/src/main/java/com/ruoyi/system/dao/po/GroupBuyActivity.java b/src/main/java/com/ruoyi/system/dao/po/GroupBuyActivity.java
new file mode 100644
index 0000000..07b02cb
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/dao/po/GroupBuyActivity.java
@@ -0,0 +1,58 @@
+package com.ruoyi.system.dao.po;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 拼团活动
+ * @create 2024-12-07 10:01
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class GroupBuyActivity {
+
+ /** 自增 */
+ private Long id;
+ /** 活动ID */
+ private Long activityId;
+ /** 活动名称 */
+ private String activityName;
+ /** 来源 */
+ private String source;
+ /** 渠道 */
+ private String channel;
+ /** 商品ID */
+ private String goodsId;
+ /** 折扣ID */
+ private String discountId;
+ /** 拼团方式(0自动成团、1达成目标拼团) */
+ private Integer groupType;
+ /** 拼团次数限制 */
+ private Integer takeLimitCount;
+ /** 拼团目标 */
+ private Integer target;
+ /** 拼团时长(分钟) */
+ private Integer validTime;
+ /** 活动状态(0创建、1生效、2过期、3废弃) */
+ private Integer status;
+ /** 活动开始时间 */
+ private Date startTime;
+ /** 活动结束时间 */
+ private Date endTime;
+ /** 人群标签规则标识 */
+ private String tagId;
+ /** 人群标签规则范围 */
+ private String tagScope;
+ /** 创建时间 */
+ private Date createTime;
+ /** 更新时间 */
+ private Date updateTime;
+
+}
diff --git a/src/main/java/com/ruoyi/system/dao/po/GroupBuyDiscount.java b/src/main/java/com/ruoyi/system/dao/po/GroupBuyDiscount.java
new file mode 100644
index 0000000..2f25e34
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/dao/po/GroupBuyDiscount.java
@@ -0,0 +1,71 @@
+package com.ruoyi.system.dao.po;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 折扣配置
+ * @create 2024-12-07 10:06
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class GroupBuyDiscount {
+
+ /**
+ * 自增ID
+ */
+ private Long id;
+
+ /**
+ * 折扣ID
+ */
+ private Integer discountId;
+
+ /**
+ * 折扣标题
+ */
+ private String discountName;
+
+ /**
+ * 折扣描述
+ */
+ private String discountDesc;
+
+ /**
+ * 折扣类型(0:base、1:tag)
+ */
+ private Byte discountType;
+
+ /**
+ * 营销优惠计划(ZJ:直减、MJ:满减、N元购)
+ */
+ private String marketPlan;
+
+ /**
+ * 营销优惠表达式
+ */
+ private String marketExpr;
+
+ /**
+ * 人群标签,特定优惠限定
+ */
+ private String tagId;
+
+ /**
+ * 创建时间
+ */
+ private Date createTime;
+
+ /**
+ * 更新时间
+ */
+ private Date updateTime;
+
+}
diff --git a/src/main/java/com/ruoyi/system/dao/po/Sku.java b/src/main/java/com/ruoyi/system/dao/po/Sku.java
new file mode 100644
index 0000000..6a55493
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/dao/po/Sku.java
@@ -0,0 +1,39 @@
+package com.ruoyi.system.dao.po;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * @author Fuzhengwei bugstack.cn @小傅哥
+ * @description 商品信息
+ * @create 2024-12-21 10:45
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class Sku {
+
+ /** 自增 */
+ private Long id;
+ /** 来源 */
+ private String source;
+ /** 渠道 */
+ private String channel;
+ /** 商品ID */
+ private String goodsId;
+ /** 商品名称 */
+ private String goodsName;
+ /** 原始价格 */
+ private BigDecimal originalPrice;
+ /** 创建时间 */
+ private Date createTime;
+ /** 更新时间 */
+ private Date updateTime;
+
+}
diff --git a/src/main/java/com/ruoyi/system/distribution/algorrirhm/DistributionDataFilter.java b/src/main/java/com/ruoyi/system/distribution/algorrirhm/DistributionDataFilter.java
new file mode 100644
index 0000000..6e06d39
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/distribution/algorrirhm/DistributionDataFilter.java
@@ -0,0 +1,50 @@
+package com.ruoyi.system.distribution.algorrirhm;
+
+import com.muta.common.utils.SecurityUtils;
+import com.muta.distribution.mapper.DistributionDataMapper;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.lang.reflect.Field;
+import java.security.Security;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /04 /27 / 14:42
+ * @Description:
+ */
+@Component
+public class DistributionDataFilter {
+ @Resource
+ private DistributionDataMapper distributionDataConfig;
+ //因为每个log的存username的字段都不一样,所以要传入相应的字段名,再根据反射获取username
+ public List dataFilter(List data,String filterName){
+ if(SecurityUtils.hasRole("admin")){
+ return data;
+ }
+ //过滤出所有符合条件的username
+ List usernameList = distributionDataConfig.usernameList(SecurityUtils.getUserId());
+ System.out.println(usernameList);
+ List res = new ArrayList<>();
+ try {
+ System.out.println(data.size());
+ for (T item : data) {
+ Field field = item.getClass().getDeclaredField(filterName);
+ field.setAccessible(true); // 设置字段可访问
+ Object username = field.get(item); // 获取username
+ System.out.println(username);
+ //如果数据符合要求,存入集合
+ if(usernameList.contains(username.toString())){
+ res.add(item);
+ }
+ }
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ System.out.println(res.size());
+ return res;
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/system/distribution/domain/FundsLog.java b/src/main/java/com/ruoyi/system/distribution/domain/FundsLog.java
new file mode 100644
index 0000000..b59626f
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/distribution/domain/FundsLog.java
@@ -0,0 +1,27 @@
+package com.ruoyi.system.distribution.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class FundsLog {
+
+ private Long id;
+ private String consumer;
+ private String beneficiaries;
+ private BigDecimal consume;
+ private BigDecimal earnings;
+ private Integer persent;
+ private Long userId;
+ @JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss")
+ private LocalDateTime createTime;
+}
diff --git a/src/main/java/com/ruoyi/system/distribution/mapper/DistributionDataMapper.java b/src/main/java/com/ruoyi/system/distribution/mapper/DistributionDataMapper.java
new file mode 100644
index 0000000..08fac15
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/distribution/mapper/DistributionDataMapper.java
@@ -0,0 +1,17 @@
+package com.ruoyi.system.distribution.mapper;
+
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /04 /27 / 15:34
+ * @Description:
+ */
+@Mapper
+public interface DistributionDataMapper {
+ public List usernameList(Long id);
+
+
+}
diff --git a/src/main/java/com/ruoyi/system/distribution/mapper/FundsLogMapper.java b/src/main/java/com/ruoyi/system/distribution/mapper/FundsLogMapper.java
new file mode 100644
index 0000000..d052892
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/distribution/mapper/FundsLogMapper.java
@@ -0,0 +1,15 @@
+package com.ruoyi.system.distribution.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.muta.common.core.domain.entity.SysUser;
+import com.muta.distribution.domain.FundsLog;
+import com.muta.system.domain.SigninLog;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+@Mapper
+public interface FundsLogMapper extends BaseMapper {
+
+ List logList(SysUser sysUser);
+}
diff --git a/src/main/java/com/ruoyi/system/distribution/service/DistributionService.java b/src/main/java/com/ruoyi/system/distribution/service/DistributionService.java
new file mode 100644
index 0000000..8892310
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/distribution/service/DistributionService.java
@@ -0,0 +1,8 @@
+package com.ruoyi.system.distribution.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+
+public interface DistributionService {
+
+ void benefit(Double basic);
+}
diff --git a/src/main/java/com/ruoyi/system/distribution/service/impl/DistributionService.java b/src/main/java/com/ruoyi/system/distribution/service/impl/DistributionService.java
new file mode 100644
index 0000000..0cd2818
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/distribution/service/impl/DistributionService.java
@@ -0,0 +1,60 @@
+package com.ruoyi.system.distribution.service.impl;
+
+import com.muta.common.core.domain.entity.SysUser;
+import com.muta.common.core.domain.entity.UserExtra;
+import com.muta.common.utils.SecurityUtils;
+import com.muta.distribution.domain.FundsLog;
+import com.muta.distribution.mapper.FundsLogMapper;
+import com.muta.system.service.ISysUserService;
+import com.muta.system.service.IUserExtraService;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /08 /12 / 1:23
+ * @Description:
+ */
+public class DistributionService {
+ @Resource
+ private IUserExtraService userExtraService;
+ @Resource
+ private FundsLogMapper fundsLogMapper;
+ @Resource
+ private ISysUserService sysUserService;
+
+ public void distribute(BigDecimal money){
+ Long userId = SecurityUtils.getUserId();
+ SysUser sysUser = sysUserService.selectUserById(userId);
+ SysUser father = sysUserService.selectUserById(sysUser.getUserExtra().getLowestId());
+ //如果最近代理直接是管理员
+ if(SecurityUtils.isAdmin(sysUser.getUserExtra().getLowestId())){
+ FundsLog fundsLog = new FundsLog();
+ fundsLog.setConsume(money);
+ fundsLog.setPersent(100);
+ fundsLog.setBeneficiaries(SecurityUtils.getUsername());
+ fundsLogMapper.insert(fundsLog);
+ }
+ //如果是一级代理
+ else if(father.getRoleId() == 1){
+ //一级
+ FundsLog fundsLog = new FundsLog();
+ fundsLog.setConsume(money.divide(BigDecimal.valueOf(father.getUserExtra().getPercentage())));
+ fundsLog.setPersent(father.getUserExtra().getPercentage());
+ fundsLog.setBeneficiaries(SecurityUtils.getUsername());
+ fundsLogMapper.insert(fundsLog);
+ //超管
+ FundsLog fundsLog1 = new FundsLog();
+ fundsLog.setConsume(money.subtract(money.divide(BigDecimal.valueOf(father.getUserExtra().getPercentage()))));
+ fundsLog.setPersent(100);
+ fundsLog.setBeneficiaries(SecurityUtils.getUsername());
+ fundsLogMapper.insert(fundsLog);
+ }
+ else {
+
+ }
+ }
+
+
+}
diff --git a/src/main/java/com/ruoyi/system/distribution/service/impl/DistributionServiceImpl.java b/src/main/java/com/ruoyi/system/distribution/service/impl/DistributionServiceImpl.java
new file mode 100644
index 0000000..4f4aabc
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/distribution/service/impl/DistributionServiceImpl.java
@@ -0,0 +1,225 @@
+package com.ruoyi.system.distribution.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.muta.common.core.domain.entity.UserExtra;
+import com.muta.common.utils.SecurityUtils;
+import com.muta.distribution.domain.FundsLog;
+import com.muta.distribution.mapper.FundsLogMapper;
+import com.muta.distribution.service.DistributionService;
+import com.muta.log.service.impl.DistributionIntegralServiceImpl;
+import com.muta.system.mapper.UserExtraMapper;
+import com.muta.system.service.ISysUserService;
+import com.muta.system.service.IUserExtraService;
+import org.apache.commons.lang3.ObjectUtils;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.Objects;
+
+@Service
+public class DistributionServiceImpl implements DistributionService {
+
+ @Resource
+ private IUserExtraService userExtraService;
+
+ @Resource
+ private ISysUserService sysUserService;
+
+ @Resource
+ private FundsLogMapper fundsLogMapper;
+
+ @Resource
+ private UserExtraMapper userExtraMapper;
+
+ @Resource
+ private DistributionIntegralServiceImpl distributionIntegralService;
+
+
+ /*@Override
+ public void efit(Double basic) {
+ Long userId = SecurityUtils.getUserId();
+ Long pid = 0L, lid = 0L, fid = 0L;
+ double persent;
+ double template = basic;
+
+ do {
+ LambdaQueryWrapper lqw = new LambdaQueryWrapper<>();
+ lqw.eq(UserExtra::getUserId, userId);
+ UserExtra tree = userExtraService.getOne(lqw);
+
+ pid = tree.getSuperiorId();
+ lid = tree.getLowestId();
+ fid = tree.getFirstId();
+
+ userId = check(pid, lid, fid) ? doCash(tree, basic) : doIntegral(pid, template);
+ LambdaQueryWrapper fatherLqw = new LambdaQueryWrapper<>();
+ fatherLqw.eq(UserExtra::getUserId, pid);
+ UserExtra father = userExtraService.getOne(fatherLqw);
+
+ persent = father.getPercentage();
+ template *= persent;
+ } while (check(pid, lid, fid));
+ }
+
+ public Long doIntegral(Long pid, double template) {
+ LambdaQueryWrapper lqw = new LambdaQueryWrapper<>();
+ lqw.eq(UserExtra::getUserId, pid);
+ UserExtra one = userExtraService.getOne(lqw);
+
+ LambdaQueryWrapper fatherLqw = new LambdaQueryWrapper<>();
+ fatherLqw.eq(UserExtra::getUserId, one.getSuperiorId());
+ UserExtra father = userExtraService.getOne(fatherLqw);
+
+ one.setIntegral((int) (one.getIntegral() + template));
+ if (!check(one.getSuperiorId(), one.getLowestId(), one.getFirstId()))
+ one.setIntegral((int) (one.getIntegral() - template * father.getPercentage()));
+
+ // TODO 积分记录
+ userExtraMapper.update(one, lqw);
+
+ return pid;
+ }*/
+
+ public Long doCash(UserExtra tree, double baisc) {
+ double persent = 1;
+
+ while (!Objects.equals(tree.getSuperiorId(), tree.getLowestId())) {
+ System.out.println("find");
+ LambdaQueryWrapper lqw = new LambdaQueryWrapper<>();
+ lqw.eq(UserExtra::getUserId, tree.getSuperiorId());
+ tree = userExtraMapper.selectOne(lqw);
+ }
+
+ do {
+ System.err.println("cash");
+ UserExtra last = tree;
+ LambdaQueryWrapper lqw = new LambdaQueryWrapper<>();
+ lqw.eq(UserExtra::getUserId, tree.getSuperiorId());
+ tree = userExtraService.getOne(lqw);
+ System.err.println("last=>" + last);
+ System.err.println("tree=>" + tree);
+ BigDecimal before = tree.getCash();
+
+ tree.setCash(tree.getCash().add(new BigDecimal(String.valueOf(baisc * persent))));
+ baisc *= persent;
+ if (ObjectUtils.isNotEmpty(tree.getSuperiorId())) {
+ LambdaQueryWrapper fatherLqw = new LambdaQueryWrapper<>();
+
+ fatherLqw.eq(UserExtra::getUserId, tree.getSuperiorId());
+ UserExtra father = userExtraService.getOne(fatherLqw);
+
+ persent = (double) father.getPercentage() / 100;
+ tree.setCash(tree.getCash().subtract(new BigDecimal(String.valueOf(baisc * persent))));
+ }
+ BigDecimal after = tree.getCash();
+
+ fundsLogMapper.insert(FundsLog.builder()
+ .consume(new BigDecimal(String.valueOf(baisc)))
+ .earnings(after.subtract(before))
+ .consumer(sysUserService.getNameById(last.getUserId()))
+ .beneficiaries(sysUserService.getNameById(tree.getUserId()))
+ .persent(tree.getPercentage())
+ .createTime(LocalDateTime.now())
+ .userId(last.getUserId())
+ .build());
+ userExtraMapper.update(tree, lqw);
+ } while (ObjectUtils.isNotEmpty(tree.getSuperiorId()));
+
+ return tree.getUserId();
+ }
+
+ public boolean check(Long pid, Long lid, Long fid) {
+ return Objects.equals(pid, lid) || Objects.equals(pid, fid) || pid == 1L;
+ }
+
+ @Override
+ public void benefit(Double basic) {
+ Long userId = SecurityUtils.getUserId();
+ if(SecurityUtils.isAdmin(SecurityUtils.getUserId())){
+ return;
+ }
+ UserExtra user = userExtraMapper.selectOne(new LambdaQueryWrapper().eq(UserExtra::getUserId, userId));
+
+ if (!check(user.getSuperiorId(), user.getLowestId(), user.getFirstId())) {
+ UserExtra father = userExtraMapper.selectOne(new LambdaQueryWrapper().eq(UserExtra::getUserId, user.getSuperiorId()));
+ father.setIntegral(father.getIntegral() + 100);
+
+ distributionIntegralService.insertDisLog(father.getId());
+
+ userExtraMapper.update(father, new LambdaQueryWrapper().eq(UserExtra::getUserId, user.getSuperiorId()));
+ }
+
+ doCash(user, basic);
+
+// UserExtra lowest = userExtraMapper.selectOne(new LambdaQueryWrapper().eq(UserExtra::getUserId, user.getLowestId()));
+// UserExtra first = userExtraMapper.selectOne(new LambdaQueryWrapper().eq(UserExtra::getUserId, user.getFirstId()));
+// UserExtra root = userExtraMapper.selectOne(new LambdaQueryWrapper().eq(UserExtra::getUserId, 1L));
+//
+//
+// double persent = 1;
+// if (ObjectUtils.isNotEmpty(lowest) && lowest.getId() != 1L) {
+// lowest.setCash(lowest.getCash().add(new BigDecimal(String.valueOf(basic * persent))));
+// BigDecimal bl = lowest.getCash();
+// BigDecimal bf = first.getCash();
+// BigDecimal br = root.getCash();
+// if (lowest.getFirstId() != null) {
+// persent = (double) first.getPercentage() / 100;
+// lowest.setCash(lowest.getCash().subtract(new BigDecimal(String.valueOf(basic * persent))));
+//
+// first.setCash(first.getCash().add(new BigDecimal(String.valueOf(basic * persent))));
+//
+// basic *= persent;
+// persent = (double) root.getPercentage() / 100;
+// first.setCash(first.getCash().subtract(new BigDecimal(String.valueOf(basic * persent))));
+// root.setCash(root.getCash().add(new BigDecimal(String.valueOf(basic * persent))));
+//
+// // TODO 资金记录
+//
+// userExtraMapper.update(first, new LambdaQueryWrapper().eq(UserExtra::getUserId, lowest.getFirstId()));
+// userExtraMapper.update(root, new LambdaQueryWrapper().eq(UserExtra::getUserId, 1L));
+// }
+// BigDecimal al = lowest.getCash();
+// BigDecimal af = first.getCash();
+// BigDecimal ar = root.getCash();
+//
+// fundsLogMapper.insert(FundsLog.builder()
+// .beneficiaries(sysUserService.getNameById(lowest.getUserId()))
+// .consumer(sysUserService.getNameById(userId))
+// .consume(new BigDecimal(String.valueOf(basic)))
+// .earnings(al.subtract(bl))
+// .persent(lowest.getPercentage())
+// .build());
+//
+// if (ObjectUtils.isNotEmpty(first))
+// fundsLogMapper.insert(FundsLog.builder()
+// .beneficiaries(sysUserService.getNameById(first.getUserId()))
+// .consumer(sysUserService.getNameById(lowest.getUserId()))
+// .consume(al.subtract(bl))
+// .earnings(af.subtract(bf))
+// .persent(first.getPercentage())
+// .build());
+//
+// if (ObjectUtils.isNotEmpty())
+//
+// userExtraMapper.update(lowest, new LambdaQueryWrapper().eq(UserExtra::getUserId, user.getLowestId()));
+// } else if (ObjectUtils.isNotEmpty(first)) {
+// first.setCash(first.getCash().add(new BigDecimal(String.valueOf(basic * persent))));
+//
+// persent = (double) root.getPercentage() / 100;
+// first.setCash(first.getCash().subtract(new BigDecimal(String.valueOf(basic * persent))));
+// root.setCash(root.getCash().add(new BigDecimal(String.valueOf(basic * persent))));
+//
+// userExtraMapper.update(first, new LambdaQueryWrapper().eq(UserExtra::getUserId, lowest.getFirstId()));
+// userExtraMapper.update(root, new LambdaQueryWrapper().eq(UserExtra::getUserId, 1L));
+// } else {
+// root.setCash(root.getCash().add(new BigDecimal(String.valueOf(basic * persent))));
+//
+// userExtraMapper.update(root, new LambdaQueryWrapper().eq(UserExtra::getUserId, 1L));
+// }
+ }
+
+
+
+}
diff --git a/src/main/java/com/ruoyi/system/file/FileSignature.java b/src/main/java/com/ruoyi/system/file/FileSignature.java
new file mode 100644
index 0000000..43946ce
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/file/FileSignature.java
@@ -0,0 +1,24 @@
+package com.ruoyi.system.file;
+
+import com.muta.common.config.AliConfig;
+import com.muta.common.core.service.ISysFileService;
+import com.muta.common.utils.oss.OSSSignatureExample;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /06 /06 / 16:23
+ * @Description:
+ */
+@Component
+public class FileSignature {
+ @Resource
+ private ISysFileService aliOssService;
+ public String getSignUrl(String fileUrl){
+ AliConfig aliConfig = new AliConfig();
+ aliOssService.getConfig(aliConfig);
+ return OSSSignatureExample.generateSignedUrl(aliConfig, fileUrl.substring(fileUrl.lastIndexOf("/") + 1));
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/gateway/dto/package-info.java b/src/main/java/com/ruoyi/system/gateway/dto/package-info.java
new file mode 100644
index 0000000..d05c6ec
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/gateway/dto/package-info.java
@@ -0,0 +1 @@
+package com.ruoyi.system.gateway.dto;
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/system/gateway/package-info.java b/src/main/java/com/ruoyi/system/gateway/package-info.java
new file mode 100644
index 0000000..343bcb5
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/gateway/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * 定义http、rpc接口,调用外部。在 adapter 中调用这部分内容。
+ */
+package com.ruoyi.system.gateway;
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/system/handler/CommonGlobalExceptionHandler.java b/src/main/java/com/ruoyi/system/handler/CommonGlobalExceptionHandler.java
new file mode 100644
index 0000000..f681a23
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/handler/CommonGlobalExceptionHandler.java
@@ -0,0 +1,27 @@
+package com.ruoyi.system.handler;
+import com.zy.exception.ConditionException;
+import com.zy.util.JsonResponse;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.http.HttpServletRequest;
+
+@ControllerAdvice
+@Order(Ordered.HIGHEST_PRECEDENCE)
+public class CommonGlobalExceptionHandler {
+
+ @ExceptionHandler(value = Exception.class)
+ @ResponseBody
+ public JsonResponse commonExceptionHandler(HttpServletRequest request, Exception e){
+ String errorMsg = e.getMessage();
+ if(e instanceof ConditionException){
+ String errorCode = ((ConditionException)e).getCode();
+ return new JsonResponse<>(errorCode, errorMsg);
+ }else{
+ return new JsonResponse<>("500",errorMsg);
+ }
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/lesong/domain/LesongLyrics.java b/src/main/java/com/ruoyi/system/lesong/domain/LesongLyrics.java
new file mode 100644
index 0000000..74ee458
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/lesong/domain/LesongLyrics.java
@@ -0,0 +1,40 @@
+package com.ruoyi.system.lesong.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * 歌词对象 lesong_lyrics
+ *
+ * @author mutaai
+ * @date 2024-05-30
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class LesongLyrics {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 唯一id
+ */
+ private Long id;
+
+ /**
+ * AI创作歌词ID
+ */
+ private String lyricsId;
+
+ /**
+ * 歌词内容
+ */
+ private String lyricsContent;
+
+ private Date createTime;
+
+}
diff --git a/src/main/java/com/ruoyi/system/lesong/domain/LesongLyricsUserRelative.java b/src/main/java/com/ruoyi/system/lesong/domain/LesongLyricsUserRelative.java
new file mode 100644
index 0000000..ac9db98
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/lesong/domain/LesongLyricsUserRelative.java
@@ -0,0 +1,39 @@
+package com.ruoyi.system.lesong.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 歌词-用户关联对象 lesong_lyrics_user_relative
+ *
+ * @author mutaai
+ * @date 2024-05-30
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class LesongLyricsUserRelative {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 唯一id
+ */
+ private Long id;
+
+ /**
+ * 用户id
+ */
+ private Long userId;
+
+ /**
+ * 歌词id
+ */
+ private Long lyricsId;
+
+
+}
diff --git a/src/main/java/com/ruoyi/system/lesong/domain/LesongSong.java b/src/main/java/com/ruoyi/system/lesong/domain/LesongSong.java
new file mode 100644
index 0000000..9a2d215
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/lesong/domain/LesongSong.java
@@ -0,0 +1,51 @@
+package com.ruoyi.system.lesong.domain;
+
+import com.muta.common.core.domain.BaseEntity;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * 歌曲对象 lesong_song
+ *
+ * @author mutaai
+ * @date 2024-05-30
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class LesongSong {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 唯一id
+ */
+ private Long id;
+
+ /**
+ * 歌曲suno_id
+ */
+ private String songId;
+
+ /**
+ * 歌曲名词
+ */
+ private String songTitle;
+
+ /**
+ * 歌曲文件oss存储地址
+ */
+ private String songUrl;
+
+ /**
+ * 歌曲封面图片oss存储地址
+ */
+ private String songCoverImageUrl;
+
+ private Date createTime;
+
+}
diff --git a/src/main/java/com/ruoyi/system/lesong/domain/LesongSongStyleRelative.java b/src/main/java/com/ruoyi/system/lesong/domain/LesongSongStyleRelative.java
new file mode 100644
index 0000000..1f1523c
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/lesong/domain/LesongSongStyleRelative.java
@@ -0,0 +1,44 @@
+package com.ruoyi.system.lesong.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.muta.common.annotation.Excel;
+import com.muta.common.core.domain.BaseEntity;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 歌曲-风格关联对象 lesong_song_style_relative
+ *
+ * @author mutaai
+ * @date 2024-05-30
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class LesongSongStyleRelative {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 唯一id
+ */
+ private Long id;
+
+ /**
+ * 歌曲id
+ */
+ private Long songId;
+
+ /**
+ * 歌曲风格id(数据字典id)
+ */
+ private Long songStyleId;
+
+
+}
diff --git a/src/main/java/com/ruoyi/system/lesong/domain/LesongSongUserRelative.java b/src/main/java/com/ruoyi/system/lesong/domain/LesongSongUserRelative.java
new file mode 100644
index 0000000..d35af01
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/lesong/domain/LesongSongUserRelative.java
@@ -0,0 +1,37 @@
+package com.ruoyi.system.lesong.domain;
+
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 歌曲-用户关联对象 lesong_song_user_relative
+ *
+ * @author mutaai
+ * @date 2024-05-30
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class LesongSongUserRelative {
+
+ /**
+ * 唯一id
+ */
+ private Long id;
+
+ /**
+ * 用户id
+ */
+ private Long userId;
+
+ /**
+ * 歌曲id
+ */
+ private Long songId;
+
+
+}
diff --git a/src/main/java/com/ruoyi/system/lesong/mapper/LesongLyricsMapper.java b/src/main/java/com/ruoyi/system/lesong/mapper/LesongLyricsMapper.java
new file mode 100644
index 0000000..03e6aca
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/lesong/mapper/LesongLyricsMapper.java
@@ -0,0 +1,61 @@
+package com.ruoyi.system.lesong.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.muta.lesong.domain.LesongLyrics;
+
+/**
+ * 歌词Mapper接口
+ *
+ * @author mutaai
+ * @date 2024-05-30
+ */
+public interface LesongLyricsMapper extends BaseMapper {
+ /**
+ * 查询歌词
+ *
+ * @param id 歌词主键
+ * @return 歌词
+ */
+ public LesongLyrics selectLesongLyricsById(Long id);
+
+ /**
+ * 查询歌词列表
+ *
+ * @param lesongLyrics 歌词
+ * @return 歌词集合
+ */
+ public List selectLesongLyricsList(LesongLyrics lesongLyrics);
+
+ /**
+ * 新增歌词
+ *
+ * @param lesongLyrics 歌词
+ * @return 结果
+ */
+ public int insertLesongLyrics(LesongLyrics lesongLyrics);
+
+ /**
+ * 修改歌词
+ *
+ * @param lesongLyrics 歌词
+ * @return 结果
+ */
+ public int updateLesongLyrics(LesongLyrics lesongLyrics);
+
+ /**
+ * 删除歌词
+ *
+ * @param id 歌词主键
+ * @return 结果
+ */
+ public int deleteLesongLyricsById(Long id);
+
+ /**
+ * 批量删除歌词
+ *
+ * @param ids 需要删除的数据主键集合
+ * @return 结果
+ */
+ public int deleteLesongLyricsByIds(Long[] ids);
+}
diff --git a/src/main/java/com/ruoyi/system/lesong/mapper/LesongLyricsUserRelativeMapper.java b/src/main/java/com/ruoyi/system/lesong/mapper/LesongLyricsUserRelativeMapper.java
new file mode 100644
index 0000000..e646b01
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/lesong/mapper/LesongLyricsUserRelativeMapper.java
@@ -0,0 +1,61 @@
+package com.ruoyi.system.lesong.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.muta.lesong.domain.LesongLyricsUserRelative;
+
+/**
+ * 歌词-用户关联Mapper接口
+ *
+ * @author mutaai
+ * @date 2024-05-30
+ */
+public interface LesongLyricsUserRelativeMapper extends BaseMapper {
+ /**
+ * 查询歌词-用户关联
+ *
+ * @param id 歌词-用户关联主键
+ * @return 歌词-用户关联
+ */
+ public LesongLyricsUserRelative selectLesongLyricsUserRelativeById(Long id);
+
+ /**
+ * 查询歌词-用户关联列表
+ *
+ * @param lesongLyricsUserRelative 歌词-用户关联
+ * @return 歌词-用户关联集合
+ */
+ public List selectLesongLyricsUserRelativeList(LesongLyricsUserRelative lesongLyricsUserRelative);
+
+ /**
+ * 新增歌词-用户关联
+ *
+ * @param lesongLyricsUserRelative 歌词-用户关联
+ * @return 结果
+ */
+ public int insertLesongLyricsUserRelative(LesongLyricsUserRelative lesongLyricsUserRelative);
+
+ /**
+ * 修改歌词-用户关联
+ *
+ * @param lesongLyricsUserRelative 歌词-用户关联
+ * @return 结果
+ */
+ public int updateLesongLyricsUserRelative(LesongLyricsUserRelative lesongLyricsUserRelative);
+
+ /**
+ * 删除歌词-用户关联
+ *
+ * @param id 歌词-用户关联主键
+ * @return 结果
+ */
+ public int deleteLesongLyricsUserRelativeById(Long id);
+
+ /**
+ * 批量删除歌词-用户关联
+ *
+ * @param ids 需要删除的数据主键集合
+ * @return 结果
+ */
+ public int deleteLesongLyricsUserRelativeByIds(Long[] ids);
+}
diff --git a/src/main/java/com/ruoyi/system/lesong/mapper/LesongSongMapper.java b/src/main/java/com/ruoyi/system/lesong/mapper/LesongSongMapper.java
new file mode 100644
index 0000000..8fd6dbd
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/lesong/mapper/LesongSongMapper.java
@@ -0,0 +1,61 @@
+package com.ruoyi.system.lesong.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.muta.lesong.domain.LesongSong;
+
+/**
+ * 歌曲Mapper接口
+ *
+ * @author mutaai
+ * @date 2024-05-30
+ */
+public interface LesongSongMapper extends BaseMapper {
+ /**
+ * 查询歌曲
+ *
+ * @param id 歌曲主键
+ * @return 歌曲
+ */
+ public LesongSong selectLesongSongById(Long id);
+
+ /**
+ * 查询歌曲列表
+ *
+ * @param lesongSong 歌曲
+ * @return 歌曲集合
+ */
+ public List selectLesongSongList(LesongSong lesongSong);
+
+ /**
+ * 新增歌曲
+ *
+ * @param lesongSong 歌曲
+ * @return 结果
+ */
+ public int insertLesongSong(LesongSong lesongSong);
+
+ /**
+ * 修改歌曲
+ *
+ * @param lesongSong 歌曲
+ * @return 结果
+ */
+ public int updateLesongSong(LesongSong lesongSong);
+
+ /**
+ * 删除歌曲
+ *
+ * @param id 歌曲主键
+ * @return 结果
+ */
+ public int deleteLesongSongById(Long id);
+
+ /**
+ * 批量删除歌曲
+ *
+ * @param ids 需要删除的数据主键集合
+ * @return 结果
+ */
+ public int deleteLesongSongByIds(Long[] ids);
+}
diff --git a/src/main/java/com/ruoyi/system/lesong/mapper/LesongSongStyleRelativeMapper.java b/src/main/java/com/ruoyi/system/lesong/mapper/LesongSongStyleRelativeMapper.java
new file mode 100644
index 0000000..1ddea90
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/lesong/mapper/LesongSongStyleRelativeMapper.java
@@ -0,0 +1,61 @@
+package com.ruoyi.system.lesong.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.muta.lesong.domain.LesongSongStyleRelative;
+
+/**
+ * 歌曲-风格关联Mapper接口
+ *
+ * @author mutaai
+ * @date 2024-05-30
+ */
+public interface LesongSongStyleRelativeMapper extends BaseMapper {
+ /**
+ * 查询歌曲-风格关联
+ *
+ * @param id 歌曲-风格关联主键
+ * @return 歌曲-风格关联
+ */
+ public LesongSongStyleRelative selectLesongSongStyleRelativeById(Long id);
+
+ /**
+ * 查询歌曲-风格关联列表
+ *
+ * @param lesongSongStyleRelative 歌曲-风格关联
+ * @return 歌曲-风格关联集合
+ */
+ public List selectLesongSongStyleRelativeList(LesongSongStyleRelative lesongSongStyleRelative);
+
+ /**
+ * 新增歌曲-风格关联
+ *
+ * @param lesongSongStyleRelative 歌曲-风格关联
+ * @return 结果
+ */
+ public int insertLesongSongStyleRelative(LesongSongStyleRelative lesongSongStyleRelative);
+
+ /**
+ * 修改歌曲-风格关联
+ *
+ * @param lesongSongStyleRelative 歌曲-风格关联
+ * @return 结果
+ */
+ public int updateLesongSongStyleRelative(LesongSongStyleRelative lesongSongStyleRelative);
+
+ /**
+ * 删除歌曲-风格关联
+ *
+ * @param id 歌曲-风格关联主键
+ * @return 结果
+ */
+ public int deleteLesongSongStyleRelativeById(Long id);
+
+ /**
+ * 批量删除歌曲-风格关联
+ *
+ * @param ids 需要删除的数据主键集合
+ * @return 结果
+ */
+ public int deleteLesongSongStyleRelativeByIds(Long[] ids);
+}
diff --git a/src/main/java/com/ruoyi/system/lesong/mapper/LesongSongUserRelativeMapper.java b/src/main/java/com/ruoyi/system/lesong/mapper/LesongSongUserRelativeMapper.java
new file mode 100644
index 0000000..4c91536
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/lesong/mapper/LesongSongUserRelativeMapper.java
@@ -0,0 +1,61 @@
+package com.ruoyi.system.lesong.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.muta.lesong.domain.LesongSongUserRelative;
+
+/**
+ * 歌曲-用户关联Mapper接口
+ *
+ * @author mutaai
+ * @date 2024-05-30
+ */
+public interface LesongSongUserRelativeMapper extends BaseMapper {
+ /**
+ * 查询歌曲-用户关联
+ *
+ * @param id 歌曲-用户关联主键
+ * @return 歌曲-用户关联
+ */
+ public LesongSongUserRelative selectLesongSongUserRelativeById(Long id);
+
+ /**
+ * 查询歌曲-用户关联列表
+ *
+ * @param lesongSongUserRelative 歌曲-用户关联
+ * @return 歌曲-用户关联集合
+ */
+ public List selectLesongSongUserRelativeList(LesongSongUserRelative lesongSongUserRelative);
+
+ /**
+ * 新增歌曲-用户关联
+ *
+ * @param lesongSongUserRelative 歌曲-用户关联
+ * @return 结果
+ */
+ public int insertLesongSongUserRelative(LesongSongUserRelative lesongSongUserRelative);
+
+ /**
+ * 修改歌曲-用户关联
+ *
+ * @param lesongSongUserRelative 歌曲-用户关联
+ * @return 结果
+ */
+ public int updateLesongSongUserRelative(LesongSongUserRelative lesongSongUserRelative);
+
+ /**
+ * 删除歌曲-用户关联
+ *
+ * @param id 歌曲-用户关联主键
+ * @return 结果
+ */
+ public int deleteLesongSongUserRelativeById(Long id);
+
+ /**
+ * 批量删除歌曲-用户关联
+ *
+ * @param ids 需要删除的数据主键集合
+ * @return 结果
+ */
+ public int deleteLesongSongUserRelativeByIds(Long[] ids);
+}
diff --git a/src/main/java/com/ruoyi/system/lesong/service/ILesongLyricsService.java b/src/main/java/com/ruoyi/system/lesong/service/ILesongLyricsService.java
new file mode 100644
index 0000000..bcb869a
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/lesong/service/ILesongLyricsService.java
@@ -0,0 +1,61 @@
+package com.ruoyi.system.lesong.service;
+
+import java.util.List;
+import com.muta.lesong.domain.LesongLyrics;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * 歌词Service接口
+ *
+ * @author mutaai
+ * @date 2024-05-30
+ */
+public interface ILesongLyricsService extends IService {
+ /**
+ * 查询歌词
+ *
+ * @param id 歌词主键
+ * @return 歌词
+ */
+ public LesongLyrics selectLesongLyricsById(Long id);
+
+ /**
+ * 查询歌词列表
+ *
+ * @param lesongLyrics 歌词
+ * @return 歌词集合
+ */
+ public List selectLesongLyricsList(LesongLyrics lesongLyrics);
+
+ /**
+ * 新增歌词
+ *
+ * @param lesongLyrics 歌词
+ * @return 结果
+ */
+ public int insertLesongLyrics(LesongLyrics lesongLyrics);
+
+ /**
+ * 修改歌词
+ *
+ * @param lesongLyrics 歌词
+ * @return 结果
+ */
+ public int updateLesongLyrics(LesongLyrics lesongLyrics);
+
+ /**
+ * 批量删除歌词
+ *
+ * @param ids 需要删除的歌词主键集合
+ * @return 结果
+ */
+ public int deleteLesongLyricsByIds(Long[] ids);
+
+ /**
+ * 删除歌词信息
+ *
+ * @param id 歌词主键
+ * @return 结果
+ */
+ public int deleteLesongLyricsById(Long id);
+}
diff --git a/src/main/java/com/ruoyi/system/lesong/service/ILesongLyricsUserRelativeService.java b/src/main/java/com/ruoyi/system/lesong/service/ILesongLyricsUserRelativeService.java
new file mode 100644
index 0000000..a9bd8c5
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/lesong/service/ILesongLyricsUserRelativeService.java
@@ -0,0 +1,61 @@
+package com.ruoyi.system.lesong.service;
+
+import java.util.List;
+import com.muta.lesong.domain.LesongLyricsUserRelative;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * 歌词-用户关联Service接口
+ *
+ * @author mutaai
+ * @date 2024-05-30
+ */
+public interface ILesongLyricsUserRelativeService extends IService {
+ /**
+ * 查询歌词-用户关联
+ *
+ * @param id 歌词-用户关联主键
+ * @return 歌词-用户关联
+ */
+ public LesongLyricsUserRelative selectLesongLyricsUserRelativeById(Long id);
+
+ /**
+ * 查询歌词-用户关联列表
+ *
+ * @param lesongLyricsUserRelative 歌词-用户关联
+ * @return 歌词-用户关联集合
+ */
+ public List selectLesongLyricsUserRelativeList(LesongLyricsUserRelative lesongLyricsUserRelative);
+
+ /**
+ * 新增歌词-用户关联
+ *
+ * @param lesongLyricsUserRelative 歌词-用户关联
+ * @return 结果
+ */
+ public int insertLesongLyricsUserRelative(LesongLyricsUserRelative lesongLyricsUserRelative);
+
+ /**
+ * 修改歌词-用户关联
+ *
+ * @param lesongLyricsUserRelative 歌词-用户关联
+ * @return 结果
+ */
+ public int updateLesongLyricsUserRelative(LesongLyricsUserRelative lesongLyricsUserRelative);
+
+ /**
+ * 批量删除歌词-用户关联
+ *
+ * @param ids 需要删除的歌词-用户关联主键集合
+ * @return 结果
+ */
+ public int deleteLesongLyricsUserRelativeByIds(Long[] ids);
+
+ /**
+ * 删除歌词-用户关联信息
+ *
+ * @param id 歌词-用户关联主键
+ * @return 结果
+ */
+ public int deleteLesongLyricsUserRelativeById(Long id);
+}
diff --git a/src/main/java/com/ruoyi/system/lesong/service/ILesongSongService.java b/src/main/java/com/ruoyi/system/lesong/service/ILesongSongService.java
new file mode 100644
index 0000000..686d001
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/lesong/service/ILesongSongService.java
@@ -0,0 +1,61 @@
+package com.ruoyi.system.lesong.service;
+
+import java.util.List;
+import com.muta.lesong.domain.LesongSong;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * 歌曲Service接口
+ *
+ * @author mutaai
+ * @date 2024-05-30
+ */
+public interface ILesongSongService extends IService {
+ /**
+ * 查询歌曲
+ *
+ * @param id 歌曲主键
+ * @return 歌曲
+ */
+ public LesongSong selectLesongSongById(Long id);
+
+ /**
+ * 查询歌曲列表
+ *
+ * @param lesongSong 歌曲
+ * @return 歌曲集合
+ */
+ public List selectLesongSongList(LesongSong lesongSong);
+
+ /**
+ * 新增歌曲
+ *
+ * @param lesongSong 歌曲
+ * @return 结果
+ */
+ public int insertLesongSong(LesongSong lesongSong);
+
+ /**
+ * 修改歌曲
+ *
+ * @param lesongSong 歌曲
+ * @return 结果
+ */
+ public int updateLesongSong(LesongSong lesongSong);
+
+ /**
+ * 批量删除歌曲
+ *
+ * @param ids 需要删除的歌曲主键集合
+ * @return 结果
+ */
+ public int deleteLesongSongByIds(Long[] ids);
+
+ /**
+ * 删除歌曲信息
+ *
+ * @param id 歌曲主键
+ * @return 结果
+ */
+ public int deleteLesongSongById(Long id);
+}
diff --git a/src/main/java/com/ruoyi/system/lesong/service/ILesongSongStyleRelativeService.java b/src/main/java/com/ruoyi/system/lesong/service/ILesongSongStyleRelativeService.java
new file mode 100644
index 0000000..8a65cfb
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/lesong/service/ILesongSongStyleRelativeService.java
@@ -0,0 +1,61 @@
+package com.ruoyi.system.lesong.service;
+
+import java.util.List;
+import com.muta.lesong.domain.LesongSongStyleRelative;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * 歌曲-风格关联Service接口
+ *
+ * @author mutaai
+ * @date 2024-05-30
+ */
+public interface ILesongSongStyleRelativeService extends IService {
+ /**
+ * 查询歌曲-风格关联
+ *
+ * @param id 歌曲-风格关联主键
+ * @return 歌曲-风格关联
+ */
+ public LesongSongStyleRelative selectLesongSongStyleRelativeById(Long id);
+
+ /**
+ * 查询歌曲-风格关联列表
+ *
+ * @param lesongSongStyleRelative 歌曲-风格关联
+ * @return 歌曲-风格关联集合
+ */
+ public List selectLesongSongStyleRelativeList(LesongSongStyleRelative lesongSongStyleRelative);
+
+ /**
+ * 新增歌曲-风格关联
+ *
+ * @param lesongSongStyleRelative 歌曲-风格关联
+ * @return 结果
+ */
+ public int insertLesongSongStyleRelative(LesongSongStyleRelative lesongSongStyleRelative);
+
+ /**
+ * 修改歌曲-风格关联
+ *
+ * @param lesongSongStyleRelative 歌曲-风格关联
+ * @return 结果
+ */
+ public int updateLesongSongStyleRelative(LesongSongStyleRelative lesongSongStyleRelative);
+
+ /**
+ * 批量删除歌曲-风格关联
+ *
+ * @param ids 需要删除的歌曲-风格关联主键集合
+ * @return 结果
+ */
+ public int deleteLesongSongStyleRelativeByIds(Long[] ids);
+
+ /**
+ * 删除歌曲-风格关联信息
+ *
+ * @param id 歌曲-风格关联主键
+ * @return 结果
+ */
+ public int deleteLesongSongStyleRelativeById(Long id);
+}
diff --git a/src/main/java/com/ruoyi/system/lesong/service/ILesongSongUserRelativeService.java b/src/main/java/com/ruoyi/system/lesong/service/ILesongSongUserRelativeService.java
new file mode 100644
index 0000000..0a744af
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/lesong/service/ILesongSongUserRelativeService.java
@@ -0,0 +1,61 @@
+package com.ruoyi.system.lesong.service;
+
+import java.util.List;
+import com.muta.lesong.domain.LesongSongUserRelative;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * 歌曲-用户关联Service接口
+ *
+ * @author mutaai
+ * @date 2024-05-30
+ */
+public interface ILesongSongUserRelativeService extends IService {
+ /**
+ * 查询歌曲-用户关联
+ *
+ * @param id 歌曲-用户关联主键
+ * @return 歌曲-用户关联
+ */
+ public LesongSongUserRelative selectLesongSongUserRelativeById(Long id);
+
+ /**
+ * 查询歌曲-用户关联列表
+ *
+ * @param lesongSongUserRelative 歌曲-用户关联
+ * @return 歌曲-用户关联集合
+ */
+ public List selectLesongSongUserRelativeList(LesongSongUserRelative lesongSongUserRelative);
+
+ /**
+ * 新增歌曲-用户关联
+ *
+ * @param lesongSongUserRelative 歌曲-用户关联
+ * @return 结果
+ */
+ public int insertLesongSongUserRelative(LesongSongUserRelative lesongSongUserRelative);
+
+ /**
+ * 修改歌曲-用户关联
+ *
+ * @param lesongSongUserRelative 歌曲-用户关联
+ * @return 结果
+ */
+ public int updateLesongSongUserRelative(LesongSongUserRelative lesongSongUserRelative);
+
+ /**
+ * 批量删除歌曲-用户关联
+ *
+ * @param ids 需要删除的歌曲-用户关联主键集合
+ * @return 结果
+ */
+ public int deleteLesongSongUserRelativeByIds(Long[] ids);
+
+ /**
+ * 删除歌曲-用户关联信息
+ *
+ * @param id 歌曲-用户关联主键
+ * @return 结果
+ */
+ public int deleteLesongSongUserRelativeById(Long id);
+}
diff --git a/src/main/java/com/ruoyi/system/lesong/service/impl/LesongLyricsServiceImpl.java b/src/main/java/com/ruoyi/system/lesong/service/impl/LesongLyricsServiceImpl.java
new file mode 100644
index 0000000..ebbc596
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/lesong/service/impl/LesongLyricsServiceImpl.java
@@ -0,0 +1,90 @@
+package com.ruoyi.system.lesong.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.muta.lesong.domain.LesongLyrics;
+import com.muta.lesong.mapper.LesongLyricsMapper;
+import com.muta.lesong.service.ILesongLyricsService;
+import com.muta.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 歌词Service业务层处理
+ *
+ * @author mutaai
+ * @date 2024-05-30
+ */
+@Service
+public class LesongLyricsServiceImpl extends ServiceImpl implements ILesongLyricsService {
+ @Autowired
+ private LesongLyricsMapper lesongLyricsMapper;
+
+ /**
+ * 查询歌词
+ *
+ * @param id 歌词主键
+ * @return 歌词
+ */
+ @Override
+ public LesongLyrics selectLesongLyricsById(Long id) {
+ return lesongLyricsMapper.selectLesongLyricsById(id);
+ }
+
+ /**
+ * 查询歌词列表
+ *
+ * @param lesongLyrics 歌词
+ * @return 歌词
+ */
+ @Override
+ public List selectLesongLyricsList(LesongLyrics lesongLyrics) {
+ return lesongLyricsMapper.selectLesongLyricsList(lesongLyrics);
+ }
+
+ /**
+ * 新增歌词
+ *
+ * @param lesongLyrics 歌词
+ * @return 结果
+ */
+ @Override
+ public int insertLesongLyrics(LesongLyrics lesongLyrics) {
+ lesongLyrics.setCreateTime(DateUtils.getNowDate());
+ return lesongLyricsMapper.insertLesongLyrics(lesongLyrics);
+ }
+
+ /**
+ * 修改歌词
+ *
+ * @param lesongLyrics 歌词
+ * @return 结果
+ */
+ @Override
+ public int updateLesongLyrics(LesongLyrics lesongLyrics) {
+ return lesongLyricsMapper.updateLesongLyrics(lesongLyrics);
+ }
+
+ /**
+ * 批量删除歌词
+ *
+ * @param ids 需要删除的歌词主键
+ * @return 结果
+ */
+ @Override
+ public int deleteLesongLyricsByIds(Long[] ids) {
+ return lesongLyricsMapper.deleteLesongLyricsByIds(ids);
+ }
+
+ /**
+ * 删除歌词信息
+ *
+ * @param id 歌词主键
+ * @return 结果
+ */
+ @Override
+ public int deleteLesongLyricsById(Long id) {
+ return lesongLyricsMapper.deleteLesongLyricsById(id);
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/lesong/service/impl/LesongLyricsUserRelativeServiceImpl.java b/src/main/java/com/ruoyi/system/lesong/service/impl/LesongLyricsUserRelativeServiceImpl.java
new file mode 100644
index 0000000..333ab93
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/lesong/service/impl/LesongLyricsUserRelativeServiceImpl.java
@@ -0,0 +1,88 @@
+package com.ruoyi.system.lesong.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.muta.lesong.domain.LesongLyricsUserRelative;
+import com.muta.lesong.mapper.LesongLyricsUserRelativeMapper;
+import com.muta.lesong.service.ILesongLyricsUserRelativeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 歌词-用户关联Service业务层处理
+ *
+ * @author mutaai
+ * @date 2024-05-30
+ */
+@Service
+public class LesongLyricsUserRelativeServiceImpl extends ServiceImpl implements ILesongLyricsUserRelativeService {
+ @Autowired
+ private LesongLyricsUserRelativeMapper lesongLyricsUserRelativeMapper;
+
+ /**
+ * 查询歌词-用户关联
+ *
+ * @param id 歌词-用户关联主键
+ * @return 歌词-用户关联
+ */
+ @Override
+ public LesongLyricsUserRelative selectLesongLyricsUserRelativeById(Long id) {
+ return lesongLyricsUserRelativeMapper.selectLesongLyricsUserRelativeById(id);
+ }
+
+ /**
+ * 查询歌词-用户关联列表
+ *
+ * @param lesongLyricsUserRelative 歌词-用户关联
+ * @return 歌词-用户关联
+ */
+ @Override
+ public List selectLesongLyricsUserRelativeList(LesongLyricsUserRelative lesongLyricsUserRelative) {
+ return lesongLyricsUserRelativeMapper.selectLesongLyricsUserRelativeList(lesongLyricsUserRelative);
+ }
+
+ /**
+ * 新增歌词-用户关联
+ *
+ * @param lesongLyricsUserRelative 歌词-用户关联
+ * @return 结果
+ */
+ @Override
+ public int insertLesongLyricsUserRelative(LesongLyricsUserRelative lesongLyricsUserRelative) {
+ return lesongLyricsUserRelativeMapper.insertLesongLyricsUserRelative(lesongLyricsUserRelative);
+ }
+
+ /**
+ * 修改歌词-用户关联
+ *
+ * @param lesongLyricsUserRelative 歌词-用户关联
+ * @return 结果
+ */
+ @Override
+ public int updateLesongLyricsUserRelative(LesongLyricsUserRelative lesongLyricsUserRelative) {
+ return lesongLyricsUserRelativeMapper.updateLesongLyricsUserRelative(lesongLyricsUserRelative);
+ }
+
+ /**
+ * 批量删除歌词-用户关联
+ *
+ * @param ids 需要删除的歌词-用户关联主键
+ * @return 结果
+ */
+ @Override
+ public int deleteLesongLyricsUserRelativeByIds(Long[] ids) {
+ return lesongLyricsUserRelativeMapper.deleteLesongLyricsUserRelativeByIds(ids);
+ }
+
+ /**
+ * 删除歌词-用户关联信息
+ *
+ * @param id 歌词-用户关联主键
+ * @return 结果
+ */
+ @Override
+ public int deleteLesongLyricsUserRelativeById(Long id) {
+ return lesongLyricsUserRelativeMapper.deleteLesongLyricsUserRelativeById(id);
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/lesong/service/impl/LesongSongServiceImpl.java b/src/main/java/com/ruoyi/system/lesong/service/impl/LesongSongServiceImpl.java
new file mode 100644
index 0000000..ec08fac
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/lesong/service/impl/LesongSongServiceImpl.java
@@ -0,0 +1,89 @@
+package com.ruoyi.system.lesong.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import java.util.List;
+ import com.muta.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.muta.lesong.mapper.LesongSongMapper;
+import com.muta.lesong.domain.LesongSong;
+import com.muta.lesong.service.ILesongSongService;
+
+/**
+ * 歌曲Service业务层处理
+ *
+ * @author mutaai
+ * @date 2024-05-30
+ */
+@Service
+public class LesongSongServiceImpl extends ServiceImpl implements ILesongSongService {
+ @Autowired
+ private LesongSongMapper lesongSongMapper;
+
+ /**
+ * 查询歌曲
+ *
+ * @param id 歌曲主键
+ * @return 歌曲
+ */
+ @Override
+ public LesongSong selectLesongSongById(Long id) {
+ return lesongSongMapper.selectLesongSongById(id);
+ }
+
+ /**
+ * 查询歌曲列表
+ *
+ * @param lesongSong 歌曲
+ * @return 歌曲
+ */
+ @Override
+ public List selectLesongSongList(LesongSong lesongSong) {
+ return lesongSongMapper.selectLesongSongList(lesongSong);
+ }
+
+ /**
+ * 新增歌曲
+ *
+ * @param lesongSong 歌曲
+ * @return 结果
+ */
+ @Override
+ public int insertLesongSong(LesongSong lesongSong) {
+ lesongSong.setCreateTime(DateUtils.getNowDate());
+ return lesongSongMapper.insertLesongSong(lesongSong);
+ }
+
+ /**
+ * 修改歌曲
+ *
+ * @param lesongSong 歌曲
+ * @return 结果
+ */
+ @Override
+ public int updateLesongSong(LesongSong lesongSong) {
+ return lesongSongMapper.updateLesongSong(lesongSong);
+ }
+
+ /**
+ * 批量删除歌曲
+ *
+ * @param ids 需要删除的歌曲主键
+ * @return 结果
+ */
+ @Override
+ public int deleteLesongSongByIds(Long[] ids) {
+ return lesongSongMapper.deleteLesongSongByIds(ids);
+ }
+
+ /**
+ * 删除歌曲信息
+ *
+ * @param id 歌曲主键
+ * @return 结果
+ */
+ @Override
+ public int deleteLesongSongById(Long id) {
+ return lesongSongMapper.deleteLesongSongById(id);
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/lesong/service/impl/LesongSongStyleRelativeServiceImpl.java b/src/main/java/com/ruoyi/system/lesong/service/impl/LesongSongStyleRelativeServiceImpl.java
new file mode 100644
index 0000000..f80dbdc
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/lesong/service/impl/LesongSongStyleRelativeServiceImpl.java
@@ -0,0 +1,87 @@
+package com.ruoyi.system.lesong.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.muta.lesong.mapper.LesongSongStyleRelativeMapper;
+import com.muta.lesong.domain.LesongSongStyleRelative;
+import com.muta.lesong.service.ILesongSongStyleRelativeService;
+
+/**
+ * 歌曲-风格关联Service业务层处理
+ *
+ * @author mutaai
+ * @date 2024-05-30
+ */
+@Service
+public class LesongSongStyleRelativeServiceImpl extends ServiceImpl implements ILesongSongStyleRelativeService {
+ @Autowired
+ private LesongSongStyleRelativeMapper lesongSongStyleRelativeMapper;
+
+ /**
+ * 查询歌曲-风格关联
+ *
+ * @param id 歌曲-风格关联主键
+ * @return 歌曲-风格关联
+ */
+ @Override
+ public LesongSongStyleRelative selectLesongSongStyleRelativeById(Long id) {
+ return lesongSongStyleRelativeMapper.selectLesongSongStyleRelativeById(id);
+ }
+
+ /**
+ * 查询歌曲-风格关联列表
+ *
+ * @param lesongSongStyleRelative 歌曲-风格关联
+ * @return 歌曲-风格关联
+ */
+ @Override
+ public List selectLesongSongStyleRelativeList(LesongSongStyleRelative lesongSongStyleRelative) {
+ return lesongSongStyleRelativeMapper.selectLesongSongStyleRelativeList(lesongSongStyleRelative);
+ }
+
+ /**
+ * 新增歌曲-风格关联
+ *
+ * @param lesongSongStyleRelative 歌曲-风格关联
+ * @return 结果
+ */
+ @Override
+ public int insertLesongSongStyleRelative(LesongSongStyleRelative lesongSongStyleRelative) {
+ return lesongSongStyleRelativeMapper.insertLesongSongStyleRelative(lesongSongStyleRelative);
+ }
+
+ /**
+ * 修改歌曲-风格关联
+ *
+ * @param lesongSongStyleRelative 歌曲-风格关联
+ * @return 结果
+ */
+ @Override
+ public int updateLesongSongStyleRelative(LesongSongStyleRelative lesongSongStyleRelative) {
+ return lesongSongStyleRelativeMapper.updateLesongSongStyleRelative(lesongSongStyleRelative);
+ }
+
+ /**
+ * 批量删除歌曲-风格关联
+ *
+ * @param ids 需要删除的歌曲-风格关联主键
+ * @return 结果
+ */
+ @Override
+ public int deleteLesongSongStyleRelativeByIds(Long[] ids) {
+ return lesongSongStyleRelativeMapper.deleteLesongSongStyleRelativeByIds(ids);
+ }
+
+ /**
+ * 删除歌曲-风格关联信息
+ *
+ * @param id 歌曲-风格关联主键
+ * @return 结果
+ */
+ @Override
+ public int deleteLesongSongStyleRelativeById(Long id) {
+ return lesongSongStyleRelativeMapper.deleteLesongSongStyleRelativeById(id);
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/lesong/service/impl/LesongSongUserRelativeServiceImpl.java b/src/main/java/com/ruoyi/system/lesong/service/impl/LesongSongUserRelativeServiceImpl.java
new file mode 100644
index 0000000..4700446
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/lesong/service/impl/LesongSongUserRelativeServiceImpl.java
@@ -0,0 +1,87 @@
+package com.ruoyi.system.lesong.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.muta.lesong.mapper.LesongSongUserRelativeMapper;
+import com.muta.lesong.domain.LesongSongUserRelative;
+import com.muta.lesong.service.ILesongSongUserRelativeService;
+
+/**
+ * 歌曲-用户关联Service业务层处理
+ *
+ * @author mutaai
+ * @date 2024-05-30
+ */
+@Service
+public class LesongSongUserRelativeServiceImpl extends ServiceImpl implements ILesongSongUserRelativeService {
+ @Autowired
+ private LesongSongUserRelativeMapper lesongSongUserRelativeMapper;
+
+ /**
+ * 查询歌曲-用户关联
+ *
+ * @param id 歌曲-用户关联主键
+ * @return 歌曲-用户关联
+ */
+ @Override
+ public LesongSongUserRelative selectLesongSongUserRelativeById(Long id) {
+ return lesongSongUserRelativeMapper.selectLesongSongUserRelativeById(id);
+ }
+
+ /**
+ * 查询歌曲-用户关联列表
+ *
+ * @param lesongSongUserRelative 歌曲-用户关联
+ * @return 歌曲-用户关联
+ */
+ @Override
+ public List selectLesongSongUserRelativeList(LesongSongUserRelative lesongSongUserRelative) {
+ return lesongSongUserRelativeMapper.selectLesongSongUserRelativeList(lesongSongUserRelative);
+ }
+
+ /**
+ * 新增歌曲-用户关联
+ *
+ * @param lesongSongUserRelative 歌曲-用户关联
+ * @return 结果
+ */
+ @Override
+ public int insertLesongSongUserRelative(LesongSongUserRelative lesongSongUserRelative) {
+ return lesongSongUserRelativeMapper.insertLesongSongUserRelative(lesongSongUserRelative);
+ }
+
+ /**
+ * 修改歌曲-用户关联
+ *
+ * @param lesongSongUserRelative 歌曲-用户关联
+ * @return 结果
+ */
+ @Override
+ public int updateLesongSongUserRelative(LesongSongUserRelative lesongSongUserRelative) {
+ return lesongSongUserRelativeMapper.updateLesongSongUserRelative(lesongSongUserRelative);
+ }
+
+ /**
+ * 批量删除歌曲-用户关联
+ *
+ * @param ids 需要删除的歌曲-用户关联主键
+ * @return 结果
+ */
+ @Override
+ public int deleteLesongSongUserRelativeByIds(Long[] ids) {
+ return lesongSongUserRelativeMapper.deleteLesongSongUserRelativeByIds(ids);
+ }
+
+ /**
+ * 删除歌曲-用户关联信息
+ *
+ * @param id 歌曲-用户关联主键
+ * @return 结果
+ */
+ @Override
+ public int deleteLesongSongUserRelativeById(Long id) {
+ return lesongSongUserRelativeMapper.deleteLesongSongUserRelativeById(id);
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/log/aop/IntegralLogAspect.java b/src/main/java/com/ruoyi/system/log/aop/IntegralLogAspect.java
new file mode 100644
index 0000000..721cd5f
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/log/aop/IntegralLogAspect.java
@@ -0,0 +1,98 @@
+package com.ruoyi.system.log.aop;
+import com.muta.common.annotation.IntegralLogInsert;
+import com.muta.common.constant.OperationConstants;
+import com.muta.common.core.domain.model.RegisterBody;
+import com.muta.common.utils.SecurityUtils;
+import com.muta.log.domain.IntegralLog;
+import com.muta.log.factory.IntegralLogFactory;
+import com.muta.basics.domain.Kamil;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.After;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Objects;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /04 /22 / 17:07
+ * @Description:
+ */
+@Aspect
+@Component()
+public class IntegralLogAspect {
+
+ @Resource
+ private IntegralLogFactory integralLogFactory;
+ @Async("asyncPoolTaskExecutor") // 指定使用自定义的 Executor
+ @After("@annotation(com.muta.common.annotation.IntegralLogInsert)")
+ public void before(JoinPoint joinPoint) {
+ MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
+ // 获取方法对象
+ Method method = methodSignature.getMethod();
+ // 获取注解实例
+ IntegralLogInsert integralLogInsert = method.getAnnotation(IntegralLogInsert.class);
+ System.err.println("进入");
+ System.err.println(SecurityUtils.getUsername());
+ //签到操作记录
+ if (Objects.equals(integralLogInsert.operation(), OperationConstants.SIGNIN)) {
+ integralLogFactory.getInstance(integralLogInsert.operation()).insertLog(new IntegralLog());
+ }
+ //注册操作记录
+// else if (Objects.equals(integralLogInsert.operation(), OperationConstants.REGISTER)) {
+//
+// Object[] args = joinPoint.getArgs(); // 获取方法参数列表
+// IntegralLog integralLog = new IntegralLog();
+// String phone = null;
+// for (Object arg : args) {
+// if (arg instanceof RegisterBody) {
+// try {
+// Field phoneField = arg.getClass().getDeclaredField("phone");
+// phoneField.setAccessible(true);
+// phone = (String) phoneField.get(arg); // 获取 RegisterBody 对象中的 phone 字段的值
+// break;
+// } catch (NoSuchFieldException | IllegalAccessException e) {
+// e.printStackTrace();
+// }
+// }
+// }
+// integralLog.setCreateBy(phone);
+// integralLogFactory.getInstance(integralLogInsert.operation()).insertLog(integralLog);
+// }
+ //卡密操作记录
+ else if (Objects.equals(integralLogInsert.operation(), OperationConstants.Kamil)) {
+ System.err.println("我进来了+++++=====");
+ Object[] args = joinPoint.getArgs();
+ IntegralLog integralLog = new IntegralLog();
+ for (Object arg : args) {
+ if (arg instanceof Kamil) {
+ try {
+ Field fieldValue = Kamil.class.getDeclaredField("value");
+ Field fieldType = Kamil.class.getDeclaredField("type");
+ // 设置字段可访问,因为它可能是私有的
+ fieldValue.setAccessible(true);
+ fieldType.setAccessible(true);
+ Integer v= (Integer) fieldValue.get(arg); // 使用 arg 对象获取字段的值
+ Integer typeValue = (Integer) fieldType.get(arg); // 使用 arg 对象获取字段的值
+ integralLog.setValue(v.toString());
+ integralLog.setType(typeValue);
+ break;
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ integralLogFactory.getInstance(integralLogInsert.operation()).insertLog(integralLog);
+ } else {
+ // 默认情况下的处理
+ }
+
+ }
+
+
+}
diff --git a/src/main/java/com/ruoyi/system/log/aop/SimpleLogInsertAspect.java b/src/main/java/com/ruoyi/system/log/aop/SimpleLogInsertAspect.java
new file mode 100644
index 0000000..24cb0c2
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/log/aop/SimpleLogInsertAspect.java
@@ -0,0 +1,98 @@
+package com.ruoyi.system.log.aop;//package com.muta.log.aop;
+//
+//import com.muta.common.annotation.LogInsert;
+//
+//import com.muta.common.core.service.BaseLogService;
+//import com.muta.common.enums.LogType;
+//import com.muta.log.config.LogConfig;
+//import org.aspectj.lang.JoinPoint;
+//import org.aspectj.lang.annotation.After;
+//import org.aspectj.lang.annotation.Aspect;
+//import org.aspectj.lang.reflect.MethodSignature;
+//import org.springframework.core.DefaultParameterNameDiscoverer;
+//import org.springframework.core.ParameterNameDiscoverer;
+//import org.springframework.scheduling.annotation.Async;
+//import org.springframework.stereotype.Component;
+//
+//import java.lang.reflect.Field;
+//import java.lang.reflect.Method;
+//import java.util.HashMap;
+//import java.util.Map;
+//
+///**
+// * @author: Larry
+// * @Date: 2024 /04 /18 / 20:29
+// * @Description:
+// */
+//
+//@Aspect
+//@Component()
+//public class SimpleLogInsertAspect extends LogConfig {
+//
+//
+// private final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
+// private final Map parameterMap = new HashMap<>();
+//
+// @After("@annotation(com.muta.common.annotation.LogInsert)")
+// public void before(JoinPoint joinPoint) {
+// MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
+// // 获取方法对象
+// Method method = methodSignature.getMethod();
+// // 获取注解实例
+// LogInsert logInsertAnnotation = method.getAnnotation(LogInsert.class);
+// LogType value = logInsertAnnotation.value();
+// switch (value) {
+// case ORDER:
+//
+// break;
+// case SIGNIN:
+// // 处理用户类型的日志
+// break;
+// // 可以根据需要添加其他枚举值的处理逻辑
+// case INVITEE:
+//
+// break;
+//
+// default:
+// // 默认处理逻辑
+// break;
+// }
+// getParameterNames(joinPoint);
+//
+//
+// }
+//
+// private void getParameterNames(JoinPoint joinPoint){
+// MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
+// String[] parameterNames = methodSignature.getParameterNames();
+// if (parameterNames == null) {
+// parameterNames = parameterNameDiscoverer.getParameterNames(methodSignature.getMethod());
+// }
+// Object[] args = joinPoint.getArgs();
+// for (int i = 0; i < args.length; i++) {
+// if (parameterNames != null) {
+// System.out.println("参数名:" + parameterNames[i]);
+// }
+// if (args[i] != null) {
+// Class> parameterType = methodSignature.getMethod().getParameterTypes()[i];
+// if (parameterType.isAssignableFrom(args[i].getClass())) {
+// Field[] fields = parameterType.getDeclaredFields();
+// for (Field field : fields) {
+// field.setAccessible(true);
+// try {
+// Object value = field.get(args[i]);
+// parameterMap.put(field.getName(),value);
+// System.out.println(parameterMap.get(field.getName()));
+// } catch (IllegalAccessException e) {
+// e.printStackTrace();
+// }
+// }
+// }
+// }
+// }
+// }
+//
+//}
+//
+//
+//
diff --git a/src/main/java/com/ruoyi/system/log/config/LogConfig.java b/src/main/java/com/ruoyi/system/log/config/LogConfig.java
new file mode 100644
index 0000000..0c9768e
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/log/config/LogConfig.java
@@ -0,0 +1,28 @@
+package com.ruoyi.system.log.config;
+
+import com.muta.common.core.domain.entity.UserExtra;
+import com.muta.common.core.service.BaseLogService;
+import com.muta.system.service.IUserExtraService;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /04 /19 / 12:21
+ * @Description:日志工厂数据支持类
+ */
+@Component
+public class LogConfig {
+ @Resource
+ private IUserExtraService userExtraService;
+ protected static Map logsMap = new ConcurrentHashMap<>();
+
+
+ public BaseLogService getByType(String type){
+ return logsMap.get(type);
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/log/domain/IntegralLog.java b/src/main/java/com/ruoyi/system/log/domain/IntegralLog.java
new file mode 100644
index 0000000..bb75cab
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/log/domain/IntegralLog.java
@@ -0,0 +1,51 @@
+package com.ruoyi.system.log.domain;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.muta.common.core.domain.BaseEntity;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * 【请填写功能名称】对象 integral_log
+ *
+ * @author mutaai
+ * @date 2024-04-22
+ */
+@TableName("integral_log")
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class IntegralLog {
+ private static final long serialVersionUID = 1L;
+ /** 主键 */
+ @TableId()
+ private Long id;
+ /** 值 */
+ private String value;
+ /** 操作类型 */
+ private String operationType;
+ /** 1有效0无效 */
+ private Long status;
+ /** 类型:增还是减 1增 0 减 */
+ private Integer type;
+ /** 操作人 */
+ private String createBy;
+ /** 操作时间 */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date createTime;
+ private Long userId;
+
+ }
+
diff --git a/src/main/java/com/ruoyi/system/log/domain/InviteLog.java b/src/main/java/com/ruoyi/system/log/domain/InviteLog.java
new file mode 100644
index 0000000..ed2c735
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/log/domain/InviteLog.java
@@ -0,0 +1,54 @@
+package com.ruoyi.system.log.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.Date;
+
+
+/**
+ * 【请填写功能名称】对象 invite_log
+ *
+ * @author mutaai
+ * @date 2024-04-23
+ */
+
+@Data
+@TableName()
+public class InviteLog
+{
+
+
+ /** 主键 */
+ @TableId(value = "id",type = IdType.AUTO)
+ private Long id;
+
+ /** 被邀请人 */
+
+ private String invitee;
+
+ /** 邀请人 */
+
+ private String inviter;
+
+ /** 报酬 */
+
+ private String reward;
+
+ /** $column.columnComment */
+
+ private String ip;
+
+ /** 邀请码 */
+
+ private String inviteCode;
+
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date createTime;
+ private Long userId;
+
+}
diff --git a/src/main/java/com/ruoyi/system/log/domain/dto/InviteLogDTO.java b/src/main/java/com/ruoyi/system/log/domain/dto/InviteLogDTO.java
new file mode 100644
index 0000000..126d394
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/log/domain/dto/InviteLogDTO.java
@@ -0,0 +1,24 @@
+package com.ruoyi.system.log.domain.dto;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Builder;
+import lombok.Data;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /04 /23 / 16:05
+ * @Description:
+ */
+@Data
+@Builder
+public class InviteLogDTO {
+ private Long userId;
+ /** 邀请人 */
+ private String inviter;
+ /** 邀请码 */
+
+ private String inviteCode;
+ /** 被邀请人 */
+ private String invitee;
+}
diff --git a/src/main/java/com/ruoyi/system/log/factory/IntegralLogFactory.java b/src/main/java/com/ruoyi/system/log/factory/IntegralLogFactory.java
new file mode 100644
index 0000000..70d3158
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/log/factory/IntegralLogFactory.java
@@ -0,0 +1,43 @@
+package com.ruoyi.system.log.factory;
+
+import com.muta.common.constant.OperationConstants;
+import com.muta.log.service.IIntegralLogService;
+import com.muta.log.service.impl.InviteIntegralLogServiceImpl;
+import com.muta.log.service.impl.KamilIntegralLogService;
+import com.muta.log.service.impl.RegisterIntegralLogServiceImpl;
+import com.muta.log.service.impl.SigninIntegralLogServiceImpl;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /04 /22 / 16:55
+ * @Description:
+ */
+@Component
+public class IntegralLogFactory {
+ public Map iIntegralLogServiceMap = new ConcurrentHashMap<>();
+ @Resource
+ private InviteIntegralLogServiceImpl inviteIntegralLogService;
+ @Resource
+ private RegisterIntegralLogServiceImpl registerIntegralLogService;
+ @Resource
+ private SigninIntegralLogServiceImpl signinIntegralLogService;
+ @Resource
+ private KamilIntegralLogService kamilIntegralLogService;
+ @PostConstruct
+ public void init(){
+ iIntegralLogServiceMap.put(OperationConstants.INVITE,inviteIntegralLogService);
+ iIntegralLogServiceMap.put(OperationConstants.Kamil,kamilIntegralLogService);
+ iIntegralLogServiceMap.put(OperationConstants.REGISTER,registerIntegralLogService);
+ iIntegralLogServiceMap.put(OperationConstants.SIGNIN,signinIntegralLogService);
+ }
+ public IIntegralLogService getInstance(String type){
+ return iIntegralLogServiceMap.get(type);
+ }
+
+ }
diff --git a/src/main/java/com/ruoyi/system/log/mapper/IntegralLogMapper.java b/src/main/java/com/ruoyi/system/log/mapper/IntegralLogMapper.java
new file mode 100644
index 0000000..c3a6efc
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/log/mapper/IntegralLogMapper.java
@@ -0,0 +1,21 @@
+package com.ruoyi.system.log.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+import com.muta.common.annotation.DataPermission;
+import com.muta.common.annotation.DataScope;
+import com.muta.common.core.domain.entity.SysUser;
+import com.muta.log.domain.IntegralLog;
+
+
+/**
+ * 【请填写功能名称】Mapper接口
+ *
+ * @author mutaai
+ * @date 2024-04-22
+ */
+public interface IntegralLogMapper extends BaseMapper {
+
+ List selectByFilter(SysUser sysUser);
+}
diff --git a/src/main/java/com/ruoyi/system/log/mapper/InviteLogMapper.java b/src/main/java/com/ruoyi/system/log/mapper/InviteLogMapper.java
new file mode 100644
index 0000000..f11655d
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/log/mapper/InviteLogMapper.java
@@ -0,0 +1,21 @@
+package com.ruoyi.system.log.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.muta.common.core.domain.entity.SysUser;
+import com.muta.log.domain.InviteLog;
+import org.apache.ibatis.annotations.Mapper;
+
+
+/**
+ * 【请填写功能名称】Mapper接口
+ *
+ * @author mutaai
+ * @date 2024-04-23
+ */
+
+public interface InviteLogMapper extends BaseMapper {
+
+
+ List selectByFilter(SysUser sysUser);
+}
diff --git a/src/main/java/com/ruoyi/system/log/service/IIntegralLogService.java b/src/main/java/com/ruoyi/system/log/service/IIntegralLogService.java
new file mode 100644
index 0000000..6a34909
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/log/service/IIntegralLogService.java
@@ -0,0 +1,27 @@
+package com.ruoyi.system.log.service;
+
+import java.util.List;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.muta.common.annotation.DataScope;
+import com.muta.common.core.domain.entity.SysUser;
+import com.muta.log.domain.IntegralLog;
+import org.springframework.scheduling.annotation.Async;
+
+/**
+ * 【请填写功能名称】Service接口
+ *
+ * @author mutaai
+ * @date 2024-04-22
+ */
+public interface IIntegralLogService extends IService {
+
+
+
+ List getList(SysUser sysUser);
+
+ void insertLog(IntegralLog integralLog);
+
+ List getByUser();
+
+}
diff --git a/src/main/java/com/ruoyi/system/log/service/IInviteLogService.java b/src/main/java/com/ruoyi/system/log/service/IInviteLogService.java
new file mode 100644
index 0000000..7d2e6bc
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/log/service/IInviteLogService.java
@@ -0,0 +1,40 @@
+package com.ruoyi.system.log.service;
+
+import java.util.List;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.muta.common.core.domain.entity.SysUser;
+import com.muta.log.domain.InviteLog;
+import com.muta.log.domain.dto.InviteLogDTO;
+
+/**
+ * 【请填写功能名称】Service接口
+ *
+ * @author mutaai
+ * @date 2024-04-23
+ */
+public interface IInviteLogService extends IService {
+ /**
+ * 查询【请填写功能名称】
+ *
+ * @param id 【请填写功能名称】主键
+ * @return 【请填写功能名称】
+ */
+
+
+ /**
+ * 查询【请填写功能名称】列表
+ *
+// * @param inviteLog 【请填写功能名称】
+ * @return 【请填写功能名称】集合
+ */
+ public List selectInviteLogListByFilter(SysUser sysUser);
+
+ /**
+ * 新增【请填写功能名称】
+ *
+ * @param inviteLog 【请填写功能名称】
+ * @return 结果
+ */
+ void insert(InviteLogDTO inviteLog);
+}
diff --git a/src/main/java/com/ruoyi/system/log/service/impl/DistributionIntegralServiceImpl.java b/src/main/java/com/ruoyi/system/log/service/impl/DistributionIntegralServiceImpl.java
new file mode 100644
index 0000000..391090d
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/log/service/impl/DistributionIntegralServiceImpl.java
@@ -0,0 +1,56 @@
+package com.ruoyi.system.log.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.muta.common.constant.ConsumerConstants;
+import com.muta.common.constant.OperationConstants;
+import com.muta.common.core.domain.entity.SysUser;
+import com.muta.common.core.domain.entity.UserExtra;
+import com.muta.log.domain.IntegralLog;
+import com.muta.log.mapper.IntegralLogMapper;
+import com.muta.log.service.IIntegralLogService;
+import com.muta.system.mapper.UserExtraMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /24 / 15:43
+ * @Description:
+ */
+@Service
+public class DistributionIntegralServiceImpl extends ServiceImpl implements IIntegralLogService{
+ @Resource
+ private UserExtraMapper userExtraMapper;
+ @Resource
+ private IntegralLogMapper integralLogMapper;
+
+ @Override
+ public List getByUser() {
+ return null;
+ }
+
+ @Override
+ public List getList(SysUser sysUser) {
+ return null;
+ }
+
+ @Override
+ public void insertLog(IntegralLog integralLog) {
+ integralLog.setType(1);
+ integralLog.setOperationType(OperationConstants.DISTRIBUTION);
+ integralLog.setValue(ConsumerConstants.DISTRIBUTION);
+ integralLog.setCreateTime(new Date());
+ integralLogMapper.insert(integralLog);
+ }
+ @Transactional
+ public void insertDisLog(Long id){
+ IntegralLog integralLog = new IntegralLog();
+ userExtraMapper.addIntegralByUserId(100,id);
+ this.insertLog(integralLog);
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/system/log/service/impl/InviteIntegralLogServiceImpl.java b/src/main/java/com/ruoyi/system/log/service/impl/InviteIntegralLogServiceImpl.java
new file mode 100644
index 0000000..423f602
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/log/service/impl/InviteIntegralLogServiceImpl.java
@@ -0,0 +1,45 @@
+package com.ruoyi.system.log.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.muta.common.constant.ConsumerConstants;
+import com.muta.common.constant.OperationConstants;
+import com.muta.common.core.domain.entity.SysUser;
+import com.muta.common.utils.SecurityUtils;
+import com.muta.log.domain.IntegralLog;
+import com.muta.log.mapper.IntegralLogMapper;
+import com.muta.log.service.IIntegralLogService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /08 / 11:04
+ * @Description:
+ */
+@Service
+public class InviteIntegralLogServiceImpl extends ServiceImpl implements IIntegralLogService {
+ @Resource
+ private IntegralLogMapper integralLogMapper;
+
+ @Override
+ public List getByUser() {
+ return null;
+ }
+
+ @Override
+ public List getList(SysUser sysUser) {
+ return null;
+ }
+
+ @Override
+ public void insertLog(IntegralLog integralLog) {
+ integralLog.setType(1);
+ integralLog.setOperationType(OperationConstants.INVITE);
+ integralLog.setValue(ConsumerConstants.INVITE);
+ integralLog.setCreateTime(new Date());
+ integralLogMapper.insert(integralLog);
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/log/service/impl/InviteLogServiceImpl.java b/src/main/java/com/ruoyi/system/log/service/impl/InviteLogServiceImpl.java
new file mode 100644
index 0000000..4bc4a24
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/log/service/impl/InviteLogServiceImpl.java
@@ -0,0 +1,78 @@
+package com.ruoyi.system.log.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+
+import java.util.Date;
+import java.util.List;
+
+import com.muta.common.annotation.DataScope;
+import com.muta.common.constant.ConsumerConstants;
+import com.muta.common.core.domain.entity.SysUser;
+import com.muta.common.utils.SecurityUtils;
+import com.muta.log.domain.InviteLog;
+import com.muta.log.domain.dto.InviteLogDTO;
+import com.muta.log.mapper.InviteLogMapper;
+import com.muta.log.service.IInviteLogService;
+
+import com.muta.system.mapper.SysUserMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+
+/**
+ * 【请填写功能名称】Service业务层处理
+ *
+ * @author mutaai
+ * @date 2024-04-23
+ */
+@Service
+public class InviteLogServiceImpl extends ServiceImpl implements IInviteLogService {
+ @Autowired
+ private InviteLogMapper inviteLogMapper;
+ @Resource
+ private SysUserMapper sysUserMapper;
+
+
+
+ /**
+ * 查询【请填写功能名称】
+ *
+ * @param id 【请填写功能名称】主键
+ * @return 【请填写功能名称】
+ */
+
+
+ /**
+ * 查询【请填写功能名称】列表
+ *
+// * @param inviteLog 【请填写功能名称】
+ * @return 【请填写功能名称】
+ */
+
+ @DataScope(type = "log")
+ @Override
+ public List selectInviteLogListByFilter(SysUser sysUser) {
+ return inviteLogMapper.selectByFilter(sysUser);
+ }
+
+ /**
+ * 新增【请填写功能名称】
+ *
+// * @param inviteLog 【请填写功能名称】
+ * @return 结果
+ */
+ @Override
+ public void insert(InviteLogDTO inviteLogDTO) {
+ InviteLog inviteLog = new InviteLog();
+ inviteLog.setInvitee(inviteLogDTO.getInvitee());
+ inviteLog.setInviter(inviteLogDTO.getInviter());
+ inviteLog.setUserId(inviteLogDTO.getUserId());
+ inviteLog.setInviteCode(inviteLogDTO.getInviteCode());
+ inviteLog.setReward(ConsumerConstants.REGISTER);
+ inviteLog.setCreateTime(new Date());
+ inviteLogMapper.insert(inviteLog);
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/system/log/service/impl/KamilIntegralLogService.java b/src/main/java/com/ruoyi/system/log/service/impl/KamilIntegralLogService.java
new file mode 100644
index 0000000..128f0f0
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/log/service/impl/KamilIntegralLogService.java
@@ -0,0 +1,58 @@
+package com.ruoyi.system.log.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.muta.common.constant.OperationConstants;
+import com.muta.common.core.domain.entity.SysUser;
+import com.muta.common.utils.SecurityUtils;
+import com.muta.log.domain.IntegralLog;
+import com.muta.log.mapper.IntegralLogMapper;
+import com.muta.log.service.IIntegralLogService;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /04 /23 / 14:12
+ * @Description:
+ */
+@Service
+public class KamilIntegralLogService extends ServiceImpl implements IIntegralLogService {
+ @Resource
+ private IntegralLogMapper integralLogMapper;
+ public KamilIntegralLogService() {
+ super();
+ }
+
+ @Override
+ public List getList(SysUser sysUser) {
+ return null;
+ }
+
+ @Override
+ public List getByUser() {
+ return null;
+ }
+
+ @Override
+ public void insertLog(IntegralLog integralLog) {
+ if (integralLog.getType().equals(0)) {
+ // 处理 type 字段为 0 的情况
+ integralLog.setValue(integralLog.getValue()+"积分");
+ } else if (integralLog.getType().equals(1)) {
+ // 处理 type 字段为 1 的情况
+ integralLog.setValue("普通会员"+integralLog.getValue()+"天");
+ } else if (integralLog.getType().equals(2)) {
+ // 处理 type 字段为 2 的情况
+ integralLog.setValue("超级会员"+integralLog.getValue()+"天");
+ }
+ integralLog.setCreateBy(SecurityContextHolder.getContext().getAuthentication().getName());
+ integralLog.setOperationType(OperationConstants.Kamil);
+ integralLog.setCreateTime(new Date());
+ integralLog.setUserId(SecurityUtils.getUserId());
+ integralLogMapper.insert(integralLog);
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/log/service/impl/MessageIntegralLogServiceImpl.java b/src/main/java/com/ruoyi/system/log/service/impl/MessageIntegralLogServiceImpl.java
new file mode 100644
index 0000000..98122c8
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/log/service/impl/MessageIntegralLogServiceImpl.java
@@ -0,0 +1,44 @@
+package com.ruoyi.system.log.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.muta.common.constant.ConsumerConstants;
+import com.muta.common.constant.OperationConstants;
+import com.muta.common.core.domain.entity.SysUser;
+import com.muta.log.domain.IntegralLog;
+import com.muta.log.mapper.IntegralLogMapper;
+import com.muta.log.service.IIntegralLogService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /24 / 12:15
+ * @Description:
+ */
+@Service
+public class MessageIntegralLogServiceImpl extends ServiceImpl implements IIntegralLogService {
+ @Resource
+ private IntegralLogMapper integralLogMapper;
+
+
+ @Override
+ public List getList(SysUser sysUser) {
+ return null;
+ }
+
+ @Override
+ public List getByUser() {
+ return null;
+ }
+
+ @Override
+ public void insertLog(IntegralLog integralLog) {
+ integralLog.setType(1);
+ integralLog.setOperationType(OperationConstants.MESSAGE);
+ integralLog.setCreateTime(new Date());
+ integralLogMapper.insert(integralLog);
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/log/service/impl/RegisterIntegralLogServiceImpl.java b/src/main/java/com/ruoyi/system/log/service/impl/RegisterIntegralLogServiceImpl.java
new file mode 100644
index 0000000..142d8b5
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/log/service/impl/RegisterIntegralLogServiceImpl.java
@@ -0,0 +1,52 @@
+package com.ruoyi.system.log.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.muta.common.annotation.DataScope;
+import com.muta.common.constant.ConsumerConstants;
+import com.muta.common.constant.OperationConstants;
+import com.muta.common.core.domain.entity.SysUser;
+import com.muta.common.utils.SecurityUtils;
+import com.muta.log.domain.IntegralLog;
+import com.muta.log.mapper.IntegralLogMapper;
+import com.muta.log.service.IIntegralLogService;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /04 /22 / 17:03
+ * @Description:注册积分日志插入服务类
+ */
+//默认查询时使用这个类
+@Primary
+@Service
+public class RegisterIntegralLogServiceImpl extends ServiceImpl implements IIntegralLogService {
+ @Resource
+ private IntegralLogMapper integralLogMapper;
+ @DataScope(type = "2")
+ @Override
+ public List getList(SysUser sysUser) {
+ sysUser.setUserId(SecurityUtils.getUserId());
+ return integralLogMapper.selectByFilter(sysUser);
+ }
+
+ @Override
+ public List getByUser() {
+ LambdaQueryWrapper integralLogLambdaQueryWrapper = new LambdaQueryWrapper<>();
+ integralLogLambdaQueryWrapper.orderByDesc(IntegralLog::getCreateTime);
+ return integralLogMapper.selectList(integralLogLambdaQueryWrapper);
+ }
+
+ @Override
+ public void insertLog(IntegralLog integralLog) {
+ integralLog.setType(1);
+ integralLog.setOperationType(OperationConstants.REGISTER);
+ integralLog.setCreateTime(new Date());
+ integralLogMapper.insert(integralLog);
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/log/service/impl/ShopIntegralLogServiceImpl.java b/src/main/java/com/ruoyi/system/log/service/impl/ShopIntegralLogServiceImpl.java
new file mode 100644
index 0000000..74767c7
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/log/service/impl/ShopIntegralLogServiceImpl.java
@@ -0,0 +1,53 @@
+package com.ruoyi.system.log.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.muta.common.constant.OperationConstants;
+import com.muta.common.core.domain.entity.SysUser;
+import com.muta.common.utils.SecurityUtils;
+import com.muta.log.domain.IntegralLog;
+import com.muta.log.mapper.IntegralLogMapper;
+import com.muta.log.service.IIntegralLogService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /06 /07 / 16:22
+ * @Description:
+ */
+@Service
+public class ShopIntegralLogServiceImpl extends ServiceImpl implements IIntegralLogService {
+ @Override
+ public List getByUser() {
+ return null;
+ }
+
+ @Resource
+ private IntegralLogMapper integralLogMapper;
+
+
+
+ @Override
+ public List getList(SysUser sysUser) {
+ return null;
+ }
+
+ @Override
+ public void insertLog(IntegralLog integralLog) {
+ integralLog.setType(1);
+ integralLog.setOperationType(OperationConstants.SHOP);
+ integralLog.setCreateBy(SecurityUtils.getUsername());
+ integralLog.setCreateTime(new Date());
+ integralLog.setUserId(SecurityUtils.getUserId());
+ integralLogMapper.insert(integralLog);
+ }
+ public void insertShop(Integer value){
+ IntegralLog integralLog =IntegralLog.builder()
+ .value(value+"积分")
+ .build();
+ this.insertLog(integralLog);
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/log/service/impl/SigninIntegralLogServiceImpl.java b/src/main/java/com/ruoyi/system/log/service/impl/SigninIntegralLogServiceImpl.java
new file mode 100644
index 0000000..802593a
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/log/service/impl/SigninIntegralLogServiceImpl.java
@@ -0,0 +1,58 @@
+package com.ruoyi.system.log.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+
+import com.muta.common.constant.ConsumerConstants;
+import com.muta.common.constant.OperationConstants;
+import com.muta.common.core.domain.entity.SysUser;
+import com.muta.common.utils.SecurityUtils;
+import com.muta.log.domain.IntegralLog;
+import com.muta.log.mapper.IntegralLogMapper;
+
+import com.muta.log.service.IIntegralLogService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.List;
+
+
+/**
+ * 【请填写功能名称】Service业务层处理
+ * @author Larry
+ * @date 2024 -04 -22
+ * 签到类型消费日志增加
+ */
+@Service
+public class SigninIntegralLogServiceImpl extends ServiceImpl implements IIntegralLogService {
+ @Override
+ public List getByUser() {
+ return null;
+ }
+
+ @Resource
+ private IntegralLogMapper integralLogMapper;
+
+
+
+ @Override
+ public List getList(SysUser sysUser) {
+ return null;
+ }
+
+ @Override
+ public void insertLog(IntegralLog integralLog) {
+ integralLog.setType(1);
+ integralLog.setOperationType(OperationConstants.SIGNIN);
+ integralLog.setCreateBy(SecurityUtils.getUsername());
+ integralLog.setCreateTime(new Date());
+ integralLog.setUserId(SecurityUtils.getUserId());
+ integralLogMapper.insert(integralLog);
+ }
+ public void insertSign(Integer value){
+ IntegralLog integralLog =IntegralLog.builder()
+ .value(value+"积分")
+ .build();
+ this.insertLog(integralLog);
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/pay/config/AliPayConfig.java b/src/main/java/com/ruoyi/system/pay/config/AliPayConfig.java
new file mode 100644
index 0000000..18d264b
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/pay/config/AliPayConfig.java
@@ -0,0 +1,58 @@
+package com.ruoyi.system.pay.config;
+
+import com.alipay.api.AlipayClient;
+import com.alipay.api.DefaultAlipayClient;
+import org.springframework.stereotype.Component;
+
+/**
+ * @ClassName AliPayConfig
+ * @Author 周政
+ * @create 2023/2/7 0007 16:56
+ */
+@Component
+public class AliPayConfig {
+ /**
+ * 网关地址
+ **/
+ public static final String PAY_GATEWAY = "https://openapi.alipay.com/gateway.do";
+ /**
+ * 支付宝 APPID
+ **/
+ public static final String APPID = "2021004141689061";
+ /*
+ * 应用私钥
+ **/
+ public static final String APP_PRI_KEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCG8XWy6d19dF6ZGboB41KSPqtOGHkW3/40To6P+5F0AP7wU+Nl14OxrQxogmAojTgf/tyQs5tt+soRwv17Lfj5WYoFTr7KJPqg38X8AUJrNCqJiwkPhJGeWtB+jmy/30aOQ1MCBuU2KmHEGcYsZAJmtV09ql22HdnZNoXl6Fq3f2Wpfrnq6xyjLWmHuOuZU9rejTh8Syy3xoNWhqWK7OhP8ykXnSZmw3xa1+MLNt6lokuH5ZnLd5V08RrcqvvCuWVAZjENh2JhjvQPirI9a2drPkC1IAqJdlVoCJxSEwwSCMyPSxa5WaWpIDDWP7W4IT/1w8rnNKRfFnmngHTlbjqbAgMBAAECggEAYNlTnAD1EmE+s6sfMNOyI3wO/pHZ9mz0yR3Ie9YV4qgEUQAkKKewwQht62QHF5OjQHNuYfxGBX0FIhJMUuf/1RZKVNzbWcGIj4WLVv6gaMib7vN2oUiIKpsLIImfy2W4AcqX/NBuGZ35ZQEKljmA764jKWrorxhljdvv5b4JvcAIHiIj7C1KvLDyFrfe9zgH2U+6Oi//bnUcbqjnk5ry/x2vaa9txTbISG6KQectWloWWc2r+q//rqBWajT4b1aIQZ7bRZaXGwhNhb9ZzrvsbcP3aZbch4nWGHtLZC97Zt4Z0wTQRePUwgTl5Ql4czjcx+Y8fpYdAQZp4qooL6QBQQKBgQDVgNfFchFUUwZSElW7v6sJTukWPXtiPDR806vjxFNKD9Jb/Sr45qk7JtCFvmzHvjN22QJsMf5dv3ygCHcx88JNyGQGw6QQs1vxRp92IpC3wvGHd2S+wuT4RMrj4j17+aUHK0ZAeNbshO0wv7QudOqr94at9lsVq9j8Hx/jWuU3UwKBgQChzY1Guvup0tJCJwZIY/669LliZIy6k6rfJrbYWV0Jzr5MI1AcGit3kY++C8DBAsehC0KAbz0eM4GlM8zXvWx7EXlVFk2qGohkWW1Wi3bDi+ijT0nAQcEpvxxYzTbblTExvJbE0iIidRFdhEs7WEerAB3Id3Fox9EJDernp9vumQKBgQDDJ9eTenXOr2lqoanOSR/NDV1P3/klTUTpCQ7ozm8XlqjBPwQFqcns8MjQR8TlO72NGEX3oicRiFQhcDuL5HWqZc7QxAn23gvf2p8t++BuqHngSslC+aEUMsWGUinDZelsSSkZC5vhbIvm8ISBpotPj52C7FpLz94ybzzVtCMrUwKBgGjwkOVD1n8hLZ8cAlYnDIoiuK2Y+zDzHwqV6FbPNqlqvj9RU962FmT5MloW80/7RpArZlk4TFJvI3GK9BskTtxOy/ukeICPrtAus9xCnadb8WkhvnqD6wzxVyg9CIxH6d0RLFPA2cSxWq7lY4m8ytacP7TJyvMjTW7q6OSQGPNZAoGAQQ6mmLoq3NM3V7aZI7s8rPIsyrAARK59p944GOAI32Dyo5Puo8sq2n8ZuRLJF800J361m8s/lEvMLBtEzbwN2RBC8KJc/BS/mG2c407hrMLGgbryABd+LdrHekGvd173oeJm/sEY4FEa6ZuCENwVfKgNw2ZKgEjMXXi6e4Pmafk=";
+ /*
+ * 支付宝公钥
+ **/
+ public static final String APP_PUB_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkPr/2sjg6tLpLxGQ0lT8za7wONaeJA/g6bz77+R9rw5LcoRjohHellKBv5fFys/EOK3vq1tOC5zritvv42AC2u9sZjRUg5nUQ9/K7xeOf36OmaGVHmhsKAnJA/PFODvhzdww/sxNi/aBMspPZrNyporPUpuDEMIsApHBmNhhDRONirmHIL2P6nJKOLcVN026RcfF2zEWvzaNSIf3b+cEpxyKHDHEHgTUOydod0eqU0QeDE8s5cKhhNpMkbpnmnHU2ulngoMyqAeJNFSWIYBpTCYFFqIrEKtDZwZuj6XwZVLkmcZ4JYeYyqRPKWUBTsm87d6cslobegd/Gm0Jwbl5twIDAQAB";
+ /**
+ * 商户生成签名
+ **/
+ public static final String SIGN_TYPE = "RSA2";
+ /**
+ * 字符编码
+ **/
+ public static final String CHARSET = "UTF-8";
+ /**
+ * 返回参数
+ **/
+ public static final String FORMAT = "json";
+
+ private volatile static AlipayClient instance = null;
+
+ /**
+ * 单例模式获取,双重检查校验
+ **/
+ public static AlipayClient getInstance() {
+ if (instance == null) {
+ synchronized (AliPayConfig.class) {
+ if (instance == null) {
+ instance = new DefaultAlipayClient(PAY_GATEWAY, APPID, APP_PRI_KEY, FORMAT, CHARSET, APP_PUB_KEY, SIGN_TYPE);
+ }
+ }
+ }
+ return instance;
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/pay/config/OrderQueueConfig.java b/src/main/java/com/ruoyi/system/pay/config/OrderQueueConfig.java
new file mode 100644
index 0000000..692f0e5
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/pay/config/OrderQueueConfig.java
@@ -0,0 +1,67 @@
+package com.ruoyi.system.pay.config;
+
+import org.springframework.amqp.core.Binding;
+import org.springframework.amqp.core.BindingBuilder;
+import org.springframework.amqp.core.DirectExchange;
+import org.springframework.amqp.core.Queue;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Larry
+ * @time: 2024/5/14 15:03
+ * @description: 订单消息队列配置
+ */
+@Configuration
+public class OrderQueueConfig {
+
+ @Bean
+ public Queue orderDelayQueue() {
+ Map config = new HashMap<>();
+ //支付单每30秒检测一次 message在该队列queue的存活时间最大为30秒
+ config.put("x-message-ttl", 30000);
+ //x-dead-letter-exchange参数是设置该队列的死信交换器(DLX)
+ config.put("x-dead-letter-exchange", "orderDeadExchange");
+ //x-dead-letter-routing-key参数是给这个DLX指定路由键
+ config.put("x-dead-letter-routing-key", "order-dead");
+ // 返回QueueA实例
+ return new Queue("order-delay-queue", true, true, false, config);
+ }
+
+
+ @Bean
+ public DirectExchange directExchangeOrderDelay() {
+ return new DirectExchange("directExchangeOrderDelay");
+ }
+
+
+ @Bean
+ public Binding bindingA() {
+ return BindingBuilder
+ .bind(orderDelayQueue())
+ .to(directExchangeOrderDelay())
+ .with("make-order");
+ }
+
+
+ @Bean
+ public Queue orderDeadQueue() {
+ return new Queue("order-dead-queue");
+ }
+
+ @Bean
+ public DirectExchange orderDeadExchange() {
+ return new DirectExchange("orderDeadExchange");
+ }
+
+ @Bean
+ public Binding bindingB() {
+ return BindingBuilder
+ .bind(orderDeadQueue())
+ .to(orderDeadExchange())
+ .with("order-dead");
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/pay/config/PayUrlConfig.java b/src/main/java/com/ruoyi/system/pay/config/PayUrlConfig.java
new file mode 100644
index 0000000..ea8aed1
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/pay/config/PayUrlConfig.java
@@ -0,0 +1,21 @@
+package com.ruoyi.system.pay.config;//package com.muta.pay.config;
+//
+//import lombok.Data;
+//import org.springframework.beans.factory.annotation.Value;
+//import org.springframework.context.annotation.Configuration;
+//
+///**
+// * @ClassName PayUrlConfig
+// * @Author Larry
+// * @create 2024/5/17 17:24
+// */
+//@Configuration
+//@Data
+//public class PayUrlConfig {
+// @Value("${alipay.success_return_url}")
+// private String alipaySuccessReturnUrl;
+//
+// @Value("${alipay.callback_url}")
+// private String callbackUrl;
+//
+//}
diff --git a/src/main/java/com/ruoyi/system/pay/constant/PayConstant.java b/src/main/java/com/ruoyi/system/pay/constant/PayConstant.java
new file mode 100644
index 0000000..ce685b4
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/pay/constant/PayConstant.java
@@ -0,0 +1,15 @@
+package com.ruoyi.system.pay.constant;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /06 /02 / 15:39
+ * @Description:
+ */
+public class PayConstant {
+ public static final Integer SUCCESS = 1;
+ //钱不够 其它
+ public static final Integer FAIL = 2;
+ public static final Integer WAIT = 3;
+ public static final Integer OVERTIME = 4;
+
+}
diff --git a/src/main/java/com/ruoyi/system/pay/domain/OrderEntity.java b/src/main/java/com/ruoyi/system/pay/domain/OrderEntity.java
new file mode 100644
index 0000000..369153f
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/pay/domain/OrderEntity.java
@@ -0,0 +1,55 @@
+package com.ruoyi.system.pay.domain;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * @author 33
+ * @time: 2024/3/7 14:49
+ * @description: 支付单信息
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@TableName("orders")
+public class OrderEntity implements Serializable {
+ /**
+ * 自增的ID
+ */
+ private Long id;
+ /**
+ * 订单编号
+ */
+ private String outTradeNo;
+ /**
+ * 商品id
+ */
+ private Long productId;
+ /**
+ * 创建时间
+ */
+ private Date createTime;
+ /**
+ * 用户id
+ */
+ private Long userId;
+ /**
+ * 支付状态
+ */
+ private Integer payStatus;
+
+// /**
+// * 支付渠道
+// */
+// private String payChannel;
+
+
+}
diff --git a/src/main/java/com/ruoyi/system/pay/domain/dto/PayDTO.java b/src/main/java/com/ruoyi/system/pay/domain/dto/PayDTO.java
new file mode 100644
index 0000000..48aed6a
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/pay/domain/dto/PayDTO.java
@@ -0,0 +1,24 @@
+package com.ruoyi.system.pay.domain.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /25 / 19:36
+ * @Description:
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class PayDTO {
+ private String title;
+ private BigDecimal count;
+ private String payStatus;
+ private String payChannel;
+}
diff --git a/src/main/java/com/ruoyi/system/pay/mapper/OrderMapper.java b/src/main/java/com/ruoyi/system/pay/mapper/OrderMapper.java
new file mode 100644
index 0000000..b319521
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/pay/mapper/OrderMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.system.pay.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.muta.pay.domain.OrderEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /25 / 21:53
+ * @Description:
+ */
+@Mapper
+public interface OrderMapper extends BaseMapper {
+
+// List list(SysUser sysUser);
+
+
+}
diff --git a/src/main/java/com/ruoyi/system/pay/mq/listener/OrderAfterListener.java b/src/main/java/com/ruoyi/system/pay/mq/listener/OrderAfterListener.java
new file mode 100644
index 0000000..f7be60c
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/pay/mq/listener/OrderAfterListener.java
@@ -0,0 +1,56 @@
+package com.ruoyi.system.pay.mq.listener;
+
+import cn.hutool.json.JSONUtil;
+import com.muta.ai.domain.MessageEntity;
+import com.muta.common.utils.SecurityUtils;
+import com.muta.pay.constant.PayConstant;
+import com.muta.pay.domain.OrderEntity;
+import com.muta.pay.service.IOrderService;
+import com.muta.trade.domain.PayLog;
+import com.muta.trade.domain.Product;
+import com.muta.trade.service.IPayLogService;
+import com.muta.trade.service.IProductService;
+import com.rabbitmq.client.Channel;
+import org.apache.catalina.security.SecurityUtil;
+import org.springframework.amqp.rabbit.annotation.RabbitHandler;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.core.Ordered;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /12 / 20:52
+ * @Description:
+ */
+
+public class OrderAfterListener {
+ @Resource
+ private IOrderService orderService;
+ @Resource
+ private IPayLogService payLogService;
+ @Resource
+ private IProductService productService;
+ @RabbitHandler
+ @RabbitListener(queues = "order-delay-queue")
+ public void listenMessage(String message, Channel channel){
+ OrderEntity orderEntity = JSONUtil.toBean(message, OrderEntity.class);
+ if(orderEntity.getPayStatus().equals(PayConstant.WAIT)){
+ Product product = productService.selectProductById(orderEntity.getProductId());
+ PayLog payLog = PayLog
+ .builder()
+ .userId(orderEntity.getUserId())
+ .outTradeNo(orderEntity.getOutTradeNo())
+ .title(product.getTitle())
+ .username(SecurityUtils.getUsername())
+ .payStatus(PayConstant.OVERTIME)
+ .payChannel("支付宝--电脑网站支付")
+ .payAmount(BigDecimal.valueOf(product.getPrice()))
+ .build();
+ payLogService.insertPay(payLog);
+ }
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/pay/mq/sender/OrderDeadTimeSender.java b/src/main/java/com/ruoyi/system/pay/mq/sender/OrderDeadTimeSender.java
new file mode 100644
index 0000000..b0a1ce3
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/pay/mq/sender/OrderDeadTimeSender.java
@@ -0,0 +1,9 @@
+package com.ruoyi.system.pay.mq.sender;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /06 /10 / 17:57
+ * @Description:
+ */
+public class OrderDeadTimeSender {
+}
diff --git a/src/main/java/com/ruoyi/system/pay/service/IAliPayService.java b/src/main/java/com/ruoyi/system/pay/service/IAliPayService.java
new file mode 100644
index 0000000..b0d0362
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/pay/service/IAliPayService.java
@@ -0,0 +1,15 @@
+package com.ruoyi.system.pay.service;
+
+import com.alipay.api.AlipayApiException;
+
+import java.math.BigDecimal;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /25 / 21:08
+ * @Description:
+ */
+public interface IAliPayService {
+ public String genPayOrder(Long productId) throws AlipayApiException;
+ public String queryOrderStatus(String outTradeNo) throws AlipayApiException;
+}
diff --git a/src/main/java/com/ruoyi/system/pay/service/IOrderService.java b/src/main/java/com/ruoyi/system/pay/service/IOrderService.java
new file mode 100644
index 0000000..535b1cf
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/pay/service/IOrderService.java
@@ -0,0 +1,23 @@
+package com.ruoyi.system.pay.service;
+
+import com.muta.pay.domain.OrderEntity;
+import org.aspectj.weaver.ast.Or;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /25 / 21:52
+ * @Description:
+ */
+public interface IOrderService {
+ void PaySuccess(String outTradeNo);
+ //延时任务
+ void PayOverTime(String outTradeNo);
+
+ void GenOrder(String outTradeNo, Long productId);
+
+
+ List list();
+}
diff --git a/src/main/java/com/ruoyi/system/pay/service/impl/AliPayServiceImpl.java b/src/main/java/com/ruoyi/system/pay/service/impl/AliPayServiceImpl.java
new file mode 100644
index 0000000..d622035
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/pay/service/impl/AliPayServiceImpl.java
@@ -0,0 +1,134 @@
+package com.ruoyi.system.pay.service.impl;
+
+import com.alipay.api.AlipayApiException;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.AlipayConstants;
+import com.alipay.api.domain.AlipayTradePagePayModel;
+import com.alipay.api.domain.AlipayTradeQueryModel;
+import com.alipay.api.internal.util.AlipaySignature;
+import com.alipay.api.request.AlipayTradePagePayRequest;
+import com.alipay.api.request.AlipayTradeQueryRequest;
+import com.alipay.api.response.AlipayTradePagePayResponse;
+import com.alipay.api.response.AlipayTradeQueryResponse;
+import com.muta.log.service.IIntegralLogService;
+import com.muta.pay.config.AliPayConfig;
+import com.muta.pay.service.IAliPayService;
+import com.muta.pay.service.IOrderService;
+import com.muta.pay.util.OutTradeNoUtil;
+import com.muta.system.service.IVipService;
+import com.muta.trade.domain.Product;
+import com.muta.trade.service.IProductService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /25 / 17:51
+ * @Description:
+ */
+@Service
+public class AliPayServiceImpl implements IAliPayService {
+ @Resource
+ private IOrderService orderService;
+ @Resource
+ private IIntegralLogService iIntegralLogService;
+ @Resource
+ private IVipService vipService;
+ @Resource
+ private IProductService productService;
+
+ @Override
+ public String genPayOrder(Long productId) throws AlipayApiException {
+ // 初始化SDK
+ AlipayClient alipayClient = AliPayConfig.getInstance();
+ // 构造请求参数以调用接口
+ AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
+ AlipayTradePagePayModel model = new AlipayTradePagePayModel();
+ LocalDateTime now = LocalDateTime.now();
+ // 在当前时间上加上30分钟
+ LocalDateTime futureTime = now.plusMinutes(30);
+ // 定义日期时间格式
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+ // 格式化futureTime为字符串
+ String timeExpire = futureTime.format(formatter);
+ // 假设model是某个对象,它有一个setTimeExpire方法
+ model.setTimeExpire(timeExpire);
+ Product product = productService.getById(productId);
+ // 设置订单标题
+ model.setSubject(product.getTitle());
+ model.setTotalAmount(String.valueOf(product.getPrice()/100));
+ // 设置产品码
+ model.setProductCode("FAST_INSTANT_TRADE_PAY");
+ // 设置PC扫码支付的方式
+ model.setQrPayMode("2");
+ // 设置请求后页面的集成方式
+ model.setIntegrationType("PCWEB");
+// // 设置商户自定义二维码宽度
+// model.setQrcodeWidth(100L);
+ // 设置商户订单号
+ String outTradeNo= OutTradeNoUtil.genOutTrade();
+ model.setOutTradeNo(outTradeNo);
+ System.out.println("xxxxxx");
+ System.out.println(outTradeNo);
+ request.setBizModel(model);
+ request.setNotifyUrl("http://lesong.nas.cpolar.cn/trade/notify");
+ request.setReturnUrl("https://lesong-app.nas.cpolar.cn/shop");
+ //设置并记录初始订单
+// String payChannel = "支付宝-电脑网站支付";
+ orderService.GenOrder(outTradeNo,productId);
+ AlipayTradePagePayResponse response = alipayClient.pageExecute(request, "POST");
+ // 如果需要返回GET请求,请使用
+ // AlipayTradePagePayResponse response = alipayClient.pageExecute(request, "GET");
+ String pageRedirectionData = response.getBody();
+ System.out.println(pageRedirectionData);
+ return pageRedirectionData;
+ }
+
+
+ public String queryOrderStatus(String outTradeNo) throws AlipayApiException {
+ // 初始化SDK
+ AlipayClient alipayClient = AliPayConfig.getInstance();
+
+ // 构造请求参数以调用接口
+ AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
+ AlipayTradeQueryModel model = new AlipayTradeQueryModel();
+
+ // 设置订单支付时传入的商户订单号
+ model.setOutTradeNo(outTradeNo);
+ orderService.PaySuccess(outTradeNo);
+
+ // 设置查询选项
+ List queryOptions = new ArrayList();
+ queryOptions.add("trade_settle_info");
+ model.setQueryOptions(queryOptions);
+
+ request.setBizModel(model);
+ AlipayTradeQueryResponse response = alipayClient.execute(request);
+ System.out.println(response.getBody());
+ if (response.isSuccess()) {
+ System.out.println("调用成功");
+ return "success";
+ } else {
+ System.out.println("调用失败");
+ return "fail";
+ // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
+ // String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
+ // System.out.println(diagnosisUrl);
+ }
+ }
+
+
+
+
+
+
+
+
+
+}
diff --git a/src/main/java/com/ruoyi/system/pay/service/impl/OrderServiceImpl.java b/src/main/java/com/ruoyi/system/pay/service/impl/OrderServiceImpl.java
new file mode 100644
index 0000000..784bf4f
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/pay/service/impl/OrderServiceImpl.java
@@ -0,0 +1,127 @@
+package com.ruoyi.system.pay.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.muta.common.enums.ShopType;
+import com.muta.common.utils.SecurityUtils;
+import com.muta.distribution.service.DistributionService;
+import com.muta.log.service.impl.ShopIntegralLogServiceImpl;
+import com.muta.pay.constant.PayConstant;
+import com.muta.pay.domain.OrderEntity;
+import com.muta.pay.service.IOrderService;
+import com.muta.pay.mapper.OrderMapper;
+import com.muta.system.service.IUserExtraService;
+import com.muta.system.service.IVipService;
+import com.muta.trade.domain.PayLog;
+import com.muta.trade.domain.Product;
+import com.muta.trade.service.IPayLogService;
+import com.muta.trade.service.IProductService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /25 / 21:52
+ * @Description:
+ */
+@Service
+public class OrderServiceImpl implements IOrderService {
+ @Resource
+ private IProductService productService;
+ @Resource
+ private IPayLogService payLogService;
+ @Resource
+ private IVipService vipService;
+ @Resource
+ private ShopIntegralLogServiceImpl shopIntegralLogService;
+ @Resource
+ private IUserExtraService userExtraService;
+ @Override
+ public void PayOverTime(String outTradeNo) {
+ updateStatus(outTradeNo,PayConstant.OVERTIME);
+ }
+
+ @Override
+ @Transactional
+ public void PaySuccess(String outTradeNo) {
+ updateStatus(outTradeNo,PayConstant.SUCCESS);
+ LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>();
+ lambdaQueryWrapper.eq(outTradeNo!=null,OrderEntity::getOutTradeNo,outTradeNo);
+ OrderEntity orderEntity = orderMapper.selectOne(lambdaQueryWrapper);
+ //发货
+ Product product = productService.selectProductById(orderEntity.getProductId());
+ System.err.println("发货"+product);
+
+ deliverGood(product,orderEntity.getUserId());
+ //分销
+ distributionService.benefit(product.getPrice().doubleValue());
+ //生成支付记录
+ PayLog payLog = PayLog.builder()
+ .payTime(new Date())
+ //单位是分
+ .payAmount(BigDecimal.valueOf(product.getPrice()))
+ .payStatus(PayConstant.SUCCESS)
+ .payChannel("支付宝-电脑网站支付")
+ .username(SecurityUtils.getUsername())
+ .userId(orderEntity.getUserId())
+ .title(product.getTitle())
+ .outTradeNo(outTradeNo)
+ .build();
+ payLogService.insertPay(payLog);
+ //修改订单状态
+ updateStatus(outTradeNo,PayConstant.SUCCESS);
+ }
+
+ @Resource
+ private OrderMapper orderMapper;
+ @Resource
+ private DistributionService distributionService;
+ //延时任务
+
+ private void updateStatus(String outTradeNo,Integer status) {
+ LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>();
+ lambdaQueryWrapper.eq(outTradeNo!=null,OrderEntity::getOutTradeNo,outTradeNo);
+ OrderEntity orderEntity = orderMapper.selectOne(lambdaQueryWrapper);
+ if(Objects.equals(orderEntity.getPayStatus(), PayConstant.WAIT)){
+ orderEntity.setPayStatus(status);
+ orderMapper.updateById(orderEntity);
+ }
+ }
+
+
+ @Override
+ public void GenOrder(String outTradeNo,Long productId){
+ OrderEntity order = OrderEntity.builder()
+ .userId(SecurityUtils.getUserId())
+ .outTradeNo(outTradeNo)
+ .productId(productId)
+ .createTime(new Date())
+ .payStatus(PayConstant.WAIT)
+ .build();
+ orderMapper.insert(order);
+ }
+
+
+
+ @Override
+ public List list() {
+ return orderMapper.selectList(null);
+ }
+ private void deliverGood(Product product,Long userId){
+ //如果是积分直购
+ if(product.getType().equals(ShopType.INTEGRAL.getCode())){
+ userExtraService.addIntegral(product.getValue(),userId);
+ shopIntegralLogService.insertShop(product.getValue());
+ }
+ //如果是充值vip
+ else{
+ System.err.println("vip--");
+ vipService.addVipDate(userId,product.getType(),product.getValue());
+ }
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/pay/task/PayTask.java b/src/main/java/com/ruoyi/system/pay/task/PayTask.java
new file mode 100644
index 0000000..6c29222
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/pay/task/PayTask.java
@@ -0,0 +1,28 @@
+package com.ruoyi.system.pay.task;
+import com.muta.pay.domain.OrderEntity;
+import com.muta.pay.service.IOrderService;
+import org.springframework.scheduling.annotation.Scheduled;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+
+/**
+ * @author: Larry
+ * @Date: 2024 /06 /07 / 14:35
+ * @Description:
+ */
+public class PayTask {
+ @Resource
+ private IOrderService orderService;
+ @Scheduled(cron = "0 0 0 1 * ?")
+ public void checkPay() {
+ List orderEntityList = orderService.list();
+ orderEntityList.forEach(
+ orderEntity -> {
+
+ }
+ );
+
+ }
+}
diff --git a/src/main/java/com/ruoyi/system/pay/util/OutTradeNoUtil.java b/src/main/java/com/ruoyi/system/pay/util/OutTradeNoUtil.java
new file mode 100644
index 0000000..8482ccd
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/pay/util/OutTradeNoUtil.java
@@ -0,0 +1,24 @@
+package com.ruoyi.system.pay.util;
+
+import com.muta.common.utils.SecurityUtils;
+import com.muta.common.utils.uuid.UUID;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * @author: Larry
+ * @Date: 2024 /05 /25 / 20:46
+ * @Description: 根据当前时间戳和uuid生成唯一订单号
+ */
+public class OutTradeNoUtil {
+ public static String genOutTrade(){
+ LocalDateTime dateTime = LocalDateTime.now();
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
+ String date = dateTime.format(formatter);
+ System.out.println(date); // 输出格式化后的日期时间字符
+ String uuid = String.valueOf(UUID.fastUUID());
+ return date+uuid;
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/system/payConfig/domain/entity/Alipay.java b/src/main/java/com/ruoyi/system/payConfig/domain/entity/Alipay.java
new file mode 100644
index 0000000..1c8d9ac
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/payConfig/domain/entity/Alipay.java
@@ -0,0 +1,26 @@
+package com.ruoyi.system.payConfig.domain.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class Alipay {
+ private Long id;
+ private String appId;
+ private String keyType;
+ private String privateKey;
+ private String alipayPublicKey;
+ private Long configId;
+
+
+
+}
+
diff --git a/src/main/java/com/ruoyi/system/payConfig/domain/entity/PayConfig.java b/src/main/java/com/ruoyi/system/payConfig/domain/entity/PayConfig.java
new file mode 100644
index 0000000..8b02398
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/payConfig/domain/entity/PayConfig.java
@@ -0,0 +1,34 @@
+package com.ruoyi.system.payConfig.domain.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class PayConfig {
+
+ private Long id;
+ private String channelName;
+ private String channelCode;
+ private String availableChannels;
+ private String status;
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+
+ private String operation;
+ private Integer isDel;
+ private Integer payWay;
+ @TableField(exist = false)
+ private Alipay alipay;
+}
diff --git a/src/main/java/com/ruoyi/system/payConfig/mapper/AlipayMapper.java b/src/main/java/com/ruoyi/system/payConfig/mapper/AlipayMapper.java
new file mode 100644
index 0000000..20ff405
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/payConfig/mapper/AlipayMapper.java
@@ -0,0 +1,14 @@
+package com.ruoyi.system.payConfig.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.muta.payConfig.domain.entity.Alipay;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+
+@Mapper
+public interface AlipayMapper extends BaseMapper {
+
+ @Select("select * from alipay where config_id = #{id}")
+ Alipay getOne(Long id);
+
+}
diff --git a/src/main/java/com/ruoyi/system/payConfig/mapper/PayConfigMapper.java b/src/main/java/com/ruoyi/system/payConfig/mapper/PayConfigMapper.java
new file mode 100644
index 0000000..f7c8d1b
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/payConfig/mapper/PayConfigMapper.java
@@ -0,0 +1,26 @@
+package com.ruoyi.system.payConfig.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.muta.payConfig.domain.entity.PayConfig;
+import org.apache.ibatis.annotations.*;
+
+import java.util.List;
+
+@Mapper
+public interface PayConfigMapper {
+ @Insert("insert into pay_config (channel_name,channel_code, available_channels, status, create_time, update_time, pay_way) values (#{channelName}, #{channelCode}, #{availableChannels}, #{status}, #{createTime}, #{updateTime}, #{payWay})")
+ @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
+ void insertPayConfig(PayConfig payConfig);
+
+ @Update("update pay_config set channel_name = #{channelName}, channel_code = #{channelCode}, available_channels = #{availableChannels}, status = #{status}, create_time = #{createTime}, update_time = #{updateTime}, pay_way = #{payWay} where id = #{id}")
+ void updatePayConfig(PayConfig payConfig);
+
+ @Update("update pay_config set is_del = 1 where id = #{id}")
+ void delete(Long id);
+
+ @Select("select * from pay_config where id = #{id}")
+ PayConfig show(Long id);
+
+ @Select("select * from pay_config where is_del = 0")
+ List list();
+}
diff --git a/src/main/java/com/ruoyi/system/payConfig/service/PayConfigService.java b/src/main/java/com/ruoyi/system/payConfig/service/PayConfigService.java
new file mode 100644
index 0000000..b56edd2
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/payConfig/service/PayConfigService.java
@@ -0,0 +1,23 @@
+package com.ruoyi.system.payConfig.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.muta.payConfig.domain.entity.Alipay;
+import com.muta.payConfig.domain.entity.PayConfig;
+
+import java.util.List;
+
+public interface PayConfigService {
+
+
+ void del(Long id);
+
+ Alipay getInfoByWay(Long id);
+
+ void add(PayConfig payConfig);
+
+ void updatePayConfig(PayConfig payConfig);
+
+ PayConfig getOne(Long id);
+
+ List list();
+}
diff --git a/src/main/java/com/ruoyi/system/payConfig/service/impl/PayConfigServiceImpl.java b/src/main/java/com/ruoyi/system/payConfig/service/impl/PayConfigServiceImpl.java
new file mode 100644
index 0000000..2693045
--- /dev/null
+++ b/src/main/java/com/ruoyi/system/payConfig/service/impl/PayConfigServiceImpl.java
@@ -0,0 +1,72 @@
+package com.ruoyi.system.payConfig.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.muta.payConfig.domain.entity.Alipay;
+import com.muta.payConfig.domain.entity.PayConfig;
+import com.muta.payConfig.mapper.AlipayMapper;
+import com.muta.payConfig.mapper.PayConfigMapper;
+import com.muta.payConfig.service.PayConfigService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+@Service
+@Slf4j
+public class PayConfigServiceImpl implements PayConfigService {
+
+ @Resource
+ private PayConfigMapper payConfigMapper;
+
+ @Resource
+ private AlipayMapper alipayMapper;
+
+ @Override
+ public void del(Long id) {
+ payConfigMapper.delete(id);
+ }
+
+ @Override
+ public Alipay getInfoByWay(Long id) {
+ return alipayMapper.getOne(id);
+ }
+
+ @Override
+ public void add(PayConfig payConfig) {
+
+ payConfigMapper.insertPayConfig(payConfig);
+
+ if (payConfig.getPayWay() == 1) {
+ Alipay alipay = payConfig.getAlipay();
+ alipay.setConfigId(payConfig.getId());
+ payConfig.setAlipay(alipay);
+ log.info("{}", payConfig);
+
+ alipayMapper.insert(payConfig.getAlipay());
+ }
+
+ }
+
+ @Override
+ public void updatePayConfig(PayConfig payConfig) {
+ log.info("{}", payConfig);
+ payConfigMapper.updatePayConfig(payConfig);
+ if (payConfig.getPayWay() == 1) {
+
+ alipayMapper.update(payConfig.getAlipay(), new LambdaQueryWrapper().eq(Alipay::getConfigId, payConfig.getId()));
+ }
+ }
+
+ @Override
+ public PayConfig getOne(Long id) {
+ PayConfig show = payConfigMapper.show(id);
+ return show;
+ }
+
+ @Override
+ public List