Compare commits

..

No commits in common. "master" and "dev" have entirely different histories.
master ... dev

29 changed files with 175 additions and 904 deletions

View File

@ -21,12 +21,10 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.utils.OssUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
@ -77,8 +75,6 @@ public class WebController extends BaseController {
private IBaseAppService appService;
@Autowired
private GoogleConfig googleConfig;
@Autowired
private OssUtil ossUtil;
/**
* 导航栏接口--所有分类
@ -176,13 +172,10 @@ public class WebController extends BaseController {
* @date 10:04 2025/7/8
**/
@ApiOperation("热门产品-前10")
@ApiImplicitParams(value = {
@ApiImplicitParam(name = "tenantId", value = "站点唯一码", required = true, dataType = "string", paramType = "query", dataTypeClass = String.class),
@ApiImplicitParam(name = "showPlat", value = "平台标识(网站|App", required = true, dataType = "string", paramType = "query", dataTypeClass = String.class)
})
@ApiImplicitParam(name = "tenantId", value = "站点唯一码", required = true, dataType = "string", paramType = "query", dataTypeClass = String.class)
@GetMapping("/hotProduct")
public R<List<BusiProdNew>> hotProduct(@RequestParam(required = true) String tenantId,@RequestParam(required = true) String showPlat) {
return R.ok(prodNewService.hotProdOrNews(tenantId, DATA_TYPE_PRODUCT, true,showPlat));
public R<List<BusiProdNew>> hotProduct(@RequestParam(required = true) String tenantId) {
return R.ok(prodNewService.hotProdOrNews(tenantId, DATA_TYPE_PRODUCT, true));
}
/**
@ -193,13 +186,10 @@ public class WebController extends BaseController {
* @date 10:04 2025/7/8
**/
@ApiOperation("普通产品-前10")
@ApiImplicitParams(value = {
@ApiImplicitParam(name = "tenantId", value = "站点唯一码", required = true, dataType = "string", paramType = "query", dataTypeClass = String.class),
@ApiImplicitParam(name = "showPlat", value = "平台标识(网站|App", required = true, dataType = "string", paramType = "query", dataTypeClass = String.class)
})
@ApiImplicitParam(name = "tenantId", value = "站点唯一码", required = true, dataType = "string", paramType = "query", dataTypeClass = String.class)
@GetMapping("/product")
public R<List<BusiProdNew>> product(@RequestParam(required = true) String tenantId,@RequestParam(required = true) String showPlat) {
return R.ok(prodNewService.hotProdOrNews(tenantId, DATA_TYPE_PRODUCT, false,showPlat));
public R<List<BusiProdNew>> product(@RequestParam(required = true) String tenantId) {
return R.ok(prodNewService.hotProdOrNews(tenantId, DATA_TYPE_PRODUCT, false));
}
/**
@ -210,13 +200,10 @@ public class WebController extends BaseController {
* @date 10:04 2025/7/8
**/
@ApiOperation("热门新闻-前10")
@ApiImplicitParams(value = {
@ApiImplicitParam(name = "tenantId", value = "站点唯一码", required = true, dataType = "string", paramType = "query", dataTypeClass = String.class),
@ApiImplicitParam(name = "showPlat", value = "平台标识(网站|App", required = true, dataType = "string", paramType = "query", dataTypeClass = String.class)
})
@ApiImplicitParam(name = "tenantId", value = "站点唯一码", required = true, dataType = "string", paramType = "query", dataTypeClass = String.class)
@GetMapping("/hotNews")
public R<List<BusiProdNew>> hotNews(@RequestParam(required = true) String tenantId,@RequestParam(required = true) String showPlat) {
return R.ok(prodNewService.hotProdOrNews(tenantId, DATA_TYPE_NEWS, true,showPlat));
public R<List<BusiProdNew>> hotNews(@RequestParam(required = true) String tenantId) {
return R.ok(prodNewService.hotProdOrNews(tenantId, DATA_TYPE_NEWS, true));
}
/**
@ -250,18 +237,16 @@ public class WebController extends BaseController {
@ApiImplicitParam(name = "pageNum", value = "页码1开始", required = true, dataType = "int", paramType = "query", dataTypeClass = Integer.class),
@ApiImplicitParam(name = "pageSize", value = "每页显示数量", required = true, dataType = "int", paramType = "query", dataTypeClass = Integer.class),
@ApiImplicitParam(name = "catgId", value = "分类id", required = false, dataType = "string", paramType = "query", dataTypeClass = String.class),
@ApiImplicitParam(name = "text", value = "搜索内容", required = false, dataType = "string", paramType = "query", dataTypeClass = String.class),
@ApiImplicitParam(name = "showPlat", value = "平台标识(网站|App", required = true, dataType = "string", paramType = "query", dataTypeClass = String.class)
@ApiImplicitParam(name = "text", value = "搜索内容", required = false, dataType = "string", paramType = "query", dataTypeClass = String.class)
})
@GetMapping("/prodPageList")
public R<IPage<BusiProdNew>> prodPageList(String tenantId, @RequestParam(required = false) String catgId, @RequestParam(required = false) String text,String showPlat,
public R<IPage<BusiProdNew>> prodPageList(String tenantId, String catgId, String text,
@RequestParam(name = "pageNum", defaultValue = "1") Integer pageNum,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
Page<BusiProdNew> page = new Page<>(pageNum, pageSize);
LambdaQueryWrapper<BusiProdNew> queryWrapper = new LambdaQueryWrapper<BusiProdNew>()
.eq(BusiProdNew::getDataType, DATA_TYPE_PRODUCT)
.eq(BusiProdNew::getIfPublic, true)
.like(BusiProdNew::getShowPlat,showPlat)
.eq(BusiProdNew::getTenantId, tenantId);
if (StringUtils.isNotEmpty(text)) {
queryWrapper.and(wq -> wq
@ -306,18 +291,16 @@ public class WebController extends BaseController {
@ApiImplicitParam(name = "pageNum", value = "页码1开始", required = true, dataType = "int", paramType = "query", dataTypeClass = Integer.class),
@ApiImplicitParam(name = "pageSize", value = "每页显示数量", required = true, dataType = "int", paramType = "query", dataTypeClass = Integer.class),
@ApiImplicitParam(name = "catgId", value = "分类id", required = false, dataType = "string", paramType = "query", dataTypeClass = String.class),
@ApiImplicitParam(name = "text", value = "搜索内容", required = false, dataType = "string", paramType = "query", dataTypeClass = String.class),
@ApiImplicitParam(name = "showPlat", value = "平台标识(网站|App", required = true, dataType = "string", paramType = "query", dataTypeClass = String.class)
@ApiImplicitParam(name = "text", value = "搜索内容", required = false, dataType = "string", paramType = "query", dataTypeClass = String.class)
})
@GetMapping("/newsPageList")
public R<IPage<BusiProdNew>> newsPageList(String tenantId, @RequestParam(required = false) String catgId, @RequestParam(required = false) String text,String showPlat,
public R<IPage<BusiProdNew>> newsPageList(String tenantId, String catgId, String text,
@RequestParam(name = "pageNum", defaultValue = "1") Integer pageNum,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
Page<BusiProdNew> page = new Page<>(pageNum, pageSize);
LambdaQueryWrapper<BusiProdNew> queryWrapper = new LambdaQueryWrapper<BusiProdNew>()
.eq(BusiProdNew::getDataType, DATA_TYPE_NEWS)
.eq(BusiProdNew::getIfPublic, true)
.like(BusiProdNew::getShowPlat,showPlat)
.eq(BusiProdNew::getTenantId, tenantId);
if (StringUtils.isNotEmpty(text)) {
queryWrapper.and(wq -> wq
@ -371,15 +354,14 @@ public class WebController extends BaseController {
@ApiImplicitParam(name = "tenantId", value = "站点唯一码", required = true, dataType = "string", paramType = "query", dataTypeClass = String.class),
@ApiImplicitParam(name = "pageNum", value = "页码1开始", required = true, dataType = "int", paramType = "query", dataTypeClass = Integer.class),
@ApiImplicitParam(name = "pageSize", value = "每页显示数量", required = true, dataType = "int", paramType = "query", dataTypeClass = Integer.class),
@ApiImplicitParam(name = "text", value = "搜索内容", required = true, dataType = "string", paramType = "query", dataTypeClass = String.class),
@ApiImplicitParam(name = "showPlat", value = "平台标识(网站|App", required = true, dataType = "string", paramType = "query", dataTypeClass = String.class)
@ApiImplicitParam(name = "text", value = "搜索内容", required = true, dataType = "string", paramType = "query", dataTypeClass = String.class)
})
@GetMapping("/searchText")
public R<IPage<BusiProdNew>> searchText(String tenantId, String text,String showPlat,
public R<IPage<BusiProdNew>> searchText(String tenantId, String text,
@RequestParam(name = "pageNum", defaultValue = "1") Integer pageNum,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
Page<BusiProdNew> page = new Page<>(pageNum, pageSize);
return R.ok(prodNewService.searchTextAll(tenantId, text, page,showPlat));
return R.ok(prodNewService.searchTextAll(tenantId, text, page));
}
/**
@ -478,17 +460,46 @@ public class WebController extends BaseController {
return R.ok(appService.selectNewApp());
}
@SneakyThrows
@ApiOperation("下载APK文件")
@GetMapping("/downloadApk")
public void downloadApk(HttpServletResponse response,@RequestParam(required = false) String id) {
BaseApp appVersion;
if(StringUtils.isNotEmpty(id)){
appVersion = appService.getById(id);
}else{
appVersion = appService.selectNewApp();
public void downloadApk(HttpServletResponse response) {
try {
// APK文件路径
File file = new File(googleConfig.getAppDownload());
// 检查文件是否存在
if (!file.exists()) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
response.getWriter().write("文件不存在");
return;
}
// 设置响应头
response.setContentType("application/vnd.android.package-archive");
response.setHeader("Content-Disposition", "attachment; filename=truck.apk");
response.setHeader("Content-Length", String.valueOf(file.length()));
// 写入响应流
FileInputStream fis = new FileInputStream(file);
OutputStream os = response.getOutputStream();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
fis.close();
os.flush();
os.close();
} catch (Exception e) {
try {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().write("文件下载失败: " + e.getMessage());
} catch (Exception ex) {
logger.error("下载APK文件时发生错误", ex);
}
}
ossUtil.downloadFile(response, appVersion.getApkUrl(), appVersion.getVersion());
}
/**

View File

@ -33,10 +33,6 @@ public class BaseApp extends DlBaseEntity
@Excel(name = "版本")
private String version;
/** app包下载地址 */
@Excel(name = "app包下载地址")
private String apkUrl;
/** 本次升级描述 */
@Excel(name = "本次升级描述")
private String content;

View File

@ -8,7 +8,6 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.busi.domain.BusiChatItem;
import com.ruoyi.busi.service.IBusiChatItemService;
import com.ruoyi.busi.vo.ChatExcelMainVO;
import com.ruoyi.busi.vo.ChatMainVO;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
@ -67,12 +66,10 @@ public class BusiChatMainController extends BaseController
@PreAuthorize("@ss.hasPermi('busi:chatMain:export')")
@Log(title = "在线聊天", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, ChatMainVO busiChatMain)
public void export(HttpServletResponse response, BusiChatMain busiChatMain)
{
// List<BusiChatMain> list = busiChatMainService.list();
// ExcelUtil<BusiChatMain> util = new ExcelUtil<BusiChatMain>(BusiChatMain.class);
List<ChatExcelMainVO> list = busiChatMainService.listChatMain(busiChatMain);
ExcelUtil<ChatExcelMainVO> util = new ExcelUtil<ChatExcelMainVO>(ChatExcelMainVO.class);
List<BusiChatMain> list = busiChatMainService.list();
ExcelUtil<BusiChatMain> util = new ExcelUtil<BusiChatMain>(BusiChatMain.class);
util.exportExcel(response, list, "在线聊天数据");
}

View File

@ -5,10 +5,8 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.base.service.IBasePicsService;
import com.ruoyi.busi.domain.BusiProdNew;
import com.ruoyi.busi.domain.BusiProdRandom;
import com.ruoyi.busi.domain.BusiRelation;
import com.ruoyi.busi.service.IBusiProdNewService;
import com.ruoyi.busi.service.IBusiProdRandomService;
import com.ruoyi.busi.service.IBusiRelationService;
import com.ruoyi.busi.utils.SimHash;
import com.ruoyi.busi.utils.TextPreprocessor;
import com.ruoyi.busi.vo.ProdNewVO;
@ -17,7 +15,6 @@ import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
@ -46,8 +43,6 @@ public class BusiNewController extends BaseController
private IBasePicsService basePicsService;
@Autowired
private IBusiProdRandomService prodRandomService;
@Autowired
private IBusiRelationService relationService;
/**
* 查询新闻列表
@ -126,13 +121,6 @@ public class BusiNewController extends BaseController
});
basePicsService.saveBatch(prodNewVO.getFileList());
}
//默认负责人就是当前用户
BusiRelation relation = new BusiRelation();
relation.setUserId(SecurityUtils.getUserId());
relation.setProdId(prodNewVO.getId());
relation.setTenantId(prodNewVO.getTenantId());
relationService.save(relation);
busiProdNewService.setAmount(prodNewVO.getTenantId());
return success();
}

View File

@ -10,14 +10,11 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.base.service.IBasePicsService;
import com.ruoyi.busi.domain.BusiProdRandom;
import com.ruoyi.busi.domain.BusiRelation;
import com.ruoyi.busi.service.IBusiProdRandomService;
import com.ruoyi.busi.service.IBusiRelationService;
import com.ruoyi.busi.utils.SimHash;
import com.ruoyi.busi.utils.TextPreprocessor;
import com.ruoyi.busi.vo.ProdNewVO;
import com.ruoyi.busi.vo.ProdRandomVO;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
@ -57,8 +54,6 @@ public class BusiProdController extends BaseController
private IBasePicsService basePicsService;
@Autowired
private IBusiProdRandomService prodRandomService;
@Autowired
private IBusiRelationService relationService;
/**
* 查询产品列表
@ -137,13 +132,6 @@ public class BusiProdController extends BaseController
});
basePicsService.saveBatch(prodNewVO.getFileList());
}
//默认负责人就是当前用户
BusiRelation relation = new BusiRelation();
relation.setUserId(SecurityUtils.getUserId());
relation.setProdId(prodNewVO.getId());
relation.setTenantId(prodNewVO.getTenantId());
relationService.save(relation);
busiProdNewService.setAmount(prodNewVO.getTenantId());
return success();
}

View File

@ -89,7 +89,7 @@ public class BusiRelationController extends BaseController
List<BusiRelation> busiRelationList = new ArrayList<>();
userIdList.forEach(item->{
BusiRelation relation = new BusiRelation();
relation.setUserId(Long.valueOf(item));
relation.setUserId(item);
relation.setProdId(busiRelation.getProdId());
relation.setTenantId(busiRelation.getTenantId());
busiRelationList.add(relation);

View File

@ -1,7 +1,6 @@
package com.ruoyi.busi.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
@ -71,15 +70,9 @@ public class BusiProdNew extends DlBaseEntity
@ApiModelProperty("文章来源")
private String newsFrom;
/** 展示平台PC、APP */
@Excel(name = "展示平台PC、APP")
@ApiModelProperty("展示平台PC、APP")
private String showPlat;
/** 文章发布日期 */
@Excel(name = "文章发布日期")
@ApiModelProperty("文章发布日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date publicDate;
/** 产品主图或文章图片 */

View File

@ -30,7 +30,7 @@ public class BusiRelation extends DlBaseEntity
/** 用户id */
@Excel(name = "用户id")
private Long userId;
private String userId;
/** 产品、新闻id */
@Excel(name = "产品、新闻id")

View File

@ -5,7 +5,6 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.busi.domain.BusiChatMain;
import com.ruoyi.busi.vo.ChartDataVO;
import com.ruoyi.busi.vo.ChatExcelMainVO;
import com.ruoyi.busi.vo.ChatMainVO;
import com.ruoyi.busi.vo.ThirdSoftVO;
import org.apache.ibatis.annotations.Param;
@ -23,8 +22,6 @@ public interface BusiChatMainMapper extends BaseMapper<BusiChatMain>
{
IPage<ChatMainVO> queryListPage(@Param("entity") ChatMainVO entity, Page<BusiChatMain> page);
List<ChatExcelMainVO> selectChatList(@Param("entity") BusiChatMain entity);
/**
* 查询IP数量
* @author vinjor-M

View File

@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.busi.domain.BusiChatMain;
import com.ruoyi.busi.vo.ChatExcelMainVO;
import com.ruoyi.busi.vo.ChatMainVO;
/**
@ -18,15 +17,6 @@ import com.ruoyi.busi.vo.ChatMainVO;
public interface IBusiChatMainService extends IService<BusiChatMain> {
IPage<ChatMainVO> queryListPage(ChatMainVO pageReqVO, Page<BusiChatMain> page);
/**
* 不分页查询聊天记录适配导出
* @author PQZ
* @date 14:03 2025/10/21
* @param chatMainVO {@link ChatMainVO}
* @return java.util.List<com.ruoyi.busi.vo.ChatMainVO>
**/
List<ChatExcelMainVO> listChatMain(ChatMainVO chatMainVO);
/**
* 校验是否需要新增
*

View File

@ -54,7 +54,7 @@ public interface IBusiProdNewService extends IService<BusiProdNew>
* @param tenantId 租户id
* @return java.util.List<com.ruoyi.busi.domain.BusiProdNew>
**/
List<BusiProdNew> hotProdOrNews(String tenantId,String dateType,Boolean ifHot,String showPlat);
List<BusiProdNew> hotProdOrNews(String tenantId,String dateType,Boolean ifHot);
/**
* web站点查看详情
@ -74,7 +74,7 @@ public interface IBusiProdNewService extends IService<BusiProdNew>
* @param page 分页对象
* @return com.baomidou.mybatisplus.core.metadata.IPage<com.ruoyi.busi.vo.ProdNewVO>
**/
IPage<BusiProdNew> searchTextAll(String tenantId, String text,Page<BusiProdNew> page,String showPlat);
IPage<BusiProdNew> searchTextAll(String tenantId, String text,Page<BusiProdNew> page);
/**
* 相似度检测

View File

@ -40,18 +40,20 @@ public class BusiCategoryServiceImpl extends ServiceImpl<BusiCategoryMapper, Bus
public List<BusiCategoryVO> treeCategory(BusiCategory category) {
//查询全部栏目
LambdaQueryWrapper<BusiCategory> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(DlBaseEntity::getDelFlag, 0)
.eq(BusiCategory::getTenantId, category.getTenantId());
if (StringUtils.isNotEmpty(category.getCatgType())) {
lambdaQueryWrapper.eq(BusiCategory::getCatgType, category.getCatgType());
lambdaQueryWrapper.eq(DlBaseEntity::getDelFlag,0)
.eq(BusiCategory::getTenantId,category.getTenantId());
if(StringUtils.isNotEmpty(category.getCatgType())){
lambdaQueryWrapper.eq(BusiCategory::getCatgType,category.getCatgType());
}
if (!StringUtils.isEmpty(category.getCatgName())) {
lambdaQueryWrapper.like(BusiCategory::getCatgName, category.getCatgName());
}
lambdaQueryWrapper.orderByDesc(BusiCategory::getSort);
lambdaQueryWrapper.orderByAsc(BusiCategory::getSort);
List<BusiCategory> list = list(lambdaQueryWrapper);
List<BusiCategoryVO> rtnList = buildCategoryTree(list);
return rtnList;
return rtnList.stream().sorted(Comparator.comparing(BusiCategoryVO::getSort,
Comparator.nullsLast(Comparator.reverseOrder())))
.collect(Collectors.toList());
}
/**
@ -150,10 +152,12 @@ public class BusiCategoryServiceImpl extends ServiceImpl<BusiCategoryMapper, Bus
/**
* 生成树结构修改版
* 生成树结构
*
* @param list 网站栏目列表
* @return java.util.List<com.ruoyi.busi.vo.BusiCategoryVO>
* @author PQZ
* @date 14:11 2025/6/23
**/
private List<BusiCategoryVO> buildCategoryTree(List<BusiCategory> list) {
// Map存放id到VO的映射
@ -161,7 +165,7 @@ public class BusiCategoryServiceImpl extends ServiceImpl<BusiCategoryMapper, Bus
// 先将所有节点转换为VO并放入Map
for (BusiCategory category : list) {
BusiCategoryVO vo = new BusiCategoryVO();
BeanUtils.copyProperties(category, vo);
BeanUtils.copyProperties(category,vo);
vo.setId(category.getId());
vo.setLabel(category.getCatgName());
idToNodeMap.put(vo.getId(), vo);
@ -179,36 +183,9 @@ public class BusiCategoryServiceImpl extends ServiceImpl<BusiCategoryMapper, Bus
parent.getChildren().add(node);
}
}
// 对所有层级节点进行排序
sortTreeNodes(roots);
return roots;
}
/**
* 递归对树节点进行排序
*
* @param nodes 节点列表
*/
private void sortTreeNodes(List<BusiCategoryVO> nodes) {
if (nodes == null || nodes.isEmpty()) {
return;
}
// 对当前层级节点排序
nodes.sort(Comparator.comparing(BusiCategoryVO::getSort,
Comparator.nullsLast(Comparator.reverseOrder())));
// 递归对子节点排序
for (BusiCategoryVO node : nodes) {
if (node.getChildren() != null && !node.getChildren().isEmpty()) {
sortTreeNodes(node.getChildren());
}
}
}
/**
* @param id 查询的栏目ID
* @return java.util.List<java.lang.String>
@ -230,55 +207,54 @@ public class BusiCategoryServiceImpl extends ServiceImpl<BusiCategoryMapper, Bus
**/
@Override
public List<BusiCategoryVO> dealFirstId(List<BusiCategoryVO> busiCategoryVOList) {
busiCategoryVOList.forEach(item -> {
busiCategoryVOList.forEach(item->{
String thisMaxParentId = item.getId();
item.setMaxParentId(thisMaxParentId);
if (null != item.getChildren() && !item.getChildren().isEmpty()) {
if(null!=item.getChildren() && !item.getChildren().isEmpty()){
//有子级
this.setChildMaxParentId(item.getChildren(), thisMaxParentId);
this.setChildMaxParentId(item.getChildren(),thisMaxParentId);
}
});
return busiCategoryVOList;
}
private void setChildMaxParentId(List<BusiCategoryVO> childList, String maxParentId) {
childList.forEach(item -> {
private void setChildMaxParentId(List<BusiCategoryVO> childList,String maxParentId){
childList.forEach(item->{
item.setMaxParentId(maxParentId);
if (null != item.getChildren() && !item.getChildren().isEmpty()) {
this.setChildMaxParentId(item.getChildren(), maxParentId);
if(null!=item.getChildren()&& !item.getChildren().isEmpty()){
this.setChildMaxParentId(item.getChildren(),maxParentId);
}
});
}
/**
* 给所有子级设置最父级ID并且反回map格式
*
* @param busiCategoryVOList 栏目树
* @return java.util.List<com.ruoyi.busi.vo.BusiCategoryVO>
* @author vinjor-M
* @date 11:23 2025/7/19
* @param busiCategoryVOList 栏目树
* @return java.util.List<com.ruoyi.busi.vo.BusiCategoryVO>
**/
@Override
public Map<String, String> dealFirstIdRtnMap(List<BusiCategoryVO> busiCategoryVOList) {
Map<String, String> rtnMap = new HashMap<>();
busiCategoryVOList.forEach(item -> {
public Map<String,String> dealFirstIdRtnMap(List<BusiCategoryVO> busiCategoryVOList){
Map<String,String> rtnMap = new HashMap<>();
busiCategoryVOList.forEach(item->{
String thisMaxParentId = item.getId();
item.setMaxParentId(thisMaxParentId);
rtnMap.put(item.getId(), thisMaxParentId);
if (null != item.getChildren() && !item.getChildren().isEmpty()) {
rtnMap.put(item.getId(),thisMaxParentId);
if(null!=item.getChildren() && !item.getChildren().isEmpty()){
//有子级
this.setChildMaxParentIdMap(item.getChildren(), thisMaxParentId, rtnMap);
this.setChildMaxParentIdMap(item.getChildren(),thisMaxParentId,rtnMap);
}
});
return rtnMap;
}
private void setChildMaxParentIdMap(List<BusiCategoryVO> childList, String maxParentId, Map<String, String> rtnMap) {
childList.forEach(item -> {
private void setChildMaxParentIdMap(List<BusiCategoryVO> childList,String maxParentId,Map<String,String> rtnMap){
childList.forEach(item->{
item.setMaxParentId(maxParentId);
rtnMap.put(item.getId(), maxParentId);
if (null != item.getChildren() && !item.getChildren().isEmpty()) {
this.setChildMaxParentIdMap(item.getChildren(), maxParentId, rtnMap);
rtnMap.put(item.getId(),maxParentId);
if(null!=item.getChildren()&& !item.getChildren().isEmpty()){
this.setChildMaxParentIdMap(item.getChildren(),maxParentId,rtnMap);
}
});
}

View File

@ -7,10 +7,8 @@ import java.util.concurrent.TimeUnit;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.base.service.IBaseManagerService;
import com.ruoyi.busi.domain.BusiChatItem;
import com.ruoyi.busi.mapper.BusiChatItemMapper;
import com.ruoyi.busi.service.IBusiChatItemService;
import com.ruoyi.busi.vo.ChatExcelMainVO;
import com.ruoyi.busi.vo.ChatMainVO;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.redis.RedisCache;
@ -55,43 +53,6 @@ public class BusiChatMainServiceImpl extends ServiceImpl<BusiChatMainMapper,Busi
return busiChatMainMapper.queryListPage(pageReqVO, page);
}
/**
* 不分页查询聊天记录适配导出
*
* @param chatMainVO {@link ChatMainVO}
* @return java.util.List<com.ruoyi.busi.vo.ChatMainVO>
* @author PQZ
* @date 14:03 2025/10/21
**/
@Override
public List<ChatExcelMainVO> listChatMain(ChatMainVO chatMainVO) {
List<ChatExcelMainVO> result = busiChatMainMapper.selectChatList(chatMainVO);
result.forEach(item -> {
item.setCreateTimeStr(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",item.getCreateTime()));
item.setUpdateTimeStr(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",item.getUpdateTime()));
// 将chatItemList转换为指定格式的字符串
if (item.getChatItemList() != null && !item.getChatItemList().isEmpty()) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < item.getChatItemList().size(); i++) {
BusiChatItem chatItem = item.getChatItemList().get(i);
String dataFromDisplay = "customer".equals(chatItem.getDataFrom()) ? "客户" : "平台";
sb.append(dataFromDisplay)
.append("")
.append(chatItem.getContent())
.append("")
.append(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", chatItem.getCreateTime()))
.append("");
// 如果不是最后一个元素添加换行符
if (i < item.getChatItemList().size() - 1) {
sb.append("\n");
}
}
item.setChatHistory(sb.toString());
}
});
return result;
}
/**
* 校验是否需要新增
*

View File

@ -146,14 +146,13 @@ public class BusiProdNewServiceImpl extends ServiceImpl<BusiProdNewMapper,BusiPr
* @date 11:33 2025/7/8
**/
@Override
public List<BusiProdNew> hotProdOrNews(String tenantId,String dateType,Boolean ifHot,String showPlat) {
public List<BusiProdNew> hotProdOrNews(String tenantId,String dateType,Boolean ifHot) {
Page<BusiProdNew> page = new Page<>(1, 10);
LambdaQueryWrapper<BusiProdNew> queryWrapper = new LambdaQueryWrapper<BusiProdNew>()
.eq(BusiProdNew::getTenantId,tenantId)
.eq(BusiProdNew::getDataType,dateType)
.eq(BusiProdNew::getIfPublic,true)
.eq(BusiProdNew::getIfReco,ifHot)
.like(BusiProdNew::getShowPlat,showPlat)
.orderByDesc(BusiProdNew::getSort);
//查所有栏目
BusiCategory category = new BusiCategory();
@ -203,11 +202,10 @@ public class BusiProdNewServiceImpl extends ServiceImpl<BusiProdNewMapper,BusiPr
* @date 13:55 2025/7/9
**/
@Override
public IPage<BusiProdNew> searchTextAll(String tenantId, String text, Page<BusiProdNew> page,String showPlat) {
public IPage<BusiProdNew> searchTextAll(String tenantId, String text, Page<BusiProdNew> page) {
LambdaQueryWrapper<BusiProdNew> queryWrapper = new LambdaQueryWrapper<BusiProdNew>()
.eq(BusiProdNew::getTenantId,tenantId)
.eq(BusiProdNew::getIfPublic,true)
.like(BusiProdNew::getShowPlat,showPlat)
.and(wq->wq
.like(BusiProdNew::getTitle,text)
.or().like(BusiProdNew::getDescription,text)

View File

@ -1,61 +0,0 @@
package com.ruoyi.busi.vo;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.busi.domain.BusiChatItem;
import com.ruoyi.common.annotation.Excel;
import lombok.*;
import java.util.Date;
import java.util.List;
@Data
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ChatExcelMainVO{
private String id;
/** 产品名称 */
@Excel(name = "产品名称")
private String prodName;
/** 来源IP */
@Excel(name = "IP")
private String ip;
/** 来源国家 */
@Excel(name = "国家")
private String national;
/** 来源洲 */
@Excel(name = "")
private String oceania;
/** 设备类型 */
@Excel(name = "设备类型")
private String equipment;
/** 用户名称 */
@Excel(name = "负责员工")
private String userName;
/** 创建时间 */
@Excel(name = "最早聊天时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private String createTimeStr;
/** 创建时间 */
@Excel(name = "最近聊天时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private String updateTimeStr;
/** 聊天记录 */
@Excel(name = "聊天记录")
private String chatHistory;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
private List<BusiChatItem> chatItemList;
}

View File

@ -1,88 +0,0 @@
package com.ruoyi.utils;
import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyuncs.utils.IOUtils;
import com.ruoyi.common.config.OssConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
@Slf4j
@Component
public class OssUtil {
@Autowired
private OssConfig ossConfig;
/**
* 上传文件(fileKey-InputStream)
*/
public void uploadFile(String fileKey, InputStream stream) throws IOException {
ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
OSS client = new OSSClientBuilder().build(ossConfig.getEndPoint(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret(), conf);
try {
client.putObject(ossConfig.getBucketName(), fileKey, stream);
} finally {
stream.close();
if (client != null) {
client.shutdown();
}
IOUtils.closeQuietly(stream);
}
}
/**
* 文件下载
*/
public void downloadFile(HttpServletResponse response, String fileKey, String fileName) throws IOException {
fileKey = fileKey.replace("https://"+ossConfig.getBucketName()+"."+ossConfig.getEndPoint()+"/","");
InputStream stream = null;
BufferedInputStream bufferedInputStream = null;
ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
OSS client = new OSSClientBuilder().build(ossConfig.getEndPoint(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret(), conf);
try {
// 在获取文件流之前先获取文件元数据
ObjectMetadata metadata = client.getObjectMetadata(ossConfig.getBucketName(), fileKey);
long contentLength = metadata.getContentLength();
stream = client.getObject(ossConfig.getBucketName(), fileKey).getObjectContent();
response.reset();
// 设置Content-Length响应头
response.setContentLengthLong(contentLength);
response.setContentType("application/octet-stream");
response.addHeader("Content-Disposition", "attachment;filename=CDbay-" + URLEncoder.encode(fileName, "UTF-8")
.replace("+", "%20")+".apk");
OutputStream outputStream = response.getOutputStream();
bufferedInputStream = new BufferedInputStream(stream);
byte[] buf = new byte[16384];
int bytesRead;
while ((bytesRead = stream.read(buf, 0, buf.length)) >= 0) {
outputStream.write(buf, 0, bytesRead);
outputStream.flush();
}
} finally {
if (client != null) {
client.shutdown();
}
if (bufferedInputStream != null || stream != null) {
try {
bufferedInputStream.close();
stream.close();
} catch (IOException e) {
log.error("Oss Download IOException,fileKey:" + fileKey, e);
}
}
}
}
}

View File

@ -5,15 +5,15 @@ spring:
driverClassName: com.mysql.cj.jdbc.Driver
druid:
# # 主库数据源-点亮开发库
master:
url: jdbc:mysql://82.156.161.160:3306/dl_site_system?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: site
password: 123456
# 主库数据源-客户生产服务器
# master:
# url: jdbc:mysql://8.220.74.244:3306/dl_site_system?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
# url: jdbc:mysql://82.156.161.160:3306/dl_site_system?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
# username: site
# password: Chengda@2025~
# password: 123456
# 主库数据源-客户测试服务器
master:
url: jdbc:mysql://8.220.74.244:3306/dl_site_system?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: site
password: Chengda@2025~
# 从库数据源
slave:
# 从数据源开关/默认关闭

View File

@ -7,7 +7,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<resultMap type="BaseApp" id="BaseAppResult">
<result property="id" column="id" />
<result property="version" column="version" />
<result property="apkUrl" column="apk_url" />
<result property="content" column="content" />
<result property="creator" column="creator" />
<result property="createTime" column="create_time" />
@ -17,7 +16,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap>
<sql id="selectBaseAppVo">
select id, version, apk_url, content, creator, create_time, updater, update_time, del_flag from dl_base_app
select id, version, content, creator, create_time, updater, update_time, del_flag from dl_base_app
</sql>
<select id="queryListPage" parameterType="BaseApp" resultMap="BaseAppResult">
@ -25,6 +24,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<where>
<if test="entity.version != null "> and version like concat('%', #{entity.version}, '%')</if>
</where>
order by create_time desc
order by version DESC,create_time desc
</select>
</mapper>

View File

@ -28,23 +28,6 @@
<result property="siteName" column="site_name"/>
</resultMap>
<resultMap type="com.ruoyi.busi.vo.ChatExcelMainVO" id="ChatExcelMainResult">
<result property="ip" column="ip"/>
<result property="national" column="national"/>
<result property="oceania" column="oceania"/>
<result property="equipment" column="equipment"/>
<result property="prodName" column="prod_name"/>
<result property="userName" column="user_name"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<!-- 添加集合映射 -->
<collection select="getChatItems"
column="id"
property="chatItemList"
javaType="java.util.List"
ofType="com.ruoyi.busi.domain.BusiChatItem"/>
</resultMap>
<select id="queryListPage" parameterType="BusiChatMain" resultMap="BusiChatMainResult">
select dbcm.*,dbpn.title AS prod_name,su.nick_name AS user_name,dbs.site_name AS site_name
@ -75,41 +58,6 @@
</where>
order BY dbcm.create_time DESC,dbcm.update_time DESC
</select>
<select id="selectChatList" parameterType="BusiChatMain" resultMap="ChatExcelMainResult">
select dbcm.*,dbpn.title AS prod_name,su.nick_name AS user_name,dbs.site_name AS site_name
from dl_busi_chat_main dbcm
left join dl_busi_prod_new dbpn on dbcm.prod_id = dbpn.id
left join sys_user su on dbcm.user_id = su.user_id
left join dl_base_site dbs ON dbcm.tenant_id = dbs.id
<where>
<if test="entity.prodName != null and entity.prodName != ''">and dbpn.title LIKE
CONCAT('%',#{entity.prodName},'%')
</if>
<if test="entity.ip != null and entity.ip != ''">and dbcm.ip = #{entity.ip}</if>
<if test="entity.equipment != null and entity.equipment != ''">and dbcm.equipment = #{entity.equipment}</if>
<if test="entity.national != null and entity.national != ''">and dbcm.national LIKE
CONCAT('%',#{entity.national},'%')
</if>
<if test="entity.oceania != null and entity.oceania != ''">and dbcm.oceania = #{entity.oceania}</if>
<if test="entity.userName != null and entity.userName != ''">and (su.nick_name LIKE
CONCAT('%',#{entity.userName},'%') OR su.user_name LIKE CONCAT('%',#{entity.userName},'%'))
</if>
<if test="entity.tenantId != null and entity.tenantId != ''">and dbcm.tenant_id = #{entity.tenantId}</if>
<if test="entity.startDate != null and entity.startDate != ''">and (dbcm.create_time &gt;=
#{entity.startDate} OR dbcm.update_time &gt;= #{entity.startDate})
</if>
<if test="entity.endDate != null and entity.endDate != ''">and (dbcm.create_time &lt;= #{entity.endDate} OR
dbcm.update_time &gt;= #{entity.startDate})
</if>
</where>
order BY dbcm.create_time DESC,dbcm.update_time DESC
</select>
<select id="getChatItems" resultType="com.ruoyi.busi.domain.BusiChatItem">
select * from dl_busi_chat_item where main_id = #{id} order by create_time asc
</select>
<select id="selectIpCount" resultType="java.lang.Integer">
SELECT
COUNT( id )

View File

@ -13,7 +13,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
select id, tenant_id from dl_busi_keyword
</sql>
<delete id="deleteByIdAndTenantId">
DELETE FROM dl_busi_keyword WHERE id =#{id} AND tenant_id=#{tenantId}
DELETE dl_busi_keyword WHERE id =#{id} AND tenant_id=#{tenantId}
</delete>
<select id="queryListPage" parameterType="BusiKeyword" resultMap="BusiKeywordResult">

View File

@ -11,7 +11,6 @@
<result property="prodTitle" column="prod_title"/>
<result property="prodKeyword" column="prod_keyword"/>
<result property="prodDescription" column="prod_description"/>
<result property="showPlat" column="show_plat"/>
<result property="newsFrom" column="news_from"/>
<result property="publicDate" column="public_date"/>
<result property="mainPic" column="main_pic"/>
@ -43,7 +42,6 @@
prod_title,
prod_keyword,
prod_description,
show_plat,
news_from,
public_date,
main_pic,
@ -108,10 +106,6 @@
AND product.news_from like concat('%',
#{entity.newsFrom}, '%')
</if>
<if test="entity.showPlat != null and entity.showPlat != ''">
AND product.show_plat like concat('%',
#{entity.showPlat}, '%')
</if>
</where>
GROUP BY
product.id

View File

@ -1,184 +1,46 @@
<template>
<div class="content">
<!-- 压缩比例设置 -->
<div class="compression-setting">
<div class="compression-info">
图片压缩比例: {{ compressionRatio.toFixed(1) }}x
<el-tooltip class="item" effect="dark" content="值越小压缩率越高,图片质量越低"
placement="bottom"
>
<i class="el-icon-question"></i>
</el-tooltip>
</div>
<el-slider
v-model="compressionRatio"
:min="0.1"
:max="1.0"
:step="0.1"
:show-stops="true"
:tooltip-format="formatCompressionRatio"
></el-slider>
</div>
<vue-ueditor-wrap v-model="value"
:destroy="true"
:config="editorConfig"
:before-upload="handleBeforeUpload"
:editorDependencies="['ueditor.config.js','ueditor.all.js']"
/>
/>
</div>
</template>
<script>
import VueUeditorWrap from 'vue-ueditor-wrap'
import VueUeditorWrap from 'vue-ueditor-wrap';
export default {
components: {
components:{
VueUeditorWrap
},
props: {
/* 编辑器的内容 */
value: {
type: String,
default: ''
default: "",
}
},
watch: {
value(newVaue, oldValue) {
this.$emit('input', newVaue)
value(newVaue,oldValue){
this.$emit('input', newVaue);
}
},
mounted() {
mounted(){
},
data() {
return {
editorConfig: {
// https://open-doc.modstart.com/ueditor-plus/backend.html
serverUrl: process.env.VUE_APP_BASE_API + '/sys/ueditor/exec',
serverUrl: process.env.VUE_APP_BASE_API+'/sys/ueditor/exec',
UEDITOR_HOME_URL: '/UEditor/',
//**231218**
UEDITOR_CORS_URL: '/UEditor/',
zIndex: 999,//z
//
imageMaxSize: 5 * 1024 * 1024, // 5MB
imageAllowFiles: ['.png', '.jpg', '.jpeg', '.gif', '.bmp']
},
// (0.1-1.0)
compressionRatio: 0.9
}
},
methods: {
//
formatCompressionRatio(value) {
return `${value.toFixed(1)}x`
},
/**
* 上传前处理图片压缩
* @param {File} file 原始文件
* @param {Function} callback 回调函数
*/
handleBeforeUpload(file, callback) {
debugger
//
if (!file.type.match(/image\/\w+/)) {
return callback(file, true) //
}
// 100KB
if (file.size < 100 * 1024) {
return callback(file, true)
}
//
this.compressImage(file).then(compressedFile => {
callback(compressedFile, true)
}).catch(err => {
console.error('图片压缩失败:', err)
callback(file, true) //
})
},
/**
* 图片压缩处理
* @param {File} file 原始图片文件
* @returns {Promise<File>} 压缩后的文件
*/
compressImage(file) {
return new Promise((resolve, reject) => {
const img = new Image()
const reader = new FileReader()
reader.onload = (e) => {
img.src = e.target.result
}
img.onload = () => {
// canvas
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
//
let width = img.width
let height = img.height
// canvas
canvas.width = width
canvas.height = height
// canvas
ctx.drawImage(img, 0, 0, width, height)
// canvasBlob
canvas.toBlob(
(blob) => {
if (!blob) {
reject(new Error('压缩失败'))
return
}
// File
const compressedFile = new File(
[blob],
file.name,
{
type: blob.type || file.type,
lastModified: Date.now()
}
)
resolve(compressedFile)
},
file.type || 'image/jpeg',
this.compressionRatio
)
}
img.onerror = (err) => {
reject(err)
}
reader.readAsDataURL(file)
})
}
}
}
</script>
<style scoped lang="scss">
//
.compression-setting {
width: 300px;
margin-bottom: 15px;
padding: 0 10px 8px 10px;
background-color: #f5f7fa;
border-radius: 4px;
.compression-info {
margin-top: 8px;
font-size: 12px;
color: #606266;
}
}
::v-deep .el-slider__runway {
margin: 0 !important;
}
</style>

View File

@ -1,25 +1,5 @@
<template>
<div class="component-upload-image">
<!-- 压缩比例设置 -->
<div class="compression-setting" v-if="showCompressionSetting">
<div class="compression-info">
压缩比例: {{ compressionRatio.toFixed(1) }}x
<el-tooltip class="item" effect="dark" content="值越小压缩率越高,图片质量越低"
placement="bottom"
>
<i class="el-icon-question"></i>
</el-tooltip>
</div>
<el-slider
v-model="compressionRatio"
:min="0.1"
:max="1.0"
:step="0.1"
:show-stops="true"
:tooltip-format="formatCompressionRatio"
></el-slider>
</div>
<el-upload
multiple
:action="uploadImgUrl"
@ -37,9 +17,8 @@
:on-preview="handlePictureCardPreview"
:disabled="disabled"
:class="{hide: this.fileList.length >= this.limit}"
:http-request="customUpload"
>
<i class="el-icon-plus"></i>
<i class="el-icon-plus"></i>
</el-upload>
<!-- 上传提示 -->
@ -85,7 +64,7 @@ export default {
type: Boolean,
default: false,
},
// , ['png', 'jpeg', 'jpg']
// , ['png', 'jpg', 'jpeg']
fileType: {
type: Array,
default: () => ["png", "jpg", "jpeg"],
@ -94,16 +73,6 @@ export default {
isShowTip: {
type: Boolean,
default: true
},
//
showCompression: {
type: Boolean,
default: true
},
//
defaultCompressionRatio: {
type: Number,
default: 0.9
}
},
data() {
@ -118,21 +87,9 @@ export default {
headers: {
Authorization: "Bearer " + getToken(),
},
fileList: [],
// (0.1-1.0)
compressionRatio: this.defaultCompressionRatio
fileList: []
};
},
computed: {
//
showTip() {
return this.isShowTip && (this.fileType || this.fileSize);
},
//
showCompressionSetting() {
return this.showCompression && !this.disabled && this.fileList.length < this.limit;
}
},
watch: {
value: {
handler(val) {
@ -157,32 +114,26 @@ export default {
},
deep: true,
immediate: true
},
//
defaultCompressionRatio: {
handler(val) {
this.compressionRatio = val;
},
immediate: true
}
},
methods: {
//
formatCompressionRatio(value) {
return `${value.toFixed(1)}x`;
computed: {
//
showTip() {
return this.isShowTip && (this.fileType || this.fileSize);
},
//
async handleBeforeUpload(file) {
},
methods: {
// loading
handleBeforeUpload(file) {
let isImg = false;
if (this.fileType.length) {
let fileExtension = "";
if (file.name.lastIndexOf(".") > -1) {
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1).toLowerCase();
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
}
isImg = this.fileType.some(type => {
if (file.type.indexOf(type) > -1) return true;
if (fileExtension && fileExtension === type.toLowerCase()) return true;
if (fileExtension && fileExtension.indexOf(type) > -1) return true;
return false;
});
} else {
@ -193,151 +144,28 @@ export default {
this.$modal.msgError(`文件格式不正确,请上传${this.fileType.join("/")}图片格式文件!`);
return false;
}
if (file.name.includes(',')) {
this.$modal.msgError('文件名不正确,不能包含英文逗号!');
return false;
}
//
this.$modal.loading("正在处理图片,请稍候...");
this.number++;
return true;
},
//
customUpload(options) {
const file = options.file;
//
this.compressImage(file, this.compressionRatio)
.then(compressedFile => {
// FormData
const formData = new FormData();
formData.append('file', compressedFile, file.name);
// XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open('post', this.uploadImgUrl, true);
//
Object.keys(this.headers).forEach(key => {
xhr.setRequestHeader(key, this.headers[key]);
});
//
xhr.upload.addEventListener('progress', (e) => {
if (e.total > 0) {
e.percent = e.loaded / e.total * 100;
}
options.onProgress(e);
});
//
xhr.addEventListener('load', () => {
if (xhr.status >= 200 && xhr.status < 300) {
const response = JSON.parse(xhr.responseText);
options.onSuccess(response);
} else {
options.onError(xhr.responseText);
}
});
//
xhr.addEventListener('error', () => {
options.onError(xhr.responseText);
});
//
xhr.send(formData);
})
.catch(error => {
this.$modal.msgError('图片压缩失败: ' + error.message);
this.$modal.closeLoading();
this.number--;
options.onError(error);
});
},
//
compressImage(file, quality = 0.8) {
return new Promise((resolve, reject) => {
//
if (!file.type.match(/image.*/)) {
resolve(file);
return;
if (this.fileSize) {
const isLt = file.size / 1024 / 1024 < this.fileSize;
if (!isLt) {
this.$modal.msgError(`上传头像图片大小不能超过 ${this.fileSize} MB!`);
return false;
}
const reader = new FileReader();
reader.onload = (e) => {
const img = new Image();
img.onload = () => {
// canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// canvas
canvas.width = img.width;
canvas.height = img.height;
// canvas
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
//
const mimeType = file.type || 'image/jpeg';
// canvasBlob
canvas.toBlob((blob) => {
if (!blob) {
reject(new Error('无法压缩图片'));
return;
}
// BlobFile
const compressedFile = new File([blob], file.name, {
type: mimeType,
lastModified: Date.now()
});
resolve(compressedFile);
}, mimeType, quality);
};
img.onerror = (error) => {
reject(new Error('无法加载图片进行压缩'));
};
//
img.src = e.target.result;
};
reader.onerror = (error) => {
reject(new Error('无法读取图片文件'));
};
//
reader.readAsDataURL(file);
});
}
this.$modal.loading("正在上传图片,请稍候...");
this.number++;
},
//
handleExceed() {
this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);
},
//
handleUploadSuccess(res, file) {
if (res.code === 200) {
this.uploadList.push({
name: res.name,
url: res.fileName,
size: res.size,
width: res.width,
height: res.height
});
this.uploadList.push({ name: res.name, url: res.fileName,size:res.size,width:res.width,height:res.height });
this.uploadedSuccessfully();
} else {
this.number--;
@ -347,7 +175,6 @@ export default {
this.uploadedSuccessfully();
}
},
//
handleDelete(file) {
const findex = this.fileList.map(f => f.name).indexOf(file.name);
@ -356,31 +183,27 @@ export default {
this.$emit("input", this.listToString(this.fileList));
}
},
//
handleUploadError() {
this.$modal.msgError("上传图片失败,请重试");
this.$modal.closeLoading();
},
//
uploadedSuccessfully() {
if (this.number > 0 && this.uploadList.length === this.number) {
this.fileList = this.fileList.concat(this.uploadList);
this.$emit('uploadedImg', this.fileList);
this.$emit('uploadedImg',this.fileList)
this.uploadList = [];
this.number = 0;
this.$emit("input", this.listToString(this.fileList));
this.$modal.closeLoading();
}
},
//
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
},
//
listToString(list, separator) {
let strs = "";
@ -390,7 +213,7 @@ export default {
strs += list[i].url.replace(this.baseUrl, "") + separator;
}
}
return strs !== '' ? strs.substr(0, strs.length - 1) : '';
return strs != '' ? strs.substr(0, strs.length - 1) : '';
}
}
};
@ -400,7 +223,6 @@ export default {
::v-deep.hide .el-upload--picture-card {
display: none;
}
//
::v-deep .el-list-enter-active,
::v-deep .el-list-leave-active {
@ -411,21 +233,6 @@ export default {
opacity: 0;
transform: translateY(0);
}
//
.compression-setting {
margin-bottom: 15px;
padding: 0 10px 8px 10px;
background-color: #f5f7fa;
border-radius: 4px;
.compression-info {
margin-top: 8px;
font-size: 12px;
color: #606266;
}
}
::v-deep .el-slider__runway{
margin:0 !important;
}
</style>

View File

@ -45,7 +45,7 @@
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['base:app:edit']"
>下载</el-button>
>修改</el-button>
<el-button
size="mini"
type="text"
@ -69,10 +69,7 @@
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="版本" prop="version">
<el-input type="input" v-model="form.version" placeholder="请输入版本" />
</el-form-item>
<el-form-item label="app包" prop="apkUrl">
<file-upload v-model="form.apkUrl" :limit="1" :fileType="fileType" :fileSize="50"/>
<el-input v-model="form.version" placeholder="请输入版本" />
</el-form-item>
<el-form-item label="本次升级描述" prop="content">
<el-input v-model="form.content" type="textarea" placeholder="请输入内容" />
@ -125,11 +122,7 @@ export default {
version: [
{ required: true, message: '请输入版本号', trigger: 'blur' }
],
apkUrl: [
{ required: true, message: '请上传程序包', trigger: 'blur' }
],
},
baseUrl: process.env.VUE_APP_BASE_API,
}
};
},
created() {
@ -155,7 +148,6 @@ export default {
this.form = {
id: null,
version: null,
apkUrl: null,
content: null,
creator: null,
createTime: null,
@ -187,18 +179,15 @@ export default {
this.open = true;
this.title = "添加app版本管理";
},
/** 下载 */
/** 修改按钮操作 */
handleUpdate(row) {
let a = document.createElement("a"); // a
a.style.display = "none";
a.href = this.baseUrl + "/web/downloadApk?id="+row.id;
a.setAttribute(
"download",
a.href.split("/")[a.href.split("/").length - 1]
); // adownload
document.body.appendChild(a); //
a.click();
document.body.removeChild(a);
this.reset();
const id = row.id || this.ids
getApp(id).then(response => {
this.form = response.data;
this.open = true;
this.title = "修改app版本管理";
});
},
/** 提交按钮 */
submitForm() {

View File

@ -48,16 +48,16 @@
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
>导出
</el-button>
</el-col>
<!-- <el-col :span="1.5">-->
<!-- <el-button-->
<!-- type="primary"-->
<!-- plain-->
<!-- icon="el-icon-plus"-->
<!-- size="mini"-->
<!-- @click="handleAdd"-->
<!-- v-hasPermi="['busi:chatMain:add']"-->
<!-- >新增</el-button>-->
<!-- </el-col>-->
<!-- <el-col :span="1.5">-->
<!-- <el-button-->
<!-- type="success"-->

View File

@ -4,16 +4,6 @@
<el-form-item label="分类" prop="catgId">
<treeselect style="width: 200px" v-model="queryParams.catgId" :options="catgOptions" :normalizer="normalizer" :noResultsText="'暂无数据'" placeholder="选择分类" />
</el-form-item>
<el-form-item label="展示平台" prop="showPlat">
<el-select v-model="queryParams.showPlat" placeholder="请选择展示平台" clearable>
<el-option
v-for="dict in dict.type.show_plateform"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="新闻标题" prop="title">
<el-input
v-model="queryParams.title"
@ -85,7 +75,6 @@
</template>
</el-table-column>
<el-table-column label="新闻负责人" align="center" prop="leaderName" />
<el-table-column label="展示平台" align="center" prop="showPlat" />
<!-- <el-table-column label="产品简介" align="center" prop="description" />-->
<el-table-column width="100" label="排序" align="center" prop="sort">
<template slot="header" slot-scope="scope">
@ -201,7 +190,7 @@ import "@riophae/vue-treeselect/dist/vue-treeselect.css";
export default {
name: "New",
dicts: ['sys_yes_no','show_plateform'],
dicts: ['sys_yes_no'],
components: { selectAllUser,selectProduct,randomProduct ,Treeselect},
data() {
return {

View File

@ -105,7 +105,7 @@
<el-form-item label="所属分类" prop="catgId">
<div class="dl-flex-column">
<treeselect style="width: 200px" v-model="form.catgId" :options="catgOptions" :normalizer="normalizer"
:noResultsText="'暂无数据'" placeholder="请选择新闻分类" :disable-branch-nodes="true"
:noResultsText="'暂无数据'" placeholder="请选择新闻分类"
/>
<div class="dl-add-catg" @click="goCatgView">添加新闻分类</div>
</div>
@ -184,7 +184,7 @@
</el-col>
</el-row>
<el-row>
<el-col :span="9">
<el-col :span="8">
<el-form-item label="新闻图" prop="mainPic">
<el-tag v-if="!form.mainPic" style="cursor: pointer" @click="choosePic('mainPic',1)">图片库选择</el-tag>
<image-upload @uploadedImg="uploadedImg" v-model="form.mainPic" :limit="1"/>
@ -202,21 +202,10 @@
</div>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="展示平台" prop="showPlat">
<el-checkbox-group v-model="showPlatList" @change="changeCheckBox">
<el-checkbox v-for="dict in dict.type.show_plateform" :label="dict.label" :value="dict.value"></el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="新闻内容">
<editor :key="showKeywords" v-model="form.content" :min-height="192"/>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="新闻内容">
<editor :key="showKeywords" v-model="form.content" :min-height="192"/>
</el-form-item>
</el-form>
</el-col>
</el-row>
@ -259,7 +248,6 @@ import SimilarityNew from './similarityNew'
export default {
name: 'newForm',
components: { SimilarityNew, Treeselect, selectPic , Hamburger , countTo},
dicts: ['show_plateform'],
data() {
return {
//--
@ -281,7 +269,6 @@ export default {
prodTitle: null,
prodKeyword: null,
prodDescription: null,
showPlat: '网站,App',
newsFrom: null,
publicDate: null,
mainPic: null,
@ -300,8 +287,6 @@ export default {
//
fileList: []
},
//
showPlatList:['网站','App'],
formSeo: {
title: '',
needUrl: true,
@ -342,9 +327,6 @@ export default {
],
description: [
{ required: true, message: '请输入新闻简介', trigger: 'blur' }
],
showPlat: [
{ required: true, message: '请选择展示平台', trigger: 'blur' }
]
},
rulesSeo:{
@ -376,12 +358,6 @@ export default {
}
},
methods: {
/**
* 选中展示平台
*/
changeCheckBox(value){
this.form.showPlat = value.join(",")
},
useProdName(){
this.formSeo.title = this.form.title
},
@ -495,7 +471,6 @@ export default {
getProdInfo(id, type) {
getProdNew(id).then(response => {
this.form = response.data
this.showPlatList = this.form.showPlat.split(',')
if (this.form.pics && this.form.pics.length > 0) {
this.canPicsNum = this.picsNum - this.form.pics.split(',').length
}

View File

@ -4,16 +4,6 @@
<el-form-item label="分类" prop="catgId">
<treeselect style="width: 200px" v-model="queryParams.catgId" :options="catgOptions" :normalizer="normalizer" :noResultsText="'暂无数据'" placeholder="选择分类" />
</el-form-item>
<el-form-item label="展示平台" prop="showPlat">
<el-select v-model="queryParams.showPlat" placeholder="请选择展示平台" clearable>
<el-option
v-for="dict in dict.type.show_plateform"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="产品名称" prop="title">
<el-input
v-model="queryParams.title"
@ -84,8 +74,7 @@
<image-preview :src="scope.row.mainPic" :width="50" :height="50"/>
</template>
</el-table-column>
<el-table-column label="产品负责人" align="center" prop="leaderName" :min-width="100" />
<el-table-column label="展示平台" align="center" prop="showPlat" />
<el-table-column label="产品负责人" align="center" prop="leaderName" :min-width="200" />
<!-- <el-table-column label="产品简介" align="center" prop="description" />-->
<el-table-column width="100" label="排序" align="center" prop="sort">
<template slot="header" slot-scope="scope">
@ -201,7 +190,7 @@ import "@riophae/vue-treeselect/dist/vue-treeselect.css";
export default {
name: "Prod",
dicts: ['sys_yes_no','show_plateform'],
dicts: ['sys_yes_no'],
components: { selectAllUser ,selectProduct,randomProduct,Treeselect},
data() {
return {

View File

@ -102,7 +102,7 @@
<el-form-item label="所属分类" prop="catgId">
<div class="dl-flex-column">
<treeselect style="width: 200px" v-model="form.catgId" :options="catgOptions" :normalizer="normalizer"
:noResultsText="'暂无数据'" placeholder="请选择产品分类" :disable-branch-nodes="true"
:noResultsText="'暂无数据'" placeholder="请选择产品分类"
/>
<div class="dl-add-catg" @click="goCatgView">添加产品分类</div>
</div>
@ -172,20 +172,11 @@
</div>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="6">
<el-form-item label="展示平台" prop="showPlat">
<el-checkbox-group v-model="showPlatList" @change="changeCheckBox">
<el-checkbox v-for="dict in dict.type.show_plateform" :label="dict.label" :value="dict.value"></el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="网站首页显示" prop="ifReco">
<el-form-item label="首页显示" prop="ifReco">
<template v-slot:label>
<span>网站首页显示</span>
<el-tooltip class="item" effect="dark" content="开启后将在网站首页优先显示"
<span>首页显示</span>
<el-tooltip class="item" effect="dark" content="开启后将在首页优先显示"
placement="bottom"
>
<i class="el-icon-question"></i>
@ -198,13 +189,9 @@
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="产品内容">
<editor :key="showKeywords" v-model="form.content" :min-height="192"/>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="产品内容">
<editor :key="showKeywords" v-model="form.content" :min-height="192"/>
</el-form-item>
</el-form>
</el-col>
</el-row>
@ -247,7 +234,6 @@ import SimilarityProduct from './similarityProduct'
export default {
name: 'prodForm',
components: { SimilarityProduct, Treeselect, selectPic, Hamburger , countTo},
dicts: ['show_plateform'],
data() {
return {
//--
@ -269,7 +255,6 @@ export default {
prodTitle: null,
prodKeyword: null,
prodDescription: null,
showPlat: '网站,App',
newsFrom: null,
mainPic: null,
pics: null,
@ -287,8 +272,6 @@ export default {
//
fileList: []
},
//
showPlatList:['网站','App'],
formSeo: {
title: '',
needUrl: true,
@ -323,9 +306,6 @@ export default {
],
description: [
{ required: true, message: '请输入产品简介', trigger: 'blur' }
],
showPlat: [
{ required: true, message: '请选择展示平台', trigger: 'blur' }
]
},
rulesSeo:{
@ -357,12 +337,6 @@ export default {
}
},
methods: {
/**
* 选中展示平台
*/
changeCheckBox(value){
this.form.showPlat = value.join(",")
},
useProdName(){
this.formSeo.title = this.form.title
},
@ -476,7 +450,6 @@ export default {
getProdInfo(id, type) {
getProdNew(id).then(response => {
this.form = response.data
this.showPlatList = this.form.showPlat.split(',')
if (this.form.pics && this.form.pics.length > 0) {
this.canPicsNum = this.picsNum - this.form.pics.split(',').length
}