forked from wangziqi/gongxue-base
feat: add CRM lead assignment strategies
This commit is contained in:
@@ -62,7 +62,17 @@ export default function TenantMarketingPage() {
|
||||
const [commissionOrders, setCommissionOrders] = useState<CommissionOrderItem[]>([]);
|
||||
const [settlements, setSettlements] = useState<CommissionSettlementItem[]>([]);
|
||||
const [members, setMembers] = useState<TenantMemberItem[]>([]);
|
||||
const [crmForm, setCrmForm] = useState({ enabled: false, url: '', secretRef: '', formName: '刷题题库', examType: '专升本', timeoutSec: '10', delaySec: '60' });
|
||||
const [crmForm, setCrmForm] = useState({
|
||||
enabled: false,
|
||||
url: '',
|
||||
secretRef: '',
|
||||
formName: '刷题题库',
|
||||
examType: '专升本',
|
||||
timeoutSec: '10',
|
||||
delaySec: '60',
|
||||
assignmentMode: 'none' as 'none' | 'direct' | 'round_robin' | 'referrer',
|
||||
assignmentPoolText: '',
|
||||
});
|
||||
const [commissionForm, setCommissionForm] = useState({ defaultRatePercent: '20', minSettlementYuan: '0', settlementCycle: 'monthly' });
|
||||
const [period, setPeriod] = useState({ startDate: monthStart(), endDate: today(), referrerUserId: '' });
|
||||
const [memberRate, setMemberRate] = useState({ userId: '', ratePercent: '' });
|
||||
@@ -112,6 +122,8 @@ export default function TenantMarketingPage() {
|
||||
examType: nextCrm.examType || '专升本',
|
||||
timeoutSec: String(nextCrm.timeoutSec || 10),
|
||||
delaySec: String(nextCrm.delaySec || 60),
|
||||
assignmentMode: nextCrm.assignmentMode || 'none',
|
||||
assignmentPoolText: (nextCrm.assignmentPool || []).join(','),
|
||||
});
|
||||
}
|
||||
if (nextSettings) {
|
||||
@@ -142,6 +154,8 @@ export default function TenantMarketingPage() {
|
||||
examType: crmForm.examType.trim() || '专升本',
|
||||
timeoutSec: Math.max(1, Math.trunc(Number(crmForm.timeoutSec || 10))),
|
||||
delaySec: Math.max(0, Math.trunc(Number(crmForm.delaySec || 60))),
|
||||
assignmentMode: crmForm.assignmentMode,
|
||||
assignmentPool: crmForm.assignmentPoolText.split(',').map(item => item.trim()).filter(Boolean),
|
||||
});
|
||||
setCrmConfig(result.item || null);
|
||||
Taro.showToast({ title: 'CRM 已保存', icon: 'success' });
|
||||
@@ -304,6 +318,18 @@ export default function TenantMarketingPage() {
|
||||
<Input className='admin-input' placeholder='考试类型' value={crmForm.examType} onInput={event => setCrmForm(prev => ({ ...prev, examType: String(event.detail.value || '') }))} />
|
||||
<Input className='admin-input' type='number' placeholder='超时秒数' value={crmForm.timeoutSec} onInput={event => setCrmForm(prev => ({ ...prev, timeoutSec: String(event.detail.value || '') }))} />
|
||||
<Input className='admin-input' type='number' placeholder='延迟推送秒数' value={crmForm.delaySec} onInput={event => setCrmForm(prev => ({ ...prev, delaySec: String(event.detail.value || '') }))} />
|
||||
<View className='admin-actions compact'>
|
||||
{(['none', 'referrer', 'direct', 'round_robin'] as const).map(mode => (
|
||||
<Button
|
||||
key={mode}
|
||||
className={`admin-button ${crmForm.assignmentMode === mode ? 'active' : ''}`}
|
||||
onClick={() => setCrmForm(prev => ({ ...prev, assignmentMode: mode }))}
|
||||
>
|
||||
{mode === 'none' ? '不分配' : mode === 'referrer' ? '归属人跟进' : mode === 'direct' ? '固定负责人' : '轮询分配'}
|
||||
</Button>
|
||||
))}
|
||||
</View>
|
||||
<Input className='admin-input' placeholder='负责人用户ID,多个用英文逗号分隔' value={crmForm.assignmentPoolText} onInput={event => setCrmForm(prev => ({ ...prev, assignmentPoolText: String(event.detail.value || '') }))} />
|
||||
</View>
|
||||
<View className='admin-actions compact'>
|
||||
<Button className='admin-button primary' loading={busy === 'crm'} onClick={saveCrmConfig}>保存 CRM</Button>
|
||||
@@ -312,6 +338,15 @@ export default function TenantMarketingPage() {
|
||||
<View className='admin-row'>
|
||||
<Text className='admin-row-main'>{crmConfig?.enabled ? 'CRM 已启用' : 'CRM 未启用'}</Text>
|
||||
<Text className='admin-row-meta'>{crmConfig?.url || '未配置 URL'} · {crmConfig?.secretRef || '未配置 secretRef'}</Text>
|
||||
<Text className='admin-row-meta'>分配策略 {crmConfig?.assignmentMode || 'none'} · 候选 {crmConfig?.assignmentPool?.length || 0} 人 · 游标 {crmConfig?.assignmentCursor || 0}</Text>
|
||||
</View>
|
||||
<View className='admin-list compact'>
|
||||
{salesMembers.slice(0, 8).map(item => (
|
||||
<View className='admin-row' key={item.userId}>
|
||||
<Text className='admin-row-main'>{item.name || item.username || item.userId}</Text>
|
||||
<Text className='admin-row-meta'>{item.role} · {item.userId}</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user