parent
329b4456b9
commit
11533092e9
@ -1,6 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17 (2)" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/ruoyi-study.iml" filepath="$PROJECT_DIR$/.idea/ruoyi-study.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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<String,String> 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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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<GroupBuyActivity> queryGroupBuyActivityList();
|
||||
|
||||
GroupBuyActivity queryValidGroupBuyActivity(GroupBuyActivity groupBuyActivityReq);
|
||||
|
||||
}
|
@ -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<GroupBuyDiscount> queryGroupBuyDiscountList();
|
||||
|
||||
GroupBuyDiscount queryGroupBuyActivityDiscountByDiscountId(String discountId);
|
||||
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -0,0 +1 @@
|
||||
package com.ruoyi.system.gateway.dto;
|
@ -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<String> 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
/**
|
||||
* 提供redis链接配置
|
||||
*/
|
||||
package com.ruoyi.system.redis;
|
@ -0,0 +1,19 @@
|
||||
package com.ruoyi.system.util;
|
||||
|
||||
public class BaseContext {
|
||||
|
||||
public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
|
||||
|
||||
public static void setCurrentId(Long id) {
|
||||
threadLocal.set(id);
|
||||
}
|
||||
|
||||
public static Long getCurrentId() {
|
||||
return threadLocal.get();
|
||||
}
|
||||
|
||||
public static void removeCurrentId() {
|
||||
threadLocal.remove();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package com.ruoyi.system.util;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.Enumeration;
|
||||
|
||||
/**
|
||||
* IP工具类
|
||||
*/
|
||||
public class IpUtil {
|
||||
|
||||
public static String getIP(HttpServletRequest httpServletRequest) {
|
||||
String ip = httpServletRequest.getHeader("X-Forwarded-For");
|
||||
if (ip != null && !"".equals(ip.trim())) {
|
||||
int index = ip.indexOf(",");
|
||||
if (index != -1) {
|
||||
ip = ip.substring(0, index);
|
||||
}
|
||||
return ip;
|
||||
} else {
|
||||
ip = httpServletRequest.getHeader("X-Real-IP");
|
||||
if (ip == null || "".equals(ip.trim())) {
|
||||
ip = httpServletRequest.getRemoteAddr();
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getLocalAddress() {
|
||||
try {
|
||||
InetAddress candidateAddress = null;
|
||||
Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
|
||||
while (ifaces.hasMoreElements()) {
|
||||
NetworkInterface iface = ifaces.nextElement();
|
||||
Enumeration<InetAddress> inetAddrs = iface.getInetAddresses();
|
||||
|
||||
while (inetAddrs.hasMoreElements()) {
|
||||
InetAddress inetAddr = inetAddrs.nextElement();
|
||||
if (!inetAddr.isLoopbackAddress()) {
|
||||
if (inetAddr.isSiteLocalAddress()) {
|
||||
return inetAddr.getHostAddress();
|
||||
}
|
||||
|
||||
if (candidateAddress == null) {
|
||||
candidateAddress = inetAddr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (candidateAddress != null) {
|
||||
return candidateAddress.getHostAddress();
|
||||
} else {
|
||||
InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
|
||||
return jdkSuppliedAddress.getHostAddress();
|
||||
}
|
||||
} catch (Exception var5) {
|
||||
return "unkown";
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package com.ruoyi.system.util;
|
||||
|
||||
public class JsonResponse<T> {
|
||||
|
||||
private String code;
|
||||
|
||||
private String msg;
|
||||
|
||||
private T data;
|
||||
|
||||
public JsonResponse(String code, String msg){
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public JsonResponse(T data){
|
||||
this.data = data;
|
||||
msg = "成功";
|
||||
code = "0";
|
||||
}
|
||||
|
||||
public static JsonResponse<String> success(){
|
||||
return new JsonResponse<>(null);
|
||||
}
|
||||
|
||||
public static JsonResponse<String> success(String data){
|
||||
return new JsonResponse<>(data);
|
||||
}
|
||||
|
||||
public static JsonResponse<String> fail(){
|
||||
return new JsonResponse<>("1", "失败");
|
||||
}
|
||||
|
||||
public static JsonResponse<String> fail(String code, String msg){
|
||||
return new JsonResponse<>(code, msg);
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
package com.ruoyi.system.util;
|
||||
|
||||
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
|
||||
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
|
||||
import com.github.tobato.fastdfs.domain.proto.storage.DownloadByteArray;
|
||||
import com.github.tobato.fastdfs.service.FastFileStorageClient;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* @author: Larry
|
||||
* @Date: 2023 /12 /05 / 13:04
|
||||
* @Description:
|
||||
*/
|
||||
@Component
|
||||
public class Utilfast {
|
||||
@Autowired
|
||||
private FastFileStorageClient storageClient;
|
||||
|
||||
@Autowired
|
||||
private FdfsWebServer fdfsWebServer;
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*
|
||||
* @return 文件访问地址
|
||||
* @throws IOException
|
||||
*/
|
||||
public String upload(MultipartFile multipartFile) throws Exception {
|
||||
String extName = FilenameUtils.getExtension(multipartFile.getOriginalFilename());
|
||||
StorePath storePath = storageClient.uploadImageAndCrtThumbImage(multipartFile.getInputStream(), multipartFile.getSize(), extName, null);
|
||||
|
||||
return storePath.getFullPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
* @param file 文件对象
|
||||
* @return 文件访问地址
|
||||
* @throws IOException
|
||||
*/
|
||||
public String uploadFile(File file) throws IOException {
|
||||
FileInputStream inputStream = new FileInputStream (file);
|
||||
StorePath storePath = storageClient.uploadFile(inputStream,file.length(), FilenameUtils.getExtension(file.getName()),null);
|
||||
inputStream.close();
|
||||
return getResAccessUrl(storePath);
|
||||
}
|
||||
/**
|
||||
* 带输入流形式的文件上传
|
||||
*
|
||||
* @param is
|
||||
* @param size
|
||||
* @param fileName
|
||||
* @return
|
||||
*/
|
||||
public String uploadFileStream(InputStream is, long size, String fileName) {
|
||||
StorePath path = storageClient.uploadFile(is, size, fileName, null);
|
||||
return getResAccessUrl(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将一段字符串生成一个文件上传
|
||||
* @param content 文件内容
|
||||
* @param fileExtension
|
||||
* @return
|
||||
*/
|
||||
public String uploadFile(String content, String fileExtension) {
|
||||
byte[] buff = content.getBytes(StandardCharsets.UTF_8);
|
||||
ByteArrayInputStream stream = new ByteArrayInputStream(buff);
|
||||
StorePath storePath = storageClient.uploadFile(stream,buff.length, fileExtension,null);
|
||||
return getResAccessUrl(storePath);
|
||||
}
|
||||
|
||||
// 封装图片完整URL地址
|
||||
private String getResAccessUrl(StorePath storePath) {
|
||||
String fileUrl = fdfsWebServer.getWebServerUrl() + storePath.getFullPath();
|
||||
return fileUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
* @param fileUrl 文件url
|
||||
* @return
|
||||
*/
|
||||
public byte[] download(String fileUrl) {
|
||||
String group = fileUrl.substring(0, fileUrl.indexOf("/"));
|
||||
String path = fileUrl.substring(fileUrl.indexOf("/") + 1);
|
||||
byte[] bytes = storageClient.downloadFile(group, path, new DownloadByteArray());
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
* @param fileUrl 文件访问地址
|
||||
* @return
|
||||
*/
|
||||
// public void deleteFile(String fileUrl) {
|
||||
// if (StringUtils.isEmpty(fileUrl)) {
|
||||
// return;
|
||||
// }
|
||||
// try {
|
||||
// StorePath storePath = StorePath.praseFromUrl(fileUrl);
|
||||
// storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
|
||||
// } catch (FdfsUnsupportStorePathException e) {
|
||||
// logger.warn(e.getMessage());
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
Loading…
Reference in new issue