坐席业绩可视化分析工具
这个交互式的坐席业绩分析工具具有以下特点:
- 数据导入功能:支持上传 CSV 文件,自动解析并展示数据
- 多维度分析:可按日 / 周 / 月分析业绩数据,支持切换不同业绩指标(接通时长 / 外呼次数 / 接通次数)
- 灵活筛选:可通过勾选坐席姓名筛选数据,支持全选 / 取消全选操作
- 数据可视化:使用 Chart.js 生成美观的趋势分析图表,支持导出为 PNG、SVG 和 CSV 格式
- 统计信息:顶部卡片展示关键业绩指标,如平均接通时长、总外呼次数和平均接通率
- 原始数据查看:点击按钮可查看完整原始数据,并支持导出为 CSV 格式
- 响应式设计:适配不同屏幕尺寸,在移动设备上也能良好展示
- 现代化 UI:采用 Tailwind CSS 构建,具有精美的动画和过渡效果
工具内置了示例数据下载功能,您可以先下载示例数据体验功能,再上传自己的业绩数据进行分析。
目标值功能适用于所有业绩指标(接通时长 / 外呼次数 / 接通次数),并且会根据当前选择的时间维度(日 / 周 / 月)自动调整显示。
代码如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>坐席业绩可视化分析工具</title><script src="https://cdn.tailwindcss.com"></script><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet"><script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.8/dist/chart.umd.min.js"></script><script src="https://cdn.jsdelivr.net/npm/papaparse@5.4.1/papaparse.min.js"></script><script>tailwind.config = {theme: {extend: {colors: {primary: '#3B82F6',secondary: '#64748B',accent: '#F97316',success: '#10B981',warning: '#F59E0B',danger: '#EF4444',dark: '#1E293B',light: '#F8FAFC'},fontFamily: {inter: ['Inter', 'system-ui', 'sans-serif'],},}}}</script><style type="text/tailwindcss">@layer utilities {.content-auto {content-visibility: auto;}.card-shadow {box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);}.hover-scale {transition: transform 0.2s ease-in-out;}.hover-scale:hover {transform: scale(1.02);}.checkbox-primary {accent-color: #3B82F6;}.input-focus {@apply focus:ring-2 focus:ring-primary/50 focus:border-primary focus:outline-none;}}</style>
</head>
<body class="bg-gray-50 font-inter text-gray-800 min-h-screen flex flex-col"><!-- 顶部导航栏 --><header class="bg-white shadow-md sticky top-0 z-50 transition-all duration-300"><div class="container mx-auto px-4 py-3 flex justify-between items-center"><div class="flex items-center space-x-2"><i class="fa-solid fa-chart-line text-primary text-2xl"></i><h1 class="text-xl md:text-2xl font-bold text-gray-800">坐席业绩可视化分析工具</h1></div><div class="flex items-center space-x-4"><div class="hidden md:flex items-center space-x-2 text-sm text-gray-600"><i class="fa-regular fa-clock"></i><span id="current-date">加载中...</span></div><button id="theme-toggle" class="p-2 rounded-full hover:bg-gray-100 transition-colors"><i class="fa-solid fa-moon text-gray-600"></i></button></div></div></header><!-- 主内容区 --><main class="flex-grow container mx-auto px-4 py-6"><!-- 文件上传区域 --><section class="bg-white rounded-xl p-6 mb-8 card-shadow hover-scale"><div class="flex flex-col md:flex-row items-center justify-between"><div class="mb-4 md:mb-0"><h2 class="text-xl font-bold mb-2">数据导入</h2><p class="text-gray-600 text-sm">请上传包含坐席业绩数据的CSV文件</p></div><div class="flex items-center space-x-4"><label for="file-upload" class="px-4 py-2 bg-primary text-white rounded-lg cursor-pointer transition-all hover:bg-primary/90 flex items-center space-x-2"><i class="fa-solid fa-upload"></i><span>选择文件</span></label><input id="file-upload" type="file" accept=".csv" class="hidden"><button id="download-sample" class="px-4 py-2 bg-gray-200 text-gray-800 rounded-lg hover:bg-gray-300 transition-all flex items-center space-x-2"><i class="fa-solid fa-download"></i><span>下载示例</span></button></div></div><div id="file-info" class="mt-4 hidden"><div class="p-4 bg-gray-50 rounded-lg border border-gray-200"><div class="flex items-center justify-between"><div><h3 class="font-medium text-gray-700" id="file-name">文件名:</h3><p class="text-sm text-gray-500" id="file-size">文件大小:</p></div><button id="remove-file" class="text-red-500 hover:text-red-700 transition-colors"><i class="fa-solid fa-times"></i></button></div><div class="mt-3 flex items-center space-x-3"><div class="w-full bg-gray-200 rounded-full h-2"><div id="upload-progress" class="bg-primary h-2 rounded-full" style="width: 0%"></div></div><span id="progress-text" class="text-sm text-gray-600">0%</span></div></div></div></section><!-- 图表和控制面板 --><div class="grid grid-cols-1 lg:grid-cols-4 gap-6"><!-- 左侧控制面板 --><div class="lg:col-span-1"><div class="bg-white rounded-xl p-6 card-shadow sticky top-24"><h2 class="text-xl font-bold mb-4">数据分析选项</h2><!-- 时间维度选择 --><div class="mb-6"><h3 class="font-medium mb-2 text-gray-700">时间维度</h3><div class="flex flex-wrap gap-2"><button class="time-option px-3 py-1.5 bg-primary text-white rounded-md text-sm" data-period="day">日</button><button class="time-option px-3 py-1.5 bg-gray-200 text-gray-700 rounded-md text-sm" data-period="week">周</button><button class="time-option px-3 py-1.5 bg-gray-200 text-gray-700 rounded-md text-sm" data-period="month">月</button></div></div><!-- 指标选择 --><div class="mb-6"><h3 class="font-medium mb-2 text-gray-700">业绩指标</h3><div class="flex flex-wrap gap-2"><button class="metric-option px-3 py-1.5 bg-primary text-white rounded-md text-sm" data-metric="duration">接通时长</button><button class="metric-option px-3 py-1.5 bg-gray-200 text-gray-700 rounded-md text-sm" data-metric="calls">外呼次数</button><button class="metric-option px-3 py-1.5 bg-gray-200 text-gray-700 rounded-md text-sm" data-metric="connected">接通次数</button></div></div><!-- 目标值设置 --><div class="mb-6"><h3 class="font-medium mb-2 text-gray-700">目标值设置</h3><div class="flex items-center space-x-2"><input type="number" id="target-value" class="flex-grow px-3 py-2 border border-gray-300 rounded-md text-sm input-focus" placeholder="输入目标值"><button id="set-target" class="px-3 py-2 bg-primary text-white rounded-md text-sm hover:bg-primary/90 transition-colors">设置</button></div><div id="current-target" class="mt-2 text-sm text-gray-600 hidden">当前目标值: <span id="target-value-display">--</span><button id="clear-target" class="ml-2 text-red-500 hover:text-red-700 transition-colors text-xs"><i class="fa-solid fa-times"></i></button></div></div><!-- 坐席选择 --><div><div class="flex justify-between items-center mb-2"><h3 class="font-medium text-gray-700">坐席筛选</h3><div class="text-xs text-gray-500"><span id="selected-agents-count">0</span>/<span id="total-agents-count">0</span></div></div><div class="space-y-2 max-h-[300px] overflow-y-auto pr-2"><div id="agent-list" class="space-y-2"><!-- 坐席列表将通过JS动态生成 --><div class="text-gray-500 text-sm italic">请先上传数据文件</div></div></div><div class="mt-3 flex space-x-2"><button id="select-all" class="px-3 py-1 bg-gray-100 text-gray-700 rounded-md text-sm hover:bg-gray-200 transition-colors">全选</button><button id="deselect-all" class="px-3 py-1 bg-gray-100 text-gray-700 rounded-md text-sm hover:bg-gray-200 transition-colors">取消全选</button></div></div></div></div><!-- 右侧图表展示区 --><div class="lg:col-span-3"><div class="bg-white rounded-xl p-6 mb-6 card-shadow hover-scale"><div class="flex flex-col md:flex-row md:items-center justify-between mb-6"><h2 class="text-xl font-bold mb-2 md:mb-0">业绩趋势分析</h2><div class="flex space-x-3"><button id="export-png" class="px-3 py-1.5 bg-gray-100 text-gray-700 rounded-md text-sm hover:bg-gray-200 transition-colors flex items-center"><i class="fa-solid fa-download mr-1"></i> PNG</button><button id="export-svg" class="px-3 py-1.5 bg-gray-100 text-gray-700 rounded-md text-sm hover:bg-gray-200 transition-colors flex items-center"><i class="fa-solid fa-download mr-1"></i> SVG</button><button id="export-csv" class="px-3 py-1.5 bg-gray-100 text-gray-700 rounded-md text-sm hover:bg-gray-200 transition-colors flex items-center"><i class="fa-solid fa-download mr-1"></i> CSV</button></div></div><div class="relative h-[400px]"><canvas id="performance-chart"></canvas><div id="chart-loading" class="absolute inset-0 flex items-center justify-center bg-white/80 rounded-lg z-10 hidden"><div class="flex flex-col items-center"><div class="w-10 h-10 border-4 border-primary/30 border-t-primary rounded-full animate-spin"></div><p class="mt-3 text-gray-600">数据加载中...</p></div></div><div id="chart-no-data" class="absolute inset-0 flex flex-col items-center justify-center bg-white/80 rounded-lg z-10 hidden"><i class="fa-solid fa-chart-line text-6xl text-gray-300 mb-4"></i><p class="text-gray-500">暂无数据可显示</p><p class="text-gray-400 text-sm mt-2">请上传数据文件并选择坐席</p></div></div></div><!-- 统计信息卡片 --><div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"><div class="bg-white rounded-xl p-6 card-shadow hover-scale"><div class="flex items-start justify-between"><div><p class="text-gray-500 text-sm">平均接通时长</p><h3 class="text-2xl font-bold mt-1" id="avg-duration">--</h3><p class="text-success text-xs mt-1 flex items-center"><i class="fa-solid fa-arrow-up mr-1"></i> 较上周增长 12%</p></div><div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center"><i class="fa-solid fa-phone text-primary"></i></div></div></div><div class="bg-white rounded-xl p-6 card-shadow hover-scale"><div class="flex items-start justify-between"><div><p class="text-gray-500 text-sm">总外呼次数</p><h3 class="text-2xl font-bold mt-1" id="total-calls">--</h3><p class="text-danger text-xs mt-1 flex items-center"><i class="fa-solid fa-arrow-down mr-1"></i> 较上周下降 3%</p></div><div class="w-10 h-10 rounded-full bg-orange-100 flex items-center justify-center"><i class="fa-solid fa-headphones text-accent"></i></div></div></div><div class="bg-white rounded-xl p-6 card-shadow hover-scale"><div class="flex items-start justify-between"><div><p class="text-gray-500 text-sm">平均接通率</p><h3 class="text-2xl font-bold mt-1" id="avg-connect-rate">--</h3><p class="text-success text-xs mt-1 flex items-center"><i class="fa-solid fa-arrow-up mr-1"></i> 较上周增长 5%</p></div><div class="w-10 h-10 rounded-full bg-green-100 flex items-center justify-center"><i class="fa-solid fa-chart-pie text-success"></i></div></div></div></div></div></div></main><!-- 页脚 --><footer class="bg-white border-t border-gray-200 mt-12"><div class="container mx-auto px-4 py-6"><div class="flex flex-col md:flex-row justify-between items-center"><div class="mb-4 md:mb-0"><p class="text-gray-500 text-sm">© 2025 坐席业绩可视化分析工具</p></div><div class="flex space-x-4"><a href="#" class="text-gray-400 hover:text-primary transition-colors"><i class="fa-solid fa-question-circle"></i></a><a href="#" class="text-gray-400 hover:text-primary transition-colors"><i class="fa-solid fa-cog"></i></a><a href="#" class="text-gray-400 hover:text-primary transition-colors"><i class="fa-solid fa-user"></i></a></div></div></div></footer><!-- 模态框:数据表格 --><div id="data-modal" class="fixed inset-0 bg-black/50 z-50 flex items-center justify-center hidden"><div class="bg-white rounded-xl w-full max-w-4xl max-h-[80vh] flex flex-col"><div class="p-6 border-b border-gray-200 flex justify-between items-center"><h3 class="text-xl font-bold">原始数据</h3><button id="close-modal" class="text-gray-400 hover:text-gray-600 transition-colors"><i class="fa-solid fa-times"></i></button></div><div class="p-6 overflow-y-auto flex-grow"><div class="overflow-x-auto"><table class="min-w-full divide-y divide-gray-200"><thead class="bg-gray-50"><tr id="table-header"><!-- 表头将通过JS动态生成 --></tr></thead><tbody class="bg-white divide-y divide-gray-200" id="table-body"><!-- 表格内容将通过JS动态生成 --><tr><td colspan="5" class="px-6 py-4 text-center text-gray-500">暂无数据</td></tr></tbody></table></div></div><div class="p-4 border-t border-gray-200 flex justify-between items-center"><div class="text-sm text-gray-500">共 <span id="total-rows">0</span> 条记录</div><div><button id="export-full-csv" class="px-4 py-2 bg-primary text-white rounded-lg text-sm hover:bg-primary/90 transition-colors"><i class="fa-solid fa-download mr-1"></i> 导出完整数据</button></div></div></div></div><script>// 全局变量let performanceChart = null;let parsedData = [];let selectedAgents = new Set();let currentPeriod = 'day';let currentMetric = 'duration';let targetValue = null;// DOM 元素const fileUpload = document.getElementById('file-upload');const fileInfo = document.getElementById('file-info');const fileName = document.getElementById('file-name');const fileSize = document.getElementById('file-size');const uploadProgress = document.getElementById('upload-progress');const progressText = document.getElementById('progress-text');const removeFile = document.getElementById('remove-file');const downloadSample = document.getElementById('download-sample');const agentList = document.getElementById('agent-list');const selectedAgentsCount = document.getElementById('selected-agents-count');const totalAgentsCount = document.getElementById('total-agents-count');const selectAllBtn = document.getElementById('select-all');const deselectAllBtn = document.getElementById('deselect-all');const timeOptions = document.querySelectorAll('.time-option');const metricOptions = document.querySelectorAll('.metric-option');const chartLoading = document.getElementById('chart-loading');const chartNoData = document.getElementById('chart-no-data');const exportPng = document.getElementById('export-png');const exportSvg = document.getElementById('export-svg');const exportCsv = document.getElementById('export-csv');const dataModal = document.getElementById('data-modal');const closeModal = document.getElementById('close-modal');const tableHeader = document.getElementById('table-header');const tableBody = document.getElementById('table-body');const totalRows = document.getElementById('total-rows');const exportFullCsv = document.getElementById('export-full-csv');const themeToggle = document.getElementById('theme-toggle');const currentDate = document.getElementById('current-date');const targetValueInput = document.getElementById('target-value');const setTargetBtn = document.getElementById('set-target');const currentTarget = document.getElementById('current-target');const targetValueDisplay = document.getElementById('target-value-display');const clearTargetBtn = document.getElementById('clear-target');// 设置当前日期function setCurrentDate() {const now = new Date();const options = { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' };currentDate.textContent = now.toLocaleDateString('zh-CN', options);}// 初始化应用function initApp() {setCurrentDate();setupEventListeners();}// 设置事件监听器function setupEventListeners() {// 文件上传fileUpload.addEventListener('change', handleFileUpload);removeFile.addEventListener('click', resetFileUpload);downloadSample.addEventListener('click', downloadSampleFile);// 时间维度选择timeOptions.forEach(option => {option.addEventListener('click', () => {setActiveButton(timeOptions, option);currentPeriod = option.dataset.period;updateChart();});});// 指标选择metricOptions.forEach(option => {option.addEventListener('click', () => {setActiveButton(metricOptions, option);currentMetric = option.dataset.metric;updateChart();});});// 坐席选择selectAllBtn.addEventListener('click', selectAllAgents);deselectAllBtn.addEventListener('click', deselectAllAgents);// 图表导出exportPng.addEventListener('click', exportChartAsPNG);exportSvg.addEventListener('click', exportChartAsSVG);exportCsv.addEventListener('click', exportChartDataAsCSV);// 数据模态框closeModal.addEventListener('click', () => {dataModal.classList.add('hidden');});// 导出完整数据exportFullCsv.addEventListener('click', exportFullDataAsCSV);// 主题切换themeToggle.addEventListener('click', toggleTheme);// 目标值设置setTargetBtn.addEventListener('click', setTargetValue);clearTargetBtn.addEventListener('click', clearTargetValue);targetValueInput.addEventListener('keypress', (e) => {if (e.key === 'Enter') {setTargetValue();}});}// 设置目标值function setTargetValue() {const value = parseFloat(targetValueInput.value);if (isNaN(value) || value <= 0) {alert('请输入有效的目标值');return;}targetValue = value;targetValueDisplay.textContent = formatTargetValue(value);currentTarget.classList.remove('hidden');updateChart();// 添加动画效果setTargetBtn.classList.add('bg-success');setTargetBtn.innerHTML = '<i class="fa-solid fa-check"></i> 已设置';setTimeout(() => {setTargetBtn.classList.remove('bg-success');setTargetBtn.innerHTML = '设置';}, 1500);}// 清除目标值function clearTargetValue() {targetValue = null;targetValueInput.value = '';currentTarget.classList.add('hidden');updateChart();}// 格式化目标值显示function formatTargetValue(value) {if (currentMetric === 'duration') {return value + ' 分钟';}return value;}// 处理文件上传function handleFileUpload(event) {const file = event.target.files[0];if (!file) return;// 显示文件信息fileInfo.classList.remove('hidden');fileName.textContent = `文件名:${file.name}`;fileSize.textContent = `文件大小:${formatFileSize(file.size)}`;// 解析CSV文件parseCSVFile(file);}// 解析CSV文件function parseCSVFile(file) {chartLoading.classList.remove('hidden');Papa.parse(file, {header: true,dynamicTyping: true,skipEmptyLines: true,step: (results, parser) => {parsedData.push(results.data);// 更新进度条const progress = Math.round((parser.cursor / file.size) * 100);uploadProgress.style.width = `${progress}%`;progressText.textContent = `${progress}%`;},complete: () => {chartLoading.classList.add('hidden');processData();updateAgentList();updateChart();updateSummaryStats();populateDataTable();},error: (error) => {chartLoading.classList.add('hidden');console.error('CSV解析错误:', error);alert('CSV解析错误: ' + error.message);}});}// 处理数据function processData() {// 扁平化数据结构parsedData = parsedData.flat();// 确保数据有必要的字段parsedData = parsedData.filter(row => row['日期'] && row['坐席姓名'] && (row['接通时长'] || row['外呼次数'] || row['接通次数']));// 转换日期格式parsedData.forEach(row => {if (row['日期']) {row['日期'] = new Date(row['日期']);}});}// 更新坐席列表function updateAgentList() {agentList.innerHTML = '';// 提取所有唯一的坐席姓名const agents = [...new Set(parsedData.map(row => row['坐席姓名']))];totalAgentsCount.textContent = agents.length;if (agents.length === 0) {agentList.innerHTML = '<div class="text-gray-500 text-sm italic">数据中未找到坐席信息</div>';return;}// 创建坐席选择框agents.forEach(agent => {const isSelected = selectedAgents.has(agent);const agentItem = document.createElement('div');agentItem.className = 'flex items-center';const checkbox = document.createElement('input');checkbox.type = 'checkbox';checkbox.id = `agent-${agent.replace(/\s+/g, '-')}`;checkbox.className = 'h-4 w-4 rounded border-gray-300 text-primary focus:ring-primary checkbox-primary';checkbox.value = agent;checkbox.checked = isSelected;checkbox.addEventListener('change', (e) => {if (e.target.checked) {selectedAgents.add(agent);} else {selectedAgents.delete(agent);}updateSelectedAgentsCount();updateChart();});const label = document.createElement('label');label.htmlFor = checkbox.id;label.className = 'ml-2 block text-sm text-gray-700 cursor-pointer';label.textContent = agent;agentItem.appendChild(checkbox);agentItem.appendChild(label);agentList.appendChild(agentItem);});updateSelectedAgentsCount();}// 更新选中的坐席数量function updateSelectedAgentsCount() {selectedAgentsCount.textContent = selectedAgents.size;}// 全选坐席function selectAllAgents() {const checkboxes = document.querySelectorAll('#agent-list input[type="checkbox"]');checkboxes.forEach(checkbox => {checkbox.checked = true;selectedAgents.add(checkbox.value);});updateSelectedAgentsCount();updateChart();}// 取消全选坐席function deselectAllAgents() {const checkboxes = document.querySelectorAll('#agent-list input[type="checkbox"]');checkboxes.forEach(checkbox => {checkbox.checked = false;selectedAgents.delete(checkbox.value);});updateSelectedAgentsCount();updateChart();}// 更新图表function updateChart() {if (parsedData.length === 0) {showNoData();return;}if (selectedAgents.size === 0) {showNoData();return;}chartLoading.classList.remove('hidden');chartNoData.classList.add('hidden');// 过滤选中的坐席数据const filteredData = parsedData.filter(row => selectedAgents.has(row['坐席姓名']));// 根据时间维度处理数据const groupedData = groupDataByTime(filteredData, currentPeriod);// 准备图表数据const chartData = prepareChartData(groupedData);// 创建或更新图表createOrUpdateChart(chartData);chartLoading.classList.add('hidden');}// 按时间维度分组数据function groupDataByTime(data, period) {const grouped = {};data.forEach(row => {let timeKey;if (period === 'day') {// 按日期分组timeKey = row['日期'].toISOString().split('T')[0];} else if (period === 'week') {// 按周分组 (以周一开始)const date = row['日期'];const day = date.getDay() || 7; // 转换为周一开始 (1-7)const monday = new Date(date);monday.setDate(date.getDate() - day + 1);timeKey = `周 ${monday.getMonth() + 1}/${monday.getDate()}`;} else if (period === 'month') {// 按月分组timeKey = `${row['日期'].getFullYear()}年 ${row['日期'].getMonth() + 1}月`;}if (!grouped[timeKey]) {grouped[timeKey] = {};}// 按坐席分组if (!grouped[timeKey][row['坐席姓名']]) {grouped[timeKey][row['坐席姓名']] = {duration: 0,calls: 0,connected: 0};}// 累加指标grouped[timeKey][row['坐席姓名']].duration += row['接通时长'] || 0;grouped[timeKey][row['坐席姓名']].calls += row['外呼次数'] || 0;grouped[timeKey][row['坐席姓名']].connected += row['接通次数'] || 0;});return grouped;}// 准备图表数据function prepareChartData(groupedData) {// 排序时间键const timeKeys = Object.keys(groupedData).sort();// 准备标签const labels = timeKeys;// 准备数据集const datasets = [];const colors = generateColors(selectedAgents.size);let agentIndex = 0;selectedAgents.forEach(agent => {const data = timeKeys.map(timeKey => {const agentData = groupedData[timeKey][agent];return agentData ? agentData[currentMetric] : 0;});datasets.push({label: agent,data: data,borderColor: colors[agentIndex],backgroundColor: `${colors[agentIndex]}40`, // 带透明度的背景色borderWidth: 2,tension: 0.3,fill: true});agentIndex++;});// 添加目标值数据if (targetValue !== null) {datasets.push({label: '目标值',data: Array(labels.length).fill(targetValue),borderColor: '#EF4444',borderWidth: 2,borderDash: [5, 5],pointRadius: 0,fill: false,tension: 0,order: 2});}return {labels: labels,datasets: datasets};}// 创建或更新图表function createOrUpdateChart(chartData) {const ctx = document.getElementById('performance-chart').getContext('2d');// 设置Y轴标签let yAxisLabel;if (currentMetric === 'duration') {yAxisLabel = '接通时长 (分钟)';} else if (currentMetric === 'calls') {yAxisLabel = '外呼次数';} else if (currentMetric === 'connected') {yAxisLabel = '接通次数';}// 设置时间维度标题let timeTitle;if (currentPeriod === 'day') {timeTitle = '日期';} else if (currentPeriod === 'week') {timeTitle = '周';} else if (currentPeriod === 'month') {timeTitle = '月份';}// 设置指标标题let metricTitle;if (currentMetric === 'duration') {metricTitle = '接通时长';} else if (currentMetric === 'calls') {metricTitle = '外呼次数';} else if (currentMetric === 'connected') {metricTitle = '接通次数';}// 如果图表已存在,则销毁它if (performanceChart) {performanceChart.destroy();}// 创建新图表performanceChart = new Chart(ctx, {type: 'line',data: chartData,options: {responsive: true,maintainAspectRatio: false,plugins: {legend: {position: 'top',labels: {usePointStyle: true,boxWidth: 6,font: {family: 'Inter',size: 12}}},tooltip: {mode: 'index',intersect: false,backgroundColor: 'rgba(255, 255, 255, 0.9)',titleColor: '#1E293B',bodyColor: '#64748B',borderColor: '#E2E8F0',borderWidth: 1,padding: 12,boxPadding: 6,usePointStyle: true,callbacks: {label: function(context) {let label = context.dataset.label || '';if (label) {label += ': ';}if (context.parsed.y !== null) {// 根据指标类型格式化数值if (currentMetric === 'duration') {label += context.parsed.y.toFixed(1) + ' 分钟';} else {label += context.parsed.y;}}return label;}}},title: {display: true,text: `${metricTitle}趋势分析 (按${timeTitle})`,font: {family: 'Inter',size: 16,weight: 'bold'},color: '#1E293B',padding: {bottom: 20}}},scales: {x: {grid: {display: false},ticks: {font: {family: 'Inter'}}},y: {beginAtZero: true,grid: {color: '#F1F5F9'},ticks: {font: {family: 'Inter'},callback: function(value) {// 根据指标类型格式化Y轴标签if (currentMetric === 'duration') {return value + ' 分钟';}return value;}},title: {display: true,text: yAxisLabel,font: {family: 'Inter',weight: 'bold'}}}},interaction: {mode: 'nearest',axis: 'x',intersect: false},animation: {duration: 1000,easing: 'easeOutQuart'}}});}// 显示无数据状态function showNoData() {if (performanceChart) {performanceChart.destroy();performanceChart = null;}chartNoData.classList.remove('hidden');}// 更新统计信息卡片function updateSummaryStats() {if (parsedData.length === 0) {document.getElementById('avg-duration').textContent = '--';document.getElementById('total-calls').textContent = '--';document.getElementById('avg-connect-rate').textContent = '--';return;}// 计算总接通时长const totalDuration = parsedData.reduce((sum, row) => sum + (row['接通时长'] || 0), 0);// 计算总外呼次数const totalCalls = parsedData.reduce((sum, row) => sum + (row['外呼次数'] || 0), 0);// 计算总接通次数const totalConnected = parsedData.reduce((sum, row) => sum + (row['接通次数'] || 0), 0);// 计算平均接通时长const avgDuration = (totalDuration / parsedData.length).toFixed(1);// 计算平均接通率const avgConnectRate = totalCalls > 0 ? ((totalConnected / totalCalls) * 100).toFixed(1) + '%' : '0%';// 更新DOMdocument.getElementById('avg-duration').textContent = avgDuration + ' 分钟';document.getElementById('total-calls').textContent = totalCalls;document.getElementById('avg-connect-rate').textContent = avgConnectRate;}// 填充数据表格function populateDataTable() {if (parsedData.length === 0) {tableHeader.innerHTML = '';tableBody.innerHTML = '<tr><td colspan="5" class="px-6 py-4 text-center text-gray-500">暂无数据</td></tr>';totalRows.textContent = '0';return;}// 获取表头const headers = Object.keys(parsedData[0]);// 清空表头tableHeader.innerHTML = '';// 创建表头单元格headers.forEach(header => {const th = document.createElement('th');th.scope = 'col';th.className = 'px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider';th.textContent = header;tableHeader.appendChild(th);});// 清空表格内容tableBody.innerHTML = '';// 填充表格内容parsedData.forEach(row => {const tr = document.createElement('tr');tr.className = 'hover:bg-gray-50 transition-colors';headers.forEach(header => {const td = document.createElement('td');td.className = 'px-6 py-4 whitespace-nowrap text-sm text-gray-500';// 格式化日期if (header === '日期' && row[header] instanceof Date) {td.textContent = row[header].toISOString().split('T')[0];} else {td.textContent = row[header] !== undefined ? row[header] : '';}tr.appendChild(td);});tableBody.appendChild(tr);});// 更新总记录数totalRows.textContent = parsedData.length;}// 导出图表为PNGfunction exportChartAsPNG() {if (!performanceChart) return;const link = document.createElement('a');link.download = `坐席业绩分析_${currentMetric}_${currentPeriod}.png`;link.href = performanceChart.toBase64Image('image/png', 1.0);link.click();}// 导出图表为SVGfunction exportChartAsSVG() {if (!performanceChart) return;// 获取图表容器const chartContainer = document.getElementById('performance-chart').parentNode;// 创建临时SVG容器const svgContainer = document.createElement('div');svgContainer.style.width = chartContainer.offsetWidth + 'px';svgContainer.style.height = chartContainer.offsetHeight + 'px';document.body.appendChild(svgContainer);// 创建临时Canvasconst tempCanvas = document.createElement('canvas');tempCanvas.width = chartContainer.offsetWidth;tempCanvas.height = chartContainer.offsetHeight;svgContainer.appendChild(tempCanvas);// 复制图表数据到临时Canvasconst tempCtx = tempCanvas.getContext('2d');tempCtx.drawImage(document.getElementById('performance-chart'), 0, 0);// 转换为SVGconst svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');svg.setAttribute('width', tempCanvas.width);svg.setAttribute('height', tempCanvas.height);const image = document.createElementNS('http://www.w3.org/2000/svg', 'image');image.setAttribute('width', tempCanvas.width);image.setAttribute('height', tempCanvas.height);image.setAttribute('href', tempCanvas.toDataURL('image/png'));svg.appendChild(image);// 创建下载链接const svgData = new XMLSerializer().serializeToString(svg);const blob = new Blob([svgData], {type: 'image/svg+xml;charset=utf-8'});const url = URL.createObjectURL(blob);const link = document.createElement('a');link.download = `坐席业绩分析_${currentMetric}_${currentPeriod}.svg`;link.href = url;link.click();// 清理document.body.removeChild(svgContainer);URL.revokeObjectURL(url);}// 导出图表数据为CSVfunction exportChartDataAsCSV() {if (parsedData.length === 0 || selectedAgents.size === 0) return;// 过滤选中的坐席数据const filteredData = parsedData.filter(row => selectedAgents.has(row['坐席姓名']));// 准备CSV数据let csvContent = '日期,坐席姓名,接通时长,外呼次数,接通次数\n';filteredData.forEach(row => {csvContent += `${row['日期'].toISOString().split('T')[0]},${row['坐席姓名']},${row['接通时长'] || 0},${row['外呼次数'] || 0},${row['接通次数'] || 0}\n`;});// 创建下载链接const blob = new Blob([csvContent], {type: 'text/csv;charset=utf-8;'});const url = URL.createObjectURL(blob);const link = document.createElement('a');link.download = `坐席业绩数据_${currentMetric}_${currentPeriod}.csv`;link.href = url;link.click();// 清理URL.revokeObjectURL(url);}// 导出完整数据为CSVfunction exportFullDataAsCSV() {if (parsedData.length === 0) return;// 获取表头const headers = Object.keys(parsedData[0]);// 准备CSV数据let csvContent = headers.join(',') + '\n';parsedData.forEach(row => {const values = headers.map(header => {// 处理日期if (header === '日期' && row[header] instanceof Date) {return row[header].toISOString().split('T')[0];}// 处理字符串值,添加引号if (typeof row[header] === 'string') {return `"${row[header].replace(/"/g, '""')}"`;}return row[header] !== undefined ? row[header] : '';});csvContent += values.join(',') + '\n';});// 创建下载链接const blob = new Blob([csvContent], {type: 'text/csv;charset=utf-8;'});const url = URL.createObjectURL(blob);const link = document.createElement('a');link.download = '完整坐席业绩数据.csv';link.href = url;link.click();// 清理URL.revokeObjectURL(url);}// 下载示例文件function downloadSampleFile() {const sampleData = [{日期: '2025-05-01', 坐席姓名: '张三', 接通时长: 12.5, 外呼次数: 30, 接通次数: 15},{日期: '2025-05-01', 坐席姓名: '李四', 接通时长: 18.2, 外呼次数: 25, 接通次数: 12},{日期: '2025-05-02', 坐席姓名: '张三', 接通时长: 15.3, 外呼次数: 35, 接通次数: 18},{日期: '2025-05-02', 坐席姓名: '李四', 接通时长: 14.7, 外呼次数: 28, 接通次数: 14},{日期: '2025-05-03', 坐席姓名: '张三', 接通时长: 10.8, 外呼次数: 27, 接通次数: 13},{日期: '2025-05-03', 坐席姓名: '李四', 接通时长: 20.1, 外呼次数: 32, 接通次数: 16},{日期: '2025-05-04', 坐席姓名: '张三', 接通时长: 16.4, 外呼次数: 33, 接通次数: 17},{日期: '2025-05-04', 坐席姓名: '李四', 接通时长: 13.9, 外呼次数: 26, 接通次数: 11},{日期: '2025-05-05', 坐席姓名: '张三', 接通时长: 14.2, 外呼次数: 31, 接通次数: 15},{日期: '2025-05-05', 坐席姓名: '李四', 接通时长: 17.8, 外呼次数: 29, 接通次数: 13}];let csvContent = '日期,坐席姓名,接通时长,外呼次数,接通次数\n';sampleData.forEach(row => {csvContent += `${row.日期},${row.坐席姓名},${row.接通时长},${row.外呼次数},${row.接通次数}\n`;});const blob = new Blob([csvContent], {type: 'text/csv;charset=utf-8;'});const url = URL.createObjectURL(blob);const link = document.createElement('a');link.download = '坐席业绩示例数据.csv';link.href = url;link.click();URL.revokeObjectURL(url);}// 重置文件上传function resetFileUpload() {fileUpload.value = '';fileInfo.classList.add('hidden');parsedData = [];selectedAgents.clear();targetValue = null;targetValueInput.value = '';currentTarget.classList.add('hidden');updateAgentList();updateChart();updateSummaryStats();populateDataTable();}// 设置活动按钮function setActiveButton(buttons, activeButton) {buttons.forEach(button => {button.classList.remove('bg-primary', 'text-white');button.classList.add('bg-gray-200', 'text-gray-700');});activeButton.classList.remove('bg-gray-200', 'text-gray-700');activeButton.classList.add('bg-primary', 'text-white');}// 生成颜色function generateColors(count) {const baseColors = ['#3B82F6', // 蓝色'#F97316', // 橙色'#10B981', // 绿色'#8B5CF6', // 紫色'#EC4899', // 粉色'#06B6D4', // 青色'#F59E0B', // 琥珀色'#EF4444', // 红色'#6366F1', // 靛蓝色'#14B8A6' // 翡翠色];const colors = [];for (let i = 0; i < count; i++) {colors.push(baseColors[i % baseColors.length]);}return colors;}// 格式化文件大小function formatFileSize(bytes) {if (bytes === 0) return '0 Bytes';const k = 1024;const sizes = ['Bytes', 'KB', 'MB', 'GB'];const i = Math.floor(Math.log(bytes) / Math.log(k));return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];}// 切换主题function toggleTheme() {const isDarkMode = document.documentElement.classList.toggle('dark');const icon = themeToggle.querySelector('i');if (isDarkMode) {document.documentElement.classList.add('dark');icon.classList.remove('fa-moon');icon.classList.add('fa-sun');} else {document.documentElement.classList.remove('dark');icon.classList.remove('fa-sun');icon.classList.add('fa-moon');}}// 初始化应用document.addEventListener('DOMContentLoaded', initApp);</script>
</body>
</html>
效果:
相关文章:
坐席业绩可视化分析工具
这个交互式的坐席业绩分析工具具有以下特点: 数据导入功能:支持上传 CSV 文件,自动解析并展示数据多维度分析:可按日 / 周 / 月分析业绩数据,支持切换不同业绩指标(接通时长 / 外呼次数 / 接通次数&#x…...
MATLAB制作柱状图与条图:数据可视化的基础利器
一、什么是柱状图与条图? 柱状图和条图都是用来表示分类数据的常见图表形式,它们的核心目的是通过矩形的长度来比较各类别的数值大小。条图其实就是“横着的柱状图”,它们的本质是一样的:用矩形的长度表示数值大小,不同…...
com.fasterxml.jackson.dataformat.xml.XmlMapper把对象转换xml格式,属性放到标签<>里边
之前从没用过xml和对象相互转换,最近项目接了政府相关的。需要用xml格式数据进行相互转换。有些小问题,困扰了我一下下。 1.有些属性需要放到标签里边,有的需要放到标签子集。 2.xml需要加<?xml version"1.0" encoding"…...
在js中大量接口调用并发批量请求处理器
并发批量请求处理器 ✨ 设计目标 该类用于批量异步请求处理,支持: 自定义并发数请求节拍控制(延时)失败重试机制进度回调通知 🔧 构造函数参数 new BulkRequestHandler({dataList, // 要处理的数据列表r…...
Azure资源创建与部署指南
本文将指导您如何在Azure平台上创建和配置必要的资源,以部署基于OpenAI的应用程序。 资源组创建 资源组是管理和组织Azure资源的逻辑容器。 在Azure门户顶端的查询框中输入"Resource groups"(英文环境)或"资源组"(中文环境)在搜索结果中点击"资…...
图解gpt之神经概率语言模型与循环神经网络
上节课我们聊了词向量表示,像Word2Vec这样的模型,它确实能捕捉到词语之间的语义关系,但问题在于,它本质上还是在孤立地看待每个词。英文的“Apple”,可以指苹果公司,也可以指水果。这种一词多义的特性&…...
Jenkins linux安装
jenkins启动 service jenkins start 重启 service jenkins restart 停止 service jenkins stop jenkins安装 命令切换到自己的下载目录 直接用命令下载 wget http://pkg.jenkins-ci.org/redhat-stable/jenkins-2.190.3-1.1.noarch.rpm 下载直接安装 rpm -ivh jenkins-2.190.3-…...
android 修改单GPS,单北斗,单伽利略等
从hal层入手,代码如下: 各个类型如下: typedef enum {MTK_CONFIG_GPS_GLONASS 0,MTK_CONFIG_GPS_BEIDOU,MTK_CONFIG_GPS_GLONASS_BEIDOU,MTK_CONFIG_GPS_ONLY,MTK_CONFIG_BEIDOU_ONLY,MTK_CONFIG_GLONASS_ONLY,MTK_CONFIG_GPS_GLONASS_BEIDO…...
CNG汽车加气站操作工岗位职责
CNG(压缩天然气)汽车加气站操作工是负责天然气加气设备操作、维护及安全管理的重要岗位。以下是该岗位的职责、技能要求、安全注意事项及职业发展方向的详细说明: *主要职责 加气操作 按照规程为车辆加注CNG,检查车辆气瓶合格证…...
纯Java实现反向传播算法:零依赖神经网络实战
在深度学习框架泛滥的今天,理解算法底层实现变得愈发重要。反向传播(Backpropagation)作为神经网络训练的基石算法,其实现往往被各种框架封装。本文将突破常规,仅用Java标准库实现完整BP算法,帮助开发者: 1) 深入理解…...
springboot3 + mybatis-plus3 创建web项目实现表增删改查
Idea创建项目 环境配置说明 在现代化的企业级应用开发中,合适的开发环境配置能够极大提升开发效率和应用性能。本文介绍的环境配置为: 操作系统:Windows 11JDK:JDK 21Maven:Maven 3.9.xIDE:IntelliJ IDEA…...
多模型协同预测在风机故障预测的应用(demo)
数据加载和预处理的真实性: 下面的代码中,DummyDataset 和数据加载部分仍然是高度简化和占位的。为了让这个训练循环真正有效,您必须用您自己的数据加载逻辑替换它。这意味着您需要创建一个 torch.utils.data.Dataset 的子类,它能…...
韩媒聚焦Lazarus攻击手段升级,CertiK联创顾荣辉详解应对之道
近日,韩国知名科技媒体《韩国IT时报》(Korea IT Times)刊文引述了CertiK联合创始人兼CEO顾荣辉教授的专业见解,聚焦黑客组织Lazarus在Web3.0领域攻击手段的持续升级,分析这一威胁的严峻性,并探讨了提升行业…...
5.9-selcct_poll_epoll 和 reactor 的模拟实现
5.9-select_poll_epoll 本文演示 select 等 io 多路复用函数的应用方法,函数具体介绍可以参考我过去写的博客。 先绑定监听的文件描述符 int sockfd socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in serveraddr; memset(&serveraddr, 0, sizeof(struc…...
图上思维:基于知识图的大型语言模型的深层可靠推理
摘要 尽管大型语言模型(LLM)在各种任务中取得了巨大的成功,但它们经常与幻觉问题作斗争,特别是在需要深入和负责任的推理的场景中。这些问题可以通过在LLM推理中引入外部知识图(KG)来部分解决。在本文中&am…...
37-智慧医疗服务平台(在线接诊/问诊)
系统功能特点: 技术栈: springBootVueMysql 功能点: 医生端 用户端 管理员端 医生端: 科室信息管理、在线挂号管理、预约体检管理、体检报告管理、药品信息管理、处方信息管理、缴费信息管理、病历信息管理、智能导诊管理、在线接诊患者功能 (和患者1V1沟通) 用户…...
【新品发布】VXI可重构信号处理系统模块系列
VXI可重构信号处理系统模块概述 VXI可重构信号处理系统模块包括了 GPU 模块,CPU 模块,射频模块、IO 模块、DSP模块、高速存储模块、交换模块,采集处理模块、回放处理模块等,全套组件为单体3U VPX架构,可自由组合到多槽…...
React 第三十八节 Router 中useRoutes 的使用详解及注意事项
前言 useRoutes 是 React Router v6 引入的一个钩子函数,允许通过 JavaScript 对象(而非传统的 JSX 语法)定义路由配置。这种方式更适合复杂路由结构,且代码更简洁易维护。 一、基础使用 1.1、useRoutes路由配置对象 useRoute…...
Redhat 系统详解
Red Hat 系统深度解析:从企业级架构到核心组件 一、Red Hat 概述:企业级 Linux 的标杆 Red Hat 是全球领先的开源解决方案供应商,其核心产品 Red Hat Enterprise Linux(RHEL) 是企业级 Linux 的黄金标准。RHEL 以 稳…...
docker常用命令总结
常用命令含义docker info查看docker 服务的信息-------------------------镜像篇docker pull XXX从官网上拉取名为XXX的镜像docker login -u name登录自己的dockerhub账号docker push XXX将XXX镜像上传到自己的dockerhub账户中(XXX的命名必须是用户名/镜像名&#x…...
【el-admin】el-admin关联数据字典
数据字典使用 一、新增数据字典1、新增【图书状态】和【图书类型】数据字典2、编辑字典值 二、代码生成配置1、表单设置2、关联字典3、验证关联数据字典 三、查询操作1、模糊查询2、按类别查询(下拉框) 四、数据校验 一、新增数据字典 1、新增【图书状态…...
component :is是什么?
问: component :is是什么? 是组件? 那我们是不是就不需要自己创建组件了?还是什么意思?component :is和什么功能是类似的,同时和类似功能相比对什么时候用component :is…...
适老化洗浴辅具产业:在技术迭代与需求升级中重塑银发经济新生态
随着中国人口老龄化程度的不断加深,老年群体对于适老化产品的需求日益增长。 适老化洗浴辅具作为保障老年人洗浴安全与舒适的关键产品,其发展状况备受关注。 深入剖析中国适老化洗浴辅具的发展现状,并探寻助力产业发展的有效路径࿰…...
『Python学习笔记』ubuntu解决matplotlit中文乱码的问题!
ubuntu解决matplotlit中文乱码的问题! 文章目录 simhei.ttf字体下载链接:http://xiazaiziti.com/210356.html将字体放到合适的地方 sudo cp SimHei.ttf /usr/share/fonts/(base) zkfzkf:~$ fc-list | grep -i "SimHei" /usr/local/share/font…...
从AI到新能源:猎板PCB的HDI技术如何定义高端制造新标准?
2025年,随着AI服务器、新能源汽车、折叠屏设备等新兴领域的爆发式增长,高密度互连(HDI)电路板成为电子制造业的“必争之地”。HDI板凭借微孔、细线宽和高层间对位精度,能够实现电子设备的高集成化与微型化,…...
汽车制造行业的数字化转型
嘿,大家好!今天来和大家聊聊汽车制造行业的数字化转型,这可是当下非常热门的话题哦! 随着科技的飞速发展,传统的汽车制造行业正经历着一场深刻的变革。数字化技术已经不再是“锦上添花”,而是车企能否在未…...
Redis 常见数据类型
Redis 常见数据类型 一、基本全局命令详解与实操 1. KEYS 命令 功能:按模式匹配返回所有符合条件的键(生产环境慎用,可能导致阻塞)。 语法: KEYS pattern 模式规则: h?llo:匹配 hello, ha…...
【计算机网络-传输层】传输层协议-TCP核心机制与可靠性保障
📚 博主的专栏 🐧 Linux | 🖥️ C | 📊 数据结构 | 💡C 算法 | 🅒 C 语言 | 🌐 计算机网络 上篇文章:传输层协议-UDP 下篇文章: 网络层 我们的讲解顺序是&…...
对golang中CSP的理解
概念: CSP模型,即通信顺序进程模型,是由英国计算机科学家C.A.R. Hoare于1978年提出的。该模型强调进程之间通过通道(channel)进行通信,并通过消息传递来协调并发执行的进程。CSP模型的核心思想是“不要通过…...
嵌入式openharmony标准系统中HDF框架底层原理分析
1、案例简介 该程序是基于OpenHarmony标准系统编写的基础外设类:简易HDF驱动。 2、基础知识 2.1、OpenHarmony HDF开发简介 HDF(Hardware Driver Foundation)驱动框架,为驱动开发者提供驱动框架能力,包括驱动加载、驱动服务管理、驱动消息机制和配置管理。旨在构建统一…...
238.除自身以外数组的乘积
给你一个数组,求出第 i 个元素以外的数组元素的乘积,不能使用除法,且时间复杂度O(n), 对于一个数,如果知道了前缀元素的乘积和后缀元素的乘积,就知道了这个元素以外的数组元素的乘积,所以现在的问题是如何…...
AI文旅|暴雨打造旅游新体验
今年"五一"假期,全国文旅市场迎来爆发式增长,从丈崖瀑布的磅礴水雾到城市商区的璀璨霓虹,从山野民宿的静谧悠然到主题乐园的欢腾喧嚣,处处人潮涌动。在这火热的景象背后,一股“无形之力”正悄然改变旅游体验…...
学习心得《How Global AI Policy and Regulations Will Impact Your Enterprise》Gartner
AI时代来临,然而与之对应的是海量的数据的安全性和合规性如何保障,如何平衡个人与智能体的利益,恰巧,最近Gartner发布了《How Global AI Policy and Regulations Will Impact Your Enterprise》,我们就其中的观点一起进行探讨。 战略规划假设 我们首先关注的是关键的战略…...
JAVA将一个同步方法改为异步执行
目的: 这么做的目的就是为了使一个高频率执行的方法能不阻塞整个程序,将该方法丢入到线程池中让线程去做异步执行,既提高了程序整体运行速度,也使得在高并发环境下程序能够更加健壮(同步执行可能会使得请求堆积以致系…...
对遗传算法思想的理解与实例详解
目录 一、概述 二、实例详解 1)问题描述与分析 2)初始化种群 3)计算种群适应度 4)遗传操作 5)基因交叉操作 6)变异操作 三、计算结果 四、总结 一、概述 遗传算法在求解最优解的问题中最为常用&a…...
数据可视化大屏——物流大数据服务平台(二)
代码分析: 物流大数据平台代码分析 这是一个基于 Bootstrap 和 ECharts 构建的物流大数据平台前端页面,设计采用了经典的三栏布局,主要展示河南省及全国的物流数据可视化内容。下面从多个维度进行分析: 1. 页面结构分析 整体采…...
MindSpore框架学习项目-ResNet药物分类-构建模型
目录 2.构建模型 2.1定义模型类 2.1.1 基础块ResidualBlockBase ResidualBlockBase代码解析 2.1.2 瓶颈块ResidualBlock ResidualBlock代码解释 2.1.3 构建层 构建层代码说明 2.1.4 定义不同组合(block,layer_nums)的ResNet网络实现 ResNet组建类代码解析…...
ChatTempMail - AI驱动的免费临时邮箱服务
在当今数字世界中,保护在线隐私的需求日益增长。ChatTempMail应运而生,作为一款融合人工智能技术的新一代临时邮箱服务,它不仅提供传统临时邮箱的基本功能,还通过AI技术大幅提升了用户体验。 核心功能与特性 1. AI驱动的智能邮件…...
(leetcode) 力扣100 9.找到字符串中所有字母异位词(滑动窗口)
题目 给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。 数据范围 1 < s.length, p.length < 3 * 104 s 和 p 仅包含小写字母 样例 示例 1: 输入: s "cbaebabacd", p &quo…...
深入了解 Stable Diffusion:AI 图像生成的奥秘
一、引言 AI 艺术与图像生成技术的兴起改变了我们创造和体验视觉内容的方式。在过去几年里,深度学习模型已经能够创造出令人惊叹的艺术作品,这些作品不仅模仿了人类艺术家的风格,甚至还能创造出前所未有的新风格。在这个领域,Sta…...
场外期权平值期权 实值期权 虚值期权有什么区别?收益如何计算?
期权汇 场外期权按价值状态分为平值、虚值、实值期权。 01|实值期权对于看涨期权而言,如果行权价格低于标的市场价格,则该期权处于实值状态;对于看跌期权,如果行权价格高于标的市场价格,则处于实值状态…...
微软系统 红帽系统 网络故障排查:ping、traceroute、netstat
在微软(Windows)和红帽(Red Hat Enterprise Linux,RHEL)等系统中,网络故障排查是确保系统正常运行的重要环节。 ping、traceroute(在Windows中为tracert)和netstat是三个常用的网络…...
HOT 100 | 【子串】76.最小覆盖子串、【普通数组】53.最大子数组和、【普通数组】56.合并区间
一、【子串】76.最小覆盖子串 1. 解题思路 定义两个哈希表分别用于 t 统计字符串 t 的字符个数,另一个sub_s用于统计字符串 t 在 s 的子串里面字符出现的频率。 为了降低时间复杂度,定义一个变量t_count用于统计 t 哈希表中元素的个数。哈希表sub_s是一…...
基于CNN的猫狗图像分类系统
一、系统概述 本系统是基于PyTorch框架构建的智能图像分类系统,专门针对CIFAR-10数据集中的猫(类别3)和狗(类别5)进行分类任务。系统采用卷积神经网络(CNN)作为核心算法,结合图形用…...
《时序数据库全球格局:国产与国外主流方案的对比分析》
引言 时序数据库(Time Series Database, TSDB)是专门用于存储、查询和分析时间序列数据的数据库系统,广泛应用于物联网(IoT)、金融、工业监控、智能运维等领域。近年来,随着大数据和物联网技术的发展&…...
力扣-2.两数相加
题目描述 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 请你将两个数相加,并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外,这两个数都…...
富乐德传感技术盘古信息 | 锚定“未来工厂”新坐标,开启传感器制造行业数字化转型新征程
在数字化浪潮下,制造业正经历深刻变革。 传感器作为智能制造的核心基础部件,正面临着质量精度要求升级、交付周期缩短、成本管控严苛等多重挑战。传统依赖人工纸质管理、设备数据孤岛化的生产模式,已成为制约高端传感器制造突破“高精度、高…...
RT-Thread 深入系列 Part 2:RT-Thread 内核核心机制深度剖析
摘要: 本文从线程管理、调度器原理、中断处理与上下文切换、IPC 同步机制、内存管理五大核心模块出发,深入剖析 RT-Thread 内核实现细节,并辅以源码解读、流程图、时序图与性能数据。 目录 线程管理与调度器原理 1.1 线程控制块(T…...
uni-app,小程序自定义导航栏实现与最佳实践
文章目录 前言为什么需要自定义导航栏?基本实现方案1. 关闭原生导航栏2. 自定义导航栏组件结构3. 获取状态栏高度4. 样式设置 内容区域适配跨平台适配要点iOS与Android差异处理 常见导航栏效果实现1. 透明导航栏2. 滚动渐变导航栏3. 自定义返回逻辑 解决常见问题1. …...
小程序消息订阅的整个实现流程
以下是微信小程序消息订阅的完整实现流程,分为 5个核心步骤 和 3个关键注意事项: 一、消息订阅完整流程 步骤1:配置订阅消息模板 登录微信公众平台进入「功能」→「订阅消息」选择公共模板或申请自定义模板,获取模板IDÿ…...