mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-22 07:03:53 +08:00
Manager web (#237)
* update:增加前端设计图 * 前端代码优化 * update:底部信息纠正 * 增加:flyio * update:去除org.quartz * update:登陆功能 * aliyunTTS常联token * 新增aliyunTTS长期Token方式 * 获取用户信息和已绑设备 * update:验证码,登录,注册 * update:去掉依赖错误代码 --------- Co-authored-by: hrz <1710360675@qq.com> Co-authored-by: CGD <3030332422@qq.com> Co-authored-by: Ken <ulxiping@qq.com>
This commit is contained in:
Executable → Regular
@@ -23,7 +23,6 @@
|
||||
<mybatisplus.version>3.5.5</mybatisplus.version>
|
||||
<hutool.version>5.8.24</hutool.version>
|
||||
<jsoup.version>1.19.1</jsoup.version>
|
||||
<jasypt.version>3.0.5</jasypt.version>
|
||||
<knife4j.version>4.6.0</knife4j.version>
|
||||
<shiro.version>2.0.2</shiro.version>
|
||||
<captcha.version>1.6.2</captcha.version>
|
||||
@@ -67,6 +66,7 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- 验证码工具包 -->
|
||||
<dependency>
|
||||
<groupId>com.github.whvcse</groupId>
|
||||
<artifactId>easy-captcha</artifactId>
|
||||
|
||||
@@ -1,40 +1,40 @@
|
||||
package xiaozhi.common.aspect;
|
||||
|
||||
import xiaozhi.common.exception.ErrorCode;
|
||||
import xiaozhi.common.exception.RenException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Redis切面处理类
|
||||
* Copyright (c) 人人开源 All rights reserved.
|
||||
* Website: https://www.renren.io
|
||||
*/
|
||||
@Slf4j
|
||||
@Aspect
|
||||
@Component
|
||||
public class RedisAspect {
|
||||
/**
|
||||
* 是否开启redis缓存 true开启 false关闭
|
||||
*/
|
||||
@Value("${renren.redis.open}")
|
||||
private boolean open;
|
||||
|
||||
@Around("execution(* xiaozhi.common.redis.RedisUtils.*(..))")
|
||||
public Object around(ProceedingJoinPoint point) throws Throwable {
|
||||
Object result = null;
|
||||
if (open) {
|
||||
try {
|
||||
result = point.proceed();
|
||||
} catch (Exception e) {
|
||||
log.error("redis error", e);
|
||||
throw new RenException(ErrorCode.REDIS_ERROR);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
package xiaozhi.common.aspect;
|
||||
|
||||
import xiaozhi.common.exception.ErrorCode;
|
||||
import xiaozhi.common.exception.RenException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Redis切面处理类
|
||||
* Copyright (c) 人人开源 All rights reserved.
|
||||
* Website: https://www.renren.io
|
||||
*/
|
||||
@Slf4j
|
||||
@Aspect
|
||||
@Component
|
||||
public class RedisAspect {
|
||||
/**
|
||||
* 是否开启redis缓存 true开启 false关闭
|
||||
*/
|
||||
@Value("${renren.redis.open}")
|
||||
private boolean open;
|
||||
|
||||
@Around("execution(* xiaozhi.common.redis.RedisUtils.*(..))")
|
||||
public Object around(ProceedingJoinPoint point) throws Throwable {
|
||||
Object result = null;
|
||||
if (open) {
|
||||
try {
|
||||
result = point.proceed();
|
||||
} catch (Exception e) {
|
||||
log.error("redis error", e);
|
||||
throw new RenException(ErrorCode.REDIS_ERROR);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,4 +40,6 @@ public interface ErrorCode {
|
||||
int PASSWORD_LENGTH_ERROR = 10030;
|
||||
int PASSWORD_WEAK_ERROR = 10031;
|
||||
int DEL_MYSELF_ERROR = 10032;
|
||||
// 验证码错误
|
||||
int VERIFICATION_CODE = 10033;
|
||||
}
|
||||
|
||||
@@ -1,108 +1,108 @@
|
||||
package xiaozhi.common.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 基础服务接口,所有Service接口都要继承
|
||||
* Copyright (c) 人人开源 All rights reserved.
|
||||
* Website: https://www.renren.io
|
||||
*/
|
||||
public interface BaseService<T> {
|
||||
Class<T> currentModelClass();
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 插入一条记录(选择字段,策略插入)
|
||||
* </p>
|
||||
*
|
||||
* @param entity 实体对象
|
||||
*/
|
||||
boolean insert(T entity);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 插入(批量),该方法不支持 Oracle、SQL Server
|
||||
* </p>
|
||||
*
|
||||
* @param entityList 实体对象集合
|
||||
*/
|
||||
boolean insertBatch(Collection<T> entityList);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 插入(批量),该方法不支持 Oracle、SQL Server
|
||||
* </p>
|
||||
*
|
||||
* @param entityList 实体对象集合
|
||||
* @param batchSize 插入批次数量
|
||||
*/
|
||||
boolean insertBatch(Collection<T> entityList, int batchSize);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 根据 ID 选择修改
|
||||
* </p>
|
||||
*
|
||||
* @param entity 实体对象
|
||||
*/
|
||||
boolean updateById(T entity);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 根据 whereEntity 条件,更新记录
|
||||
* </p>
|
||||
*
|
||||
* @param entity 实体对象
|
||||
* @param updateWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}
|
||||
*/
|
||||
boolean update(T entity, Wrapper<T> updateWrapper);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 根据ID 批量更新
|
||||
* </p>
|
||||
*
|
||||
* @param entityList 实体对象集合
|
||||
*/
|
||||
boolean updateBatchById(Collection<T> entityList);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 根据ID 批量更新
|
||||
* </p>
|
||||
*
|
||||
* @param entityList 实体对象集合
|
||||
* @param batchSize 更新批次数量
|
||||
*/
|
||||
boolean updateBatchById(Collection<T> entityList, int batchSize);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 根据 ID 查询
|
||||
* </p>
|
||||
*
|
||||
* @param id 主键ID
|
||||
*/
|
||||
T selectById(Serializable id);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 根据 ID 删除
|
||||
* </p>
|
||||
*
|
||||
* @param id 主键ID
|
||||
*/
|
||||
boolean deleteById(Serializable id);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 删除(根据ID 批量删除)
|
||||
* </p>
|
||||
*
|
||||
* @param idList 主键ID列表
|
||||
*/
|
||||
boolean deleteBatchIds(Collection<? extends Serializable> idList);
|
||||
package xiaozhi.common.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 基础服务接口,所有Service接口都要继承
|
||||
* Copyright (c) 人人开源 All rights reserved.
|
||||
* Website: https://www.renren.io
|
||||
*/
|
||||
public interface BaseService<T> {
|
||||
Class<T> currentModelClass();
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 插入一条记录(选择字段,策略插入)
|
||||
* </p>
|
||||
*
|
||||
* @param entity 实体对象
|
||||
*/
|
||||
boolean insert(T entity);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 插入(批量),该方法不支持 Oracle、SQL Server
|
||||
* </p>
|
||||
*
|
||||
* @param entityList 实体对象集合
|
||||
*/
|
||||
boolean insertBatch(Collection<T> entityList);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 插入(批量),该方法不支持 Oracle、SQL Server
|
||||
* </p>
|
||||
*
|
||||
* @param entityList 实体对象集合
|
||||
* @param batchSize 插入批次数量
|
||||
*/
|
||||
boolean insertBatch(Collection<T> entityList, int batchSize);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 根据 ID 选择修改
|
||||
* </p>
|
||||
*
|
||||
* @param entity 实体对象
|
||||
*/
|
||||
boolean updateById(T entity);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 根据 whereEntity 条件,更新记录
|
||||
* </p>
|
||||
*
|
||||
* @param entity 实体对象
|
||||
* @param updateWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}
|
||||
*/
|
||||
boolean update(T entity, Wrapper<T> updateWrapper);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 根据ID 批量更新
|
||||
* </p>
|
||||
*
|
||||
* @param entityList 实体对象集合
|
||||
*/
|
||||
boolean updateBatchById(Collection<T> entityList);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 根据ID 批量更新
|
||||
* </p>
|
||||
*
|
||||
* @param entityList 实体对象集合
|
||||
* @param batchSize 更新批次数量
|
||||
*/
|
||||
boolean updateBatchById(Collection<T> entityList, int batchSize);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 根据 ID 查询
|
||||
* </p>
|
||||
*
|
||||
* @param id 主键ID
|
||||
*/
|
||||
T selectById(Serializable id);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 根据 ID 删除
|
||||
* </p>
|
||||
*
|
||||
* @param id 主键ID
|
||||
*/
|
||||
boolean deleteById(Serializable id);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 删除(根据ID 批量删除)
|
||||
* </p>
|
||||
*
|
||||
* @param idList 主键ID列表
|
||||
*/
|
||||
boolean deleteBatchIds(Collection<? extends Serializable> idList);
|
||||
}
|
||||
@@ -1,214 +1,214 @@
|
||||
package xiaozhi.common.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.enums.SqlMethod;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
|
||||
import xiaozhi.common.constant.Constant;
|
||||
import xiaozhi.common.page.PageData;
|
||||
import xiaozhi.common.service.BaseService;
|
||||
import xiaozhi.common.utils.ConvertUtils;
|
||||
import org.apache.ibatis.binding.MapperMethod;
|
||||
import org.apache.ibatis.logging.Log;
|
||||
import org.apache.ibatis.logging.LogFactory;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
* 基础服务类,所有Service都要继承
|
||||
* Copyright (c) 人人开源 All rights reserved.
|
||||
* Website: https://www.renren.io
|
||||
*/
|
||||
public abstract class BaseServiceImpl<M extends BaseMapper<T>, T> implements BaseService<T> {
|
||||
@Autowired
|
||||
protected M baseDao;
|
||||
protected Log log = LogFactory.getLog(getClass());
|
||||
|
||||
/**
|
||||
* 获取分页对象
|
||||
*
|
||||
* @param params 分页查询参数
|
||||
* @param defaultOrderField 默认排序字段
|
||||
* @param isAsc 排序方式
|
||||
*/
|
||||
protected IPage<T> getPage(Map<String, Object> params, String defaultOrderField, boolean isAsc) {
|
||||
//分页参数
|
||||
long curPage = 1;
|
||||
long limit = 10;
|
||||
|
||||
if (params.get(Constant.PAGE) != null) {
|
||||
curPage = Long.parseLong((String) params.get(Constant.PAGE));
|
||||
}
|
||||
if (params.get(Constant.LIMIT) != null) {
|
||||
limit = Long.parseLong((String) params.get(Constant.LIMIT));
|
||||
}
|
||||
|
||||
//分页对象
|
||||
Page<T> page = new Page<>(curPage, limit);
|
||||
|
||||
//分页参数
|
||||
params.put(Constant.PAGE, page);
|
||||
|
||||
//排序字段
|
||||
String orderField = (String) params.get(Constant.ORDER_FIELD);
|
||||
String order = (String) params.get(Constant.ORDER);
|
||||
|
||||
//前端字段排序
|
||||
if (StringUtils.isNotBlank(orderField) && StringUtils.isNotBlank(order)) {
|
||||
if (Constant.ASC.equalsIgnoreCase(order)) {
|
||||
return page.addOrder(OrderItem.asc(orderField));
|
||||
} else {
|
||||
return page.addOrder(OrderItem.desc(orderField));
|
||||
}
|
||||
}
|
||||
|
||||
//没有排序字段,则不排序
|
||||
if (StringUtils.isBlank(defaultOrderField)) {
|
||||
return page;
|
||||
}
|
||||
|
||||
//默认排序
|
||||
if (isAsc) {
|
||||
page.addOrder(OrderItem.asc(defaultOrderField));
|
||||
} else {
|
||||
page.addOrder(OrderItem.desc(defaultOrderField));
|
||||
}
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
protected <T> PageData<T> getPageData(List<?> list, long total, Class<T> target) {
|
||||
List<T> targetList = ConvertUtils.sourceToTarget(list, target);
|
||||
|
||||
return new PageData<>(targetList, total);
|
||||
}
|
||||
|
||||
protected <T> PageData<T> getPageData(IPage page, Class<T> target) {
|
||||
return getPageData(page.getRecords(), page.getTotal(), target);
|
||||
}
|
||||
|
||||
protected void paramsToLike(Map<String, Object> params, String... likes) {
|
||||
for (String like : likes) {
|
||||
String val = (String) params.get(like);
|
||||
if (StringUtils.isNotBlank(val)) {
|
||||
params.put(like, "%" + val + "%");
|
||||
} else {
|
||||
params.put(like, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 判断数据库操作是否成功
|
||||
* </p>
|
||||
* <p>
|
||||
* 注意!! 该方法为 Integer 判断,不可传入 int 基本类型
|
||||
* </p>
|
||||
*
|
||||
* @param result 数据库操作返回影响条数
|
||||
* @return boolean
|
||||
*/
|
||||
protected static boolean retBool(Integer result) {
|
||||
return SqlHelper.retBool(result);
|
||||
}
|
||||
|
||||
protected Class<M> currentMapperClass() {
|
||||
return (Class<M>) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseServiceImpl.class, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> currentModelClass() {
|
||||
return (Class<T>) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseServiceImpl.class, 1);
|
||||
}
|
||||
|
||||
protected String getSqlStatement(SqlMethod sqlMethod) {
|
||||
return SqlHelper.getSqlStatement(this.currentMapperClass(), sqlMethod);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean insert(T entity) {
|
||||
return BaseServiceImpl.retBool(baseDao.insert(entity));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean insertBatch(Collection<T> entityList) {
|
||||
return insertBatch(entityList, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量插入
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean insertBatch(Collection<T> entityList, int batchSize) {
|
||||
String sqlStatement = getSqlStatement(SqlMethod.INSERT_ONE);
|
||||
return executeBatch(entityList, batchSize, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity));
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行批量操作
|
||||
*/
|
||||
protected <E> boolean executeBatch(Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) {
|
||||
return SqlHelper.executeBatch(this.currentModelClass(), this.log, list, batchSize, consumer);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean updateById(T entity) {
|
||||
return BaseServiceImpl.retBool(baseDao.updateById(entity));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(T entity, Wrapper<T> updateWrapper) {
|
||||
return BaseServiceImpl.retBool(baseDao.update(entity, updateWrapper));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean updateBatchById(Collection<T> entityList) {
|
||||
return updateBatchById(entityList, 30);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean updateBatchById(Collection<T> entityList, int batchSize) {
|
||||
String sqlStatement = getSqlStatement(SqlMethod.UPDATE_BY_ID);
|
||||
return executeBatch(entityList, batchSize, (sqlSession, entity) -> {
|
||||
MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
|
||||
param.put(Constants.ENTITY, entity);
|
||||
sqlSession.update(sqlStatement, param);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public T selectById(Serializable id) {
|
||||
return baseDao.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteById(Serializable id) {
|
||||
return SqlHelper.retBool(baseDao.deleteById(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteBatchIds(Collection<? extends Serializable> idList) {
|
||||
return SqlHelper.retBool(baseDao.deleteBatchIds(idList));
|
||||
}
|
||||
package xiaozhi.common.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.enums.SqlMethod;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
|
||||
import xiaozhi.common.constant.Constant;
|
||||
import xiaozhi.common.page.PageData;
|
||||
import xiaozhi.common.service.BaseService;
|
||||
import xiaozhi.common.utils.ConvertUtils;
|
||||
import org.apache.ibatis.binding.MapperMethod;
|
||||
import org.apache.ibatis.logging.Log;
|
||||
import org.apache.ibatis.logging.LogFactory;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
* 基础服务类,所有Service都要继承
|
||||
* Copyright (c) 人人开源 All rights reserved.
|
||||
* Website: https://www.renren.io
|
||||
*/
|
||||
public abstract class BaseServiceImpl<M extends BaseMapper<T>, T> implements BaseService<T> {
|
||||
@Autowired
|
||||
protected M baseDao;
|
||||
protected Log log = LogFactory.getLog(getClass());
|
||||
|
||||
/**
|
||||
* 获取分页对象
|
||||
*
|
||||
* @param params 分页查询参数
|
||||
* @param defaultOrderField 默认排序字段
|
||||
* @param isAsc 排序方式
|
||||
*/
|
||||
protected IPage<T> getPage(Map<String, Object> params, String defaultOrderField, boolean isAsc) {
|
||||
//分页参数
|
||||
long curPage = 1;
|
||||
long limit = 10;
|
||||
|
||||
if (params.get(Constant.PAGE) != null) {
|
||||
curPage = Long.parseLong((String) params.get(Constant.PAGE));
|
||||
}
|
||||
if (params.get(Constant.LIMIT) != null) {
|
||||
limit = Long.parseLong((String) params.get(Constant.LIMIT));
|
||||
}
|
||||
|
||||
//分页对象
|
||||
Page<T> page = new Page<>(curPage, limit);
|
||||
|
||||
//分页参数
|
||||
params.put(Constant.PAGE, page);
|
||||
|
||||
//排序字段
|
||||
String orderField = (String) params.get(Constant.ORDER_FIELD);
|
||||
String order = (String) params.get(Constant.ORDER);
|
||||
|
||||
//前端字段排序
|
||||
if (StringUtils.isNotBlank(orderField) && StringUtils.isNotBlank(order)) {
|
||||
if (Constant.ASC.equalsIgnoreCase(order)) {
|
||||
return page.addOrder(OrderItem.asc(orderField));
|
||||
} else {
|
||||
return page.addOrder(OrderItem.desc(orderField));
|
||||
}
|
||||
}
|
||||
|
||||
//没有排序字段,则不排序
|
||||
if (StringUtils.isBlank(defaultOrderField)) {
|
||||
return page;
|
||||
}
|
||||
|
||||
//默认排序
|
||||
if (isAsc) {
|
||||
page.addOrder(OrderItem.asc(defaultOrderField));
|
||||
} else {
|
||||
page.addOrder(OrderItem.desc(defaultOrderField));
|
||||
}
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
protected <T> PageData<T> getPageData(List<?> list, long total, Class<T> target) {
|
||||
List<T> targetList = ConvertUtils.sourceToTarget(list, target);
|
||||
|
||||
return new PageData<>(targetList, total);
|
||||
}
|
||||
|
||||
protected <T> PageData<T> getPageData(IPage page, Class<T> target) {
|
||||
return getPageData(page.getRecords(), page.getTotal(), target);
|
||||
}
|
||||
|
||||
protected void paramsToLike(Map<String, Object> params, String... likes) {
|
||||
for (String like : likes) {
|
||||
String val = (String) params.get(like);
|
||||
if (StringUtils.isNotBlank(val)) {
|
||||
params.put(like, "%" + val + "%");
|
||||
} else {
|
||||
params.put(like, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 判断数据库操作是否成功
|
||||
* </p>
|
||||
* <p>
|
||||
* 注意!! 该方法为 Integer 判断,不可传入 int 基本类型
|
||||
* </p>
|
||||
*
|
||||
* @param result 数据库操作返回影响条数
|
||||
* @return boolean
|
||||
*/
|
||||
protected static boolean retBool(Integer result) {
|
||||
return SqlHelper.retBool(result);
|
||||
}
|
||||
|
||||
protected Class<M> currentMapperClass() {
|
||||
return (Class<M>) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseServiceImpl.class, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> currentModelClass() {
|
||||
return (Class<T>) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseServiceImpl.class, 1);
|
||||
}
|
||||
|
||||
protected String getSqlStatement(SqlMethod sqlMethod) {
|
||||
return SqlHelper.getSqlStatement(this.currentMapperClass(), sqlMethod);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean insert(T entity) {
|
||||
return BaseServiceImpl.retBool(baseDao.insert(entity));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean insertBatch(Collection<T> entityList) {
|
||||
return insertBatch(entityList, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量插入
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean insertBatch(Collection<T> entityList, int batchSize) {
|
||||
String sqlStatement = getSqlStatement(SqlMethod.INSERT_ONE);
|
||||
return executeBatch(entityList, batchSize, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity));
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行批量操作
|
||||
*/
|
||||
protected <E> boolean executeBatch(Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) {
|
||||
return SqlHelper.executeBatch(this.currentModelClass(), this.log, list, batchSize, consumer);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean updateById(T entity) {
|
||||
return BaseServiceImpl.retBool(baseDao.updateById(entity));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(T entity, Wrapper<T> updateWrapper) {
|
||||
return BaseServiceImpl.retBool(baseDao.update(entity, updateWrapper));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean updateBatchById(Collection<T> entityList) {
|
||||
return updateBatchById(entityList, 30);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean updateBatchById(Collection<T> entityList, int batchSize) {
|
||||
String sqlStatement = getSqlStatement(SqlMethod.UPDATE_BY_ID);
|
||||
return executeBatch(entityList, batchSize, (sqlSession, entity) -> {
|
||||
MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
|
||||
param.put(Constants.ENTITY, entity);
|
||||
sqlSession.update(sqlStatement, param);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public T selectById(Serializable id) {
|
||||
return baseDao.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteById(Serializable id) {
|
||||
return SqlHelper.retBool(baseDao.deleteById(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteBatchIds(Collection<? extends Serializable> idList) {
|
||||
return SqlHelper.retBool(baseDao.deleteBatchIds(idList));
|
||||
}
|
||||
}
|
||||
Executable → Regular
@@ -1,59 +1,59 @@
|
||||
package xiaozhi.modules.sys.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import xiaozhi.common.utils.DateUtils;
|
||||
import xiaozhi.common.validator.group.AddGroup;
|
||||
import xiaozhi.common.validator.group.DefaultGroup;
|
||||
import xiaozhi.common.validator.group.UpdateGroup;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Null;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 字典数据
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "字典数据")
|
||||
public class SysDictDataDTO implements Serializable {
|
||||
|
||||
|
||||
@Schema(description = "id")
|
||||
@Null(message = "{id.null}", groups = AddGroup.class)
|
||||
@NotNull(message = "{id.require}", groups = UpdateGroup.class)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "字典类型ID")
|
||||
@NotNull(message = "{sysdict.type.require}", groups = DefaultGroup.class)
|
||||
private Long dictTypeId;
|
||||
|
||||
@Schema(description = "字典标签")
|
||||
@NotBlank(message = "{sysdict.label.require}", groups = DefaultGroup.class)
|
||||
private String dictLabel;
|
||||
|
||||
@Schema(description = "字典值")
|
||||
private String dictValue;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "排序")
|
||||
@Min(value = 0, message = "{sort.number}", groups = DefaultGroup.class)
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
@JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN)
|
||||
private Date createDate;
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
@JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN)
|
||||
private Date updateDate;
|
||||
package xiaozhi.modules.sys.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import xiaozhi.common.utils.DateUtils;
|
||||
import xiaozhi.common.validator.group.AddGroup;
|
||||
import xiaozhi.common.validator.group.DefaultGroup;
|
||||
import xiaozhi.common.validator.group.UpdateGroup;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Null;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 字典数据
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "字典数据")
|
||||
public class SysDictDataDTO implements Serializable {
|
||||
|
||||
|
||||
@Schema(description = "id")
|
||||
@Null(message = "{id.null}", groups = AddGroup.class)
|
||||
@NotNull(message = "{id.require}", groups = UpdateGroup.class)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "字典类型ID")
|
||||
@NotNull(message = "{sysdict.type.require}", groups = DefaultGroup.class)
|
||||
private Long dictTypeId;
|
||||
|
||||
@Schema(description = "字典标签")
|
||||
@NotBlank(message = "{sysdict.label.require}", groups = DefaultGroup.class)
|
||||
private String dictLabel;
|
||||
|
||||
@Schema(description = "字典值")
|
||||
private String dictValue;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "排序")
|
||||
@Min(value = 0, message = "{sort.number}", groups = DefaultGroup.class)
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
@JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN)
|
||||
private Date createDate;
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
@JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN)
|
||||
private Date updateDate;
|
||||
}
|
||||
@@ -1,55 +1,55 @@
|
||||
package xiaozhi.modules.sys.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import xiaozhi.common.utils.DateUtils;
|
||||
import xiaozhi.common.validator.group.AddGroup;
|
||||
import xiaozhi.common.validator.group.DefaultGroup;
|
||||
import xiaozhi.common.validator.group.UpdateGroup;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Null;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 字典类型
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "字典类型")
|
||||
public class SysDictTypeDTO implements Serializable {
|
||||
|
||||
|
||||
@Schema(description = "id")
|
||||
@Null(message = "{id.null}", groups = AddGroup.class)
|
||||
@NotNull(message = "{id.require}", groups = UpdateGroup.class)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "字典类型")
|
||||
@NotBlank(message = "{sysdict.type.require}", groups = DefaultGroup.class)
|
||||
private String dictType;
|
||||
|
||||
@Schema(description = "字典名称")
|
||||
@NotBlank(message = "{sysdict.name.require}", groups = DefaultGroup.class)
|
||||
private String dictName;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "排序")
|
||||
@Min(value = 0, message = "{sort.number}", groups = DefaultGroup.class)
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
@JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN)
|
||||
private Date createDate;
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
private Date updateDate;
|
||||
package xiaozhi.modules.sys.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import xiaozhi.common.utils.DateUtils;
|
||||
import xiaozhi.common.validator.group.AddGroup;
|
||||
import xiaozhi.common.validator.group.DefaultGroup;
|
||||
import xiaozhi.common.validator.group.UpdateGroup;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Null;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 字典类型
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "字典类型")
|
||||
public class SysDictTypeDTO implements Serializable {
|
||||
|
||||
|
||||
@Schema(description = "id")
|
||||
@Null(message = "{id.null}", groups = AddGroup.class)
|
||||
@NotNull(message = "{id.require}", groups = UpdateGroup.class)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "字典类型")
|
||||
@NotBlank(message = "{sysdict.type.require}", groups = DefaultGroup.class)
|
||||
private String dictType;
|
||||
|
||||
@Schema(description = "字典名称")
|
||||
@NotBlank(message = "{sysdict.name.require}", groups = DefaultGroup.class)
|
||||
private String dictName;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "排序")
|
||||
@Min(value = 0, message = "{sort.number}", groups = DefaultGroup.class)
|
||||
private Integer sort;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
@JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN)
|
||||
private Date createDate;
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
private Date updateDate;
|
||||
}
|
||||
@@ -1,52 +1,52 @@
|
||||
package xiaozhi.modules.sys.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import xiaozhi.common.utils.DateUtils;
|
||||
import xiaozhi.common.validator.group.AddGroup;
|
||||
import xiaozhi.common.validator.group.DefaultGroup;
|
||||
import xiaozhi.common.validator.group.UpdateGroup;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Null;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 参数管理
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "参数管理")
|
||||
public class SysParamsDTO implements Serializable {
|
||||
|
||||
|
||||
@Schema(description = "id")
|
||||
@Null(message = "{id.null}", groups = AddGroup.class)
|
||||
@NotNull(message = "{id.require}", groups = UpdateGroup.class)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "参数编码")
|
||||
@NotBlank(message = "{sysparams.paramcode.require}", groups = DefaultGroup.class)
|
||||
private String paramCode;
|
||||
|
||||
@Schema(description = "参数值")
|
||||
@NotBlank(message = "{sysparams.paramvalue.require}", groups = DefaultGroup.class)
|
||||
private String paramValue;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
@JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN)
|
||||
private Date createDate;
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
@JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN)
|
||||
private Date updateDate;
|
||||
|
||||
}
|
||||
package xiaozhi.modules.sys.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import xiaozhi.common.utils.DateUtils;
|
||||
import xiaozhi.common.validator.group.AddGroup;
|
||||
import xiaozhi.common.validator.group.DefaultGroup;
|
||||
import xiaozhi.common.validator.group.UpdateGroup;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Null;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 参数管理
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "参数管理")
|
||||
public class SysParamsDTO implements Serializable {
|
||||
|
||||
|
||||
@Schema(description = "id")
|
||||
@Null(message = "{id.null}", groups = AddGroup.class)
|
||||
@NotNull(message = "{id.require}", groups = UpdateGroup.class)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "参数编码")
|
||||
@NotBlank(message = "{sysparams.paramcode.require}", groups = DefaultGroup.class)
|
||||
private String paramCode;
|
||||
|
||||
@Schema(description = "参数值")
|
||||
@NotBlank(message = "{sysparams.paramvalue.require}", groups = DefaultGroup.class)
|
||||
private String paramValue;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
@JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN)
|
||||
private Date createDate;
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
@JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN)
|
||||
private Date updateDate;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package xiaozhi.modules.sys.service;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* @author zjy
|
||||
* @since 2025-3-7
|
||||
*/
|
||||
public interface CaptchaService {
|
||||
/**
|
||||
* 生成验证码
|
||||
* @param response 响应对象
|
||||
* @param uuid 验证码唯一id
|
||||
*/
|
||||
void create(HttpServletResponse response, String uuid);
|
||||
|
||||
/**
|
||||
* 验证码验证
|
||||
* @param uuid 验证码唯一id
|
||||
* @param code 验证码内容
|
||||
* @return
|
||||
*/
|
||||
void validate(String uuid, String code);
|
||||
}
|
||||
+29
-29
@@ -1,30 +1,30 @@
|
||||
package xiaozhi.modules.sys.service;
|
||||
|
||||
import xiaozhi.common.page.PageData;
|
||||
import xiaozhi.common.service.BaseService;
|
||||
import xiaozhi.modules.sys.dto.SysDictTypeDTO;
|
||||
import xiaozhi.modules.sys.entity.DictType;
|
||||
import xiaozhi.modules.sys.entity.SysDictTypeEntity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 数据字典
|
||||
*/
|
||||
public interface SysDictTypeService extends BaseService<SysDictTypeEntity> {
|
||||
|
||||
PageData<SysDictTypeDTO> page(Map<String, Object> params);
|
||||
|
||||
SysDictTypeDTO get(Long id);
|
||||
|
||||
void save(SysDictTypeDTO dto);
|
||||
|
||||
void update(SysDictTypeDTO dto);
|
||||
|
||||
void delete(Long[] ids);
|
||||
|
||||
List<DictType> getAllList();
|
||||
|
||||
List<DictType> getDictTypeList();
|
||||
package xiaozhi.modules.sys.service;
|
||||
|
||||
import xiaozhi.common.page.PageData;
|
||||
import xiaozhi.common.service.BaseService;
|
||||
import xiaozhi.modules.sys.dto.SysDictTypeDTO;
|
||||
import xiaozhi.modules.sys.entity.DictType;
|
||||
import xiaozhi.modules.sys.entity.SysDictTypeEntity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 数据字典
|
||||
*/
|
||||
public interface SysDictTypeService extends BaseService<SysDictTypeEntity> {
|
||||
|
||||
PageData<SysDictTypeDTO> page(Map<String, Object> params);
|
||||
|
||||
SysDictTypeDTO get(Long id);
|
||||
|
||||
void save(SysDictTypeDTO dto);
|
||||
|
||||
void update(SysDictTypeDTO dto);
|
||||
|
||||
void delete(Long[] ids);
|
||||
|
||||
List<DictType> getAllList();
|
||||
|
||||
List<DictType> getDictTypeList();
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package xiaozhi.modules.sys.service;
|
||||
|
||||
public interface TokenService {
|
||||
/**
|
||||
* 生成token
|
||||
*
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
String createToken(long userId);
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
package xiaozhi.modules.sys.service.impl;
|
||||
|
||||
|
||||
import com.wf.captcha.SpecCaptcha;
|
||||
import com.wf.captcha.base.Captcha;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import xiaozhi.common.exception.ErrorCode;
|
||||
import xiaozhi.common.exception.RenException;
|
||||
import xiaozhi.common.redis.RedisUtils;
|
||||
import xiaozhi.modules.sys.service.CaptchaService;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author zjy
|
||||
* @since 2025-3-7
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Service("captchaService")
|
||||
public class CaptchaServiceImpl implements CaptchaService {
|
||||
private final RedisUtils redisUtils;
|
||||
|
||||
@Value("${captcha.expire}")
|
||||
private Integer captchaExpireTime;
|
||||
|
||||
|
||||
@Override
|
||||
public void create(HttpServletResponse response, String uuid) {
|
||||
response.setContentType("image/png");
|
||||
response.setHeader("Pragma", "No-cache");
|
||||
response.setHeader("Cache-Control", "no-cache");
|
||||
response.setDateHeader("Expires", 0);
|
||||
|
||||
// 创建验证码对象 宽度、高度、字符长度
|
||||
SpecCaptcha captcha = new SpecCaptcha(130, 48, 5);
|
||||
// 默认字符类型
|
||||
captcha.setCharType(Captcha.TYPE_DEFAULT);
|
||||
// 缓存验证码
|
||||
redisUtils.set(uuid,captcha.text(),captchaExpireTime);
|
||||
|
||||
// 输出验证码图片
|
||||
try {
|
||||
captcha.out(response.getOutputStream());
|
||||
} catch (IOException e) {
|
||||
throw new RenException(ErrorCode.VERIFICATION_CODE,"验证码生成错误");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(String uuid, String code) {
|
||||
// 从缓存中获取验证码
|
||||
Object storedCode = redisUtils.get(uuid);
|
||||
//对验证码进行验证过程
|
||||
if(storedCode == null){
|
||||
throw new RenException(ErrorCode.VERIFICATION_CODE,"验证码过期,请从新获取");
|
||||
}else if(code.equalsIgnoreCase(storedCode.toString())){
|
||||
throw new RenException(ErrorCode.VERIFICATION_CODE,"验证码错误");
|
||||
}
|
||||
// 从缓存删除验证码
|
||||
redisUtils.delete(uuid);
|
||||
}
|
||||
}
|
||||
+101
-101
@@ -1,102 +1,102 @@
|
||||
package xiaozhi.modules.sys.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import xiaozhi.common.page.PageData;
|
||||
import xiaozhi.common.service.impl.BaseServiceImpl;
|
||||
import xiaozhi.common.utils.ConvertUtils;
|
||||
import xiaozhi.modules.sys.dao.SysDictDataDao;
|
||||
import xiaozhi.modules.sys.dao.SysDictTypeDao;
|
||||
import xiaozhi.modules.sys.dto.SysDictTypeDTO;
|
||||
import xiaozhi.modules.sys.entity.DictData;
|
||||
import xiaozhi.modules.sys.entity.DictType;
|
||||
import xiaozhi.modules.sys.entity.SysDictTypeEntity;
|
||||
import xiaozhi.modules.sys.service.SysDictTypeService;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 字典类型
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Service
|
||||
public class SysDictTypeServiceImpl extends BaseServiceImpl<SysDictTypeDao, SysDictTypeEntity> implements SysDictTypeService {
|
||||
private final SysDictDataDao sysDictDataDao;
|
||||
|
||||
@Override
|
||||
public PageData<SysDictTypeDTO> page(Map<String, Object> params) {
|
||||
IPage<SysDictTypeEntity> page = baseDao.selectPage(
|
||||
getPage(params, "sort", true),
|
||||
getWrapper(params)
|
||||
);
|
||||
|
||||
return getPageData(page, SysDictTypeDTO.class);
|
||||
}
|
||||
|
||||
private QueryWrapper<SysDictTypeEntity> getWrapper(Map<String, Object> params) {
|
||||
String dictType = (String) params.get("dictType");
|
||||
String dictName = (String) params.get("dictName");
|
||||
|
||||
QueryWrapper<SysDictTypeEntity> wrapper = new QueryWrapper<>();
|
||||
wrapper.like(StringUtils.isNotBlank(dictType), "dict_type", dictType);
|
||||
wrapper.like(StringUtils.isNotBlank(dictName), "dict_name", dictName);
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysDictTypeDTO get(Long id) {
|
||||
SysDictTypeEntity entity = baseDao.selectById(id);
|
||||
|
||||
return ConvertUtils.sourceToTarget(entity, SysDictTypeDTO.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void save(SysDictTypeDTO dto) {
|
||||
SysDictTypeEntity entity = ConvertUtils.sourceToTarget(dto, SysDictTypeEntity.class);
|
||||
|
||||
insert(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void update(SysDictTypeDTO dto) {
|
||||
SysDictTypeEntity entity = ConvertUtils.sourceToTarget(dto, SysDictTypeEntity.class);
|
||||
|
||||
updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delete(Long[] ids) {
|
||||
//删除
|
||||
deleteBatchIds(Arrays.asList(ids));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DictType> getAllList() {
|
||||
List<DictType> typeList = baseDao.getDictTypeList();
|
||||
List<DictData> dataList = sysDictDataDao.getDictDataList();
|
||||
for (DictType type : typeList) {
|
||||
for (DictData data : dataList) {
|
||||
if (type.getId().equals(data.getDictTypeId())) {
|
||||
type.getDataList().add(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
return typeList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DictType> getDictTypeList() {
|
||||
return baseDao.getDictTypeList();
|
||||
}
|
||||
|
||||
package xiaozhi.modules.sys.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import xiaozhi.common.page.PageData;
|
||||
import xiaozhi.common.service.impl.BaseServiceImpl;
|
||||
import xiaozhi.common.utils.ConvertUtils;
|
||||
import xiaozhi.modules.sys.dao.SysDictDataDao;
|
||||
import xiaozhi.modules.sys.dao.SysDictTypeDao;
|
||||
import xiaozhi.modules.sys.dto.SysDictTypeDTO;
|
||||
import xiaozhi.modules.sys.entity.DictData;
|
||||
import xiaozhi.modules.sys.entity.DictType;
|
||||
import xiaozhi.modules.sys.entity.SysDictTypeEntity;
|
||||
import xiaozhi.modules.sys.service.SysDictTypeService;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 字典类型
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Service
|
||||
public class SysDictTypeServiceImpl extends BaseServiceImpl<SysDictTypeDao, SysDictTypeEntity> implements SysDictTypeService {
|
||||
private final SysDictDataDao sysDictDataDao;
|
||||
|
||||
@Override
|
||||
public PageData<SysDictTypeDTO> page(Map<String, Object> params) {
|
||||
IPage<SysDictTypeEntity> page = baseDao.selectPage(
|
||||
getPage(params, "sort", true),
|
||||
getWrapper(params)
|
||||
);
|
||||
|
||||
return getPageData(page, SysDictTypeDTO.class);
|
||||
}
|
||||
|
||||
private QueryWrapper<SysDictTypeEntity> getWrapper(Map<String, Object> params) {
|
||||
String dictType = (String) params.get("dictType");
|
||||
String dictName = (String) params.get("dictName");
|
||||
|
||||
QueryWrapper<SysDictTypeEntity> wrapper = new QueryWrapper<>();
|
||||
wrapper.like(StringUtils.isNotBlank(dictType), "dict_type", dictType);
|
||||
wrapper.like(StringUtils.isNotBlank(dictName), "dict_name", dictName);
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysDictTypeDTO get(Long id) {
|
||||
SysDictTypeEntity entity = baseDao.selectById(id);
|
||||
|
||||
return ConvertUtils.sourceToTarget(entity, SysDictTypeDTO.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void save(SysDictTypeDTO dto) {
|
||||
SysDictTypeEntity entity = ConvertUtils.sourceToTarget(dto, SysDictTypeEntity.class);
|
||||
|
||||
insert(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void update(SysDictTypeDTO dto) {
|
||||
SysDictTypeEntity entity = ConvertUtils.sourceToTarget(dto, SysDictTypeEntity.class);
|
||||
|
||||
updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delete(Long[] ids) {
|
||||
//删除
|
||||
deleteBatchIds(Arrays.asList(ids));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DictType> getAllList() {
|
||||
List<DictType> typeList = baseDao.getDictTypeList();
|
||||
List<DictData> dataList = sysDictDataDao.getDictDataList();
|
||||
for (DictType type : typeList) {
|
||||
for (DictData data : dataList) {
|
||||
if (type.getId().equals(data.getDictTypeId())) {
|
||||
type.getDataList().add(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
return typeList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DictType> getDictTypeList() {
|
||||
return baseDao.getDictTypeList();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package xiaozhi.modules.sys.service.impl;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import xiaozhi.common.redis.RedisUtils;
|
||||
import xiaozhi.modules.security.oauth2.TokenGenerator;
|
||||
import xiaozhi.modules.sys.service.TokenService;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Service
|
||||
public class TokenServiceImpl implements TokenService {
|
||||
private final RedisUtils redisUtils;
|
||||
/**
|
||||
* 3小时无操作过期
|
||||
*/
|
||||
private final static int EXPIRE = 60 * 60 * 3;
|
||||
|
||||
@Override
|
||||
public String createToken(long userId) {
|
||||
//生成一个token
|
||||
String token = TokenGenerator.generateValue();
|
||||
|
||||
//当前时间
|
||||
Date now = new Date();
|
||||
//过期时间
|
||||
Date expireTime = new Date(now.getTime() + EXPIRE * 1000);
|
||||
return token;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +1,52 @@
|
||||
knife4j:
|
||||
production: false
|
||||
enable: true
|
||||
basic:
|
||||
enable: false
|
||||
username: renren
|
||||
password: 2ZABCDEUgF
|
||||
setting:
|
||||
enableFooter: false
|
||||
jasypt:
|
||||
encryptor:
|
||||
password: P9Hx718z8L
|
||||
spring:
|
||||
datasource:
|
||||
druid:
|
||||
#MySQL
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost:3306/xiaozhi_esp32_server?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
|
||||
username: root
|
||||
password: 123456
|
||||
initial-size: 10
|
||||
max-active: 100
|
||||
min-idle: 10
|
||||
max-wait: 6000
|
||||
pool-prepared-statements: true
|
||||
max-pool-prepared-statement-per-connection-size: 20
|
||||
time-between-eviction-runs-millis: 60000
|
||||
min-evictable-idle-time-millis: 300000
|
||||
test-while-idle: true
|
||||
test-on-borrow: false
|
||||
test-on-return: false
|
||||
stat-view-servlet:
|
||||
enabled: true
|
||||
url-pattern: /druid/*
|
||||
login-username: admin
|
||||
login-password: D7Xj810i1C
|
||||
filter:
|
||||
stat:
|
||||
log-slow-sql: true
|
||||
slow-sql-millis: 1000
|
||||
merge-sql: false
|
||||
wall:
|
||||
config:
|
||||
multi-statement-allow: true
|
||||
|
||||
logging:
|
||||
level:
|
||||
org.flowable.engine.impl.persistence.entity.*: debug
|
||||
org.flowable.task.service.impl.persistence.entity.*: debug
|
||||
knife4j:
|
||||
production: false
|
||||
enable: true
|
||||
basic:
|
||||
enable: false
|
||||
username: renren
|
||||
password: 2ZABCDEUgF
|
||||
setting:
|
||||
enableFooter: false
|
||||
jasypt:
|
||||
encryptor:
|
||||
password: P9Hx718z8L
|
||||
spring:
|
||||
datasource:
|
||||
druid:
|
||||
#MySQL
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://192.168.110.130:3306/xiaozhi_esp32_server?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
|
||||
username: root
|
||||
password: 123456
|
||||
initial-size: 10
|
||||
max-active: 100
|
||||
min-idle: 10
|
||||
max-wait: 6000
|
||||
pool-prepared-statements: true
|
||||
max-pool-prepared-statement-per-connection-size: 20
|
||||
time-between-eviction-runs-millis: 60000
|
||||
min-evictable-idle-time-millis: 300000
|
||||
test-while-idle: true
|
||||
test-on-borrow: false
|
||||
test-on-return: false
|
||||
stat-view-servlet:
|
||||
enabled: true
|
||||
url-pattern: /druid/*
|
||||
login-username: admin
|
||||
login-password: D7Xj810i1C
|
||||
filter:
|
||||
stat:
|
||||
log-slow-sql: true
|
||||
slow-sql-millis: 1000
|
||||
merge-sql: false
|
||||
wall:
|
||||
config:
|
||||
multi-statement-allow: true
|
||||
|
||||
logging:
|
||||
level:
|
||||
org.flowable.engine.impl.persistence.entity.*: debug
|
||||
org.flowable.task.service.impl.persistence.entity.*: debug
|
||||
# 登录验证码过期时间(秒)
|
||||
captcha:
|
||||
expire: 300
|
||||
@@ -1,50 +1,50 @@
|
||||
<?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="xiaozhi.modules.sys.dao.SysUserDao">
|
||||
|
||||
<select id="getList" resultType="xiaozhi.modules.sys.entity.SysUserEntity">
|
||||
select t1.*, (select t2.name from sys_dept t2 where t2.id=t1.dept_id) deptName
|
||||
from sys_user t1 where t1.super_admin = 0
|
||||
<if test="username != null and username.trim() != ''">
|
||||
and t1.username like #{username}
|
||||
</if>
|
||||
<if test="deptId != null and deptId.trim() != ''">
|
||||
and t1.dept_id = #{deptId}
|
||||
</if>
|
||||
<if test="gender != null and gender.trim() != ''">
|
||||
and t1.gender = #{gender}
|
||||
</if>
|
||||
<if test="deptIdList != null">
|
||||
and t1.dept_id in
|
||||
<foreach item="id" collection="deptIdList" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="getById" resultType="xiaozhi.modules.sys.entity.SysUserEntity">
|
||||
select t1.*, (select t2.name from sys_dept t2 where t2.id=t1.dept_id) deptName from sys_user t1
|
||||
where t1.id = #{value}
|
||||
</select>
|
||||
|
||||
<select id="getByUsername" resultType="xiaozhi.modules.sys.entity.SysUserEntity">
|
||||
select * from sys_user where username = #{value}
|
||||
</select>
|
||||
|
||||
<update id="updatePassword">
|
||||
update sys_user set password = #{newPassword} where id = #{id}
|
||||
</update>
|
||||
|
||||
<select id="getCountByDeptId" resultType="int">
|
||||
select count(*) from sys_user where dept_id = #{value}
|
||||
</select>
|
||||
|
||||
<select id="getUserIdListByDeptId" resultType="Long">
|
||||
select id from sys_user where dept_id in
|
||||
<foreach item="deptId" collection="list" open="(" separator="," close=")">
|
||||
#{deptId}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<?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="xiaozhi.modules.sys.dao.SysUserDao">
|
||||
|
||||
<select id="getList" resultType="xiaozhi.modules.sys.entity.SysUserEntity">
|
||||
select t1.*, (select t2.name from sys_dept t2 where t2.id=t1.dept_id) deptName
|
||||
from sys_user t1 where t1.super_admin = 0
|
||||
<if test="username != null and username.trim() != ''">
|
||||
and t1.username like #{username}
|
||||
</if>
|
||||
<if test="deptId != null and deptId.trim() != ''">
|
||||
and t1.dept_id = #{deptId}
|
||||
</if>
|
||||
<if test="gender != null and gender.trim() != ''">
|
||||
and t1.gender = #{gender}
|
||||
</if>
|
||||
<if test="deptIdList != null">
|
||||
and t1.dept_id in
|
||||
<foreach item="id" collection="deptIdList" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="getById" resultType="xiaozhi.modules.sys.entity.SysUserEntity">
|
||||
select t1.*, (select t2.name from sys_dept t2 where t2.id=t1.dept_id) deptName from sys_user t1
|
||||
where t1.id = #{value}
|
||||
</select>
|
||||
|
||||
<select id="getByUsername" resultType="xiaozhi.modules.sys.entity.SysUserEntity">
|
||||
select * from sys_user where username = #{value}
|
||||
</select>
|
||||
|
||||
<update id="updatePassword">
|
||||
update sys_user set password = #{newPassword} where id = #{id}
|
||||
</update>
|
||||
|
||||
<select id="getCountByDeptId" resultType="int">
|
||||
select count(*) from sys_user where dept_id = #{value}
|
||||
</select>
|
||||
|
||||
<select id="getUserIdListByDeptId" resultType="Long">
|
||||
select id from sys_user where dept_id in
|
||||
<foreach item="deptId" collection="list" open="(" separator="," close=")">
|
||||
#{deptId}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -1,25 +0,0 @@
|
||||
package xiaozhi;
|
||||
|
||||
import org.jasypt.encryption.StringEncryptor;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* 单元测试
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
public class DbEncTest {
|
||||
|
||||
@Autowired
|
||||
StringEncryptor stringEncryptor;
|
||||
|
||||
@Test
|
||||
public void jiami() {
|
||||
System.out.println("username:" + stringEncryptor.encrypt("07e43e8d669fb946e31ccd4ef5f32c9f2287619c79b766a5985d2c99ad7b7c7e"));
|
||||
System.out.println("password:" + stringEncryptor.encrypt("042e94093fd2c2765ea45cf13ddbfd38e93026df4b6d5e4206ea5ac90956d63ab73e8b82c6daf7829f9aea7e27e1db5bb0a90944c4c4985af44db0ef49c46d6ad6"));
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package xiaozhi;
|
||||
|
||||
import xiaozhi.common.redis.RedisUtils;
|
||||
import xiaozhi.modules.sys.entity.SysUserEntity;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
public class RedisTest {
|
||||
@Resource
|
||||
private RedisUtils redisUtils;
|
||||
|
||||
@Test
|
||||
public void contextLoads() {
|
||||
SysUserEntity user = new SysUserEntity();
|
||||
user.setEmail("123456@qq.com");
|
||||
redisUtils.set("user", user);
|
||||
|
||||
System.out.println(ToStringBuilder.reflectionToString(redisUtils.get("user")));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package xiaozhi.service;
|
||||
|
||||
import xiaozhi.modules.sys.dao.SysUserDao;
|
||||
import xiaozhi.modules.sys.entity.SysUserEntity;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 测试多数据源
|
||||
*/
|
||||
@Service
|
||||
public class DynamicDataSourceTestService {
|
||||
@Resource
|
||||
private SysUserDao sysUserDao;
|
||||
|
||||
//@Transactional
|
||||
public void updateUser(Long id) {
|
||||
SysUserEntity user = new SysUserEntity();
|
||||
user.setId(id);
|
||||
user.setMobile("13500000000");
|
||||
//sysUserDao.updateById(user);
|
||||
System.out.println(sysUserDao.selectById(id));
|
||||
}
|
||||
}
|
||||
Generated
+1074
-307
File diff suppressed because it is too large
Load Diff
@@ -7,11 +7,13 @@
|
||||
"build": "vue-cli-service build"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.8.1",
|
||||
"element-ui": "^2.15.14",
|
||||
"flyio": "^0.6.14",
|
||||
"normalize.css": "^8.0.1",
|
||||
"vue": "^2.6.14",
|
||||
"vue-router": "^3.5.1",
|
||||
"vue-axios": "^3.5.2",
|
||||
"vue-router": "^3.6.5",
|
||||
"vuex": "^3.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// 引入各个模块的请求
|
||||
import user from './module/user.js'
|
||||
|
||||
/**
|
||||
* 接口地址
|
||||
* 在开发阶段,如果地址写的是相对路径,请与vue.config.js的devServer配置相结合,方便跨域请求
|
||||
@@ -11,12 +12,13 @@ const DEV_API_SERVICE = 'https://apifoxmock.com/m1/5931378-5618560-default'
|
||||
* 根据开发环境返回接口url
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getServiceUrl () {
|
||||
return DEV_API_SERVICE
|
||||
export function getServiceUrl() {
|
||||
return DEV_API_SERVICE
|
||||
}
|
||||
|
||||
|
||||
/** request服务封装 */
|
||||
export default {
|
||||
getServiceUrl,
|
||||
user
|
||||
getServiceUrl,
|
||||
user,
|
||||
}
|
||||
|
||||
@@ -16,5 +16,31 @@ export default {
|
||||
this.login(loginForm, callback)
|
||||
})
|
||||
}).send()
|
||||
}
|
||||
},
|
||||
// 获取用户信息
|
||||
getUserInfo(callback) {
|
||||
RequestService.sendRequest().url(`${getServiceUrl()}/api/v1/user/info`).method('GET')
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime()
|
||||
callback(res)
|
||||
})
|
||||
.fail(() => {
|
||||
RequestService.reAjaxFun(() => {
|
||||
this.getUserInfo()
|
||||
})
|
||||
}).send()
|
||||
},
|
||||
// 获取设备信息
|
||||
getHomeList(callback) {
|
||||
RequestService.sendRequest().url(`${getServiceUrl()}/api/v1/user/device/bind`).method('GET')
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime()
|
||||
callback(res)
|
||||
})
|
||||
.fail(() => {
|
||||
RequestService.reAjaxFun(() => {
|
||||
this.getUserInfo()
|
||||
})
|
||||
}).send()
|
||||
},
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<el-container style="height: 100%;">
|
||||
<el-header class="header">
|
||||
<div style="display: flex;justify-content: space-between;">
|
||||
<div style="display: flex;align-items: center;gap: 8px;">
|
||||
<div style="display: flex;align-items: center;gap: 8px;margin-top: 10px;">
|
||||
<img src="@/assets/xiaozhi-logo.png" alt="" style="width: 45px;height: 45px;" />
|
||||
<img src="@/assets/xiaozhi-ai.png" alt="" style="width: 70px;height: 13px;" />
|
||||
<div class="equipment-management" @click="settingDevice=false">
|
||||
@@ -19,7 +19,7 @@
|
||||
<img src="@/assets/home/close.png" alt="" style="width: 6px;height: 6px;" />
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex;align-items: center;gap: 8px;">
|
||||
<div style="display: flex;align-items: center;gap: 8px;margin-top: 10px">
|
||||
<div class="serach-box">
|
||||
<el-input placeholder="输入名称搜索.." v-model="serach" style="border: none; background: transparent;" />
|
||||
<img src="@/assets/home/search.png" alt=""
|
||||
@@ -27,7 +27,8 @@
|
||||
</div>
|
||||
<img src="@/assets/home/avatar.png" alt="" style="width: 21px;height: 21px;" />
|
||||
<div class="user-info">
|
||||
158 3632 4642</div>
|
||||
{{ userInfo.mobile }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-header>
|
||||
@@ -56,10 +57,11 @@
|
||||
</div>
|
||||
<div
|
||||
style="display: flex;flex-wrap: wrap;margin-top: 15px;gap: 15px;justify-content: space-between;box-sizing: border-box;">
|
||||
<div class="device-item" v-for="(item,index) in 10" :key="index">
|
||||
<div class="device-item" v-for="(item,index) in deviceList" :key="index">
|
||||
<div style="display: flex;justify-content: space-between;">
|
||||
<div style="font-weight: 700;font-size: 18px;text-align: left;color: #3d4566;">
|
||||
CC:ba:97:11:a6:ac
|
||||
<!-- CC:ba:97:11:a6:ac-->
|
||||
{{item.list[0]?.mac_address}}
|
||||
</div>
|
||||
<div>
|
||||
<img src="@/assets/home/delete.png" alt=""
|
||||
@@ -68,7 +70,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="device-name">
|
||||
设备型号:esp32-s3-touch-amoled-1.8
|
||||
设备型号:{{item.list[0]?.device_type}}
|
||||
</div>
|
||||
<div style="display: flex;gap: 8px;align-items: center;">
|
||||
<div class="settings-btn" @click="clickSettingDevice">
|
||||
@@ -77,12 +79,12 @@
|
||||
声纹识别</div>
|
||||
<div class="settings-btn">
|
||||
历史对话</div>
|
||||
<el-switch v-model="switchValue" inactive-text="OTA升级:" :width="32"
|
||||
<el-switch :value="item.list[0]?.ota_upgrade && true || false" inactive-text="OTA升级:" :width="32"
|
||||
style="margin-left: auto;" />
|
||||
</div>
|
||||
<div class="version-info">
|
||||
<div>最近对话:6天前</div>
|
||||
<div>APP版本:1.1.0</div>
|
||||
<div>最近对话:{{item.list[0]?.recent_chat_time}}</div>
|
||||
<div>APP版本:{{item.list[0]?.app_version}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -185,7 +187,8 @@
|
||||
</div>
|
||||
<div
|
||||
style="font-size: 12px;font-weight: 400;margin-top: auto;padding-top: 30px;color: #979db1;">
|
||||
©2025 xiaozhi-esp32-server</div>
|
||||
©2025 xiaozhi-esp32-server
|
||||
</div>
|
||||
</el-main>
|
||||
</el-container>
|
||||
<el-dialog :visible.sync="addDeviceDialogVisible" width="400px" center>
|
||||
@@ -220,6 +223,8 @@
|
||||
<script>
|
||||
// @ is an alias to /src
|
||||
|
||||
import Api from '@/apis/api';
|
||||
|
||||
export default {
|
||||
name: 'home',
|
||||
data() {
|
||||
@@ -242,8 +247,12 @@ export default {
|
||||
}, {
|
||||
value: '选项2',
|
||||
label: '双皮奶'
|
||||
}]
|
||||
}
|
||||
}],
|
||||
userInfo: {
|
||||
mobile: '' // 初始化用户信息
|
||||
},
|
||||
deviceList:[]
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
showAddDialog() {
|
||||
@@ -251,10 +260,28 @@ export default {
|
||||
},
|
||||
clickSettingDevice() {
|
||||
this.settingDevice = true
|
||||
},
|
||||
// 获取用户信息
|
||||
fetchUserInfo() {
|
||||
Api.user.getUserInfo(({data}) => {
|
||||
this.userInfo = data.data
|
||||
});
|
||||
},
|
||||
// 获取已绑设备
|
||||
getList(){
|
||||
Api.user.getHomeList(({data})=>{
|
||||
console.log(data.data)
|
||||
this.deviceList = data.data
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchUserInfo(); // 组件加载时获取用户信息
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.welcome {
|
||||
min-width: 900px;
|
||||
@@ -464,7 +491,7 @@ export default {
|
||||
}
|
||||
}
|
||||
.device-item {
|
||||
width: 350px;
|
||||
width: 345px;
|
||||
border-radius: 15px;
|
||||
background: #fafcfe;
|
||||
padding: 22px;
|
||||
@@ -507,6 +534,7 @@ audio::-webkit-media-controls-panel {
|
||||
line-height: 34px;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
}
|
||||
.save-btn {
|
||||
border-radius: 23px;
|
||||
|
||||
@@ -305,8 +305,11 @@ TTS:
|
||||
type: aliyun
|
||||
output_file: tmp/
|
||||
appkey: 你的阿里云智能语音交互服务项目Appkey
|
||||
token: 你的阿里云智能语音交互服务AccessToken
|
||||
token: 你的阿里云智能语音交互服务AccessToken,临时的24小时,要长期用下方的access_key_id,access_key_secret
|
||||
voice: xiaoyun
|
||||
access_key_id: 你的阿里云账号access_key_id
|
||||
access_key_secret: 你的阿里云账号access_key_secret
|
||||
|
||||
# 以下可不用设置,使用默认设置
|
||||
# format: wav
|
||||
# sample_rate: 16000
|
||||
|
||||
@@ -1,19 +1,94 @@
|
||||
import os
|
||||
import uuid
|
||||
import json
|
||||
import hmac
|
||||
import hashlib
|
||||
import base64
|
||||
import requests
|
||||
from datetime import datetime
|
||||
from core.providers.tts.base import TTSProviderBase
|
||||
|
||||
import http.client
|
||||
import urllib.parse
|
||||
import time
|
||||
import uuid
|
||||
from urllib import parse
|
||||
class AccessToken:
|
||||
@staticmethod
|
||||
def _encode_text(text):
|
||||
encoded_text = parse.quote_plus(text)
|
||||
return encoded_text.replace('+', '%20').replace('*', '%2A').replace('%7E', '~')
|
||||
|
||||
@staticmethod
|
||||
def _encode_dict(dic):
|
||||
keys = dic.keys()
|
||||
dic_sorted = [(key, dic[key]) for key in sorted(keys)]
|
||||
encoded_text = parse.urlencode(dic_sorted)
|
||||
return encoded_text.replace('+', '%20').replace('*', '%2A').replace('%7E', '~')
|
||||
|
||||
@staticmethod
|
||||
def create_token(access_key_id, access_key_secret):
|
||||
parameters = {'AccessKeyId': access_key_id,
|
||||
'Action': 'CreateToken',
|
||||
'Format': 'JSON',
|
||||
'RegionId': 'cn-shanghai',
|
||||
'SignatureMethod': 'HMAC-SHA1',
|
||||
'SignatureNonce': str(uuid.uuid1()),
|
||||
'SignatureVersion': '1.0',
|
||||
'Timestamp': time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
|
||||
'Version': '2019-02-28'}
|
||||
# 构造规范化的请求字符串
|
||||
query_string = AccessToken._encode_dict(parameters)
|
||||
print('规范化的请求字符串: %s' % query_string)
|
||||
# 构造待签名字符串
|
||||
string_to_sign = 'GET' + '&' + AccessToken._encode_text('/') + '&' + AccessToken._encode_text(query_string)
|
||||
print('待签名的字符串: %s' % string_to_sign)
|
||||
# 计算签名
|
||||
secreted_string = hmac.new(bytes(access_key_secret + '&', encoding='utf-8'),
|
||||
bytes(string_to_sign, encoding='utf-8'),
|
||||
hashlib.sha1).digest()
|
||||
signature = base64.b64encode(secreted_string)
|
||||
print('签名: %s' % signature)
|
||||
# 进行URL编码
|
||||
signature = AccessToken._encode_text(signature)
|
||||
print('URL编码后的签名: %s' % signature)
|
||||
# 调用服务
|
||||
full_url = 'http://nls-meta.cn-shanghai.aliyuncs.com/?Signature=%s&%s' % (signature, query_string)
|
||||
print('url: %s' % full_url)
|
||||
# 提交HTTP GET请求
|
||||
response = requests.get(full_url)
|
||||
if response.ok:
|
||||
root_obj = response.json()
|
||||
key = 'Token'
|
||||
if key in root_obj:
|
||||
token = root_obj[key]['Id']
|
||||
expire_time = root_obj[key]['ExpireTime']
|
||||
return token, expire_time
|
||||
print(response.text)
|
||||
return None, None
|
||||
|
||||
|
||||
class TTSProvider(TTSProviderBase):
|
||||
|
||||
|
||||
def __init__(self, config, delete_audio_file):
|
||||
super().__init__(config, delete_audio_file)
|
||||
|
||||
# 新增空值判断逻辑
|
||||
access_key_id = config.get("access_key_id")
|
||||
access_key_secret = config.get("access_key_secret")
|
||||
if access_key_id and access_key_secret:
|
||||
# 使用密钥对生成临时token
|
||||
token, expire_time = AccessToken.create_token(access_key_id, access_key_secret)
|
||||
else:
|
||||
# 直接使用预生成的长期token
|
||||
token = config.get("token")
|
||||
expire_time = None
|
||||
|
||||
print('token: %s, expire time(s): %s' % (token, expire_time))
|
||||
|
||||
self.appkey = config.get("appkey")
|
||||
self.token = config.get("token")
|
||||
self.token = token
|
||||
self.format = config.get("format", "wav")
|
||||
self.sample_rate = config.get("sample_rate", 16000)
|
||||
self.voice = config.get("voice", "xiaoyun")
|
||||
|
||||
Reference in New Issue
Block a user