From 96cba121a8102f69ae57f6f247affed87d002da8 Mon Sep 17 00:00:00 2001 From: nanguaboss <602995148@qq.com> Date: Mon, 3 Aug 2026 23:22:33 +0800 Subject: [PATCH] =?UTF-8?q?v1.0.12:=20=E4=BC=81=E4=B8=9A/=E4=BA=BA?= =?UTF-8?q?=E5=91=98/=E5=AA=92=E4=BD=93=E5=8E=BB=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E5=85=A5=E5=8F=A3=EF=BC=9B=E4=BC=81=E4=B8=9A/=E4=BA=BA?= =?UTF-8?q?=E5=91=98=E5=8A=A0=E4=BA=A7=E5=93=81=E5=85=A5=E5=8F=A3=EF=BC=9B?= =?UTF-8?q?=E4=BC=81=E4=B8=9A=E8=AF=A6=E6=83=85=E5=8E=BB=E4=BA=A7=E5=93=81?= =?UTF-8?q?=E5=93=81=E7=B1=BB/=E5=85=B3=E8=81=94=E8=81=94=E7=B3=BB?= =?UTF-8?q?=E4=BA=BA=EF=BC=9B=E7=BC=96=E8=BE=91=E4=BC=81=E4=B8=9A=E6=94=B9?= =?UTF-8?q?Tab=E5=8D=A1(=E5=B7=A5=E5=95=86=E4=BF=A1=E6=81=AF/=E8=B4=A2?= =?UTF-8?q?=E5=8A=A1=E4=BF=A1=E6=81=AF/=E8=B5=84=E8=B4=A8=E8=AE=A4?= =?UTF-8?q?=E8=AF=81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/common/helpers.php | 112 +++++++++++++++++ api/company/add.php | 27 ++++ api/company/cert_types.php | 15 +++ api/company/detail.php | 15 +++ api/company/employees.php | 4 + api/company/products.php | 41 ++++++ api/company/update.php | 43 ++++++- api/person/companies.php | 16 ++- api/person/products.php | 48 +++++++ static/css/style.css | 61 +++++++++ static/js/company.js | 251 +++++++++++++++++++++++++++++++------ static/js/config.js | 2 +- static/js/media.js | 9 -- static/js/person.js | 83 ++++++++---- 14 files changed, 644 insertions(+), 83 deletions(-) create mode 100644 api/company/cert_types.php create mode 100644 api/company/products.php create mode 100644 api/person/products.php diff --git a/api/common/helpers.php b/api/common/helpers.php index b529491..30ad0f7 100644 --- a/api/common/helpers.php +++ b/api/common/helpers.php @@ -90,3 +90,115 @@ function buildUpdate($data) } 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 $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 certification_types WHERE id = ?"); + $ins = $pdo->prepare( + "INSERT INTO company_certifications + (company_id, certification_type_id, certificate_number, 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['issue_date'] ?? null), + strOrNull($ct['expiry_date'] ?? null), + ]); + } +} diff --git a/api/company/add.php b/api/company/add.php index 374ee0c..aa1a212 100644 --- a/api/company/add.php +++ b/api/company/add.php @@ -26,5 +26,32 @@ $pdo = DB::getInstance()->getPdo(); $pdo->prepare("INSERT INTO companies $sql")->execute($params); $newId = (int)$pdo->lastInsertId(); +// 财务信息 / 资质认证(可选,整表替换) +if (array_key_exists('financials', $_POST) || array_key_exists('certifications', $_POST)) { + $pdo->beginTransaction(); + try { + if (array_key_exists('financials', $_POST)) { + $financials = json_decode($_POST['financials'], true); + if (!is_array($financials)) { + $pdo->rollBack(); + Response::error('财务信息格式错误', 400); + } + saveCompanyFinancials($pdo, $newId, $financials); + } + if (array_key_exists('certifications', $_POST)) { + $certs = json_decode($_POST['certifications'], true); + if (!is_array($certs)) { + $pdo->rollBack(); + Response::error('资质认证格式错误', 400); + } + saveCompanyCertifications($pdo, $newId, $certs); + } + $pdo->commit(); + } catch (Exception $e) { + $pdo->rollBack(); + Response::error('关联信息保存失败:' . $e->getMessage()); + } +} + logCurrent('add', 'company', 'companies', $newId, $data); Response::success(['id' => $newId], '新增成功'); diff --git a/api/company/cert_types.php b/api/company/cert_types.php new file mode 100644 index 0000000..11392e2 --- /dev/null +++ b/api/company/cert_types.php @@ -0,0 +1,15 @@ +getPdo(); +$types = $pdo->query("SELECT id, name FROM certification_types WHERE is_active = 1 ORDER BY sort_order, id")->fetchAll(); + +Response::success(['types' => $types]); diff --git a/api/company/detail.php b/api/company/detail.php index aaa3dfe..d195cb0 100644 --- a/api/company/detail.php +++ b/api/company/detail.php @@ -48,6 +48,19 @@ $relations = $pdo->prepare( ); $relations->execute([$id]); +// 资质认证(瞪羚企业等,JOIN 字典表取名称) +$certs = $pdo->prepare( + "SELECT cc.certification_type_id, ct.name AS certification_name, cc.certificate_number, + cc.issue_date, cc.expiry_date + FROM company_certifications cc + INNER JOIN certification_types ct ON ct.id = cc.certification_type_id + WHERE cc.company_id = ? + ORDER BY ct.sort_order, ct.id" +); +$certs->execute([$id]); + +$certTypes = $pdo->query("SELECT id, name FROM certification_types WHERE is_active = 1 ORDER BY sort_order, id")->fetchAll(); + // 关联联系人(工作经历 + 联系方式) $contacts = $pdo->prepare( "SELECT p.id, p.full_name, @@ -71,4 +84,6 @@ Response::success([ 'financials' => $financials->fetchAll(), 'relations' => $relations->fetchAll(), 'contacts' => $contacts->fetchAll(), + 'certifications' => $certs->fetchAll(), + 'certification_types' => $certTypes, ]); diff --git a/api/company/employees.php b/api/company/employees.php index bac7aaa..33cfa9c 100644 --- a/api/company/employees.php +++ b/api/company/employees.php @@ -38,6 +38,10 @@ if ($jobLevel !== '') { $where[] = 'pwe.job_level = ?'; $params[] = $jobLevel; } +if (isset($_REQUEST['is_current']) && $_REQUEST['is_current'] !== '') { + $where[] = 'pwe.is_current = ?'; + $params[] = (int)$_REQUEST['is_current'] ? 1 : 0; +} $whereSql = implode(' AND ', $where); // 总数 diff --git a/api/company/products.php b/api/company/products.php new file mode 100644 index 0000000..ce088fd --- /dev/null +++ b/api/company/products.php @@ -0,0 +1,41 @@ +getPdo(); + +$chk = $pdo->prepare("SELECT COUNT(*) FROM companies WHERE id = ?"); +$chk->execute([$companyId]); +if ((int)$chk->fetchColumn() === 0) { + Response::error('企业不存在'); +} + +$stmt = $pdo->prepare("SELECT COUNT(*) FROM company_products WHERE company_id = ? AND is_active = 1"); +$stmt->execute([$companyId]); +$total = (int)$stmt->fetchColumn(); + +$offset = ($page - 1) * $limit; +$stmt = $pdo->prepare( + "SELECT id, category_name, category_description, is_core, is_active + FROM company_products + WHERE company_id = ? AND is_active = 1 + ORDER BY is_core DESC, id DESC + LIMIT $limit OFFSET $offset" +); +$stmt->execute([$companyId]); + +Response::success(['list' => $stmt->fetchAll(), 'total' => $total, 'page' => $page, 'limit' => $limit]); diff --git a/api/company/update.php b/api/company/update.php index 8b34137..3879f6f 100644 --- a/api/company/update.php +++ b/api/company/update.php @@ -19,7 +19,9 @@ if ($id <= 0) { $data = extractFields(COMPANY_FIELDS); unset($data['display_name']); // 显示名称不允许通过编辑接口置空/改名,如需改名请走完整字段 -if (empty($data)) { +$hasFinancials = array_key_exists('financials', $_POST); +$hasCertifications = array_key_exists('certifications', $_POST); +if (empty($data) && !$hasFinancials && !$hasCertifications) { Response::error('没有需要更新的字段', 400); } @@ -32,9 +34,40 @@ if (!$old) { Response::error('企业不存在'); } -[$sets, $params] = buildUpdate($data); -$params[] = $id; -$pdo->prepare("UPDATE companies SET $sets WHERE id = ?")->execute($params); +if (!empty($data)) { + [$sets, $params] = buildUpdate($data); + $params[] = $id; + $pdo->prepare("UPDATE companies SET $sets WHERE id = ?")->execute($params); +} -logCurrent('update', 'company', 'companies', $id, ['before' => $old, 'after' => $data]); +// 财务信息 / 资质认证(可选,整表替换) +if ($hasFinancials || $hasCertifications) { + $pdo->beginTransaction(); + try { + if ($hasFinancials) { + $financials = json_decode($_POST['financials'], true); + if (!is_array($financials)) { + $pdo->rollBack(); + Response::error('财务信息格式错误', 400); + } + saveCompanyFinancials($pdo, $id, $financials); + } + if ($hasCertifications) { + $certs = json_decode($_POST['certifications'], true); + if (!is_array($certs)) { + $pdo->rollBack(); + Response::error('资质认证格式错误', 400); + } + saveCompanyCertifications($pdo, $id, $certs); + } + $pdo->commit(); + } catch (Exception $e) { + $pdo->rollBack(); + Response::error('关联信息保存失败:' . $e->getMessage()); + } +} + +if (!empty($data)) { + logCurrent('update', 'company', 'companies', $id, ['before' => $old, 'after' => $data]); +} Response::success(null, '更新成功'); diff --git a/api/person/companies.php b/api/person/companies.php index 4ba7dd6..3a47f81 100644 --- a/api/person/companies.php +++ b/api/person/companies.php @@ -25,12 +25,20 @@ if ((int)$chk->fetchColumn() === 0) { Response::error('人员不存在'); } +$where = ['pwe.person_id = ?', 'pwe.is_active = 1']; +$params = [$personId]; +if (isset($_REQUEST['is_current']) && $_REQUEST['is_current'] !== '') { + $where[] = 'pwe.is_current = ?'; + $params[] = (int)$_REQUEST['is_current'] ? 1 : 0; +} +$whereSql = implode(' AND ', $where); + $stmt = $pdo->prepare( "SELECT COUNT(*) FROM person_work_experiences pwe INNER JOIN companies c ON c.id = pwe.company_id - WHERE pwe.person_id = ? AND pwe.is_active = 1" + WHERE $whereSql" ); -$stmt->execute([$personId]); +$stmt->execute($params); $total = (int)$stmt->fetchColumn(); $offset = ($page - 1) * $limit; @@ -42,11 +50,11 @@ $stmt = $pdo->prepare( pwe.start_date, pwe.end_date, pwe.is_current FROM person_work_experiences pwe INNER JOIN companies c ON c.id = pwe.company_id - WHERE pwe.person_id = ? AND pwe.is_active = 1 + WHERE $whereSql ORDER BY pwe.is_current DESC, pwe.start_date DESC LIMIT $limit OFFSET $offset" ); -$stmt->execute([$personId]); +$stmt->execute($params); $list = $stmt->fetchAll(); Response::success(['list' => $list, 'total' => $total, 'page' => $page, 'limit' => $limit]); diff --git a/api/person/products.php b/api/person/products.php new file mode 100644 index 0000000..c8e84e7 --- /dev/null +++ b/api/person/products.php @@ -0,0 +1,48 @@ +getPdo(); + +$chk = $pdo->prepare("SELECT COUNT(*) FROM persons WHERE id = ?"); +$chk->execute([$personId]); +if ((int)$chk->fetchColumn() === 0) { + Response::error('人员不存在'); +} + +$join = "FROM person_work_experiences pwe + INNER JOIN company_products cp ON cp.company_id = pwe.company_id AND cp.is_active = 1 + INNER JOIN companies c ON c.id = pwe.company_id + WHERE pwe.person_id = ? AND pwe.is_active = 1"; + +$stmt = $pdo->prepare("SELECT COUNT(DISTINCT cp.id) $join"); +$stmt->execute([$personId]); +$total = (int)$stmt->fetchColumn(); + +$offset = ($page - 1) * $limit; +$stmt = $pdo->prepare( + "SELECT DISTINCT cp.id, cp.category_name, cp.category_description, cp.is_core, cp.is_active, + CASE WHEN c.name_zh IS NOT NULL AND c.name_zh <> '' THEN c.name_zh + ELSE COALESCE(c.name_en, c.display_name) END AS company_name + $join + ORDER BY company_name, cp.id DESC + LIMIT $limit OFFSET $offset" +); +$stmt->execute([$personId]); + +Response::success(['list' => $stmt->fetchAll(), 'total' => $total, 'page' => $page, 'limit' => $limit]); diff --git a/static/css/style.css b/static/css/style.css index 7deacd7..6f9ea54 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -462,6 +462,67 @@ table.grid .ops a:hover { text-decoration: underline; } color: #fff; } +/* ---------- 编辑弹窗 Tab 卡(工商信息/财务信息/资质认证) ---------- */ +.edit-tabs { border: 1px solid #e5e9f0; border-radius: 6px; } +.edit-tabs-head { + display: flex; + border-bottom: 1px solid #e5e9f0; + background: #f7f9fc; + border-radius: 6px 6px 0 0; +} +.edit-tabs-head .edit-tab { + padding: 10px 24px; + font-size: 13px; + color: #5a6472; + cursor: pointer; + border-right: 1px solid #e5e9f0; + user-select: none; + background: transparent; +} +.edit-tabs-head .edit-tab:hover { color: #2a5298; } +.edit-tabs-head .edit-tab.active { + background: #fff; + color: #2a5298; + font-weight: bold; + border-bottom: 2px solid #2a5298; + margin-bottom: -1px; +} +.edit-tabs-body { + padding: 14px 16px; + background: #fff; + border-radius: 0 0 6px 6px; + max-height: 62vh; + overflow-y: auto; +} +.fin-year { + border: 1px solid #eef0f4; + border-radius: 6px; + padding: 10px 14px; + margin-bottom: 10px; + background: #fbfcfe; +} +.fin-year-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; } +.fin-year-head b { font-size: 13px; color: #1e2a3a; font-weight: bold; } +.fin-year-head input { + width: 100px; + border: 1px solid #d9dee8; + border-radius: 4px; + padding: 5px 8px; + font-size: 13px; + margin-left: 6px; +} +.cert-row { display: flex; gap: 8px; margin-bottom: 8px; align-items: center; flex-wrap: wrap; } +.cert-row select, .cert-row input { + border: 1px solid #d9dee8; + border-radius: 4px; + padding: 7px 8px; + font-size: 13px; + background: #fff; +} +.cert-row select { width: 200px; } +.cert-row input[type="text"] { width: 170px; } +.cert-row input[type="date"] { width: 140px; } + /* ---------- 页脚(版权/备案) ---------- */ .footer { padding: 14px 22px; diff --git a/static/js/company.js b/static/js/company.js index b708ddc..d9f3a7c 100644 --- a/static/js/company.js +++ b/static/js/company.js @@ -29,7 +29,6 @@ $(function () { ' ' + ' ' + ' ' + - ' ' + ' ' + '
' + ' ' + @@ -67,8 +66,8 @@ $(function () { ''; }); if (!rows.length) { @@ -87,18 +86,26 @@ $(function () { }); /* ---------- 新增/编辑 ---------- */ - $('#btn-add').on('click', function () { openForm(null); }); + $('#btn-add').on('click', function () { + httpGet('company/cert_types.php').then(function (d) { + openForm(null, [], [], d.types || []); + }); + }); window.editCompany = function (id) { httpGet('company/detail.php', { id: id }).then(function (d) { - openForm(d.company); + openForm(d.company, d.financials, d.certifications, d.certification_types); }); }; - function openForm(company) { + function openForm(company, financials, certifications, certTypes) { var isEdit = !!company; var c = company || {}; - var content = - '' + + financials = financials || []; + certifications = certifications || []; + certTypes = certTypes || []; + + // Tab1 工商信息 + var bizHtml = '
' + '
' + '
' + @@ -106,32 +113,81 @@ $(function () { '
' + '
' + '
' + + '
' + '
' + '
' + '
' + - '
' + - '
' + '
' + - '
' + - '
' + + '
' + + '
' + '
' + '
' + '
' + + '
'; + + // Tab2 财务信息:最新冗余字段 + 年度财务明细列表 + var finRowsHtml = ''; + if (!financials.length) { + finRowsHtml = finYearRowHtml(null); + } else { + financials.forEach(function (f) { finRowsHtml += finYearRowHtml(f); }); + } + var finHtml = + '
' + + '
' + + '
' + '
' + + '
' + + ' 年度财务明细' + + ' ' + + '
' + + '
' + finRowsHtml + '
'; + + // Tab3 资质认证:列表形式(瞪羚企业等) + var certRowsHtml = ''; + if (!certifications.length) { + certRowsHtml = certRowHtml(null, certTypes); + } else { + certifications.forEach(function (ct) { certRowsHtml += certRowHtml(ct, certTypes); }); + } + var certHtml = + '
' + + ' 资质认证' + + ' ' + + '
' + + '
' + certRowsHtml + '
' + + '
如:瞪羚企业、国家高新技术企业、专精特新企业、ISO9001认证等
'; + + var content = + '' + + '
' + + '
' + + ' 工商信息' + + ' 财务信息' + + ' 资质认证' + + '
' + + '
' + + '
' + bizHtml + '
' + + ' ' + + ' ' + + '
' + + '
' + '' + ''; var idx = Dialog.open({ title: isEdit ? '编辑企业' : '新增企业', - area: ['760px', 'auto'], + area: ['820px', 'auto'], content: content, btn: false }); $('#form-cancel').on('click', function () { Dialog.close(idx); }); + $('#add-fin-row').on('click', function () { $('#fin-rows').append(finYearRowHtml(null)); }); + $('#add-cert-row').on('click', function () { $('#cert-rows').append(certRowHtml(null, certTypes)); }); $('#company-form').on('submit', function (e) { e.preventDefault(); @@ -143,6 +199,45 @@ $(function () { Dialog.error('公司名称或英文名称至少填写一项'); return; } + + // 年度财务明细(整表替换) + var financials = []; + $('#fin-rows .fin-year').each(function () { + var $y = $(this); + var year = $.trim($y.find('[name="fin-fiscal_year"]').val()); + if (!year) return; + financials.push({ + fiscal_year: year, + employee_count: $y.find('[name="fin-employee_count"]').val(), + total_revenue: $y.find('[name="fin-total_revenue"]').val(), + net_profit: $y.find('[name="fin-net_profit"]').val(), + total_assets: $y.find('[name="fin-total_assets"]').val(), + total_liabilities: $y.find('[name="fin-total_liabilities"]').val(), + owner_equity: $y.find('[name="fin-owner_equity"]').val(), + gross_margin: $y.find('[name="fin-gross_margin"]').val(), + net_margin: $y.find('[name="fin-net_margin"]').val(), + debt_ratio: $y.find('[name="fin-debt_ratio"]').val(), + financial_report_url: $y.find('[name="fin-financial_report_url"]').val(), + data_source: $y.find('[name="fin-data_source"]').val() + }); + }); + fd.append('financials', JSON.stringify(financials)); + + // 资质认证(整表替换) + var certs = []; + $('#cert-rows .cert-row').each(function () { + var $r = $(this); + var tid = $r.find('[name="cert-type"]').val(); + if (!tid) return; + certs.push({ + certification_type_id: tid, + certificate_number: $r.find('[name="cert-number"]').val(), + issue_date: $r.find('[name="cert-issue"]').val(), + expiry_date: $r.find('[name="cert-expiry"]').val() + }); + }); + fd.append('certifications', JSON.stringify(certs)); + httpPost(isEdit ? 'company/update.php' : 'company/add.php', fd, true).then(function () { Dialog.success('保存成功', function () { Dialog.close(idx); @@ -152,6 +247,56 @@ $(function () { }); } + /* ---------- 编辑弹窗 Tab 切换 ---------- */ + window.switchEditTab = function (el) { + var $tabs = $(el).closest('.edit-tabs'); + $tabs.find('.edit-tab').removeClass('active'); + $(el).addClass('active'); + $tabs.find('.edit-pane').hide(); + $('#edit-pane-' + $(el).data('tab')).show(); + }; + + /** 年度财务明细行模板 */ + function finYearRowHtml(f) { + f = f || {}; + var empty = function (v) { return (v === null || v === undefined) ? '' : v; }; + return '
' + + '
' + + ' 财年 ' + + ' ' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
'; + } + + /** 资质认证行模板 */ + function certRowHtml(ct, certTypes) { + ct = ct || {}; + var opts = ''; + certTypes.forEach(function (t) { + opts += ''; + }); + return '
' + + '' + + '' + + '' + + '' + + '' + + '
'; + } + function roleOptions(sel) { var opts = ['', 'manufacturer', 'integrator', 'distributor', 'brand_operator', 'others']; var labels = { 'manufacturer': '生产型', 'integrator': '集成商', 'distributor': '代理商', 'brand_operator': '品牌运营', 'others': '其他' }; @@ -163,27 +308,6 @@ $(function () { return html; } - /* ---------- 删除(软删除) ---------- */ - window.delCompany = function (id) { - Dialog.confirm('确定删除该企业吗?(软删除,可恢复)', function () { - httpPost('company/delete.php', { id: id }).then(function () { - Dialog.success('删除成功', function () { loadList(currentPage); }); - }); - }); - }; - - /* ---------- 批量删除 ---------- */ - $('#btn-del-batch').on('click', function () { - var ids = []; - $('.row-check:checked').each(function () { ids.push($(this).val()); }); - if (!ids.length) { Dialog.error('请先勾选记录'); return; } - Dialog.confirm('确定删除选中的 ' + ids.length + ' 条记录吗?', function () { - httpPost('company/delete.php', { ids: ids.join(',') }).then(function () { - Dialog.success('删除成功', function () { loadList(currentPage); }); - }); - }); - }); - /* ---------- 导入 ---------- */ $('#btn-import').on('click', function () { triggerFileInput('.csv', function (file) { @@ -226,9 +350,7 @@ $(function () { detailRow('是否上市', c.is_listed ? '是' : '否') + detailRow('股票代码', c.stock_code) + '' + '

经营范围

' + escHtml(c.business_scope || '-') + '
' + - '

产品品类

' + miniTable(['品类', '描述', '核心'], d.products.map(function (p) { return [p.category_name, p.category_description || '-', p.is_core ? '是' : '否']; })) + '

关联需求

' + miniTable(['联系人', '需求大类', '意向品类', '场景'], d.needs.map(function (n) { return [n.contact_person || '-', n.need_category || '-', n.target_product_category || '-', n.application_scenario || '-']; })) + - '

关联联系人

' + miniTable(['姓名', '职位', '联系方式'], d.contacts.map(function (p) { return [p.full_name || '-', p.position || '-', p.contacts || '-']; })) + ''; Dialog.open({ title: '企业详情', area: ['820px', 'auto'], content: html, btn: ['关闭'] }); }); @@ -256,15 +378,18 @@ $(function () { empCompanyId = companyId; empPage = 1; var content = - '
' + - '
' + - ' ' + - ' ' + + '
' + + '
' + + ' ' + + ' ' + + ' 状态:' + + ' ' + + ' ' + ' ' + ' ' + '
' + - '
ID公司名称行业行业细分国家业务角色注册号法人上市创建时间操作
' + ' 详情' + ' 员工' + + ' 产品' + ' 编辑' + - ' 删除' + '
' + - ' ' + + '
姓名联系方式邮箱职级部门岗位入职日期是否在职
' + + ' ' + ' ' + '
姓名联系方式邮箱职级部门岗位入职日期状态
' + ' ' + @@ -278,6 +403,8 @@ $(function () { $('#emp-reset').on('click', function () { $('#emp-keyword').val(''); $('#emp-level').val(''); + $('#emp-cur').prop('checked', true); + $('#emp-off').prop('checked', true); loadEmployees(1); }); }; @@ -287,8 +414,13 @@ $(function () { var params = { company_id: empCompanyId, page: page, limit: 5 }; var kw = $.trim($('#emp-keyword').val()); var lv = $('#emp-level').val(); + var cur = $('#emp-cur').prop('checked'); + var off = $('#emp-off').prop('checked'); if (kw) params.keyword = kw; if (lv) params.job_level = lv; + // 状态筛选:只勾一项则按该项过滤;都不勾视为全部 + if (cur && !off) params.is_current = 1; + else if (!cur && off) params.is_current = 0; httpGet('company/employees.php', params).then(function (data) { var rows = data.list || []; @@ -323,4 +455,41 @@ $(function () { renderPagination($('#emp-pagination'), data, loadEmployees); }); } + + /* ---------- 产品品类弹窗(按企业查看产品品类,分页) ---------- */ + var prodCompanyId = 0; + + window.viewProducts = function (companyId) { + prodCompanyId = companyId; + var content = + '
' + + '
' + + ' ' + + ' ' + + '
品类名称品类描述是否核心状态
' + + ' ' + + '
'; + Dialog.open({ title: '产品品类', area: ['720px', 'auto'], content: content, btn: ['关闭'] }); + loadProducts(1); + }; + + function loadProducts(page) { + httpGet('company/products.php', { company_id: prodCompanyId, page: page, limit: 5 }).then(function (data) { + var rows = data.list || []; + var html = ''; + rows.forEach(function (r) { + html += '' + + '' + escHtml(r.category_name) + '' + + '' + escHtml(r.category_description || '-') + '' + + '' + (r.is_core ? '核心' : '-') + '' + + '' + (r.is_active ? '在产' : '停产') + '' + + ''; + }); + if (!rows.length) { + html = '暂无产品品类'; + } + $('#prod-tbody').html(html); + renderPagination($('#prod-pagination'), data, loadProducts); + }); + } }); diff --git a/static/js/config.js b/static/js/config.js index 6323391..87961b1 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.10'; +var APP_VERSION = 'v1.0.12'; /** 页脚版权/备案信息(在 config.js 中修改) */ var FOOTER_TEXT = '© 2026 SuperLink 管理系统 版权所有 | 备案号:请替换为真实备案号'; diff --git a/static/js/media.js b/static/js/media.js index 6e2bb94..1bd54ae 100644 --- a/static/js/media.js +++ b/static/js/media.js @@ -66,7 +66,6 @@ $(function () { '' + ' 详情' + ' 编辑' + - ' 删除' + ''; }); if (!rows.length) { @@ -195,14 +194,6 @@ $(function () { return html; } - window.delMedia = function (id) { - Dialog.confirm('确定删除该媒体账号吗?(软删除)', function () { - httpPost('media/delete.php', { id: id }).then(function () { - Dialog.success('删除成功', function () { loadList(currentPage); }); - }); - }); - }; - $('#btn-del-batch').on('click', function () { var ids = []; $('.row-check:checked').each(function () { ids.push($(this).val()); }); diff --git a/static/js/person.js b/static/js/person.js index b1b5235..4cf83a6 100644 --- a/static/js/person.js +++ b/static/js/person.js @@ -28,7 +28,6 @@ $(function () { ' ' + ' ' + ' ' + - ' ' + ' ' + '
' + ' ' + @@ -64,8 +63,8 @@ $(function () { ''; }); if (!rows.length) { @@ -197,25 +196,7 @@ $(function () { }); } - window.delPerson = function (id) { - Dialog.confirm('确定删除该人员吗?(软删除,可恢复)', function () { - httpPost('person/delete.php', { id: id }).then(function () { - Dialog.success('删除成功', function () { loadList(currentPage); }); - }); - }); - }; - - $('#btn-del-batch').on('click', function () { - var ids = []; - $('.row-check:checked').each(function () { ids.push($(this).val()); }); - if (!ids.length) { Dialog.error('请先勾选记录'); return; } - Dialog.confirm('确定删除选中的 ' + ids.length + ' 条记录吗?', function () { - httpPost('person/delete.php', { ids: ids.join(',') }).then(function () { - Dialog.success('删除成功', function () { loadList(currentPage); }); - }); - }); - }); - + /* ---------- 导入 ---------- */ $('#btn-import').on('click', function () { triggerFileInput('.csv', function (file) { var fd = new FormData(); @@ -281,8 +262,15 @@ $(function () { window.viewCompanies = function (personId) { compPersonId = personId; var content = - '
' + - '
ID姓名性别国籍工作所在地家乡学历联系方式创建时间操作
' + ' 详情' + ' 公司' + + ' 产品' + ' 编辑' + - ' 删除' + '
' + + '
' + + '
' + + ' 状态:' + + ' ' + + ' ' + + ' ' + + ' ' + + '
' + + '
' + ' ' + ' ' + '
公司名称部门岗位职级入职日期是否在岗
' + @@ -290,10 +278,22 @@ $(function () { ''; Dialog.open({ title: '任职公司', area: ['720px', 'auto'], content: content, btn: ['关闭'] }); loadCompanies(1); + + $('#comp-search').on('click', function () { loadCompanies(1); }); + $('#comp-reset').on('click', function () { + $('#comp-cur').prop('checked', true); + $('#comp-off').prop('checked', true); + loadCompanies(1); + }); }; function loadCompanies(page) { var params = { person_id: compPersonId, page: page, limit: 5 }; + var cur = $('#comp-cur').prop('checked'); + var off = $('#comp-off').prop('checked'); + // 状态筛选:只勾一项则按该项过滤;都不勾视为全部 + if (cur && !off) params.is_current = 1; + else if (!cur && off) params.is_current = 0; httpGet('person/companies.php', params).then(function (data) { var rows = data.list || []; var html = ''; @@ -314,4 +314,41 @@ $(function () { renderPagination($('#comp-pagination'), data, loadCompanies); }); } + + /* ---------- 产品品类弹窗(按人员任职公司查看产品,分页) ---------- */ + var ppPersonId = 0; + + window.viewPersonProducts = function (personId) { + ppPersonId = personId; + var content = + '
' + + '
' + + ' ' + + ' ' + + '
公司品类名称品类描述是否核心
' + + ' ' + + '
'; + Dialog.open({ title: '产品品类', area: ['760px', 'auto'], content: content, btn: ['关闭'] }); + loadPersonProducts(1); + }; + + function loadPersonProducts(page) { + httpGet('person/products.php', { person_id: ppPersonId, page: page, limit: 5 }).then(function (data) { + var rows = data.list || []; + var html = ''; + rows.forEach(function (r) { + html += '' + + '' + escHtml(r.company_name) + '' + + '' + escHtml(r.category_name) + '' + + '' + escHtml(r.category_description || '-') + '' + + '' + (r.is_core ? '核心' : '-') + '' + + ''; + }); + if (!rows.length) { + html = '暂无产品品类'; + } + $('#pp-tbody').html(html); + renderPagination($('#pp-pagination'), data, loadPersonProducts); + }); + } });