diff --git a/api/common/completeness.php b/api/common/completeness.php index 91f6e71..c63ece1 100644 --- a/api/common/completeness.php +++ b/api/common/completeness.php @@ -24,7 +24,8 @@ const COMPLETENESS_LAYERS = [ 'important' => ['address', 'country'], 'optional' => ['registration_number', 'legal_form', 'legal_representative', 'business_scope', 'established_date', 'registered_capital', 'industry_subdivision', - 'latest_employee_count', 'latest_annual_revenue', 'is_listed', 'stock_code', 'website'], + 'latest_employee_count', 'latest_annual_revenue', 'is_listed', 'website'], + 'conditional' => ['stock_code' => ['layer' => 'optional', 'when' => ['is_listed' => '1']]], // 股票代码仅在“是否上市=是”时参与完整度 'virtual' => [], ], 'social_accounts' => [ @@ -93,8 +94,6 @@ function completenessCalc($table, $row) $result = []; $missing = ['core' => [], 'important' => [], 'optional' => []]; - $totalAll = 0; - $filledAll = 0; foreach (['core', 'important', 'optional'] as $layer) { $total = count($layers[$layer]); @@ -118,15 +117,39 @@ function completenessCalc($table, $row) $filled++; } } - $rate = $total > 0 ? round($filled / $total * 100, 1) : 100; - $result[$layer] = [ - 'filled' => $filled, - 'total' => $total, - 'rate' => $rate, - 'passed' => $rate >= COMPLETENESS_THRESHOLDS[$layer], - ]; - $totalAll += $total; - $filledAll += $filled; + $result[$layer] = ['filled' => $filled, 'total' => $total, 'rate' => 0, 'passed' => false]; + } + + // 条件字段:满足条件才计入完整度(如 stock_code 仅在 is_listed=1 时统计) + foreach (($layers['conditional'] ?? []) as $cf => $cond) { + $layer = $cond['layer'] ?? 'optional'; + $match = true; + foreach (($cond['when'] ?? []) as $wf => $wv) { + if ((string)($row[$wf] ?? '') !== (string)$wv) { + $match = false; + break; + } + } + if (!$match) { + continue; + } + $result[$layer]['total']++; + if (completenessIsMissing($row[$cf] ?? null)) { + $missing[$layer][] = $cf; + } else { + $result[$layer]['filled']++; + } + } + + // 条件字段处理完后重算各层 rate/passed 与整体 + $totalAll = 0; + $filledAll = 0; + foreach (['core', 'important', 'optional'] as $layer) { + $rate = $result[$layer]['total'] > 0 ? round($result[$layer]['filled'] / $result[$layer]['total'] * 100, 1) : 100; + $result[$layer]['rate'] = $rate; + $result[$layer]['passed'] = $rate >= COMPLETENESS_THRESHOLDS[$layer]; + $totalAll += $result[$layer]['total']; + $filledAll += $result[$layer]['filled']; } $overall = $totalAll > 0 ? round($filledAll / $totalAll * 100, 1) : 100; diff --git a/api/company/add.php b/api/company/add.php index 1e51d36..4ec2af5 100644 --- a/api/company/add.php +++ b/api/company/add.php @@ -22,6 +22,11 @@ if (empty($data['display_name'])) { Response::error('企业名称(中文名称)为必填项', 400); } +// 非上市(否或空白)不允许有股票代码 +if ((int)($data['is_listed'] ?? 0) !== 1) { + $data['stock_code'] = null; +} + $pdo = DB::getInstance()->getPdo(); [$sql, $params] = buildInsert($data); $pdo->prepare("INSERT INTO companies $sql")->execute($params); diff --git a/api/company/update.php b/api/company/update.php index 06e6f23..6a00835 100644 --- a/api/company/update.php +++ b/api/company/update.php @@ -20,6 +20,10 @@ if ($id <= 0) { $data = extractFields(COMPANY_FIELDS); unset($data['display_name']); // 显示名称不允许通过编辑接口置空/改名,如需改名请走完整字段 +// 非上市(否)不允许有股票代码:提交 is_listed=0 时强制清空 +if (array_key_exists('is_listed', $data) && (int)$data['is_listed'] !== 1) { + $data['stock_code'] = null; +} $hasFinancials = array_key_exists('financials', $_POST); $hasCertifications = array_key_exists('certifications', $_POST); $hasAccounts = array_key_exists('accounts', $_POST); diff --git a/static/js/company.js b/static/js/company.js index 3370dca..d22c091 100644 --- a/static/js/company.js +++ b/static/js/company.js @@ -367,10 +367,10 @@ $(function () { } var finHtml = '
' + - '
' + ' ' + '
' + - '
' + + '
' + '
' + '
' + '
' + @@ -434,6 +434,14 @@ $(function () { Dialog.alert('工商查询API预留中,接入后可通过企业名称自动查询并填写企业名称、注册号、注册地址等信息'); }); + // 是否上市 → 股票代码 联动:非上市(否/空白)时禁用股票代码 + function syncStockCodeDisabled() { + var listed = $('#company-is-listed').val() === '1'; + $('#company-stock-code').prop('disabled', !listed); + } + $('#company-is-listed').on('change', syncStockCodeDisabled); + syncStockCodeDisabled(); + $('#company-form').on('submit', function (e) { e.preventDefault(); var fd = new FormData(this); @@ -444,6 +452,9 @@ $(function () { Dialog.error('企业名称为必填项'); return; } + if ($('#company-is-listed').val() !== '1') { + fd.set('stock_code', ''); // 非上市不允许有股票代码,提交空值由后端清空 + } // 年度财务明细(整表替换) var financials = []; diff --git a/static/js/config.js b/static/js/config.js index 19007ca..06b93f9 100644 --- a/static/js/config.js +++ b/static/js/config.js @@ -5,7 +5,7 @@ var BASE_URL = '/api/'; var PAGE_SIZE = 20; /** 系统版本号(logo旁展示):修改代码后运行 tools/bump_version.php 自动递增 */ -var APP_VERSION = 'v1.0.30'; +var APP_VERSION = 'v1.0.31'; /** 页脚版权/备案信息(在 config.js 中修改) */ var FOOTER_TEXT = '© 2026 SuperLink 管理系统 版权所有 | 备案号:请替换为真实备案号';