import { getDetail, getList as getCustomerList } from '@/api/vehicle/customer-archive'; import { getList as getDriverList } from '@/api/transportCapacity/driver'; import { getList as getVehicleList } from '@/api/transportCapacity/transport-vehicle'; const orgNameCache = new Map(); const extractRecords = res => { const data = res?.data?.data ?? res?.data ?? res; if (Array.isArray(data)) return data; if (Array.isArray(data?.records)) return data.records; if (Array.isArray(data?.data)) return data.data; return []; }; const normalizeOrgName = value => String(value || '').trim(); const uniqueOrgNames = (values = []) => { const seen = new Set(); const result = []; values.forEach(value => { const name = normalizeOrgName(value); if (!name || seen.has(name)) return; seen.add(name); result.push(name); }); return result; }; // 候选司机取数上限:超出后只能靠关键字缩小范围 const DRIVER_CANDIDATE_MAX_SIZE = 200; /** * 派单候选司机:租户内的司机档案,按岗位等条件过滤。 * * 与组织、承运商都无关——司机档案与组织树、承运商之间没有外键,`organization_name` * 只是自由文本,用它做匹配会让小程序自动建档的司机永远进不了候选。 */ export const fetchDriverCandidates = async (query = {}) => { const params = { ...query }; const size = Math.min(Math.max(Number(params.size) || 50, 50), DRIVER_CANDIDATE_MAX_SIZE); delete params.size; const res = await getDriverList(1, size, params); return extractRecords(res).slice(0, size); }; /** * 司机候选项的展示文本:姓名(手机尾号后 4 位)。 * * 只用于下拉渲染。写回表单的仍是姓名本身,别把带尾号的文本当值用。 */ export const driverOptionText = (item = {}) => { const name = normalizeOrgName(item.driverName || item.name); const mobile = String(item.mobile || item.phone || item.driverPhone || '').trim(); if (!name) return ''; return mobile.length >= 4 ? `${name}(${mobile.slice(-4)})` : name; }; /** * 解析承运商客商档案上联系人的所属组织(branchName),无联系人时回退客商所属组织。 */ export const resolveCarrierOrganizationNames = async ({ carrierId, carrierName } = {}) => { const id = String(carrierId || '').trim(); const name = normalizeOrgName(carrierName); const cacheKey = id || name; if (!cacheKey) return []; if (orgNameCache.has(cacheKey)) return orgNameCache.get(cacheKey); let detail = null; if (id) { try { const res = await getDetail(id); detail = res?.data?.data || res?.data || null; } catch (error) { detail = null; } } if (!detail && name) { try { const res = await getCustomerList(1, 20, { fullName: name }); const records = extractRecords(res); const matched = records.find(item => normalizeOrgName(item.fullName || item.customerName) === name) || records[0]; if (matched?.id) { const detailRes = await getDetail(matched.id); detail = detailRes?.data?.data || detailRes?.data || matched; } } catch (error) { detail = null; } } const contacts = Array.isArray(detail?.contacts) ? detail.contacts : []; const orgNames = uniqueOrgNames([ ...contacts.map(item => item.branchName), detail?.deptName, detail?.organizationName, ]); orgNameCache.set(cacheKey, orgNames); if (id && name) orgNameCache.set(name, orgNames); return orgNames; }; export const matchOrganizationName = (value, orgNames = []) => { const text = normalizeOrgName(value); if (!text || !orgNames.length) return false; return orgNames.some(org => text === org || text.includes(org) || org.includes(text)); }; const filterByOrganizations = (records = [], orgNames = []) => { if (!orgNames.length) return []; return records.filter(item => matchOrganizationName(item.organizationName, orgNames)); }; /** * 按承运商联系人所属组织筛选车辆。 * 未选择承运商时返回空列表(需先选承运商)。 */ export const fetchVehiclesByCarrierOrganizations = async ( query = {}, { carrierId, carrierName } = {} ) => { if (!String(carrierId || '').trim() && !normalizeOrgName(carrierName)) { return []; } const orgNames = await resolveCarrierOrganizationNames({ carrierId, carrierName }); if (!orgNames.length) return []; const size = Math.max(Number(query.size) || 50, 50); const params = { ...query }; delete params.size; if (orgNames.length === 1) { params.organizationName = orgNames[0]; } const res = await getVehicleList(1, Math.min(size * 5, 200), params); return filterByOrganizations(extractRecords(res), orgNames).slice(0, size); };