Files
superlink/api/common/helpers.php
T

290 lines
9.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 通用辅助函数与字段白名单(供各模块 add/update/import 复用)
*/
require_once __DIR__ . '/db.php';
require_once __DIR__ . '/response.php';
/** 企业表可写入字段白名单(key => 类型标记:s字符串/i整数/d日期/n数字) */
const COMPANY_FIELDS = [
'name_zh' => 's', 'name_en' => 's', 'display_name' => 's',
'business_role' => 's', 'country' => 's', 'registration_number' => 's',
'address' => 's', 'legal_form' => 's', 'legal_representative' => 's',
'business_scope' => 's', 'established_date' => 'd', 'registered_capital' => 's',
'industry' => 's', 'industry_subdivision' => 's',
'latest_employee_count' => 'i', 'latest_annual_revenue' => 's',
'is_listed' => 'i', 'stock_code' => 's', 'website' => 's',
'source_channel' => 's', 'source_detail' => 's',
];
/** 人员表可写入字段白名单 */
const PERSON_FIELDS = [
'union_id' => 's', 'full_name' => 's', 'gender' => 's', 'nationality' => 's',
'id_type' => 's', 'id_number' => 's', 'education' => 's', 'graduated_from' => 's',
'hometown' => 's', 'work_location' => 's',
'source_channel' => 's', 'source_detail' => 's',
];
/** 媒体(社交账号)表可写入字段白名单 */
const MEDIA_FIELDS = [
'owner_type' => 's', 'owner_id' => 'i', 'platform' => 's', 'account_id' => 's',
'profile_url' => 's', 'remark' => 's', 'is_primary' => 'i', 'is_defult' => 'i',
];
/** 媒体商业属性表可写入字段白名单 */
const MEDIA_ATTR_FIELDS = [
'account_level' => 's', 'content_categories' => 's', 'follower_count' => 'i',
'avg_read_count' => 'i', 'certification_type' => 's',
'special_requirements' => 's', 'media_remark' => 's',
];
/** 需求表可写入字段白名单 */
const NEED_FIELDS = [
'company_id' => 'i', 'contact_person' => 's', 'need_category' => 's',
'target_product_category' => 's', 'application_scenario' => 's', 'description' => 's',
];
/**
* 从 POST 中按白名单提取并清洗数据
* @param array $allowlist
* @return array
*/
function extractFields($allowlist)
{
$data = [];
foreach ($allowlist as $key => $type) {
$val = $_POST[$key] ?? null;
if ($val === null) {
continue;
}
$val = trim((string)$val);
if ($val === '') {
continue;
}
switch ($type) {
case 'i':
$data[$key] = (int)$val;
break;
case 'd':
$data[$key] = (strtotime($val) !== false) ? date('Y-m-d', strtotime($val)) : null;
break;
default:
$data[$key] = $val;
}
}
return $data;
}
/** 生成 INSERT 语句片段:字段名列表 + 占位符 */
function buildInsert($data)
{
$cols = array_keys($data);
$sql = '(`' . implode('`,`', $cols) . '`) VALUES (' . rtrim(str_repeat('?,', count($cols)), ',') . ')';
return [$sql, array_values($data)];
}
/** 生成 UPDATE SET 片段 */
function buildUpdate($data)
{
$sets = [];
foreach (array_keys($data) as $col) {
$sets[] = "`$col` = ?";
}
return [implode(',', $sets), array_values($data)];
}
/** 数字字符串或 null(空串转 null,避免写入空值) */
function numOrNull($v)
{
$v = trim((string)$v);
return ($v === '') ? null : $v;
}
/** 字符串或 null(空串转 null) */
function strOrNull($v)
{
if ($v === null) {
return null;
}
$v = trim((string)$v);
return ($v === '') ? null : $v;
}
/**
* 保存人员工作履历(整表替换:先删后插)
* @param PDO $pdo
* @param int $personId
* @param array $experiences JSON 解码后的数组 [{company_id,position,department,job_level,start_date,end_date,is_current}]
*/
function savePersonExperiences($pdo, $personId, $experiences)
{
$del = $pdo->prepare("DELETE FROM person_work_experiences WHERE person_id = ?");
$del->execute([$personId]);
if (empty($experiences)) {
return;
}
$ins = $pdo->prepare(
"INSERT INTO person_work_experiences
(person_id, company_id, position, department, job_level, start_date, end_date, is_current)
VALUES (?,?,?,?,?,?,?,?)"
);
foreach ($experiences as $e) {
if (!is_array($e)) {
continue;
}
$companyId = (int)($e['company_id'] ?? 0);
if ($companyId <= 0) {
continue;
}
$start = strOrNull($e['start_date'] ?? null);
$end = strOrNull($e['end_date'] ?? null);
$ins->execute([
$personId,
$companyId,
strOrNull($e['position'] ?? null),
strOrNull($e['department'] ?? null),
strOrNull($e['job_level'] ?? null),
$start !== null && strtotime($start) !== false ? date('Y-m-d', strtotime($start)) : null,
$end !== null && strtotime($end) !== false ? date('Y-m-d', strtotime($end)) : null,
!empty($e['is_current']) ? 1 : 0,
]);
}
}
/**
* 保存企业联系方式(social_accounts,整表替换:先删后插)
* 只操作 owner_type = 'company' 的记录
* @param PDO $pdo
* @param int $companyId
* @param array $accounts JSON 解码后的数组 [{platform,account_id,profile_url,remark,is_active,is_defult}]
*/
function saveCompanyAccounts($pdo, $companyId, $accounts)
{
$del = $pdo->prepare("DELETE FROM social_accounts WHERE owner_type = 'company' AND owner_id = ?");
$del->execute([$companyId]);
if (empty($accounts)) {
return;
}
$ins = $pdo->prepare(
"INSERT INTO social_accounts
(owner_type, owner_id, platform, account_id, profile_url, remark, is_primary, is_defult, is_active)
VALUES ('company', ?, ?, ?, ?, ?, 0, ?, ?)"
);
foreach ($accounts as $a) {
if (!is_array($a)) {
continue;
}
$platform = trim($a['platform'] ?? '');
$accountId = trim($a['account_id'] ?? '');
if ($platform === '' || $accountId === '') {
continue;
}
$ins->execute([
$companyId,
$platform,
$accountId,
strOrNull($a['profile_url'] ?? null),
strOrNull($a['remark'] ?? null),
!empty($a['is_defult']) ? 1 : 0,
!empty($a['is_active']) ? 1 : 0,
]);
}
}
/**
* 保存企业年度财务明细(整表替换:先删后插)
* @param PDO $pdo
* @param int $companyId
* @param array $financials JSON 解码后的数组
*/
function saveCompanyFinancials($pdo, $companyId, $financials)
{
$del = $pdo->prepare("DELETE FROM company_financials WHERE company_id = ?");
$del->execute([$companyId]);
if (empty($financials)) {
return;
}
$ins = $pdo->prepare(
"INSERT INTO company_financials
(company_id, fiscal_year, employee_count, total_revenue, net_profit, total_assets,
total_liabilities, owner_equity, gross_margin, net_margin, debt_ratio, financial_report_url, data_source)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"
);
$seen = [];
foreach ($financials as $f) {
if (!is_array($f)) {
continue;
}
$year = (int)($f['fiscal_year'] ?? 0);
if ($year < 1990 || $year > 2100) {
continue;
}
if (isset($seen[$year])) {
continue; // 同一财年只保留一条
}
$seen[$year] = true;
$ins->execute([
$companyId,
$year,
numOrNull($f['employee_count'] ?? null),
numOrNull($f['total_revenue'] ?? null),
numOrNull($f['net_profit'] ?? null),
numOrNull($f['total_assets'] ?? null),
numOrNull($f['total_liabilities'] ?? null),
numOrNull($f['owner_equity'] ?? null),
numOrNull($f['gross_margin'] ?? null),
numOrNull($f['net_margin'] ?? null),
numOrNull($f['debt_ratio'] ?? null),
strOrNull($f['financial_report_url'] ?? null),
strOrNull($f['data_source'] ?? null) ?? '手动录入',
]);
}
}
/**
* 保存企业资质认证(整表替换:先删后插)
* @param PDO $pdo
* @param int $companyId
* @param array $certifications JSON 解码后的数组
*/
function saveCompanyCertifications($pdo, $companyId, $certifications)
{
$del = $pdo->prepare("DELETE FROM company_certifications WHERE company_id = ?");
$del->execute([$companyId]);
if (empty($certifications)) {
return;
}
$valid = $pdo->prepare("SELECT id FROM data_dict_certificate WHERE id = ?");
$ins = $pdo->prepare(
"INSERT INTO company_certifications
(company_id, certification_type_id, certificate_number, level, issuing_authority, issue_date, expiry_date)
VALUES (?,?,?,?,?,?,?)"
);
$seen = [];
foreach ($certifications as $ct) {
if (!is_array($ct)) {
continue;
}
$tid = (int)($ct['certification_type_id'] ?? 0);
if ($tid <= 0 || isset($seen[$tid])) {
continue;
}
$valid->execute([$tid]);
if (!$valid->fetch()) {
continue; // 认证类型不存在
}
$seen[$tid] = true;
$ins->execute([
$companyId,
$tid,
strOrNull($ct['certificate_number'] ?? null),
strOrNull($ct['level'] ?? null),
strOrNull($ct['issuing_authority'] ?? null),
strOrNull($ct['issue_date'] ?? null),
strOrNull($ct['expiry_date'] ?? null),
]);
}
}