327 lines
18 KiB
JavaScript
327 lines
18 KiB
JavaScript
/**
|
||
* company.js - 企业数据管理逻辑(列表+筛选+分页 / 新增编辑弹窗 / 导入导出 / 详情)
|
||
*/
|
||
$(function () {
|
||
renderShell('企业数据', '数据管理 / 企业数据');
|
||
renderPage();
|
||
initPage('company', function (user) {
|
||
if (!checkPagePermission('company')) return;
|
||
loadList(1);
|
||
});
|
||
|
||
var currentPage = 1;
|
||
|
||
/** 渲染页面内容(工具栏+表格+分页) */
|
||
function renderPage() {
|
||
$('#page-content').html(
|
||
'<div class="card">' +
|
||
' <div class="toolbar">' +
|
||
' <input type="text" data-filter="keyword" placeholder="公司名/注册号关键词">' +
|
||
' <input type="text" data-filter="industry" placeholder="行业(精确匹配)">' +
|
||
' <select data-filter="business_role"><option value="">全部业务角色</option>' +
|
||
' <option value="manufacturer">生产型</option><option value="integrator">集成商</option>' +
|
||
' <option value="distributor">代理商</option><option value="brand_operator">品牌运营</option>' +
|
||
' <option value="others">其他</option></select>' +
|
||
' <input type="text" data-filter="country" placeholder="国家/地区">' +
|
||
' <button class="btn btn-primary" id="btn-search">搜索</button>' +
|
||
' <button class="btn" id="btn-reset">重置</button>' +
|
||
' <span class="spacer"></span>' +
|
||
' <button class="btn btn-success" id="btn-add">+ 新增</button>' +
|
||
' <button class="btn btn-warning" id="btn-import">导入CSV</button>' +
|
||
' <button class="btn" id="btn-export">导出</button>' +
|
||
' <button class="btn btn-danger" id="btn-del-batch">批量删除</button>' +
|
||
' </div>' +
|
||
' <div class="table-wrap"><table class="grid">' +
|
||
' <thead><tr><th><input type="checkbox" id="check-all"></th><th>ID</th><th>公司名称</th><th>行业</th><th>行业细分</th><th>国家</th><th>业务角色</th><th>注册号</th><th>法人</th><th>上市</th><th>创建时间</th><th>操作</th></tr></thead>' +
|
||
' <tbody id="company-tbody"></tbody>' +
|
||
' </table></div>' +
|
||
' <div class="pagination" id="pagination"></div>' +
|
||
'</div>'
|
||
);
|
||
$('#check-all').on('change', function () { $('.row-check').prop('checked', this.checked); });
|
||
}
|
||
|
||
/* ---------- 列表 ---------- */
|
||
function loadList(page) {
|
||
currentPage = page;
|
||
var params = buildFilterParam();
|
||
params.page = page;
|
||
params.limit = PAGE_SIZE;
|
||
|
||
httpGet('company/list.php', params).then(function (data) {
|
||
var rows = data.list || [];
|
||
var html = '';
|
||
rows.forEach(function (r) {
|
||
html += '<tr>' +
|
||
'<td><input type="checkbox" class="row-check" value="' + r.id + '"></td>' +
|
||
'<td>' + r.id + '</td>' +
|
||
'<td title="' + escHtml(r.name_zh || r.name_en || '') + '">' + escHtml(r.name_zh || r.name_en || '-') + '</td>' +
|
||
'<td>' + escHtml(r.industry || '-') + '</td>' +
|
||
'<td>' + escHtml(r.industry_subdivision || '-') + '</td>' +
|
||
'<td>' + escHtml(r.country || '-') + '</td>' +
|
||
'<td>' + escHtml(r.business_role || '-') + '</td>' +
|
||
'<td>' + escHtml(r.registration_number || '-') + '</td>' +
|
||
'<td>' + escHtml(r.legal_representative || '-') + '</td>' +
|
||
'<td>' + (r.is_listed ? '<span class="tag">上市</span>' : '-') + '</td>' +
|
||
'<td>' + fmtDate(r.created_at) + '</td>' +
|
||
'<td class="ops">' +
|
||
' <a onclick="viewCompany(' + r.id + ')">详情</a>' +
|
||
' <a onclick="viewEmployees(' + r.id + ')">员工</a>' +
|
||
' <a onclick="editCompany(' + r.id + ')">编辑</a>' +
|
||
' <a class="danger" onclick="delCompany(' + r.id + ')">删除</a>' +
|
||
'</td></tr>';
|
||
});
|
||
if (!rows.length) {
|
||
html = '<tr><td colspan="12" class="empty-tip" style="padding:40px 0;">暂无数据</td></tr>';
|
||
}
|
||
$('#company-tbody').html(html);
|
||
renderPagination($('#pagination'), data, loadList);
|
||
});
|
||
}
|
||
|
||
/* ---------- 筛选 ---------- */
|
||
$('#btn-search').on('click', function () { loadList(1); });
|
||
$('#btn-reset').on('click', function () {
|
||
$('.toolbar [data-filter]').val('');
|
||
loadList(1);
|
||
});
|
||
|
||
/* ---------- 新增/编辑 ---------- */
|
||
$('#btn-add').on('click', function () { openForm(null); });
|
||
window.editCompany = function (id) {
|
||
httpGet('company/detail.php', { id: id }).then(function (d) {
|
||
openForm(d.company);
|
||
});
|
||
};
|
||
|
||
function openForm(company) {
|
||
var isEdit = !!company;
|
||
var c = company || {};
|
||
var content =
|
||
'<form id="company-form" style="padding:18px 22px 4px;">' +
|
||
'<div class="form-grid">' +
|
||
' <div class="form-item"><label>公司名称<span class="req">*</span></label><input type="text" name="name_zh" value="' + escHtml(c.name_zh) + '"></div>' +
|
||
' <div class="form-item"><label>英文名称</label><input type="text" name="name_en" value="' + escHtml(c.name_en) + '"></div>' +
|
||
' <div class="form-item"><label>业务角色</label><select name="business_role">' + roleOptions(c.business_role) + '</select></div>' +
|
||
' <div class="form-item"><label>国家/地区</label><input type="text" name="country" value="' + escHtml(c.country) + '"></div>' +
|
||
' <div class="form-item"><label>注册号</label><input type="text" name="registration_number" value="' + escHtml(c.registration_number) + '"></div>' +
|
||
' <div class="form-item"><label>注册地址</label><input type="text" name="address" value="' + escHtml(c.address) + '"></div>' +
|
||
' <div class="form-item"><label>法定代表人</label><input type="text" name="legal_representative" value="' + escHtml(c.legal_representative) + '"></div>' +
|
||
' <div class="form-item"><label>行业</label><input type="text" name="industry" value="' + escHtml(c.industry) + '"></div>' +
|
||
' <div class="form-item"><label>行业细分</label><input type="text" name="industry_subdivision" value="' + escHtml(c.industry_subdivision) + '"></div>' +
|
||
' <div class="form-item"><label>官网</label><input type="text" name="website" value="' + escHtml(c.website) + '"></div>' +
|
||
' <div class="form-item"><label>注册资本(万元)</label><input type="text" name="registered_capital" value="' + escHtml(c.registered_capital) + '"></div>' +
|
||
' <div class="form-item"><label>成立日期</label><input type="date" name="established_date" value="' + escHtml(c.established_date) + '"></div>' +
|
||
' <div class="form-item"><label>员工数</label><input type="number" name="latest_employee_count" value="' + escHtml(c.latest_employee_count) + '"></div>' +
|
||
' <div class="form-item"><label>最新年营收</label><input type="text" name="latest_annual_revenue" value="' + escHtml(c.latest_annual_revenue) + '"></div>' +
|
||
' <div class="form-item"><label>是否上市</label><select name="is_listed">' +
|
||
' <option value="0"' + (c.is_listed ? '' : ' selected') + '>否</option>' +
|
||
' <option value="1"' + (c.is_listed ? ' selected' : '') + '>是</option></select></div>' +
|
||
' <div class="form-item"><label>股票代码</label><input type="text" name="stock_code" value="' + escHtml(c.stock_code) + '"></div>' +
|
||
' <div class="form-item full"><label>经营范围</label><textarea name="business_scope">' + escHtml(c.business_scope) + '</textarea></div>' +
|
||
'</div>' +
|
||
'<div class="dialog-footer"><button type="button" class="btn" id="form-cancel">取消</button>' +
|
||
'<button type="submit" class="btn btn-primary">保存</button></div>' +
|
||
'</form>';
|
||
|
||
var idx = Dialog.open({
|
||
title: isEdit ? '编辑企业' : '新增企业',
|
||
area: ['760px', 'auto'],
|
||
content: content,
|
||
btn: false
|
||
});
|
||
|
||
$('#form-cancel').on('click', function () { Dialog.close(idx); });
|
||
|
||
$('#company-form').on('submit', function (e) {
|
||
e.preventDefault();
|
||
var fd = new FormData(this);
|
||
var nameZh = fd.get('name_zh');
|
||
var nameEn = fd.get('name_en');
|
||
if (isEdit) fd.delete('display_name'); // 编辑不允许改显示名称
|
||
if (!isEdit && !nameZh && !nameEn) {
|
||
Dialog.error('公司名称或英文名称至少填写一项');
|
||
return;
|
||
}
|
||
httpPost(isEdit ? 'company/update.php' : 'company/add.php', fd, true).then(function () {
|
||
Dialog.success('保存成功', function () {
|
||
Dialog.close(idx);
|
||
loadList(currentPage);
|
||
});
|
||
});
|
||
});
|
||
}
|
||
|
||
function roleOptions(sel) {
|
||
var opts = ['', 'manufacturer', 'integrator', 'distributor', 'brand_operator', 'others'];
|
||
var labels = { 'manufacturer': '生产型', 'integrator': '集成商', 'distributor': '代理商', 'brand_operator': '品牌运营', 'others': '其他' };
|
||
var html = '<option value="">-</option>';
|
||
opts.forEach(function (v) {
|
||
if (v === '') return;
|
||
html += '<option value="' + v + '"' + (sel === v ? ' selected' : '') + '>' + (labels[v] || v) + '</option>';
|
||
});
|
||
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) {
|
||
var fd = new FormData();
|
||
fd.append('file', file);
|
||
httpPost('company/import.php', fd, true).then(function (d) {
|
||
Dialog.alert('导入结果:成功 ' + d.inserted + ' 条,失败 ' + d.failed + ' 条', function () {
|
||
loadList(1);
|
||
});
|
||
});
|
||
});
|
||
});
|
||
|
||
/* ---------- 导出(仅导出勾选的企业,未勾选弹窗提醒) ---------- */
|
||
$('#btn-export').on('click', function () {
|
||
var ids = [];
|
||
$('.row-check:checked').each(function () { ids.push($(this).val()); });
|
||
if (!ids.length) {
|
||
layer.alert('请先选择需要导出的企业数据', { icon: 2, title: '提示' });
|
||
return;
|
||
}
|
||
download('company/export.php', { ids: ids.join(',') });
|
||
});
|
||
|
||
/* ---------- 详情 ---------- */
|
||
window.viewCompany = function (id) {
|
||
httpGet('company/detail.php', { id: id }).then(function (d) {
|
||
var c = d.company;
|
||
var html =
|
||
'<div style="padding:18px 22px;">' +
|
||
' <h3 style="margin-bottom:14px;">' + escHtml(c.name_zh || c.name_en || '企业 #' + c.id) + '</h3>' +
|
||
' <div class="detail-grid" style="display:grid;grid-template-columns:1fr 1fr;gap:8px 24px;font-size:13px;">' +
|
||
detailRow('公司名称', c.name_zh) + detailRow('英文名称', c.name_en) +
|
||
detailRow('业务角色', c.business_role) + detailRow('国家/地区', c.country) +
|
||
detailRow('注册号', c.registration_number) + detailRow('地址', c.address) +
|
||
detailRow('法定代表人', c.legal_representative) + detailRow('行业', c.industry) +
|
||
detailRow('行业细分', c.industry_subdivision) + detailRow('官网', c.website) +
|
||
detailRow('注册资本', c.registered_capital) + detailRow('成立日期', c.established_date) +
|
||
detailRow('员工数', c.latest_employee_count) + detailRow('年营收', c.latest_annual_revenue) +
|
||
detailRow('是否上市', c.is_listed ? '是' : '否') + detailRow('股票代码', c.stock_code) +
|
||
'</div>' +
|
||
' <h4 style="margin:16px 0 8px;">经营范围</h4><div style="font-size:13px;color:#5a6472;">' + escHtml(c.business_scope || '-') + '</div>' +
|
||
' <h4 style="margin:16px 0 8px;">产品品类</h4>' + miniTable(['品类', '描述', '核心'], d.products.map(function (p) { return [p.category_name, p.category_description || '-', p.is_core ? '是' : '否']; })) +
|
||
' <h4 style="margin:16px 0 8px;">关联需求</h4>' + miniTable(['联系人', '需求大类', '意向品类', '场景'], d.needs.map(function (n) { return [n.contact_person || '-', n.need_category || '-', n.target_product_category || '-', n.application_scenario || '-']; })) +
|
||
' <h4 style="margin:16px 0 8px;">关联联系人</h4>' + miniTable(['姓名', '职位', '联系方式'], d.contacts.map(function (p) { return [p.full_name || '-', p.position || '-', p.contacts || '-']; })) +
|
||
'</div>';
|
||
Dialog.open({ title: '企业详情', area: ['820px', 'auto'], content: html, btn: ['关闭'] });
|
||
});
|
||
};
|
||
|
||
function detailRow(label, val) {
|
||
return '<div><b>' + label + ':</b>' + escHtml(val || '-') + '</div>';
|
||
}
|
||
|
||
function miniTable(headers, rows) {
|
||
if (!rows.length) return '<div style="font-size:13px;color:#b6bfcc;">暂无数据</div>';
|
||
var html = '<table class="grid" style="font-size:12px;">';
|
||
html += '<tr>' + headers.map(function (h) { return '<th>' + h + '</th>'; }).join('') + '</tr>';
|
||
rows.forEach(function (r) {
|
||
html += '<tr>' + r.map(function (v) { return '<td>' + escHtml(v) + '</td>'; }).join('') + '</tr>';
|
||
});
|
||
return html + '</table>';
|
||
}
|
||
|
||
/* ---------- 员工列表弹窗(按公司查看员工,分页 + 姓名/职级筛选) ---------- */
|
||
var empCompanyId = 0;
|
||
var empPage = 1;
|
||
|
||
window.viewEmployees = function (companyId) {
|
||
empCompanyId = companyId;
|
||
empPage = 1;
|
||
var content =
|
||
'<div style="padding:16px 18px 6px;">' +
|
||
' <div class="toolbar">' +
|
||
' <input type="text" id="emp-keyword" placeholder="姓名关键词">' +
|
||
' <select id="emp-level"><option value="">全部职级</option></select>' +
|
||
' <button class="btn btn-primary btn-sm" id="emp-search">搜索</button>' +
|
||
' <button class="btn btn-sm" id="emp-reset">重置</button>' +
|
||
' </div>' +
|
||
' <div class="table-wrap"><table class="grid">' +
|
||
' <thead><tr><th>姓名</th><th>联系方式</th><th>邮箱</th><th>职级</th><th>部门</th><th>岗位</th><th>入职日期</th><th>是否在职</th></tr></thead>' +
|
||
' <tbody id="emp-tbody"></tbody>' +
|
||
' </table></div>' +
|
||
' <div class="pagination" id="emp-pagination"></div>' +
|
||
'</div>';
|
||
var idx = Dialog.open({ title: '员工列表', area: ['920px', 'auto'], content: content, btn: ['关闭'] });
|
||
window.__empDialogIdx = idx;
|
||
|
||
loadEmployees(1);
|
||
|
||
$('#emp-search').on('click', function () { loadEmployees(1); });
|
||
$('#emp-reset').on('click', function () {
|
||
$('#emp-keyword').val('');
|
||
$('#emp-level').val('');
|
||
loadEmployees(1);
|
||
});
|
||
};
|
||
|
||
function loadEmployees(page) {
|
||
empPage = page;
|
||
var params = { company_id: empCompanyId, page: page, limit: 5 };
|
||
var kw = $.trim($('#emp-keyword').val());
|
||
var lv = $('#emp-level').val();
|
||
if (kw) params.keyword = kw;
|
||
if (lv) params.job_level = lv;
|
||
|
||
httpGet('company/employees.php', params).then(function (data) {
|
||
var rows = data.list || [];
|
||
var html = '';
|
||
rows.forEach(function (r) {
|
||
html += '<tr>' +
|
||
'<td>' + escHtml(r.full_name) + '</td>' +
|
||
'<td>' + escHtml(r.phone || '-') + '</td>' +
|
||
'<td>' + escHtml(r.email || '-') + '</td>' +
|
||
'<td>' + escHtml(r.job_level || '-') + '</td>' +
|
||
'<td>' + escHtml(r.department || '-') + '</td>' +
|
||
'<td>' + escHtml(r.position || '-') + '</td>' +
|
||
'<td>' + escHtml(r.start_date || '-') + '</td>' +
|
||
'<td>' + (r.is_current ? '<span class="tag tag-green">在职</span>' : '<span class="tag tag-gray">离职</span>') + '</td>' +
|
||
'</tr>';
|
||
});
|
||
if (!rows.length) {
|
||
html = '<tr><td colspan="8" class="empty-tip" style="padding:30px 0;">暂无员工</td></tr>';
|
||
}
|
||
$('#emp-tbody').html(html);
|
||
|
||
// 职级下拉(仅首次填充)
|
||
var $lv = $('#emp-level');
|
||
if ($lv.find('option').length <= 1) {
|
||
var optHtml = '<option value="">全部职级</option>';
|
||
(data.levels || []).forEach(function (l) {
|
||
optHtml += '<option value="' + escHtml(l) + '">' + escHtml(l) + '</option>';
|
||
});
|
||
$lv.html(optHtml);
|
||
}
|
||
|
||
renderPagination($('#emp-pagination'), data, loadEmployees);
|
||
});
|
||
}
|
||
});
|