Merge branch 'develop' into yongpxu-dev

This commit is contained in:
笔记本里的永平
2025-07-21 18:22:47 +08:00
8 changed files with 177 additions and 21 deletions

View File

@@ -98,6 +98,7 @@ export default function NewPlan() {
sceneId: Number(detail.scenario) || 1,
remarkFormat: detail.remarkFormat ?? "",
addFriendInterval: detail.addFriendInterval ?? 1,
tips: detail.tips ?? "",
}));
}
} else {
@@ -178,6 +179,7 @@ export default function NewPlan() {
case 1:
return (
<BasicSettings
isEdit={isEdit}
formData={formData}
onChange={onChange}
onNext={handleNext}

View File

@@ -12,6 +12,7 @@ import EyeIcon from "@/components/icons/EyeIcon";
import { uploadFile } from "@/api/utils";
interface BasicSettingsProps {
isEdit: boolean;
formData: any;
onChange: (data: any) => void;
onNext?: () => void;
@@ -89,6 +90,7 @@ const generatePosterMaterials = (): Material[] => {
};
export function BasicSettings({
isEdit,
formData,
onChange,
onNext,
@@ -123,6 +125,7 @@ export function BasicSettings({
// 自定义标签相关状态
const [customTagInput, setCustomTagInput] = useState("");
const [customTags, setCustomTags] = useState(formData.customTags || []);
const [tips, setTips] = useState(formData.tips || "");
const [selectedScenarioTags, setSelectedScenarioTags] = useState(
formData.scenarioTags || []
);
@@ -188,7 +191,11 @@ export function BasicSettings({
const today = new Date().toLocaleDateString("zh-CN").replace(/\//g, "");
const sceneItem = sceneList.find((v) => formData.scenario === v.id);
onChange({ ...formData, name: `${sceneItem?.name || "海报"}${today}` });
}, [sceneList]);
}, [isEdit]);
useEffect(() => {
setTips(formData.tips || "");
}, [formData.tips]);
// 选中场景
const handleScenarioSelect = (sceneId: number) => {
@@ -494,6 +501,22 @@ export function BasicSettings({
</div>
</div>
{/* 输入获客成功提示 */}
<div className="flex pt-4">
<div className="border p-2 flex-1">
<input
type="text"
value={tips}
onChange={(e) => {
setTips(e.target.value);
onChange({ ...formData, tips: e.target.value });
}}
placeholder="请输入获客成功提示"
className="w-full"
/>
</div>
</div>
{/* 选素材 */}
<div className="my-4" style={openPoster}>
<div className="mb-4"></div>

View File

@@ -97,9 +97,6 @@ Route::group('v1', function () {
Route::get('autoCreate', 'app\api\controller\AllotRuleController@autoCreateAllotRules');// 自动创建分配规则 √
});
Route::group('scenarios', function () {
Route::any('', 'app\cunkebao\controller\plan\PostExternalApiV1Controller@index');
});
});
});

View File

@@ -118,8 +118,13 @@ Route::group('v1/', function () {
Route::group('v1/frontend', function () {
Route::group('v1/api/scenarios', function () {
Route::any('', 'app\cunkebao\controller\plan\PostExternalApiV1Controller@index');
});
//小程序
Route::group('v1/frontend', function () {
Route::group('business/poster', function () {
Route::post('getone', 'app\cunkebao\controller\plan\PosterWeChatMiniProgram@getPosterTaskData');
Route::post('decryptphone', 'app\cunkebao\controller\plan\PosterWeChatMiniProgram@getPhoneNumber');
@@ -129,5 +134,4 @@ Route::group('v1/frontend', function () {
return [];

View File

@@ -0,0 +1,121 @@
<?php
namespace app\cunkebao\controller;
use think\Controller;
use think\Db;
class TrafficController extends Controller
{
public function getList(){
$page = $this->request->param('page',1);
$pageSize = $this->request->param('pageSize',10);
$device = $this->request->param('device','');
$packageId = $this->request->param('packageId',''); // 流量池id
$userValue = $this->request->param('userValue',''); // 1高价值客户 2中价值客户 3低价值客户
$addStatus = $this->request->param('addStatus',''); // 1待添加 2已添加 3添加失败 4重复用户
$keyword = $this->request->param('keyword','');
$companyId = $this->request->userInfo['companyId'];
// 1 文字 3图片 47动态图片 34语言 43视频 42名片 40/20链接 49文件 419430449转账 436207665红包
$where = [];
// 添加筛选条件
if (!empty($device)) {
$where['d.id'] = $device;
}
if (!empty($packageId)) {
$where['tp.id'] = $packageId;
}
if (!empty($userValue)) {
$where['tp.userValue'] = $userValue;
}
if (!empty($addStatus)) {
$where['tp.addStatus'] = $addStatus;
}
// 构建查询 - 通过traffic_pool的identifier关联wechat_account的wechatId、alias或phone
$query = Db::name('traffic_pool')->alias('tp')
->join('wechat_account wa', 'wa.wechatId = tp.wechatId', 'LEFT')
->field('tp.id, tp.identifier,tp.createTime, tp.updateTime,
wa.wechatId, wa.alias, wa.phone, wa.nickname, wa.avatar')
->where($where);
// 关键词搜索 - 支持通过wechat_friendship的identifier关联wechat_account的wechatId、alias或phone
if (!empty($keyword)) {
$query->where(function($q) use ($keyword) {
$q->where('tp.identifier', 'like', '%' . $keyword . '%')
->whereOr('wa.wechatId', 'like', '%' . $keyword . '%')
->whereOr('wa.alias', 'like', '%' . $keyword . '%')
->whereOr('wa.phone', 'like', '%' . $keyword . '%')
->whereOr('wa.nickname', 'like', '%' . $keyword . '%');
});
}
// 获取总数
$total = $query->count();
// 分页查询
$list = $query->order('tp.createTime desc')
->group('tp.identifier')
->order('tp.id desc')
->page($page, $pageSize)
->select();
return json([
'code' => 200,
'msg' => '获取成功',
'data' => [
'list' => $list,
'total' => $total,
]
]);
}
/**
* 用户旅程
* @return false|string
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function getUserJourney()
{
$page = $this->request->param('page',1);
$pageSize = $this->request->param('pageSize',10);
$userId = $this->request->param('userId','');
if(empty($userId)){
return json_encode(['code' => 500, 'msg' => '用户id不能为空']);
}
$query = Db::name('user_portrait')
->field('id,type,trafficPoolId,remark,count,createTime,updateTime')
->where(['trafficPoolId' => $userId]);
$total = $query->count();
$list = $query->order('createTime desc')
->page($page,$pageSize)
->select();
foreach ($list as $k=>$v){
$list[$k]['createTime'] = date('Y-m-d H:i:s',$v['createTime']);
$list[$k]['updateTime'] = date('Y-m-d H:i:s',$v['updateTime']);
}
return json_encode(['code' => 200,'data'=>['list' => $list,'total'=>$total],'获取成功']);
}
}

View File

@@ -96,7 +96,8 @@ class PostExternalApiV1Controller extends Controller
if (!$trafficPool) {
$trafficPoolId =Db::name('traffic_pool')->insertGetId([
'identifier' => $identifier,
'mobile' => $params['phone']
'mobile' => !empty($params['phone']) ? $params['phone'] : '',
'createTime' => time()
]);
}else{
$trafficPoolId = $trafficPool['id'];

View File

@@ -126,7 +126,10 @@ class PosterWeChatMiniProgram extends Controller
// todo 获取海报获客任务的任务/海报数据 -- 表还没设计好,不急 ck_customer_acquisition_task
public function getPosterTaskData() {
$id = request()->param('id');
$task = Db::name('customer_acquisition_task')->where(['id' => $id,'deleteTime' => 0])->find();
$task = Db::name('customer_acquisition_task')
->where(['id' => $id,'deleteTime' => 0])
->field('id,name,sceneConf,status')
->find();
if (!$task) {
return json([
'code' => 400,
@@ -150,13 +153,20 @@ class PosterWeChatMiniProgram extends Controller
}
if(isset($sceneConf['tips'])) {
$sTip = $sceneConf['tips'];
} else {
$sTip = '';
}
unset($task['sceneConf']);
$task['sTip'] = $sTip;
$data = [
'id' => $task['id'],
'name' => $task['name'],
'poster' => ['sUrl' => $posterUrl],
'sTip' => '',
'task' => $task,
];

View File

@@ -191,7 +191,6 @@ class Adapter implements WeChatServiceInterface
}
//筛选出设备在线微信在线
$wechatIdAccountIdMap = $this->getWeChatIdsAccountIdsMapByDeviceIds($task_info['reqConf']['device']);
if (empty($wechatIdAccountIdMap)) {
continue;
}
@@ -213,11 +212,9 @@ class Adapter implements WeChatServiceInterface
continue;
}
// 判断24h内加的好友数量friend_task 先固定10个人 getLast24hAddedFriendsCount
$last24hAddedFriendsCount = $this->getLast24hAddedFriendsCount($wechatId);
if ($last24hAddedFriendsCount >= 10) {
if ($last24hAddedFriendsCount >= 20) {
continue;
}
@@ -233,14 +230,15 @@ class Adapter implements WeChatServiceInterface
$task['processed_wechat_ids'] = $task['processed_wechat_ids'] . ',' . $wechatId; // 处理失败任务用,用于过滤已处理的微信号
break;
}
Db::name('task_customer')
$res = Db::name('task_customer')
->where('id', $task['id'])
->update([
'status' => $friendAddTaskCreated ? 1 : 3,
'fail_reason' => $friendAddTaskCreated ? '' : '已经是好友了',
'processed_wechat_ids' => $task['processed_wechat_ids'],
'updated_at' => time()
]); // ~~不用管,回头再添加再判断即可~~
'updateTime' => time()
]);
// ~~不用管,回头再添加再判断即可~~
// 失败一定是另一个进程/定时器在检查的
}
@@ -254,9 +252,9 @@ class Adapter implements WeChatServiceInterface
$tasks = Db::name('task_customer')
->whereIn('status', [1,2])
->where('updated_at', '>=', (time() - 86400 * 3))
->where('updateTime', '>=', (time() - 86400 * 3))
->limit(50)
->order('updated_at DESC')
->order('updateTime DESC')
->select();
if (empty($tasks)) {
@@ -296,7 +294,7 @@ class Adapter implements WeChatServiceInterface
Db::name('task_customer')
->where('id', $task['id'])
->update(['status' => 4, 'updated_at' => time()]);
->update(['status' => 4, 'updateTime' => time()]);
$wechatFriendRecord = $this->getWeChatAccoutIdAndFriendIdByWeChatIdAndFriendPhone($passedWeChatId, $task['phone']);
$msgConf = is_string($task_info['msgConf']) ? json_decode($task_info['msgConf'], 1) : $task_info['msgConf'];
@@ -316,7 +314,7 @@ class Adapter implements WeChatServiceInterface
if (isset($latestFriendTask['status']) && $latestFriendTask['status'] == 1) {
Db::name('task_customer')
->where('id', $task['id'])
->update(['status' => 2, 'updated_at' => time()]);
->update(['status' => 2, 'updateTime' => time()]);
break;
}
@@ -324,7 +322,7 @@ class Adapter implements WeChatServiceInterface
if (isset($latestFriendTask['status']) && $latestFriendTask['status'] == 2) {
Db::name('task_customer')
->where('id', $task['id'])
->update(['status' => 3, 'fail_reason' => $latestFriendTask['extra'] ?? '未知原因', 'updated_at' => time()]);
->update(['status' => 3, 'fail_reason' => $latestFriendTask['extra'] ?? '未知原因', 'updateTime' => time()]);
break;
}
}