296 lines
8.2 KiB
TypeScript
296 lines
8.2 KiB
TypeScript
/**
|
|
* 线索管理 API(门户 POST 风格,兼容原 CRM 函数名)
|
|
*/
|
|
import request from '@/utils/http'
|
|
import type {
|
|
ClueQuery,
|
|
ClueForm,
|
|
ClueAssignParams,
|
|
ClueStatusParams,
|
|
ClueLevelParams,
|
|
ClueConvertParams,
|
|
ClueFollowQuery,
|
|
ClueFollowForm
|
|
} from './types'
|
|
|
|
const BASE = '/web/crm/clue'
|
|
|
|
function unwrapData(res: any) {
|
|
return res?.data ?? res ?? {}
|
|
}
|
|
|
|
function mapListQuery(query: ClueQuery = {}): Record<string, any> {
|
|
const body: Record<string, any> = {
|
|
page: query.pageNum ?? 1,
|
|
pageSize: query.pageSize ?? 20
|
|
}
|
|
if (query.clueName) body.clueName = query.clueName
|
|
if (query.company) body.company = query.company
|
|
if (query.mobile) body.mobile = query.mobile
|
|
if (query.source) body.source = query.source
|
|
if (query.level) body.level = query.level
|
|
if (query.status) body.status = query.status
|
|
if (query.industry) body.industry = query.industry
|
|
if (query.parkArea) body.parkArea = query.parkArea
|
|
if (query.ownerUserId != null) body.ownerUserId = String(query.ownerUserId)
|
|
if (query.beginTime) body.beginTime = query.beginTime
|
|
if (query.endTime) body.endTime = query.endTime
|
|
if (query.keyword) body.keyword = query.keyword
|
|
if (query.isConverted === 1) body.viewType = 'converted'
|
|
return body
|
|
}
|
|
|
|
async function postList(url: string, query?: ClueQuery) {
|
|
const res = await request.post({ url, data: mapListQuery(query) })
|
|
const data = unwrapData(res)
|
|
return { rows: data.list || data.rows || [], total: data.total ?? 0 }
|
|
}
|
|
|
|
// ── 线索 CRUD ──
|
|
|
|
export function listClue(query?: ClueQuery) {
|
|
return postList(`${BASE}/list`, query)
|
|
}
|
|
|
|
export function listMyClue(query?: ClueQuery) {
|
|
return postList(`${BASE}/mine`, query)
|
|
}
|
|
|
|
export function listToFollowClue(query?: ClueQuery) {
|
|
return postList(`${BASE}/toFollow`, query)
|
|
}
|
|
|
|
export async function listTodayNewClue(query?: ClueQuery) {
|
|
return postList(`${BASE}/todayNew`, query)
|
|
}
|
|
|
|
export async function getClue(id: number | string) {
|
|
const res = await request.post({ url: `${BASE}/detail`, data: { id: String(id) } })
|
|
return { data: unwrapData(res) }
|
|
}
|
|
|
|
export function addClue(data: ClueForm) {
|
|
return request.post({ url: `${BASE}/add`, data })
|
|
}
|
|
|
|
export function updateClue(data: ClueForm) {
|
|
return request.post({ url: `${BASE}/update`, data })
|
|
}
|
|
|
|
export function delClue(ids: number | number[] | string | string[]) {
|
|
const idList = Array.isArray(ids) ? ids.map(String) : [String(ids)]
|
|
return request.post({ url: `${BASE}/delete`, data: { ids: idList } })
|
|
}
|
|
|
|
export function assignClue(data: ClueAssignParams) {
|
|
return request.post({
|
|
url: `${BASE}/assign`,
|
|
data: {
|
|
ids: (data.ids || []).map(String),
|
|
ownerUserId: data.ownerUserId != null ? String(data.ownerUserId) : undefined,
|
|
remark: data.remark
|
|
}
|
|
})
|
|
}
|
|
|
|
export function updateClueStatus(data: ClueStatusParams) {
|
|
const id = data.id ?? (Array.isArray(data.ids) ? data.ids[0] : undefined)
|
|
return request.post({
|
|
url: `${BASE}/updateStatus`,
|
|
data: { id: String(id), status: data.status }
|
|
})
|
|
}
|
|
|
|
export function markInvalid(data: {
|
|
id?: string | number
|
|
ids?: (string | number)[]
|
|
remark?: string
|
|
}) {
|
|
const body: Record<string, any> = { remark: data.remark }
|
|
if (data.ids?.length) {
|
|
body.ids = data.ids.map(String)
|
|
} else if (data.id != null) {
|
|
body.id = String(data.id)
|
|
}
|
|
return request.post({
|
|
url: `${BASE}/invalid`,
|
|
data: body
|
|
})
|
|
}
|
|
|
|
export function updateClueLevel(data: ClueLevelParams) {
|
|
return request.post({
|
|
url: `${BASE}/updateLevel`,
|
|
data: {
|
|
ids: (data.ids || []).map(String),
|
|
level: data.level
|
|
}
|
|
})
|
|
}
|
|
|
|
export function convertClue(data: ClueConvertParams) {
|
|
const clueId = data.clueId ?? (data as any).id
|
|
return request.post({
|
|
url: `${BASE}/convert`,
|
|
data: {
|
|
id: String(clueId),
|
|
customerName: data.customerName,
|
|
customerType: data.customerType,
|
|
contactName: data.contactName,
|
|
contactMobile: data.contactMobile,
|
|
remark: data.remark
|
|
}
|
|
})
|
|
}
|
|
|
|
export async function checkConvert(id: number | string) {
|
|
const res = await request.post({ url: `${BASE}/checkConvert`, data: { id: String(id) } })
|
|
return { data: unwrapData(res) }
|
|
}
|
|
|
|
export function exportClue(data: Record<string, any> = {}) {
|
|
const { ids, columns, ...rest } = data
|
|
const body: Record<string, any> = {
|
|
...mapListQuery(rest as ClueQuery),
|
|
...(ids ? { ids } : {}),
|
|
...(columns ? { columns } : {})
|
|
}
|
|
return request.post({
|
|
url: `${BASE}/export`,
|
|
data: body,
|
|
responseType: 'blob',
|
|
showErrorMessage: false
|
|
})
|
|
}
|
|
|
|
export function importTemplate() {
|
|
return request.post({
|
|
url: `${BASE}/importTemplate`,
|
|
responseType: 'blob'
|
|
})
|
|
}
|
|
|
|
export function importClue(file: File, updateSupport = false) {
|
|
const formData = new FormData()
|
|
formData.append('file', file)
|
|
formData.append('updateSupport', String(updateSupport))
|
|
return request.post({
|
|
url: `${BASE}/import`,
|
|
data: formData,
|
|
headers: { 'Content-Type': 'multipart/form-data' }
|
|
})
|
|
}
|
|
|
|
export async function checkDuplicateClue(data: {
|
|
mobile?: string
|
|
company?: string
|
|
excludeId?: string | number
|
|
}) {
|
|
const res = await request.post({ url: `${BASE}/checkDuplicate`, data })
|
|
return unwrapData(res)
|
|
}
|
|
|
|
export async function getParkAreaList() {
|
|
const res = await request.post({ url: `${BASE}/parkAreaList`, data: {} })
|
|
return { data: unwrapData(res) }
|
|
}
|
|
|
|
// ── 跟进记录 ──
|
|
|
|
export async function listClueFollow(query: ClueFollowQuery) {
|
|
const res = await request.post({
|
|
url: `${BASE}/follow/list`,
|
|
data: {
|
|
clueId: String(query.clueId),
|
|
page: query.pageNum ?? 1,
|
|
pageSize: query.pageSize ?? 20
|
|
}
|
|
})
|
|
const data = unwrapData(res)
|
|
return { rows: data.list || [], total: data.total ?? 0 }
|
|
}
|
|
|
|
export async function getClueFollow(id: number | string) {
|
|
const res = await request.post({ url: `${BASE}/follow/detail`, data: { id: String(id) } })
|
|
return { data: unwrapData(res) }
|
|
}
|
|
|
|
export function addClueFollow(data: ClueFollowForm) {
|
|
return request.post({
|
|
url: `${BASE}/follow/add`,
|
|
data: {
|
|
...data,
|
|
clueId: String(data.clueId)
|
|
}
|
|
})
|
|
}
|
|
|
|
export function updateClueFollow(data: ClueFollowForm) {
|
|
return request.post({
|
|
url: `${BASE}/follow/update`,
|
|
data: {
|
|
...data,
|
|
id: data.id != null ? String(data.id) : undefined,
|
|
clueId: String(data.clueId)
|
|
}
|
|
})
|
|
}
|
|
|
|
export function delClueFollow(ids: number | number[] | string | string[]) {
|
|
const idList = Array.isArray(ids) ? ids.map(String) : [String(ids)]
|
|
return request.post({ url: `${BASE}/follow/delete`, data: { ids: idList } })
|
|
}
|
|
|
|
// ── 统计 ──
|
|
|
|
function mapStatisticsParams(params: Record<string, any> = {}) {
|
|
const body: Record<string, any> = {}
|
|
if (params.beginTime) body.beginTime = params.beginTime
|
|
if (params.endTime) body.endTime = params.endTime
|
|
if (params.ownerUserId != null) body.ownerUserId = String(params.ownerUserId)
|
|
if (params.type) body.timeUnit = params.type
|
|
if (params.timeUnit) body.timeUnit = params.timeUnit
|
|
return body
|
|
}
|
|
|
|
export async function getStatisticsOverview(params?: Record<string, any>) {
|
|
const res = await request.post({
|
|
url: `${BASE}/statistics/overview`,
|
|
data: mapStatisticsParams(params)
|
|
})
|
|
return { data: unwrapData(res) }
|
|
}
|
|
|
|
export async function getStatisticsBySource(params?: Record<string, any>) {
|
|
const res = await request.post({
|
|
url: `${BASE}/statistics/source`,
|
|
data: mapStatisticsParams(params)
|
|
})
|
|
const data = unwrapData(res)
|
|
return { data: Array.isArray(data) ? data : data?.list || [] }
|
|
}
|
|
|
|
export async function getStatisticsByLevel() {
|
|
const res = await request.post({ url: `${BASE}/statistics/level`, data: {} })
|
|
const data = unwrapData(res)
|
|
return { data: Array.isArray(data) ? data : data?.list || [] }
|
|
}
|
|
|
|
export async function getStatisticsTrend(params?: Record<string, any>) {
|
|
const res = await request.post({
|
|
url: `${BASE}/statistics/trend`,
|
|
data: mapStatisticsParams(params)
|
|
})
|
|
const data = unwrapData(res)
|
|
return { data: Array.isArray(data) ? data : data?.list || [] }
|
|
}
|
|
|
|
export async function getStatisticsByOwner(params?: Record<string, any>) {
|
|
const res = await request.post({
|
|
url: `${BASE}/statistics/owner`,
|
|
data: mapStatisticsParams(params)
|
|
})
|
|
const data = unwrapData(res)
|
|
return { data: Array.isArray(data) ? data : data?.list || [] }
|
|
}
|