/** * 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-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(), 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 = '
' + '
' + '
' + 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(); var isCompany = (t === 'company'); var isPerson = (t === 'person'); // 企业相关:名称/行业/注册号/业务类型/国家/地址 $('#ha-f-company_name').toggle(t !== 'person'); $('#ha-f-industry').toggle(isCompany); $('#ha-f-regnum').toggle(isCompany); $('#ha-f-bizrole').toggle(isCompany); $('#ha-f-country').toggle(isCompany); $('#ha-f-address').toggle(isCompany); // 人员相关:姓名/工作所在地/身份证号码 $('#ha-f-person_name').toggle(true); $('#ha-f-person_name label').text((isPerson || t === 'mixed') ? '姓名' : '联系人'); $('#ha-f-workloc').toggle(isPerson); $('#ha-f-idnumber').toggle(isPerson); // 社媒联系方式:仅企业/人员 var showSocial = (isCompany || isPerson); $('#ha-f-platform').toggle(showSocial); $('#ha-f-account').toggle(showSocial); $('#ha-f-profile').toggle(showSocial); } $('#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 }); $('#cv-platform').val(d.platform || ''); function syncFields() { var t = $('#cv-type').val(); var isCompany = (t === 'company'); var isPerson = (t === 'person'); // 企业相关:名称/行业/注册号/业务类型/国家/地址 $('#cv-f-company_name').toggle(t !== 'person'); $('#cv-f-industry').toggle(isCompany); $('#cv-f-regnum').toggle(isCompany); $('#cv-f-bizrole').toggle(isCompany); $('#cv-f-country').toggle(isCompany); $('#cv-f-address').toggle(isCompany); // 人员相关:姓名/工作所在地/身份证号码 $('#cv-f-person_name').toggle(true); $('#cv-f-person_name label').text((isPerson || t === 'mixed') ? '姓名' : '联系人'); $('#cv-f-workloc').toggle(isPerson); $('#cv-f-idnumber').toggle(isPerson); // 社媒联系方式:仅企业/人员 var showSocial = (isCompany || isPerson); $('#cv-f-platform').toggle(showSocial); $('#cv-f-account').toggle(showSocial); $('#cv-f-profile').toggle(showSocial); } $('#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; } // 各类型转软碎片基本要求预检 if (target === 'company' && (!d.industry || !d.registration_number)) { Dialog.error('企业类型转软碎片:请先「继续补全」填写行业和注册号'); return; } if (target === 'person' && !d.person_name) { Dialog.error('人员类型转软碎片:请先「继续补全」填写姓名'); return; } if (target === 'product' && !d.company_name) { Dialog.error('产品类型转软碎片:请先「继续补全」填写公司名称'); return; } if (target === 'need' && !d.company_name) { 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); }); }); }); }); }; });