/** * 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 '
' + '
' + '
' + '' + score + '%
'; } /** 渲染页面内容:指标卡 + 硬碎片 + 软碎片 两个独立区块 */ 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-status').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_new + '
本月新增
' + '
' + d.month_processed + '
本月处理
' + '
' + d.cumulative + '
累计处理
' ); }); } /* ================= 硬碎片列表 ================= */ function loadHardList(page) { hardPage = page; var params = { page: page, source_type: $('#hard-type').val(), source_channel: $('#hard-source').val(), status: $('#hard-status').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.created_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 = '
' + '
' + '
' + typeSel + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '' + '
'; 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(t === 'person' || t === 'mixed'); } $('#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 typeSel = ''; var content = '
' + '
' + '
' + typeSel + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '
' + '' + '
'; var idx = Dialog.open({ title: '硬碎片补全录入', area: ['640px', 'auto'], content: content, btn: false }); function syncFields() { var t = $('#cv-type').val(); $('#cv-f-company_name').toggle(t !== 'person'); $('#cv-f-person_name').toggle(t === 'person'); $('#cv-f-category').toggle(t === 'product' || t === 'need'); $('#cv-f-industry').toggle(t === 'company'); $('#cv-f-needcat').toggle(t === 'need'); $('#cv-f-scenario').toggle(t === 'need'); } $('#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, textarea').each(function () { var name = $(this).attr('name'); if (name) fd[name] = $(this).val(); }); fd.id = id; fd.target_type = $('#cv-type').val(); // 格式校验:手机 / 邮箱 if (fd.contact_phone && !validatePhoneCN(fd.contact_phone)) { Dialog.error('手机号码格式不正确(应为国内 11 位手机号,如 13812345678)'); return; } if (fd.contact_email && !validateEmail(fd.contact_email)) { Dialog.error('邮箱格式不正确'); return; } httpPost('fragment/hard_convert.php', fd).then(function () { Dialog.success('转换成功', function () { Dialog.close(idx); loadStats(); loadHardList(hardPage); loadSoftList(1); }); }); }); }); }; /* ================= 硬碎片:转软碎片(不弹窗,直接转换) ================= */ 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; } 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 = '
' + '
整体完整度 ' + d.overall + '%,各层:' + layerDesc + '
' + '
核心层须 100%、重要层 ≥60%、非必要层 ≥40%,补全后自动重新计算。
' + '
' + inputs + '
' + '' + '
'; 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); }); }); }); }); }; });