v1.0.40: 碎片处理板块调整 - 区块改名(硬数据新增与处理/软数据碎片处理)+软碎片列表时间列改updated_at(social_accounts补列迁移)+硬数据新增加全字段唯一性校验(企业名/手机/邮箱/身份证/账号ID同平台/主页链接)+格式校验(身份证/主页URL)+extra_info存储
This commit is contained in:
@@ -11,6 +11,7 @@ require_once __DIR__ . '/../common/response.php';
|
||||
require_once __DIR__ . '/../common/auth.php';
|
||||
require_once __DIR__ . '/../common/logger.php';
|
||||
require_once __DIR__ . '/../common/validate.php';
|
||||
require_once __DIR__ . '/../common/duplicate_check.php';
|
||||
|
||||
checkAjax();
|
||||
checkPermission('preliminary');
|
||||
@@ -24,6 +25,10 @@ $companyName = trim($_POST['company_name'] ?? '');
|
||||
$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'] ?? '');
|
||||
$category = trim($_POST['target_product_category'] ?? '');
|
||||
$description = trim($_POST['description'] ?? '');
|
||||
$sourceChannel = trim($_POST['source_channel'] ?? '');
|
||||
@@ -31,21 +36,53 @@ if ($sourceChannel === '') {
|
||||
$sourceChannel = '手动录入';
|
||||
}
|
||||
|
||||
// 格式校验:手机 / 邮箱
|
||||
// 格式校验:手机 / 邮箱 / 身份证 / 主页链接
|
||||
checkFieldFormat('phone', $phone);
|
||||
checkFieldFormat('email', $email);
|
||||
checkFieldFormat('id_number', $idNumber);
|
||||
if ($profileUrl !== '' && !preg_match('/^https?:\/\//i', $profileUrl)) {
|
||||
Response::error('主页链接格式不正确(应以 http:// 或 https:// 开头)', 400);
|
||||
}
|
||||
|
||||
// 唯一性校验(收集全部重复):企业名称 / 手机 / 邮箱 / 身份证 / 账号ID(同平台)/ 主页链接
|
||||
$pdo = DB::getInstance()->getPdo();
|
||||
$dups = [];
|
||||
if ($companyName !== '') {
|
||||
$dup = findDuplicate($pdo, 'company_name', $companyName);
|
||||
if ($dup) $dups[] = $dup;
|
||||
}
|
||||
$dups = array_merge($dups, checkSingleAccountDuplicate($pdo, $phone !== '' ? 'phone' : '', $phone, $profileUrl));
|
||||
if ($email !== '') {
|
||||
$dup = findDuplicate($pdo, 'email', $email);
|
||||
if ($dup) $dups[] = $dup;
|
||||
}
|
||||
if ($idNumber !== '') {
|
||||
$dup = findDuplicate($pdo, 'id_number', $idNumber);
|
||||
if ($dup) $dups[] = $dup;
|
||||
}
|
||||
if ($accountId !== '' && $platform !== '') {
|
||||
$dup = findDuplicate($pdo, 'account_id', $accountId, [], $platform);
|
||||
if ($dup) $dups[] = $dup;
|
||||
}
|
||||
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 ($companyName === '' && $personName === '' && $phone === '' && $email === '' && $category === '' && $description === '') {
|
||||
if ($companyName === '' && $personName === '' && $phone === '' && $email === '' && $category === '' && $description === '' && !$extra) {
|
||||
Response::error('请至少填写一项内容', 400);
|
||||
}
|
||||
|
||||
$pdo = DB::getInstance()->getPdo();
|
||||
$pdo->prepare(
|
||||
"INSERT INTO preliminary_data
|
||||
(source_type, company_name, person_name, contact_phone, contact_email,
|
||||
target_product_category, description, source_channel, recorded_by, status)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, '待处理')"
|
||||
target_product_category, description, source_channel, recorded_by, status, extra_info)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, '待处理', ?)"
|
||||
)->execute([
|
||||
$sourceType,
|
||||
$companyName !== '' ? $companyName : null,
|
||||
@@ -56,6 +93,7 @@ $pdo->prepare(
|
||||
$description !== '' ? $description : null,
|
||||
$sourceChannel,
|
||||
$_SESSION['username'] ?? null,
|
||||
$extra ? json_encode($extra, JSON_UNESCAPED_UNICODE) : null,
|
||||
]);
|
||||
$newId = (int)$pdo->lastInsertId();
|
||||
|
||||
@@ -65,6 +103,7 @@ logCurrent('add', 'fragment', 'preliminary_data', $newId, [
|
||||
'person_name' => $personName,
|
||||
'phone' => $phone,
|
||||
'email' => $email,
|
||||
'extra' => $extra,
|
||||
]);
|
||||
|
||||
Response::success(['id' => $newId], '新增成功');
|
||||
|
||||
@@ -34,13 +34,13 @@ foreach ($tableMap as $t => $cfg) {
|
||||
}
|
||||
if ($t === 'media') {
|
||||
$rows = $pdo->query(
|
||||
"SELECT m.social_account_id AS id, sa.account_id AS name, sa.created_at AS created_at
|
||||
"SELECT m.social_account_id AS id, sa.account_id AS name, m.updated_at AS updated_at
|
||||
FROM media_commercial_attributes m
|
||||
LEFT JOIN social_accounts sa ON sa.id = m.social_account_id
|
||||
WHERE m.is_incomplete = 1"
|
||||
)->fetchAll();
|
||||
} else {
|
||||
$rows = $pdo->query("SELECT id, {$cfg['name']} AS name, created_at FROM `$t` WHERE is_incomplete = 1")->fetchAll();
|
||||
$rows = $pdo->query("SELECT id, {$cfg['name']} AS name, updated_at FROM `$t` WHERE is_incomplete = 1")->fetchAll();
|
||||
}
|
||||
foreach ($rows as $r) {
|
||||
$info = completenessInfo($pdo, $t, (int)$r['id']);
|
||||
@@ -65,17 +65,17 @@ foreach ($tableMap as $t => $cfg) {
|
||||
'optional' => $info['layers']['optional']['rate'],
|
||||
],
|
||||
'missing_fields' => array_map(function ($f) { return COMPLETENESS_LABELS[$f] ?? $f; }, $missingFields),
|
||||
'created_at' => $r['created_at'] ?? null,
|
||||
'updated_at' => $r['updated_at'] ?? null,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// 排序:整体完整度升序(最残缺在前),同分按时间倒序
|
||||
// 排序:整体完整度升序(最残缺在前),同分按更新时间倒序
|
||||
usort($all, function ($a, $b) {
|
||||
if ($a['overall'] !== $b['overall']) {
|
||||
return $a['overall'] <=> $b['overall'];
|
||||
}
|
||||
return strcmp($b['created_at'] ?? '', $a['created_at'] ?? '');
|
||||
return strcmp($b['updated_at'] ?? '', $a['updated_at'] ?? '');
|
||||
});
|
||||
|
||||
if ($keyword !== '') {
|
||||
|
||||
Reference in New Issue
Block a user