feat(genmai): 集成跟卖精灵账号管理系统跟
- 新增卖精灵账号管理功能,支持多账号切换 - 实现账号增删改查接口与前端交互逻辑 -优化打开跟卖精灵流程,增加账号选择界面 - 添加账号权限限制与订阅升级提醒 - 完善后端账号实体类及数据库映射 - 更新系统控制器以支持指定账号启动功能- 调整HTTP请求路径适配新工具模块路由- 升级客户端版本至2.5.3并优化代码结构
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
package com.ruoyi.system.domain;
|
||||
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 跟卖精灵账号实体(数据库持久化)
|
||||
*/
|
||||
public class GenmaiAccount extends BaseEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long id;
|
||||
/** 显示名 */
|
||||
private String name;
|
||||
/** 登录用户名(nickname) */
|
||||
private String username;
|
||||
/** 登录密码(服务端刷新Token用,不对外返回) */
|
||||
private String password;
|
||||
/** 客户端账号用户名(关联client_account.username) */
|
||||
private String clientUsername;
|
||||
/** 访问 Token(跨设备共享) */
|
||||
private String token;
|
||||
/** Token 过期时间(可选) */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date tokenExpireAt;
|
||||
/** 状态 1启用 0停用 */
|
||||
private Integer status;
|
||||
/** 备注 */
|
||||
private String remark;
|
||||
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
public String getName() { return name; }
|
||||
public void setName(String name) { this.name = name; }
|
||||
public String getUsername() { return username; }
|
||||
public void setUsername(String username) { this.username = username; }
|
||||
public String getPassword() { return password; }
|
||||
public void setPassword(String password) { this.password = password; }
|
||||
public String getClientUsername() { return clientUsername; }
|
||||
public void setClientUsername(String clientUsername) { this.clientUsername = clientUsername; }
|
||||
public String getToken() { return token; }
|
||||
public void setToken(String token) { this.token = token; }
|
||||
public Date getTokenExpireAt() { return tokenExpireAt; }
|
||||
public void setTokenExpireAt(Date tokenExpireAt) { this.tokenExpireAt = tokenExpireAt; }
|
||||
public Integer getStatus() { return status; }
|
||||
public void setStatus(Integer status) { this.status = status; }
|
||||
@Override public String getRemark() { return remark; }
|
||||
@Override public void setRemark(String remark) { this.remark = remark; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.ruoyi.system.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import com.ruoyi.system.domain.GenmaiAccount;
|
||||
|
||||
/**
|
||||
* 跟卖精灵账号 Mapper
|
||||
*/
|
||||
public interface GenmaiAccountMapper {
|
||||
GenmaiAccount selectById(Long id);
|
||||
List<GenmaiAccount> selectList(GenmaiAccount query);
|
||||
int insert(GenmaiAccount entity);
|
||||
int update(GenmaiAccount entity);
|
||||
int deleteById(Long id);
|
||||
int deleteByClientUsername(@Param("clientUsername") String clientUsername);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.ruoyi.system.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.ruoyi.system.domain.GenmaiAccount;
|
||||
|
||||
/**
|
||||
* 跟卖精灵账号 Service 接口
|
||||
*/
|
||||
public interface IGenmaiAccountService {
|
||||
/**
|
||||
* 获取所有账号(简化信息,密码置空)
|
||||
*/
|
||||
List<GenmaiAccount> listSimple();
|
||||
|
||||
/**
|
||||
* 获取指定客户端用户的账号列表
|
||||
*/
|
||||
List<GenmaiAccount> listSimple(String clientUsername);
|
||||
|
||||
/**
|
||||
* 保存或更新账号
|
||||
*/
|
||||
Long saveOrUpdate(GenmaiAccount entity);
|
||||
|
||||
/**
|
||||
* 保存或更新账号(带客户端用户名)
|
||||
*/
|
||||
Long saveOrUpdate(GenmaiAccount entity, String clientUsername);
|
||||
|
||||
/**
|
||||
* 删除账号
|
||||
*/
|
||||
void remove(Long id);
|
||||
|
||||
/**
|
||||
* 验证token是否有效(调用跟卖精灵接口)
|
||||
*/
|
||||
boolean validateToken(String token);
|
||||
|
||||
/**
|
||||
* 刷新token(仅在token失效时)
|
||||
*/
|
||||
boolean refreshTokenIfNeeded(Long id);
|
||||
|
||||
/**
|
||||
* 验证账号密码并获取Token(不保存到数据库)
|
||||
*/
|
||||
String validateAndGetToken(String username, String password);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.ruoyi.system.service.impl;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.ruoyi.system.domain.GenmaiAccount;
|
||||
import com.ruoyi.system.domain.ClientAccount;
|
||||
import com.ruoyi.system.mapper.GenmaiAccountMapper;
|
||||
import com.ruoyi.system.mapper.ClientAccountMapper;
|
||||
import com.ruoyi.system.service.IGenmaiAccountService;
|
||||
|
||||
@Service
|
||||
public class GenmaiAccountServiceImpl implements IGenmaiAccountService {
|
||||
|
||||
@Autowired
|
||||
private GenmaiAccountMapper mapper;
|
||||
@Autowired
|
||||
private ClientAccountMapper clientAccountMapper;
|
||||
private final RestTemplate restTemplate = new RestTemplate();
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
private int getAccountLimit(String clientUsername) {
|
||||
ClientAccount client = clientAccountMapper.selectClientAccountByUsername(clientUsername);
|
||||
return "paid".equals(client.getAccountType()) && new Date().before(client.getExpireTime()) ? 3 : 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GenmaiAccount> listSimple() {
|
||||
return listSimple(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GenmaiAccount> listSimple(String clientUsername) {
|
||||
GenmaiAccount query = new GenmaiAccount();
|
||||
query.setClientUsername(clientUsername);
|
||||
List<GenmaiAccount> list = mapper.selectList(query);
|
||||
list.forEach(a -> a.setPassword(null));
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long saveOrUpdate(GenmaiAccount entity) {
|
||||
return saveOrUpdate(entity, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long saveOrUpdate(GenmaiAccount entity, String clientUsername) {
|
||||
entity.setClientUsername(clientUsername);
|
||||
|
||||
if (entity.getId() == null) {
|
||||
int count = mapper.selectList(entity).size();
|
||||
if (count >= getAccountLimit(clientUsername)) {
|
||||
throw new RuntimeException("账号数量已达上限");
|
||||
}
|
||||
mapper.insert(entity);
|
||||
} else {
|
||||
mapper.update(entity);
|
||||
}
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Long id) {
|
||||
mapper.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateToken(String token) {
|
||||
try {
|
||||
HttpEntity<String> entity = new HttpEntity<>(null, null);
|
||||
ResponseEntity<String> response = restTemplate.exchange(
|
||||
"https://www.genmaijl.com/manage/user/balance",
|
||||
HttpMethod.GET, entity, String.class);
|
||||
return objectMapper.readTree(response.getBody()).get("code").asInt() == 0;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean refreshTokenIfNeeded(Long id) {
|
||||
GenmaiAccount account = mapper.selectById(id);
|
||||
if (validateToken(account.getToken())) return true;
|
||||
|
||||
String token = validateAndGetToken(account.getUsername(), account.getPassword());
|
||||
account.setToken(token);
|
||||
account.setTokenExpireAt(new Date(System.currentTimeMillis() + 30L * 24 * 60 * 60 * 1000));
|
||||
mapper.update(account);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String validateAndGetToken(String username, String password) {
|
||||
try {
|
||||
Map<String, String> body = new HashMap<>();
|
||||
body.put("nickname", username);
|
||||
body.put("password", password);
|
||||
ResponseEntity<String> response = restTemplate.exchange(
|
||||
"https://www.genmaijl.com/manage/user/subLogin",
|
||||
HttpMethod.POST, new HttpEntity<>(body), String.class);
|
||||
return objectMapper.readTree(response.getBody()).get("result").asText();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.system.mapper.GenmaiAccountMapper">
|
||||
|
||||
<resultMap id="GenmaiAccountResult" type="com.ruoyi.system.domain.GenmaiAccount">
|
||||
<result property="id" column="id"/>
|
||||
<result property="name" column="name"/>
|
||||
<result property="username" column="username"/>
|
||||
<result property="password" column="password"/>
|
||||
<result property="clientUsername" column="client_username"/>
|
||||
<result property="token" column="token"/>
|
||||
<result property="tokenExpireAt" column="token_expire_at"/>
|
||||
<result property="status" column="status"/>
|
||||
<result property="remark" column="remark"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="Base_Column_List">
|
||||
id, name, username, password, client_username, token, token_expire_at, status, remark, create_by, create_time, update_by, update_time
|
||||
</sql>
|
||||
|
||||
<select id="selectById" parameterType="long" resultMap="GenmaiAccountResult">
|
||||
select <include refid="Base_Column_List"/> from genmai_account where id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="selectList" parameterType="com.ruoyi.system.domain.GenmaiAccount" resultMap="GenmaiAccountResult">
|
||||
select <include refid="Base_Column_List"/> from genmai_account
|
||||
<where>
|
||||
<if test="clientUsername != null and clientUsername != ''"> and client_username = #{clientUsername}</if>
|
||||
<if test="name != null and name != ''"> and name like concat('%', #{name}, '%')</if>
|
||||
<if test="username != null and username != ''"> and username like concat('%', #{username}, '%')</if>
|
||||
<if test="status != null"> and status = #{status}</if>
|
||||
</where>
|
||||
order by create_time desc
|
||||
</select>
|
||||
|
||||
<insert id="insert" parameterType="com.ruoyi.system.domain.GenmaiAccount" useGeneratedKeys="true" keyProperty="id">
|
||||
insert into genmai_account
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="name != null">name,</if>
|
||||
<if test="username != null">username,</if>
|
||||
<if test="password != null">password,</if>
|
||||
<if test="clientUsername != null">client_username,</if>
|
||||
<if test="token != null">token,</if>
|
||||
<if test="tokenExpireAt != null">token_expire_at,</if>
|
||||
<if test="status != null">status,</if>
|
||||
<if test="remark != null">remark,</if>
|
||||
<if test="createBy != null">create_by,</if>
|
||||
create_time
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="name != null">#{name},</if>
|
||||
<if test="username != null">#{username},</if>
|
||||
<if test="password != null">#{password},</if>
|
||||
<if test="clientUsername != null">#{clientUsername},</if>
|
||||
<if test="token != null">#{token},</if>
|
||||
<if test="tokenExpireAt != null">#{tokenExpireAt},</if>
|
||||
<if test="status != null">#{status},</if>
|
||||
<if test="remark != null">#{remark},</if>
|
||||
<if test="createBy != null">#{createBy},</if>
|
||||
sysdate()
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<update id="update" parameterType="com.ruoyi.system.domain.GenmaiAccount">
|
||||
update genmai_account
|
||||
<trim prefix="set" suffixOverrides=",">
|
||||
<if test="name != null">name=#{name},</if>
|
||||
<if test="username != null">username=#{username},</if>
|
||||
<if test="password != null">password=#{password},</if>
|
||||
<if test="clientUsername != null">client_username=#{clientUsername},</if>
|
||||
<if test="token != null">token=#{token},</if>
|
||||
<if test="tokenExpireAt != null">token_expire_at=#{tokenExpireAt},</if>
|
||||
<if test="status != null">status=#{status},</if>
|
||||
<if test="remark != null">remark=#{remark},</if>
|
||||
<if test="updateBy != null">update_by=#{updateBy},</if>
|
||||
update_time = sysdate()
|
||||
</trim>
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<delete id="deleteById" parameterType="long">
|
||||
delete from genmai_account where id = #{id}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteByClientUsername">
|
||||
delete from genmai_account where client_username = #{clientUsername}
|
||||
</delete>
|
||||
|
||||
</mapper>
|
||||
|
||||
Reference in New Issue
Block a user