/**
* fragment.js - 碎片处理中心(v1.0.27)
* 布局:顶部指标卡 + 【硬碎片】独立区块 + 【软碎片】独立区块(不用 Tab)
* 硬碎片:preliminary_data 中未终结记录(完整度/类型/内容摘要/来源/录入人/时间/状态/操作)
* 软碎片:四张主表 is_incomplete=1 记录(完整度/缺失层级标签/名称/缺失字段/所属表/时间/操作)
*/
$(function () {
renderShell('碎片处理中心', '数据管理 / 碎片处理');
renderPage();
initPage('preliminary', function (user) {
if (!checkPagePermission('preliminary')) return;
loadStats();
loadHardList(1);
loadSoftList(1);
loadDicts();
});
var hardPage = 1, softPage = 1;
var hardRows = [], softRows = [];
/** 缺失层级标签样式 */
function levelTagHtml(level) {
if (level === 'core') return '缺核心';
if (level === 'important') return '缺重要';
if (level === 'optional') return '待补充';
return '完整';
}
/** 完整度进度条 + 百分比 */
function completenessHtml(score) {
var color = score >= 80 ? '#2f8f46' : (score >= 65 ? '#e6a23c' : '#d9534f');
return '
';
}
/** 渲染页面内容:指标卡 + 硬碎片 + 软碎片 两个独立区块 */
function renderPage() {
$('#page-content').html(
'' +
// ================= 硬碎片 =================
'' +
'
' +
' 硬数据新增与处理' +
' 关键字段缺失、未入主表的原始线索(不含已转换/已废弃)' +
'
' +
'
' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
' ' +
'
' +
'
' +
' | 完整度 | 类型 | 内容摘要 | 来源 | 录入人 | 最后修改 | 操作 |
' +
' ' +
'
' +
' ' +
'
' +
// ================= 软碎片 =================
'' +
'
' +
' 软数据碎片处理' +
' 已入主表但完整度低于阈值的记录(is_incomplete=1)' +
'
' +
'
' +
' ' +
' ' +
' ' +
' ' +
' ' +
'
' +
'
' +
' | 完整度 | 缺失层级 | 名称 | 各层完整度 | 缺失字段 | 所属表 | 最近更新 | 操作 |
' +
' ' +
'
' +
' ' +
'
'
);
$('#hard-search').on('click', function () { loadHardList(1); });
$('#hard-keyword').on('keydown', function (e) { if (e.keyCode === 13) loadHardList(1); });
$('#hard-reset').on('click', function () {
$('#hard-type').val(''); $('#hard-source').val(''); $('#hard-keyword').val('');
loadHardList(1);
});
$('#hard-add').on('click', function () { openHardAdd(); });
$('#soft-search').on('click', function () { loadSoftList(1); });
$('#soft-keyword').on('keydown', function (e) { if (e.keyCode === 13) loadSoftList(1); });
$('#soft-reset').on('click', function () {
$('#soft-table').val(''); $('#soft-level').val(''); $('#soft-keyword').val('');
loadSoftList(1);
});
}
/** 来源渠道下拉选项 */
function loadDicts() {
httpGet('common/dicts.php', { type: 'all' }).then(function (d) {
var html = '';
(d.source_channels || []).forEach(function (c) {
html += '';
});
$('#hard-source').html(html);
}).catch(function () {});
}
/* ================= 顶部概览指标卡 ================= */
function loadStats() {
httpGet('fragment/stats_overview.php').then(function (d) {
$('#stat-cards').html(
'' + d.hard_total + '/' + d.soft_total + '
碎片总数(硬/软)
' +
'' +
'' + d.month_processed + '
本月处理
' +
''
);
});
}
/* ================= 硬碎片列表 ================= */
function loadHardList(page) {
hardPage = page;
var params = {
page: page,
source_type: $('#hard-type').val(),
source_channel: $('#hard-source').val(),
keyword: $.trim($('#hard-keyword').val())
};
httpGet('fragment/hard_list.php', params).then(function (d) {
hardRows = d.list || [];
var html = '';
hardRows.forEach(function (r) {
html += '' +
'| ' + completenessHtml(r.completeness) + ' | ' +
'' + escHtml(r.source_type_label) + ' | ' +
'' + escHtml(r.summary || '-') + ' | ' +
'' + escHtml(r.source_channel || '-') + ' | ' +
'' + escHtml(r.recorded_by || '-') + ' | ' +
'' + fmtDate(r.updated_at) + ' | ' +
'' +
' 查看' +
' 继续补全' +
' 转软碎片' +
' 废弃' +
' |
';
});
if (!hardRows.length) {
html = '| 暂无硬碎片 |
';
}
$('#hard-tbody').html(html);
renderPagination($('#hard-pagination'), d, loadHardList);
});
}
/* ================= 软碎片列表 ================= */
function loadSoftList(page) {
softPage = page;
var params = {
page: page,
table: $('#soft-table').val(),
level: $('#soft-level').val(),
keyword: $.trim($('#soft-keyword').val())
};
httpGet('fragment/soft_list.php', params).then(function (d) {
softRows = d.list || [];
var html = '';
softRows.forEach(function (r) {
var missing = (r.missing_fields || []).join('、') || '-';
var layers = r.layer_rates || {};
var layerHtml = '核心' + (layers.core !== undefined ? layers.core : '-') + '% / 重要' + (layers.important !== undefined ? layers.important : '-') + '% / 非必要' + (layers.optional !== undefined ? layers.optional : '-') + '%';
html += '' +
'| ' + completenessHtml(r.overall) + ' | ' +
'' + levelTagHtml(r.level) + ' | ' +
'' + escHtml(r.name) + ' | ' +
'' + layerHtml + ' | ' +
'' + escHtml(missing) + ' | ' +
'' + escHtml(r.table_label) + ' | ' +
'' + fmtDate(r.updated_at) + ' | ' +
'补全 |
';
});
if (!softRows.length) {
html = '| 暂无软碎片 |
';
}
$('#soft-tbody').html(html);
renderPagination($('#soft-pagination'), d, loadSoftList);
});
}
/* ================= 硬碎片:新增 ================= */
function openHardAdd() {
var typeSel = '';
var content =
'';
var idx = Dialog.open({
title: '新增硬碎片',
area: ['640px', 'auto'],
content: content,
btn: false
});
// 来源渠道选项(与 source_channels 字典保持一致,不额外添加选项)
httpGet('common/dicts.php', { type: 'all' }).then(function (d) {
var html = '';
(d.source_channels || []).forEach(function (c) {
html += '';
});
$('#ha-source').html(html);
}).catch(function () {});
function syncFields() {
var t = $('#ha-type').val();
// 公司名称:除人员外都显示
$('#ha-f-company_name').toggle(t !== 'person');
// 姓名/联系人:人员与混合显示「姓名」,其它类型显示「联系人」
$('#ha-f-person_name').toggle(true);
$('#ha-f-person_name label').text((t === 'person' || t === 'mixed') ? '姓名' : '联系人');
// 企业专属:行业 / 注册号
$('#ha-f-industry').toggle(t === 'company');
$('#ha-f-regnum').toggle(t === 'company');
// 产品:品类;需求:需求类别
$('#ha-f-category').toggle(t === 'product');
$('#ha-f-needcat').toggle(t === 'need');
// 身份证 / 社媒平台 / 账号 / 主页:企业与人员显示
var showIdSocial = (t === 'company' || t === 'person');
$('#ha-f-idnumber').toggle(showIdSocial);
$('#ha-f-platform').toggle(showIdSocial);
$('#ha-f-account').toggle(showIdSocial);
$('#ha-f-profile').toggle(showIdSocial);
}
$('#ha-type').on('change', syncFields);
syncFields();
$('#ha-cancel').on('click', function () { Dialog.close(idx); });
$('#ha-form').on('submit', function (e) {
e.preventDefault();
var fd = {};
$(this).find('input, select, textarea').each(function () {
var name = $(this).attr('name');
if (name) fd[name] = $(this).val();
});
fd.source_type = $('#ha-type').val();
// 硬数据标准校验:企业/产品/需求 → 企业名称必填;人员 → 手机、邮箱至少一项
if (fd.source_type !== 'person' && !$.trim(fd.company_name)) { Dialog.error('企业类型硬数据:企业名称为必填项'); return; }
if (fd.source_type === 'person' && !$.trim(fd.contact_phone) && !$.trim(fd.contact_email)) { Dialog.error('人员类型硬数据:手机号码、邮箱至少填写一项'); return; }
// 格式校验:手机 / 邮箱 / 身份证
if (fd.contact_phone && !validatePhoneCN(fd.contact_phone)) { Dialog.error('手机号码格式不正确(应为国内 11 位手机号,如 13812345678)'); return; }
if (fd.contact_email && !validateEmail(fd.contact_email)) { Dialog.error('邮箱格式不正确'); return; }
if (fd.id_number && !validateIdCard(fd.id_number)) { Dialog.error('身份证号码格式不正确(应为 15 或 18 位)'); return; }
if (fd.profile_url && !/^https?:\/\//.test(fd.profile_url)) { Dialog.error('主页链接格式不正确(应以 http:// 或 https:// 开头)'); return; }
httpPost('fragment/hard_add.php', fd).then(function () {
Dialog.success('新增成功', function () {
Dialog.close(idx);
loadStats();
loadHardList(1);
});
});
});
}
/* ================= 硬碎片:查看 ================= */
window.viewHard = function (id) {
httpGet('fragment/hard_detail.php', { id: id }).then(function (d) {
var rowHtml = '';
var fields = [
['类型', d.source_type_label], ['公司名称', d.company_name], ['联系人', d.person_name],
['联系电话', d.contact_phone], ['联系邮箱', d.contact_email],
['来源渠道', d.source_channel], ['录入人', d.recorded_by], ['状态', d.status],
['录入时间', d.created_at], ['处理时间', d.processed_at]
];
fields.forEach(function (f) {
rowHtml += '' + f[0] + '' +
'' + escHtml(f[1] || '-') + '
';
});
Dialog.open({
title: '硬碎片详情(完整度 ' + d.completeness + '%)',
area: ['560px', 'auto'],
content: '' + rowHtml + '
',
btn: ['关闭']
});
});
};
/* ================= 硬碎片:补全录入(转换) ================= */
window.convertHard = function (id) {
httpGet('fragment/hard_detail.php', { id: id }).then(function (d) {
var ex = d.extra_info || {};
if (typeof ex === 'string') { try { ex = JSON.parse(ex); } catch (e) { ex = {}; } }
var typeSel = '';
var content =
'';
var idx = Dialog.open({
title: '硬数据继续补全',
area: ['640px', 'auto'],
content: content,
btn: false
});
$('#cv-platform').val(ex.platform || '');
function syncFields() {
var t = $('#cv-type').val();
$('#cv-f-company_name').toggle(t !== 'person');
$('#cv-f-person_name').toggle(true);
$('#cv-f-person_name label').text((t === 'person' || t === 'mixed') ? '姓名' : '联系人');
$('#cv-f-industry').toggle(t === 'company');
$('#cv-f-regnum').toggle(t === 'company');
$('#cv-f-category').toggle(t === 'product');
$('#cv-f-needcat').toggle(t === 'need');
var showIdSocial = (t === 'company' || t === 'person');
$('#cv-f-idnumber').toggle(showIdSocial);
$('#cv-f-platform').toggle(showIdSocial);
$('#cv-f-account').toggle(showIdSocial);
$('#cv-f-profile').toggle(showIdSocial);
}
$('#cv-type').on('change', syncFields);
syncFields();
function syncFields() {
var t = $('#cv-type').val();
$('#cv-f-company_name').toggle(t !== 'person');
$('#cv-f-person_name').toggle(t === 'person' || t === 'mixed');
}
$('#cv-type').on('change', syncFields);
syncFields();
$('#cv-cancel').on('click', function () { Dialog.close(idx); });
$('#cv-form').on('submit', function (e) {
e.preventDefault();
var fd = {};
$(this).find('input, select').each(function () {
var name = $(this).attr('name');
if (name) fd[name] = $(this).val();
});
fd.id = id;
// 类型标准校验
if (fd.source_type !== 'person' && fd.source_type !== 'mixed' && !$.trim(fd.company_name)) { Dialog.error('企业类型硬数据:企业名称为必填项'); return; }
if (fd.source_type === 'person' && !$.trim(fd.contact_phone) && !$.trim(fd.contact_email)) { Dialog.error('人员类型硬数据:手机号码、邮箱至少填写一项'); return; }
// 格式校验:手机 / 邮箱 / 身份证 / 主页链接
if (fd.contact_phone && !validatePhoneCN(fd.contact_phone)) { Dialog.error('手机号码格式不正确(应为国内 11 位手机号,如 13812345678)'); return; }
if (fd.contact_email && !validateEmail(fd.contact_email)) { Dialog.error('邮箱格式不正确'); return; }
if (fd.id_number && !validateIdCard(fd.id_number)) { Dialog.error('身份证号码格式不正确(应为 15 或 18 位)'); return; }
if (fd.profile_url && !/^https?:\/\//.test(fd.profile_url)) { Dialog.error('主页链接格式不正确(应以 http:// 或 https:// 开头)'); return; }
httpPost('fragment/hard_update.php', fd).then(function () {
Dialog.success('已保存,点击「转软碎片」完成转换', function () {
Dialog.close(idx);
loadHardList(hardPage);
});
});
});
});
};
/* ================= 硬碎片:转软碎片(不弹窗,直接转换) ================= */
window.convertHardQuick = function (id) {
httpGet('fragment/hard_detail.php', { id: id }).then(function (d) {
var target = d.source_type;
if (target === 'mixed') {
target = d.company_name ? 'company' : (d.person_name ? 'person' : '');
}
if (!target) {
Dialog.error('该碎片缺少可转换信息,请使用「继续补全」');
return;
}
var ex = d.extra_info || {};
if (typeof ex === 'string') { try { ex = JSON.parse(ex); } catch (e) { ex = {}; } }
// 各类型转软碎片基本要求预检
if (target === 'company' && (!d.industry || !d.registration_number)) {
Dialog.error('企业类型转软碎片:请先「继续补全」填写行业和注册号');
return;
}
if (target === 'person' && !d.person_name) {
Dialog.error('人员类型转软碎片:请先「继续补全」填写姓名');
return;
}
if (target === 'product' && !ex.category) {
Dialog.error('产品类型转软碎片:请先「继续补全」填写产品品类');
return;
}
if (target === 'need' && !ex.need_category) {
Dialog.error('需求类型转软碎片:请先「继续补全」填写需求类别');
return;
}
Dialog.confirm('确定将该硬数据直接转换为软数据碎片吗?', function () {
httpPost('fragment/hard_convert.php', { id: id, target_type: target }).then(function () {
Dialog.success('已转为软碎片', function () {
loadStats();
loadHardList(hardPage);
loadSoftList(1);
});
});
});
});
};
/* ================= 硬碎片:废弃 ================= */
window.discardHard = function (id) {
Dialog.confirm('确定废弃该碎片吗?废弃后不可恢复。', function () {
httpPost('fragment/hard_discard.php', { id: id }).then(function () {
Dialog.success('已废弃', function () {
loadStats();
loadHardList(hardPage);
});
});
});
};
/* ================= 软碎片:补全 ================= */
window.completeSoft = function (table, id) {
httpGet('fragment/soft_detail.php', { table: table, id: id }).then(function (d) {
var allMissing = [].concat(d.missing_core || [], d.missing_important || [], d.missing_optional || []);
var inputs = '';
allMissing.forEach(function (m) {
var isDate = (m.key === 'established_date');
inputs += '' +
'
';
});
var layers = d.layers || {};
var layerDesc = '核心' + (layers.core ? layers.core.rate : '-') + '% / 重要' + (layers.important ? layers.important.rate : '-') + '% / 非必要' + (layers.optional ? layers.optional.rate : '-') + '%';
var content =
'';
var idx = Dialog.open({
title: '软碎片补全 - ' + escHtml(d.name) + '(' + d.table_label + ')',
area: ['640px', 'auto'],
content: content,
btn: false
});
$('#soft-cancel').on('click', function () { Dialog.close(idx); });
$('#soft-form').on('submit', function (e) {
e.preventDefault();
var fd = { table: table, id: id };
$(this).find('input').each(function () {
var name = $(this).attr('name');
if (name) fd[name] = $(this).val();
});
// 格式校验:身份证 / 手机 / 邮箱
if (fd.id_number && !validateIdCard(fd.id_number)) { Dialog.error('身份证号码格式不正确(应为 15 或 18 位)'); return; }
if (fd.phone && !validatePhoneCN(fd.phone)) { Dialog.error('手机号码格式不正确(应为国内 11 位手机号,如 13812345678)'); return; }
if (fd.email && !validateEmail(fd.email)) { Dialog.error('邮箱格式不正确'); return; }
httpPost('fragment/soft_update.php', fd).then(function (res) {
Dialog.success(res && res.is_complete ? '补全完成' : '已保存(整体完整度 ' + (res && res.overall) + '%)', function () {
Dialog.close(idx);
loadStats();
loadSoftList(softPage);
loadHardList(hardPage);
});
});
});
});
};
});