290 lines
9.4 KiB
PHP
290 lines
9.4 KiB
PHP
<?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', '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),
|
||
]);
|
||
}
|
||
}
|