线索问题

This commit is contained in:
Yifei Kuang 2025-01-19 11:39:25 +08:00
parent b02c9b41a7
commit 8b14c4479b
12 changed files with 559 additions and 10 deletions

View File

@ -2,10 +2,7 @@ package com.ruoyi.web.controller.system;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.Key; import java.security.Key;
import java.util.Arrays; import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
@ -81,6 +78,13 @@ public class ClewController extends BaseController
return prefix + "/clew"; return prefix + "/clew";
} }
@RequiresPermissions("system:clew:view")
@GetMapping("publicClew")
public String publicClew(ModelMap modelMap)
{
return prefix + "/publicClew";
}
/** /**
* 查询线索列表 * 查询线索列表
*/ */
@ -122,6 +126,37 @@ public class ClewController extends BaseController
return getDataTable(list); return getDataTable(list);
} }
@RequiresPermissions("system:clew:list")
@PostMapping("/listPublic")
@ResponseBody
public TableDataInfo listPublic(Clew clew)
{
startPage();
clew.setSaleId(2L);
List<Clew> list = clewService.selectClewPublicList(clew);
list.forEach(model->{
if(model.getSaleId() != null){
SysUser user = sysUserService.selectUserById(model.getSaleId());
if(user != null){
model.setSaleName(user.getUserName());
}
SysUser sourceUser = sysUserService.selectUserById(model.getSourceSaleId());
if(sourceUser != null){
model.setSourceSaleName(sourceUser.getUserName());
}
}
if(model.getSourceApp() != null){
CompanyApp param = new CompanyApp();
param.setCompanyId(model.getSourceApp());
List<CompanyApp> result = companyAppService.selectCompanyAppList(param);
model.setSourceAppName(result.get(0).getAppName());
}else {
model.setSourceAppName("黑猫APP");
}
});
return getDataTable(list);
}
/** /**
* 导出线索列表 * 导出线索列表
*/ */
@ -350,6 +385,7 @@ public class ClewController extends BaseController
return AjaxResult.error("该线索已被人取走!"); return AjaxResult.error("该线索已被人取走!");
} }
sourceClew.setSaleId(getSysUser().getUserId()); sourceClew.setSaleId(getSysUser().getUserId());
sourceClew.setUpdateTime(new Date());
return toAjax(clewService.updateClew(sourceClew)); return toAjax(clewService.updateClew(sourceClew));
} }

View File

@ -74,8 +74,14 @@ public class NoticeController {
@GetMapping("/download") @GetMapping("/download")
@ResponseBody @ResponseBody
public AjaxResult download(){ public AjaxResult download(@RequestParam("aid")String aid,
@RequestParam("appId")String appId,
@RequestParam("oaid")String oaid,
@RequestParam("idType")String idType,
@RequestParam("uniqueId")String uniqueId,
@RequestParam("actionType")String actionType,
@RequestParam("callBack")String callBack){
log.info("归因转化回调内容,{},{},{},{},{},{},{}", aid, appId, oaid, idType, uniqueId, actionType, callBack);
return AjaxResult.success("下载成功!"); return AjaxResult.success("下载成功!");
} }

View File

@ -296,8 +296,6 @@
align: 'center', align: 'center',
formatter: function(value, row, index) { formatter: function(value, row, index) {
var actions = []; var actions = [];
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="getBackClew(\'' + row.id + '\')"><i class="fa fa-remove"></i>取回线索</a>');
actions.push('<a class="btn btn-danger btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="addPublicClew(\'' + row.id + '\')"><i class="fa fa-remove"></i>放入公海池</a>');
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="changeUser(\'' + row.id + '\')"><i class="fa fa-remove"></i>分配客服</a>'); actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="changeUser(\'' + row.id + '\')"><i class="fa fa-remove"></i>分配客服</a>');
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.id + '\')"><i class="fa fa-edit"></i>编辑</a> '); actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.id + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.id + '\')"><i class="fa fa-remove"></i>删除</a>'); actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.id + '\')"><i class="fa fa-remove"></i>删除</a>');

View File

@ -0,0 +1,334 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('公海池列表')" />
</head>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<div class="col-sm-12 search-collapse">
<form id="formId">
<div class="select-list">
<ul>
<li>
<label>手机号:</label>
<input type="text" name="phone"/>
</li>
<li>
App来源<select name="remark" th:with="type=${@dict.getType('app_source')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</li>
<li>
加微:<select name="isAddWx" th:with="type=${@dict.getType('is_add_wx')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</li>
<li>
有效:<select name="isEffective" th:with="type=${@dict.getType('is_effective')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</li>
<li>
意向:<select name="isPlan" th:with="type=${@dict.getType('is_plan')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</li>
<li>
成交:<select name="isDeal" th:with="type=${@dict.getType('is_deal')}">
<option value="">所有</option>
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
</select>
</li>
<li>
来源应用:<select name="sourceApp">
<option value="">所有</option>
<option value="1">黑猫搞定逾期</option>
<option value="2">大象债务处理</option>
<option value="8">百度来源</option>
</select>
</li>
<li class="select-time">
<label>创建时间: </label>
<input type="text" class="time-input" id="startTime" placeholder="开始时间" name="params[beginTime]"/>
<span>-</span>
<input type="text" class="time-input" id="endTime" placeholder="结束时间" name="params[endTime]"/>
</li>
<li class="select-time">
<label>分配时间: </label>
<input type="text" class="time-input" id="updateStartTime" placeholder="开始时间" name="params[updateStartTime]"/>
<span>-</span>
<input type="text" class="time-input" id="updateEndTime" placeholder="结束时间" name="params[updateEndTime]"/>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="btn-group-sm" id="toolbar" role="group">
<a class="btn btn-primary multiple disabled" onclick="changeBatchUser()" shiro:hasPermission="system:clew:edit">
<i class="fa fa-remove"></i> 批量分配
</a>
<a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="system:clew:add">
<i class="fa fa-plus"></i> 添加
</a>
<a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="system:clew:edit">
<i class="fa fa-edit"></i> 修改
</a>
<a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="system:clew:remove">
<i class="fa fa-remove"></i> 删除
</a>
<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="system:clew:export">
<i class="fa fa-download"></i> 导出
</a>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
</div>
</div>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var editFlag = [[${@permission.hasPermi('system:clew:edit')}]];
var removeFlag = [[${@permission.hasPermi('system:clew:remove')}]];
var isAddWx = [[${@dict.getType('is_add_wx')}]];
var isEffective = [[${@dict.getType('is_effective')}]];
var isPlan = [[${@dict.getType('is_plan')}]];
var isDeal = [[${@dict.getType('is_deal')}]];
var customerStatus = [[${@dict.getType('customer_status')}]];
var assignStatus = [[${@dict.getType('assign_status')}]];
var prefix = ctx + "system/clew";
$(function() {
var options = {
url: prefix + "/listPublic",
createUrl: prefix + "/add",
updateUrl: prefix + "/edit/{id}",
removeUrl: prefix + "/remove",
exportUrl: prefix + "/export",
modalName: "线索",
columns: [{
checkbox: true
},
{
field: 'id',
title: '主键',
visible: false
},
{
field: 'sourceAppName',
title: '来源App'
},
{
field: 'phone',
title: '手机号'
},
{
field: 'customerName',
title: '姓名'
},
{
field: 'wxName',
title: '微信昵称',
visible: false
},
{
field: 'debtType',
title: '债务类型',
visible: false
},
{
field: 'debtMoney',
title: '债务金额'
},
{
field: 'remark',
title: 'App来源'
},
{
field: 'customerRemark',
title: '客户情况备注'
},
{
field: 'twoCustomerRemark',
title: '二次跟进情况'
},
{
field: 'createTime',
title: '创建时间'
},
{
field: 'updateTime',
title: '分配时间'
},
{
field: 'assignTimes',
title: '二次分配',
formatter: function(value, row, index) {
return $.table.selectDictLabel(assignStatus, value);
}
},
{
field: 'sourceType',
title: '推广来源',
visible: false
},
{
field: 'customerStatus',
title: '客户状态',
formatter: function(value, row, index) {
return $.table.selectDictLabel(customerStatus, value);
}
},
{
field: 'customerLevel',
title: '客户评级',
visible: false
},
{
field: 'nextTime',
title: '下次跟进日期',
visible: false
},
{
field: 'touchQrcode',
title: '是否长按识别二维码',
visible: false
},
{
field: 'contactNumber',
title: '跟进次数',
visible: false
},
{
field: 'isTouch',
title: '是否触达',
visible: false
},
{
field: 'isAddWx',
title: '是否加微',
formatter: function(value, row, index) {
return $.table.selectDictLabel(isAddWx, value);
}
},
{
field: 'isEffective',
title: '是否有效',
formatter: function(value, row, index) {
return $.table.selectDictLabel(isEffective, value);
}
},
{
field: 'isPlan',
title: '是否意向',
formatter: function(value, row, index) {
return $.table.selectDictLabel(isPlan, value);
}
},
{
field: 'isDeal',
title: '成交状态',
formatter: function(value, row, index) {
return $.table.selectDictLabel(isDeal, value);
}
},
{
field: 'wxAccount',
title: '成交金额'
},
{
field: 'provinceName',
title: '省份'
},
{
field: 'cityName',
title: '城市',
visible: false
},
{
field: 'contactTime',
title: '方便接电话时间',
visible: false
},
{
field: 'otherPhone',
title: '其他联系方式',
visible: false
},
{
field: 'company',
title: '广告主',
visible: false
},
{
field: 'sourceSaleName',
title: '原始销售'
},
{
field: 'saleName',
title: '销售'
},
{
field: 'infoFlow',
title: '信息流',
visible: false
},
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="getBackClew(\'' + row.id + '\')"><i class="fa fa-remove"></i>取回线索</a>');
return actions.join('');
}
}]
};
$.table.init(options);
});
/* 用户管理-停用 */
function getBackClew(id) {
$.modal.confirm("确定要取回该线索吗?", function() {
$.operate.post(prefix + "/getBackClew", { "id": id});
})
}
/* 用户管理启用 */
function addPublicClew(id) {
$.modal.confirm("确定要加入公海池吗?", function() {
$.operate.post(prefix + "/addPublicClew", { "id": id});
})
}
/* 选择供应商 */
function changeUser(clewId) {
var url = prefix + '/changeUser/' + clewId;
$.modal.open("选择客服", url, '800', '300');
}
function changeBatchUser(){
table.set();
var rows = $.common.isEmpty(table.options.uniqueId) ? $.table.selectFirstColumns() : $.table.selectColumns(table.options.uniqueId);
if (rows.length == 0) {
$.modal.alertWarning("请至少选择一条记录");
return;
}
$.modal.confirm("确认分配吗?", function() {
$.modal.open("选择客服", prefix + '/changeBatchUser/' + rows.join(), '800', '300');
})
}
</script>
</body>
</html>

View File

@ -40,6 +40,10 @@
<artifactId>ruoyi-system</artifactId> <artifactId>ruoyi-system</artifactId>
</dependency> </dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -0,0 +1,10 @@
package com.ruoyi.quartz.service;
public interface PublicClewService {
/**
* 更新 3天未添加微信/ 12天未成交
*/
void updateOvertimeClew();
}

View File

@ -0,0 +1,22 @@
package com.ruoyi.quartz.service.impl;
import cn.hutool.core.date.DateUtil;
import com.ruoyi.quartz.service.PublicClewService;
import com.ruoyi.system.service.IClewService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
@Service
public class PublicClewServiceImpl implements PublicClewService {
@Autowired
private IClewService clewService;
@Override
public void updateOvertimeClew() {
clewService.updateSuitAbleNotAddWx(DateUtil.offsetDay(new Date(), -3));
clewService.updateSuitAbleNotDeal(DateUtil.offsetDay(new Date(), -12));
}
}

View File

@ -0,0 +1,21 @@
package com.ruoyi.quartz.task;
import com.ruoyi.quartz.service.PublicClewService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @author clunt
* <p>公海池定时任务</p>
*/
@Component("publicClewTask")
public class PublicClewTask {
@Autowired
private PublicClewService publicClewService;
public void ryParams() {
publicClewService.updateOvertimeClew();
}
}

View File

@ -1,7 +1,9 @@
package com.ruoyi.system.mapper; package com.ruoyi.system.mapper;
import java.util.Date;
import java.util.List; import java.util.List;
import com.ruoyi.system.domain.Clew; import com.ruoyi.system.domain.Clew;
import org.apache.ibatis.annotations.Param;
/** /**
* 线索Mapper接口 * 线索Mapper接口
@ -27,6 +29,8 @@ public interface ClewMapper
*/ */
public List<Clew> selectClewList(Clew clew); public List<Clew> selectClewList(Clew clew);
public List<Clew> selectClewPublicList(Clew clew);
/** /**
* 新增线索 * 新增线索
* *
@ -60,4 +64,10 @@ public interface ClewMapper
* @return 结果 * @return 结果
*/ */
public int deleteClewByIds(String[] ids); public int deleteClewByIds(String[] ids);
void updateSuitAbleNotAddWx(@Param("beginTime")Date beginTime);
void updateSuitAbleNotDeal(@Param("beginTime")Date beginTime);
} }

View File

@ -1,5 +1,6 @@
package com.ruoyi.system.service; package com.ruoyi.system.service;
import java.util.Date;
import java.util.List; import java.util.List;
import com.ruoyi.system.domain.Clew; import com.ruoyi.system.domain.Clew;
@ -27,6 +28,9 @@ public interface IClewService
*/ */
public List<Clew> selectClewList(Clew clew); public List<Clew> selectClewList(Clew clew);
public List<Clew> selectClewPublicList(Clew clew);
/** /**
* 新增线索 * 新增线索
* *
@ -60,4 +64,9 @@ public interface IClewService
* @return 结果 * @return 结果
*/ */
public int deleteClewById(Long id); public int deleteClewById(Long id);
void updateSuitAbleNotAddWx(Date beginTime);
void updateSuitAbleNotDeal(Date beginTime);
} }

View File

@ -1,5 +1,6 @@
package com.ruoyi.system.service.impl; package com.ruoyi.system.service.impl;
import java.util.Date;
import java.util.List; import java.util.List;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
@ -52,6 +53,12 @@ public class ClewServiceImpl implements IClewService
return clewMapper.selectClewList(clew); return clewMapper.selectClewList(clew);
} }
@Override
public List<Clew> selectClewPublicList(Clew clew)
{
return clewMapper.selectClewPublicList(clew);
}
/** /**
* 新增线索 * 新增线索
* *
@ -125,4 +132,14 @@ public class ClewServiceImpl implements IClewService
{ {
return clewMapper.deleteClewById(id); return clewMapper.deleteClewById(id);
} }
@Override
public void updateSuitAbleNotAddWx(Date beginTime) {
clewMapper.updateSuitAbleNotAddWx(beginTime);
}
@Override
public void updateSuitAbleNotDeal(Date beginTime) {
clewMapper.updateSuitAbleNotDeal(beginTime);
}
} }

View File

@ -55,7 +55,8 @@
<include refid="selectClewVo"/> <include refid="selectClewVo"/>
<where> <where>
<if test="company != null "> and company = #{company}</if> <if test="company != null "> and company = #{company}</if>
<if test="saleId != null "> and (sale_id = #{saleId} or sale_id = 2)</if> <if test="saleId != null "> and sale_id = #{saleId}</if>
<if test="saleId == null"> and sale_id != 2</if>
<if test="infoFlow != null and infoFlow != ''"> and info_flow = #{infoFlow}</if> <if test="infoFlow != null and infoFlow != ''"> and info_flow = #{infoFlow}</if>
<if test="nextTime != null "> and next_time = #{nextTime}</if> <if test="nextTime != null "> and next_time = #{nextTime}</if>
<if test="wxName != null and wxName != ''"> and wx_name like concat('%', #{wxName}, '%')</if> <if test="wxName != null and wxName != ''"> and wx_name like concat('%', #{wxName}, '%')</if>
@ -110,7 +111,7 @@
</where> </where>
<choose> <choose>
<when test="saleId != null "> <when test="saleId != null ">
order by update_time desc order by create_time desc
</when> </when>
<otherwise> <otherwise>
order by create_time desc order by create_time desc
@ -118,6 +119,68 @@
</choose> </choose>
</select> </select>
<select id="selectClewPublicList" parameterType="Clew" resultMap="ClewResult">
<include refid="selectClewVo"/>
<where>
<if test="company != null "> and company = #{company}</if>
<if test="saleId != null "> and sale_id = #{saleId}</if>
<if test="saleId == null"> and sale_id != 2</if>
<if test="infoFlow != null and infoFlow != ''"> and info_flow = #{infoFlow}</if>
<if test="nextTime != null "> and next_time = #{nextTime}</if>
<if test="wxName != null and wxName != ''"> and wx_name like concat('%', #{wxName}, '%')</if>
<if test="phone != null and phone != ''"> and phone = #{phone}</if>
<if test="debtType != null and debtType != ''"> and debt_type = #{debtType}</if>
<if test="debtMoney != null and debtMoney != ''"> and debt_money = #{debtMoney}</if>
<if test="sourceType != null and sourceType != ''"> and source_type = #{sourceType}</if>
<if test="sourceApp != null "> and source_app = #{sourceApp}</if>
<if test="wxAccount != null and wxAccount != ''"> and wx_account = #{wxAccount}</if>
<if test="customerStatus != null and customerStatus != ''"> and customer_status = #{customerStatus}</if>
<if test="customerLevel != null and customerLevel != ''"> and customer_level = #{customerLevel}</if>
<if test="touchQrcode != null and touchQrcode != ''"> and touch_qrcode = #{touchQrcode}</if>
<if test="contactNumber != null "> and contact_number = #{contactNumber}</if>
<if test="isTouch != null and isTouch != ''"> and is_touch = #{isTouch}</if>
<if test="isAddWx != null and isAddWx != ''"> and is_add_wx = #{isAddWx}</if>
<if test="isEffective != null and isEffective != ''"> and is_effective = #{isEffective}</if>
<if test="isPlan != null and isPlan != ''"> and is_plan = #{isPlan}</if>
<if test="isDeal != null and isDeal != ''"> and is_deal = #{isDeal}</if>
<if test="provinceName != null and provinceName != ''"> and province_name like concat('%', #{provinceName}, '%')</if>
<if test="cityName != null and cityName != ''"> and city_name like concat('%', #{cityName}, '%')</if>
<if test="customerName != null and customerName != ''"> and customer_name like concat('%', #{customerName}, '%')</if>
<if test="contactTime != null "> and contact_time = #{contactTime}</if>
<if test="otherPhone != null and otherPhone != ''"> and other_phone = #{otherPhone}</if>
<if test="remark != null and remark != ''"> and remark = #{remark}</if>
<if test="searchStatus == '01'">
and is_add_wx = '1'
</if>
<if test="searchStatus == '02'">
and is_effective = '0'
</if>
<if test="searchStatus == '03'">
and is_plan = '1'
</if>
<if test="searchStatus == '04'">
and is_deal = '1'
</if>
<if test="searchStatus == '05'">
and is_add_wx != '1'
</if>
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
AND date_format(create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
</if>
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
AND date_format(create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
</if>
<if test="params.updateStartTime != null and params.updateStartTime != ''"><!-- 开始时间检索 -->
AND date_format(update_time,'%y%m%d') &gt;= date_format(#{params.updateStartTime},'%y%m%d')
</if>
<if test="params.updateEndTime != null and params.updateEndTime != ''"><!-- 结束时间检索 -->
AND date_format(update_time,'%y%m%d') &lt;= date_format(#{params.updateEndTime},'%y%m%d')
</if>
</where>
order by update_time desc
</select>
<select id="selectClewById" parameterType="Long" resultMap="ClewResult"> <select id="selectClewById" parameterType="Long" resultMap="ClewResult">
<include refid="selectClewVo"/> <include refid="selectClewVo"/>
where id = #{id} where id = #{id}
@ -260,4 +323,23 @@
</foreach> </foreach>
</delete> </delete>
<update id="updateSuitAbleNotAddWx">
update clew set update_time = sysdate(), sale_id = 2 where
is_deal = 0 and
is_add_wx != 1 and
sale_id != 2 and
update_time &lt;= #{beginTime}
</update>
<update id="updateSuitAbleNotDeal">
update
clew
set
update_time = sysdate(), sale_id = 2
where
is_deal = 0
and is_add_wx = 1
and sale_id != 2
and update_time &lt;= #{beginTime}
</update>
</mapper> </mapper>