v1.0.48: preliminary_data重构按三层原则 - 核心+重要字段正式化(business_role/country/address/work_location/id_number/platform/account_id/profile_url新增列,身份证/社媒/主页从extra_info提为正式列)+删除extra_info(品类/需求类别等非必要不再存放)+表单/转换/列表全部适配(product品类默认未分类)

This commit is contained in:
nanguaboss
2026-08-10 00:53:09 +08:00
parent 6cf2aabc91
commit 319fbbe34c
7 changed files with 150 additions and 118 deletions
+26 -23
View File
@@ -22,17 +22,19 @@ if (!in_array($sourceType, ['company', 'person', 'product', 'need', 'mixed'], tr
}
$companyName = trim($_POST['company_name'] ?? '');
$industry = trim($_POST['industry'] ?? ''); // 核心-企业
$registrationNum = trim($_POST['registration_number'] ?? ''); // 核心-企业
$businessRole = trim($_POST['business_role'] ?? ''); // 重要-企业
$country = trim($_POST['country'] ?? ''); // 重要-企业
$address = trim($_POST['address'] ?? ''); // 重要-企业
$personName = trim($_POST['person_name'] ?? '');
$phone = trim($_POST['contact_phone'] ?? '');
$email = trim($_POST['contact_email'] ?? '');
$idNumber = trim($_POST['id_number'] ?? '');
$platform = trim($_POST['platform'] ?? '');
$accountId = trim($_POST['account_id'] ?? '');
$profileUrl = trim($_POST['profile_url'] ?? '');
$industry = trim($_POST['industry'] ?? ''); // 企业:行业
$registrationNum = trim($_POST['registration_number'] ?? ''); // 企业:注册号
$category = trim($_POST['target_product_category'] ?? ''); // 产品:品类(存 extra)
$needCategory = trim($_POST['need_category'] ?? ''); // 需求:需求类别(存 extra)
$workLocation = trim($_POST['work_location'] ?? ''); // 重要-人员
$idNumber = trim($_POST['id_number'] ?? ''); // 重要-人员
$platform = trim($_POST['platform'] ?? ''); // 核心-社媒
$accountId = trim($_POST['account_id'] ?? ''); // 核心-社媒
$profileUrl = trim($_POST['profile_url'] ?? ''); // 重要-主页
$sourceChannel = trim($_POST['source_channel'] ?? '');
// 硬数据标准校验:
@@ -74,36 +76,35 @@ if ($accountId !== '' && $platform !== '') {
}
if (!empty($dups)) Response::duplicates($dups);
// 额外信息(身份证/社媒平台/账号ID/主页链接/产品品类/需求类别)存 extra_info
$extra = [];
if ($idNumber !== '') $extra['id_number'] = $idNumber;
if ($platform !== '') $extra['platform'] = $platform;
if ($accountId !== '') $extra['account_id'] = $accountId;
if ($profileUrl !== '') $extra['profile_url'] = $profileUrl;
if ($category !== '') $extra['category'] = $category;
if ($needCategory !== '') $extra['need_category'] = $needCategory;
// 至少有一项内容才能录为碎片
if ($companyName === '' && $personName === '' && $phone === '' && $email === '' && !$extra) {
if ($companyName === '' && $personName === '' && $phone === '' && $email === '' && $idNumber === '' && $accountId === '') {
Response::error('请至少填写一项内容', 400);
}
$pdo->prepare(
"INSERT INTO preliminary_data
(source_type, company_name, industry, registration_number, person_name, contact_phone, contact_email,
source_channel, recorded_by, status, extra_info)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, '待处理', ?)"
(source_type, company_name, industry, registration_number, business_role, country, address,
person_name, contact_phone, contact_email, work_location, id_number, platform, account_id, profile_url,
source_channel, recorded_by, status)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '待处理')"
)->execute([
$sourceType,
$companyName !== '' ? $companyName : null,
$industry !== '' ? $industry : null,
$registrationNum !== '' ? $registrationNum : null,
$businessRole !== '' ? $businessRole : null,
$country !== '' ? $country : null,
$address !== '' ? $address : null,
$personName !== '' ? $personName : null,
$phone !== '' ? $phone : null,
$email !== '' ? $email : null,
$workLocation !== '' ? $workLocation : null,
$idNumber !== '' ? $idNumber : null,
$platform !== '' ? $platform : null,
$accountId !== '' ? $accountId : null,
$profileUrl !== '' ? $profileUrl : null,
$sourceChannel !== '' ? $sourceChannel : null, // 未选择来源保持空白
$_SESSION['username'] ?? null,
$extra ? json_encode($extra, JSON_UNESCAPED_UNICODE) : null,
]);
$newId = (int)$pdo->lastInsertId();
@@ -113,7 +114,9 @@ logCurrent('add', 'fragment', 'preliminary_data', $newId, [
'person_name' => $personName,
'phone' => $phone,
'email' => $email,
'extra' => $extra,
'id_number' => $idNumber,
'platform' => $platform,
'account_id' => $accountId,
]);
Response::success(['id' => $newId], '新增成功');
+50 -47
View File
@@ -39,25 +39,27 @@ $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'] ?? ''));
$category = trim($_POST['target_product_category'] ?? ''); // 仅补全录入表单提供(表中已无该字段)
$description = trim($_POST['description'] ?? ''); // 仅补全录入表单提供
$industry = trim($_POST['industry'] ?? ($frag['industry'] ?? '')); // 企业:行业(转软碎片必填)
$registrationNum = trim($_POST['registration_number'] ?? ($frag['registration_number'] ?? '')); // 企业:注册号(转软碎片必填)
$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;
// 补全表单额外信息(extra_info)
$fragExtra = json_decode($frag['extra_info'] ?? 'null', true);
if (!is_array($fragExtra)) {
$fragExtra = [];
}
if ($category === '') $category = trim((string)($fragExtra['category'] ?? ''));
$needCategory = trim($_POST['need_category'] ?? ($fragExtra['need_category'] ?? ''));
$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) {
@@ -84,17 +86,11 @@ switch ($targetType) {
if ($companyName === '') {
Response::error('产品类型转软碎片:公司名称为必填项,请先「继续补全」', 400);
}
if ($category === '') {
Response::error('产品类型转软碎片:产品品类为必填项,请先「继续补全」填写品类', 400);
}
break;
case 'need':
if ($companyName === '') {
Response::error('需求类型转软碎片:公司名称为必填项,请先「继续补全」', 400);
}
if ($needCategory === '') {
Response::error('需求类型转软碎片:需求类别为必填项,请先「继续补全」填写需求类别', 400);
}
break;
}
@@ -126,6 +122,20 @@ $saveContacts = function ($ownerType, $ownerId) use ($pdo, $phone, $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");
@@ -143,69 +153,62 @@ $resolveCompany = function () use ($pdo, $companyName, $sourceChannel, $industry
switch ($targetType) {
case 'company':
$pdo->prepare(
"INSERT INTO companies (display_name, name_zh, industry, registration_number, business_scope, source_channel, source_detail)
VALUES (?, ?, ?, ?, ?, ?, ?)"
"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,
$description !== '' ? $description : null,
$businessRole !== '' ? $businessRole : null,
$country !== '' ? $country : null,
$address !== '' ? $address : null,
$sourceChannel,
$description !== '' ? $description : null,
]);
$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':
if ($personName === '') {
Response::error('联系人为必填项', 400);
}
$unionId = 'P' . date('YmdHis') . substr(uniqid(), -6);
$pdo->prepare(
"INSERT INTO persons (union_id, full_name, source_channel, source_detail) VALUES (?, ?, ?, ?)"
)->execute([$unionId, $personName, $sourceChannel, $description !== '' ? $description : null]);
"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':
if ($companyName === '') {
Response::error('公司名称为必填项', 400);
}
if ($category === '') {
Response::error('产品品类为必填项', 400);
}
$companyId = $resolveCompany();
// 品类字段已在 preliminary 移除(非必要/待定),转换时默认「未分类」
$pdo->prepare(
"INSERT INTO company_products (company_id, category_name, category_description)
VALUES (?, ?, ?)"
)->execute([$companyId, $category, $description !== '' ? $description : null]);
"INSERT INTO company_products (company_id, category_name)
VALUES (?, '未分类')"
)->execute([$companyId]);
$convertedId = (int)$pdo->lastInsertId();
updateIncomplete($pdo, 'companies', $companyId);
break;
case 'need':
if ($companyName === '') {
Response::error('公司名称为必填项', 400);
}
$companyId = $resolveCompany();
$contactPerson = trim($_POST['contact_person'] ?? ($frag['person_name'] ?? ''));
$scenario = trim($_POST['application_scenario'] ?? '');
$pdo->prepare(
"INSERT INTO company_needs (company_id, contact_person, need_category, target_product_category, application_scenario, description)
VALUES (?, ?, ?, ?, ?, ?)"
"INSERT INTO company_needs (company_id, contact_person, description)
VALUES (?, ?, ?)"
)->execute([
$companyId,
$contactPerson !== '' ? $contactPerson : null,
$needCategory !== '' ? $needCategory : null,
$category !== '' ? $category : null,
$scenario !== '' ? $scenario : null,
$description !== '' ? $description : null,
null,
]);
$convertedId = (int)$pdo->lastInsertId();
updateIncomplete($pdo, 'companies', $companyId);
+2 -1
View File
@@ -37,7 +37,8 @@ $total = (int)$stmt->fetchColumn();
$offset = ($page - 1) * $limit;
$stmt = $pdo->prepare(
"SELECT id, source_type, company_name, person_name, contact_phone, contact_email,
"SELECT id, source_type, company_name, industry, registration_number, business_role, country, address,
person_name, contact_phone, contact_email, work_location, id_number, platform, account_id, profile_url,
status, source_channel, recorded_by,
follow_person, converted_type, converted_id, created_at, updated_at
FROM preliminary_data
+17 -20
View File
@@ -32,17 +32,19 @@ if (in_array($frag['status'], ['已转换', '已废弃'], true)) {
$sourceType = trim($_POST['source_type'] ?? ($frag['source_type'] ?? ''));
$companyName = trim($_POST['company_name'] ?? '');
$industry = trim($_POST['industry'] ?? '');
$registrationNum = trim($_POST['registration_number'] ?? '');
$businessRole = trim($_POST['business_role'] ?? '');
$country = trim($_POST['country'] ?? '');
$address = trim($_POST['address'] ?? '');
$personName = trim($_POST['person_name'] ?? '');
$phone = trim($_POST['contact_phone'] ?? '');
$email = trim($_POST['contact_email'] ?? '');
$workLocation = trim($_POST['work_location'] ?? '');
$idNumber = trim($_POST['id_number'] ?? '');
$platform = trim($_POST['platform'] ?? '');
$accountId = trim($_POST['account_id'] ?? '');
$profileUrl = trim($_POST['profile_url'] ?? '');
$industry = trim($_POST['industry'] ?? ''); // 企业:行业
$registrationNum = trim($_POST['registration_number'] ?? ''); // 企业:注册号
$category = trim($_POST['target_product_category'] ?? ''); // 产品:品类
$needCategory = trim($_POST['need_category'] ?? ''); // 需求:需求类别
if (!in_array($sourceType, ['company', 'person', 'product', 'need', 'mixed'], true)) {
Response::error('碎片类型不合法', 400);
}
@@ -84,32 +86,27 @@ if ($accountId !== '' && $platform !== '') {
}
if (!empty($dups)) Response::duplicates($dups);
// extra_info 合并更新(身份证/平台/账号ID/主页链接/品类/需求类别)
$extra = json_decode($frag['extra_info'] ?? 'null', true);
if (!is_array($extra)) {
$extra = [];
}
if ($idNumber !== '') $extra['id_number'] = $idNumber; else unset($extra['id_number']);
if ($platform !== '') $extra['platform'] = $platform; else unset($extra['platform']);
if ($accountId !== '') $extra['account_id'] = $accountId; else unset($extra['account_id']);
if ($profileUrl !== '') $extra['profile_url'] = $profileUrl; else unset($extra['profile_url']);
if ($category !== '') $extra['category'] = $category; else unset($extra['category']);
if ($needCategory !== '') $extra['need_category'] = $needCategory; else unset($extra['need_category']);
$pdo->prepare(
"UPDATE preliminary_data
SET source_type = ?, company_name = ?, industry = ?, registration_number = ?, person_name = ?,
contact_phone = ?, contact_email = ?, extra_info = ?
SET source_type = ?, company_name = ?, industry = ?, registration_number = ?, business_role = ?, country = ?, address = ?,
person_name = ?, contact_phone = ?, contact_email = ?, work_location = ?, id_number = ?, platform = ?, account_id = ?, profile_url = ?
WHERE id = ?"
)->execute([
$sourceType,
$companyName !== '' ? $companyName : null,
$industry !== '' ? $industry : null,
$registrationNum !== '' ? $registrationNum : null,
$businessRole !== '' ? $businessRole : null,
$country !== '' ? $country : null,
$address !== '' ? $address : null,
$personName !== '' ? $personName : null,
$phone !== '' ? $phone : null,
$email !== '' ? $email : null,
$extra ? json_encode($extra, JSON_UNESCAPED_UNICODE) : null,
$workLocation !== '' ? $workLocation : null,
$idNumber !== '' ? $idNumber : null,
$platform !== '' ? $platform : null,
$accountId !== '' ? $accountId : null,
$profileUrl !== '' ? $profileUrl : null,
$id,
]);
@@ -119,7 +116,7 @@ logCurrent('update', 'fragment', 'preliminary_data', $id, [
'person_name' => $personName,
'phone' => $phone,
'email' => $email,
'extra' => $extra,
'id_number' => $idNumber,
]);
Response::success(null, '已保存,点击「转软碎片」完成转换');