230 lines
10 KiB
PHP
230 lines
10 KiB
PHP
<?php
|
||
/**
|
||
* 硬碎片转换为主表接口 POST /api/fragment/hard_convert.php
|
||
* 入参:id(硬碎片ID,必填)/ target_type(company|person|product|need,必填)/
|
||
* 补全字段:company_name, person_name, contact_phone, contact_email, target_product_category,
|
||
* description, industry, need_category, application_scenario, contact_person
|
||
* 逻辑:按目标类型写入主表(product/need 缺公司时自动建公司)→ 标记碎片已转换(converted_type/id, processed_at)
|
||
*/
|
||
require_once __DIR__ . '/../common/db.php';
|
||
require_once __DIR__ . '/../common/response.php';
|
||
require_once __DIR__ . '/../common/auth.php';
|
||
require_once __DIR__ . '/../common/logger.php';
|
||
require_once __DIR__ . '/../common/completeness.php';
|
||
require_once __DIR__ . '/../common/duplicate_check.php';
|
||
require_once __DIR__ . '/../common/validate.php';
|
||
|
||
checkAjax();
|
||
checkPermission('preliminary');
|
||
|
||
$id = (int)($_POST['id'] ?? 0);
|
||
$targetType = trim($_POST['target_type'] ?? '');
|
||
if ($id <= 0 || !in_array($targetType, ['company', 'person', 'product', 'need'], true)) {
|
||
Response::error('参数错误', 400);
|
||
}
|
||
|
||
$pdo = DB::getInstance()->getPdo();
|
||
|
||
$stmt = $pdo->prepare("SELECT * FROM preliminary_data WHERE id = ? AND is_active = 1");
|
||
$stmt->execute([$id]);
|
||
$frag = $stmt->fetch();
|
||
if (!$frag) {
|
||
Response::error('碎片不存在');
|
||
}
|
||
if ($frag['converted_id']) {
|
||
Response::error('该碎片已处理(已转换)');
|
||
}
|
||
|
||
$companyName = trim($_POST['company_name'] ?? ($frag['company_name'] ?? ''));
|
||
$personName = trim($_POST['person_name'] ?? ($frag['person_name'] ?? ''));
|
||
$phone = trim($_POST['contact_phone'] ?? ($frag['contact_phone'] ?? ''));
|
||
$email = trim($_POST['contact_email'] ?? ($frag['contact_email'] ?? ''));
|
||
$industry = trim($_POST['industry'] ?? ($frag['industry'] ?? '')); // 核心-企业(转软碎片必填)
|
||
$registrationNum = trim($_POST['registration_number'] ?? ($frag['registration_number'] ?? '')); // 核心-企业(转软碎片必填)
|
||
$businessRole = trim($_POST['business_role'] ?? ($frag['business_role'] ?? ''));
|
||
$country = trim($_POST['country'] ?? ($frag['country'] ?? ''));
|
||
$address = trim($_POST['address'] ?? ($frag['address'] ?? ''));
|
||
$workLocation = trim($_POST['work_location'] ?? ($frag['work_location'] ?? ''));
|
||
$idNumber = trim($_POST['id_number'] ?? ($frag['id_number'] ?? ''));
|
||
$platform = trim($_POST['platform'] ?? ($frag['platform'] ?? ''));
|
||
$accountId = trim($_POST['account_id'] ?? ($frag['account_id'] ?? ''));
|
||
$profileUrl = trim($_POST['profile_url'] ?? ($frag['profile_url'] ?? ''));
|
||
$sourceChannel = $frag['source_channel'] ?? null;
|
||
|
||
$convertedId = 0;
|
||
|
||
// 格式校验:手机 / 邮箱 / 身份证 / 主页链接
|
||
checkFieldFormat('phone', $phone);
|
||
checkFieldFormat('email', $email);
|
||
checkFieldFormat('id_number', $idNumber);
|
||
if ($profileUrl !== '' && !preg_match('/^https?:\/\//i', $profileUrl)) {
|
||
Response::error('主页链接格式不正确(应以 http:// 或 https:// 开头)', 400);
|
||
}
|
||
|
||
// 各类型转软碎片基本要求
|
||
switch ($targetType) {
|
||
case 'company':
|
||
if ($companyName === '') {
|
||
Response::error('企业类型转软碎片:企业名称为必填项,请先「手动补全」', 400);
|
||
}
|
||
if ($industry === '') {
|
||
Response::error('企业类型转软碎片:行业为必填项,请先「手动补全」填写行业', 400);
|
||
}
|
||
if ($registrationNum === '') {
|
||
Response::error('企业类型转软碎片:注册号为必填项,请先「手动补全」填写注册号', 400);
|
||
}
|
||
break;
|
||
case 'person':
|
||
if ($personName === '') {
|
||
Response::error('人员类型转软碎片:姓名为必填项,请先「手动补全」', 400);
|
||
}
|
||
if ($phone === '' && $email === '') {
|
||
Response::error('人员类型转软碎片:手机号码、邮箱至少填写一项,请先「手动补全」', 400);
|
||
}
|
||
break;
|
||
case 'product':
|
||
if ($companyName === '') {
|
||
Response::error('产品类型转软碎片:公司名称为必填项,请先「手动补全」', 400);
|
||
}
|
||
break;
|
||
case 'need':
|
||
if ($companyName === '') {
|
||
Response::error('需求类型转软碎片:公司名称为必填项,请先「手动补全」', 400);
|
||
}
|
||
break;
|
||
}
|
||
|
||
// 唯一性校验:按目标类型,收集全部重复
|
||
$dups = [];
|
||
if ($targetType === 'company' && $companyName !== '') {
|
||
$dup = findDuplicate($pdo, 'company_name', $companyName);
|
||
if ($dup) $dups[] = $dup;
|
||
}
|
||
if (in_array($targetType, ['person', 'company'], true)) {
|
||
$dups = array_merge($dups, checkSingleAccountDuplicate($pdo, $phone !== '' ? 'phone' : '', $phone, ''));
|
||
$dups = array_merge($dups, checkSingleAccountDuplicate($pdo, $email !== '' ? 'email' : '', $email, ''));
|
||
}
|
||
if (!empty($dups)) Response::duplicates($dups);
|
||
|
||
/** 创建 social_accounts(phone/email,常用) */
|
||
$saveContacts = function ($ownerType, $ownerId) use ($pdo, $phone, $email) {
|
||
if ($phone !== '') {
|
||
$pdo->prepare(
|
||
"INSERT INTO social_accounts (owner_type, owner_id, platform, account_id, is_primary, is_defult)
|
||
VALUES (?, ?, 'phone', ?, 1, 1)"
|
||
)->execute([$ownerType, $ownerId, $phone]);
|
||
}
|
||
if ($email !== '') {
|
||
$pdo->prepare(
|
||
"INSERT INTO social_accounts (owner_type, owner_id, platform, account_id, is_primary, is_defult)
|
||
VALUES (?, ?, 'email', ?, 1, 1)"
|
||
)->execute([$ownerType, $ownerId, $email]);
|
||
}
|
||
};
|
||
|
||
/** 写入社媒账号(platform + account_id,主页链接作备注) */
|
||
function saveSocialAccountIfAny(PDO $pdo, $ownerType, $ownerId, $platform, $accountId, $profileUrl = '')
|
||
{
|
||
$platform = trim((string)$platform);
|
||
$accountId = trim((string)$accountId);
|
||
if ($platform === '' || $accountId === '' || in_array($platform, ['phone', 'email'], true)) {
|
||
return;
|
||
}
|
||
$pdo->prepare(
|
||
"INSERT INTO social_accounts (owner_type, owner_id, platform, account_id, profile_url, is_primary, is_defult)
|
||
VALUES (?, ?, ?, ?, ?, 0, 0)"
|
||
)->execute([$ownerType, $ownerId, $platform, $accountId, trim((string)$profileUrl) !== '' ? $profileUrl : null]);
|
||
}
|
||
|
||
/** 按名称找公司,找不到则自动创建 */
|
||
$resolveCompany = function () use ($pdo, $companyName, $sourceChannel, $industry, $registrationNum) {
|
||
$stmt = $pdo->prepare("SELECT id FROM companies WHERE display_name = ? AND is_active = 1 LIMIT 1");
|
||
$stmt->execute([$companyName]);
|
||
$cid = (int)$stmt->fetchColumn();
|
||
if ($cid > 0) {
|
||
return $cid;
|
||
}
|
||
$pdo->prepare(
|
||
"INSERT INTO companies (display_name, name_zh, industry, registration_number, source_channel) VALUES (?, ?, ?, ?, ?)"
|
||
)->execute([$companyName, $companyName, $industry !== '' ? $industry : null, $registrationNum !== '' ? $registrationNum : null, $sourceChannel]);
|
||
return (int)$pdo->lastInsertId();
|
||
};
|
||
|
||
switch ($targetType) {
|
||
case 'company':
|
||
$pdo->prepare(
|
||
"INSERT INTO companies (display_name, name_zh, industry, registration_number, business_role, country, address, source_channel)
|
||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
|
||
)->execute([
|
||
$companyName, $companyName,
|
||
$industry !== '' ? $industry : null,
|
||
$registrationNum !== '' ? $registrationNum : null,
|
||
$businessRole !== '' ? $businessRole : null,
|
||
$country !== '' ? $country : null,
|
||
$address !== '' ? $address : null,
|
||
$sourceChannel,
|
||
]);
|
||
$convertedId = (int)$pdo->lastInsertId();
|
||
$saveContacts('company', $convertedId);
|
||
saveSocialAccountIfAny($pdo, 'company', $convertedId, $platform, $accountId, $profileUrl);
|
||
updateIncomplete($pdo, 'companies', $convertedId);
|
||
updateAccountsIncomplete($pdo, 'company', $convertedId);
|
||
break;
|
||
|
||
case 'person':
|
||
$unionId = 'P' . date('YmdHis') . substr(uniqid(), -6);
|
||
$pdo->prepare(
|
||
"INSERT INTO persons (union_id, full_name, work_location, id_number, source_channel) VALUES (?, ?, ?, ?, ?)"
|
||
)->execute([
|
||
$unionId, $personName,
|
||
$workLocation !== '' ? $workLocation : null,
|
||
$idNumber !== '' ? $idNumber : null,
|
||
$sourceChannel,
|
||
]);
|
||
$convertedId = (int)$pdo->lastInsertId();
|
||
$saveContacts('person', $convertedId);
|
||
saveSocialAccountIfAny($pdo, 'person', $convertedId, $platform, $accountId, $profileUrl);
|
||
updateIncomplete($pdo, 'persons', $convertedId);
|
||
updateAccountsIncomplete($pdo, 'person', $convertedId);
|
||
break;
|
||
|
||
case 'product':
|
||
$companyId = $resolveCompany();
|
||
// 品类字段已在 preliminary 移除(非必要/待定),转换时默认「未分类」
|
||
$pdo->prepare(
|
||
"INSERT INTO company_products (company_id, category_name)
|
||
VALUES (?, '未分类')"
|
||
)->execute([$companyId]);
|
||
$convertedId = (int)$pdo->lastInsertId();
|
||
updateIncomplete($pdo, 'companies', $companyId);
|
||
break;
|
||
|
||
case 'need':
|
||
$companyId = $resolveCompany();
|
||
$contactPerson = trim($_POST['contact_person'] ?? ($frag['person_name'] ?? ''));
|
||
$pdo->prepare(
|
||
"INSERT INTO company_needs (company_id, contact_person, description)
|
||
VALUES (?, ?, ?)"
|
||
)->execute([
|
||
$companyId,
|
||
$contactPerson !== '' ? $contactPerson : null,
|
||
null,
|
||
]);
|
||
$convertedId = (int)$pdo->lastInsertId();
|
||
updateIncomplete($pdo, 'companies', $companyId);
|
||
break;
|
||
}
|
||
|
||
// 标记碎片已转换(v1.0.50 起不再写 status 字段,以 converted_id 非空标识已转换)
|
||
$pdo->prepare(
|
||
"UPDATE preliminary_data SET converted_type = ?, converted_id = ?, processed_at = NOW() WHERE id = ?"
|
||
)->execute([$targetType, $convertedId, $id]);
|
||
|
||
logCurrent('convert', 'fragment', 'preliminary_data', $id, [
|
||
'target_type' => $targetType,
|
||
'converted_id' => $convertedId,
|
||
'fields' => ['company_name' => $companyName, 'person_name' => $personName, 'phone' => $phone, 'email' => $email],
|
||
]);
|
||
|
||
Response::success(['converted_type' => $targetType, 'converted_id' => $convertedId], '转换成功');
|