- customers 表新增 rating_score/rating_time(V13 迁移 + V10 SQL + init-dev 同步)
- 新端点 PUT /customers/{id}/rating:评分是档案属性,只存总分与评级时间(五项明细不落库)
- 列表排序 order_by=rating_score,未评分客户升序/降序都垫底,id desc 兜底稳定分页
- 前端 RatingCalculatorDialog 并入客户管理(评分列 + 评级计算按钮),删除独立页与路由
- 测试:评级保存/越界/排序垫底 3 例,test_customers.py 18 passed;schema 同步 216 passed
149 lines
5.2 KiB
TypeScript
149 lines
5.2 KiB
TypeScript
import { request } from './request'
|
||
import type { PageData } from './types'
|
||
|
||
/**
|
||
* 客户列表项(对应后端 `CustomerOut`)。
|
||
*
|
||
* owner_personnel_name 由联表带出:归属人员不可考(被物理删除)时为 null,
|
||
* owner_personnel_id 仍保留原值供追溯。
|
||
*/
|
||
export interface CustomerItem {
|
||
id: number
|
||
company_name: string
|
||
/** 客户公司的负责人姓名(非系统内营销人员) */
|
||
owner_name: string
|
||
contact_person: string | null
|
||
contact_phone: string | null
|
||
address: string | null
|
||
industry: string | null
|
||
/** personal 个人户 / manager_personal 经理个人户 / enterprise 企业户(计提规则锚点) */
|
||
customer_type: string
|
||
owner_personnel_id: number | null
|
||
owner_personnel_name: string | null
|
||
remark: string | null
|
||
/** 评级总分(0-100,评级计算器保存;null=未评分) */
|
||
rating_score: number | null
|
||
/** 最近评级时间(评级计算器保存评分时刷新;null=从未评级) */
|
||
rating_time: string | null
|
||
}
|
||
|
||
export interface CustomerQueryParams {
|
||
pageNum?: number
|
||
pageSize?: number
|
||
/** 公司名称或客户负责人,模糊匹配 */
|
||
keyword?: string
|
||
customer_type?: string
|
||
owner_personnel_id?: number
|
||
/** 排序键(后端白名单:id 建档序 / rating_score 评分),默认 id 倒序 */
|
||
order_by?: 'id' | 'rating_score'
|
||
/** 排序方向,默认 desc */
|
||
order?: 'asc' | 'desc'
|
||
}
|
||
|
||
/** 新增客户(owner_personnel_id 为初始归属,可空:先建档后派归属也合法) */
|
||
export interface CustomerCreateParams {
|
||
company_name: string
|
||
owner_name: string
|
||
contact_person?: string | null
|
||
contact_phone?: string | null
|
||
address?: string | null
|
||
industry?: string | null
|
||
customer_type: string
|
||
owner_personnel_id?: number | null
|
||
remark?: string | null
|
||
}
|
||
|
||
/**
|
||
* 编辑客户:不含归属字段 —— 归属调整统一走 `PUT /{id}/ownership`
|
||
* (唯一写归属留痕的入口),编辑表单即使提交归属也会被后端忽略。
|
||
*/
|
||
export type CustomerUpdateParams = Omit<CustomerCreateParams, 'owner_personnel_id'>
|
||
|
||
/** 归属变更入参(new_owner_personnel_id 空 = 清空归属) */
|
||
export interface CustomerOwnershipParams {
|
||
new_owner_personnel_id?: number | null
|
||
reason?: string | null
|
||
}
|
||
|
||
/** 保存评级入参:只存总分(五项明细不落库,评分是档案属性而非审计事件) */
|
||
export interface CustomerRatingParams {
|
||
score: number
|
||
}
|
||
|
||
/** 归属变更留痕条目(对应后端 `OwnershipChangeLogOut`;姓名可随人员消失,ID 固化) */
|
||
export interface OwnershipLogItem {
|
||
id: number
|
||
customer_id: number
|
||
old_owner_personnel_id: number | null
|
||
new_owner_personnel_id: number | null
|
||
old_owner_name: string | null
|
||
new_owner_name: string | null
|
||
change_reason: string | null
|
||
operator_id: number | null
|
||
operator_name: string
|
||
create_time: string
|
||
}
|
||
|
||
/** 客户分类下拉项(与后端 `core/constants.py` 的值域一致) */
|
||
export const CUSTOMER_TYPE_OPTIONS = [
|
||
{ label: '个人户', value: 'personal' },
|
||
{ label: '经理个人户', value: 'manager_personal' },
|
||
{ label: '企业户', value: 'enterprise' },
|
||
] as const
|
||
|
||
/** 分类编码 → 展示名(表格列展示用,未知编码原样回显) */
|
||
export function customerTypeLabel(code: string): string {
|
||
return CUSTOMER_TYPE_OPTIONS.find((o) => o.value === code)?.label ?? code
|
||
}
|
||
|
||
/** 分页查询客户(keyword 对公司名称/客户负责人模糊匹配,附归属人员姓名) */
|
||
export function listCustomers(params: CustomerQueryParams): Promise<PageData<CustomerItem>> {
|
||
return request({ url: '/v1/base/customers', method: 'get', params })
|
||
}
|
||
|
||
/** 新增客户(公司名称+负责人组合唯一,冲突由后端拦截) */
|
||
export function createCustomer(data: CustomerCreateParams): Promise<CustomerItem> {
|
||
return request({ url: '/v1/base/customers', method: 'post', data })
|
||
}
|
||
|
||
/** 编辑客户档案(不含归属;全量提交) */
|
||
export function updateCustomer(
|
||
customerId: number,
|
||
data: CustomerUpdateParams,
|
||
): Promise<CustomerItem> {
|
||
return request({ url: `/v1/base/customers/${customerId}`, method: 'put', data })
|
||
}
|
||
|
||
/** 删除客户(物理删除) */
|
||
export function deleteCustomer(customerId: number): Promise<null> {
|
||
return request({ url: `/v1/base/customers/${customerId}`, method: 'delete' })
|
||
}
|
||
|
||
/** 归属变更(唯一写归属留痕的入口;新旧相同后端报「归属未变化」) */
|
||
export function changeOwnership(
|
||
customerId: number,
|
||
data: CustomerOwnershipParams,
|
||
): Promise<CustomerItem> {
|
||
return request({ url: `/v1/base/customers/${customerId}/ownership`, method: 'put', data })
|
||
}
|
||
|
||
/** 保存评级(评级计算器「保存评分」;只存总分与评级时间,评分只走本端点) */
|
||
export function rateCustomer(
|
||
customerId: number,
|
||
data: CustomerRatingParams,
|
||
): Promise<CustomerItem> {
|
||
return request({ url: `/v1/base/customers/${customerId}/rating`, method: 'put', data })
|
||
}
|
||
|
||
/** 查某客户的归属变更留痕(分页,按变更时间倒序) */
|
||
export function listOwnershipLogs(
|
||
customerId: number,
|
||
params: { pageNum?: number; pageSize?: number },
|
||
): Promise<PageData<OwnershipLogItem>> {
|
||
return request({
|
||
url: `/v1/base/customers/${customerId}/ownership-logs`,
|
||
method: 'get',
|
||
params,
|
||
})
|
||
}
|