您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
https://i.shengcaiyoushu.com/volunteer/operation/activity/user?id=XXX 作为一个懒人,不想手动统计,干脆做个工具一目了然
// ==UserScript== // @name 生财有术志愿者后台打卡统计专用 // @namespace http://www.heigoou.com // @version 1.1 // @description https://i.shengcaiyoushu.com/volunteer/operation/activity/user?id=XXX 作为一个懒人,不想手动统计,干脆做个工具一目了然 // @author 北封,jexxx // @match https://i.shengcaiyoushu.com/volunteer/operation/activity/user* // @require https://fastly.jsdelivr.net/npm/[email protected]/dist/echarts.min.js // @icon data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMzYwcHgiIGhlaWdodD0iMzYwcHgiIHZpZXdCb3g9IjAgMCAzNjAgMzYwIiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgogICAgPCEtLSBHZW5lcmF0b3I6IFNrZXRjaCA2MC4xICg4ODEzMykgLSBodHRwczovL3NrZXRjaC5jb20gLS0+CiAgICA8dGl0bGU+57yW57uEPC90aXRsZT4KICAgIDxkZXNjPkNyZWF0ZWQgd2l0aCBTa2V0Y2guPC9kZXNjPgogICAgPGRlZnM+CiAgICAgICAgPHBvbHlnb24gaWQ9InBhdGgtMSIgcG9pbnRzPSIxLjEzMzQwMjI0ZS0wNSAwIDM1OS45OTk4NjMgMCAzNTkuOTk5ODYzIDM2MCAxLjEzMzQwMjI0ZS0wNSAzNjAiPjwvcG9seWdvbj4KICAgIDwvZGVmcz4KICAgIDxnIGlkPSIxLjEt5by556qXIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8ZyBpZD0i57yW57uEIj4KICAgICAgICAgICAgPGc+CiAgICAgICAgICAgICAgICA8bWFzayBpZD0ibWFzay0yIiBmaWxsPSJ3aGl0ZSI+CiAgICAgICAgICAgICAgICAgICAgPHVzZSB4bGluazpocmVmPSIjcGF0aC0xIj48L3VzZT4KICAgICAgICAgICAgICAgIDwvbWFzaz4KICAgICAgICAgICAgICAgIDxnIGlkPSJDbGlwLTIiPjwvZz4KICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xOTAuMTU5NCwzMzUuMDA1MiBDOTYuNTE4NCwzNDAuOTk2MiAxOS4wMDA0LDI2My40NzgyIDI0Ljk5MzQsMTY5LjgzODIgQzI5Ljk0NjQsOTIuNDQ2MiA5Mi40NjE0LDI5LjkzNjIgMTY5Ljg1MjQsMjQuOTkxMiBDMjYzLjQ4MjQsMTkuMDA5MiAzNDAuOTg3NCw5Ni41MTMyIDMzNS4wMDg0LDE5MC4xNDQyIEMzMzAuMDYzNCwyNjcuNTM3MiAyNjcuNTUzNCwzMzAuMDUzMiAxOTAuMTU5NCwzMzUuMDA1MiBNMTg4LjQ0ODQsMC4xOTQyIEM4Mi41NDE0LC00LjY3MzggLTQuNjczNiw4Mi41NDIyIDAuMTk0NCwxODguNDQ3MiBDNC40Mzg0LDI4MC43ODMyIDc5LjIxNjQsMzU1LjU2MTIgMTcxLjU1MjQsMzU5LjgwNjIgQzI3Ny40NTc0LDM2NC42NzQyIDM2NC42NzQ0LDI3Ny40NTkyIDM1OS44MDU0LDE3MS41NTIyIEMzNTUuNTU4NCw3OS4yMTYyIDI4MC43ODM0LDQuNDQxMiAxODguNDQ4NCwwLjE5NDIiIGlkPSJGaWxsLTEiIGZpbGw9IiMwQTVENEYiIG1hc2s9InVybCgjbWFzay0yKSI+PC9wYXRoPgogICAgICAgICAgICA8L2c+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNjYuMzQ5OCwyMDguOTY4MSBMMTY2LjM0OTgsMjIxLjc4OTEgTDE0OC43MjM4LDIyMS43ODkxIEMxNDguMDYxOCwyMjEuNzg5MSAxNDcuODA3OCwyMjAuOTI0MSAxNDguMzYzOCwyMjAuNTY0MSBMMTY2LjM0OTgsMjA4Ljk2ODEgWiBNMTkzLjY0ODgsMTYxLjQ5MTEgTDE5My42NDg4LDE0OS4wMTAxIEwyMTAuNTk4OCwxNDkuMDEwMSBDMjExLjMzNjgsMTQ5LjAxMDEgMjExLjYyMDgsMTQ5Ljk3NTEgMjEwLjk5NzgsMTUwLjM3MzEgTDE5My42NDg4LDE2MS40OTExIFogTTI0Ny40NjY4LDIyMS43ODkxIEwxOTMuODc3OCwyMjEuNzg5MSBMMTkzLjY1MDgsMjE5LjU5MjEgTDE5My42NDg4LDE5MS40NzkxIEwyNDguMTM1OCwxNTYuNzY4MSBDMjUzLjQ2MzgsMTUzLjM3MzEgMjU2Ljc0NTgsMTQ1LjM5ODEgMjU0LjIwMzgsMTM2Ljg1NTEgQzI1MS43ODI4LDEyOS4yNzIxIDI0NC43MzM4LDEyNC4xMjQxIDIzNi43NzI4LDEyNC4xMjQxIEwxOTMuNjQ4OCwxMjQuMTI0MSBMMTkzLjY0ODgsODcuOTcyMSBDMTkzLjY0ODgsODQuMTYzMSAxOTAuNTYwOCw4MS4wNzYxIDE4Ni43NTE4LDgxLjA3NjEgTDE3My4yNDI4LDgxLjA3NjEgQzE2OS40MzU4LDgxLjA3NjEgMTY2LjM0OTgsODQuMTYyMSAxNjYuMzQ5OCw4Ny45NjkxIEwxNjYuMzQ5OCwxMjQuMTI0MSBMMTEyLjc0NjgsMTI0LjEyNDEgQzEwNy45Nzk4LDEyNC4xMjQxIDEwNC4xMTI4LDEyNy45ODkxIDEwNC4xMTI4LDEzMi43NTkxIEwxMDQuMTEyOCwxNDAuMjA5MSBDMTA0LjExMjgsMTQ1LjA3MTEgMTA4LjA1MzgsMTQ5LjAxMDEgMTEyLjkxMjgsMTQ5LjAxMDEgTDE2Ni4zNDk4LDE0OS4wMTAxIEwxNjYuMzQ5OCwxNzkuMDEzMSBMMTEyLjczMjgsMjEzLjQxODEgQzEwNi44Njg4LDIxNy4xODgxIDEwMy4yMjM4LDIyNS44MTIxIDEwNS40OTQ4LDIzMy41NzIxIEMxMDcuODUwOCwyNDEuMjM5MSAxMTQuOTMzOCwyNDYuNDc0MSAxMjIuOTU2OCwyNDYuNDc0MSBMMTY2LjM0OTgsMjQ2LjQ3NDEgTDE2Ni4zNDk4LDI3NS41NDQxIEMxNjYuMzQ5OCwyNzkuMzU0MSAxNjkuNDM3OCwyODIuNDQwMSAxNzMuMjQ1OCwyODIuNDQwMSBMMTg2Ljc2MDgsMjgyLjQ0MDEgQzE5MC41NjQ4LDI4Mi40NDAxIDE5My42NDg4LDI3OS4zNTgxIDE5My42NDg4LDI3NS41NTMxIEwxOTMuNjQ4OCwyNDYuNDc0MSBMMjQ3LjU2MDgsMjQ2LjQ3NDEgQzI1Mi4xNTY4LDI0Ni40NzQxIDI1NS44ODM4LDI0Mi43NDYxIDI1NS44ODM4LDIzOC4xNTAxIEwyNTUuODgzOCwyMzAuMjA0MSBDMjU1Ljg4MzgsMjI1LjU1NzEgMjUyLjExNjgsMjIxLjc4OTEgMjQ3LjQ2NjgsMjIxLjc4OTEgTDI0Ny40NjY4LDIyMS43ODkxIFoiIGlkPSJGaWxsLTMiIGZpbGw9IiMwQTVENEYiPjwvcGF0aD4KICAgICAgICAgICAgPHBhdGggZD0iTTIyOC45Mjg5LDEwNi42NjQ0IEwyNDEuMTM0OSwxMDYuNjY0NCBDMjQ1LjI0NTksMTA2LjY2NDQgMjQ4LjU3ODksMTAzLjMzMTQgMjQ4LjU3ODksOTkuMjIxNCBMMjQ4LjU3ODksODguNTIzNCBDMjQ4LjU3ODksODQuNDExNCAyNDUuMjQzOSw4MS4wNzY0IDI0MS4xMzE5LDgxLjA3NjQgTDIyOC45Mjg5LDgxLjA3NjQgQzIyNC44MTg5LDgxLjA3NjQgMjIxLjQ4NTksODQuNDA5NCAyMjEuNDg1OSw4OC41MTk0IEwyMjEuNDg1OSw5OS4yMjE0IEMyMjEuNDg1OSwxMDMuMzMxNCAyMjQuODE4OSwxMDYuNjY0NCAyMjguOTI4OSwxMDYuNjY0NCIgaWQ9IkZpbGwtNSIgZmlsbD0iIzBBNUQ0RiI+PC9wYXRoPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+ // @grant none // @license GPLv3 // @run-at document-end // ==/UserScript== (function () { 'use strict'; let baseData = data; let stage = baseData.stage; let xData = []; let dayInfo = {}; for (let d = 0; d < stage.length; d++) { let dayItem = stage[d]; let time = dayItem.gmt_start * 1000; if (time > new Date().getTime()) { // 还没到的时间,就不统计了 break; } let date = new Date(time); let year = date.getFullYear(); let month = date.getMonth() + 1; // 月份 let day = date.getDate(); // 日 let dayStr = year + '-' + month + '-' + day; let dayData = { id: dayItem.id, idx: dayItem.idx, name: dayItem.name, dayStr: dayStr, }; dayInfo[dayData.id] = dayData; xData.push(dayData.name + '\r\n' + dayData.dayStr); } $('.cxd-Panel--form').after('<div id="bf-container" style="width: 100%;height: 400px"></div>'); $('#bf-container').after('<div id="pf-container" style="width: 100%;height: 400px"></div>'); $('#pf-container').after('<div id="text-container" style="width: 90%;margin-left:auto;"></div>') $.post(window.location.href.replace('user', 'user/ajax'), function (response) { var items = response.data.items var result = {}; // let totalPeople = Object.keys(response.data.extra.user).length; let yDaKaDataObject = {}; const days = Object.keys(dayInfo); const highPoints = []; // 重点关注对象 let wxids = new Set(); for (let dd = 0; dd < days.length; dd++) { const dInfo = dayInfo[days[dd]]; for (var k = 0; k < items.length; k++) { const item = items[k]; if (item.identity) { // identity: "志愿者" 领队 教练角色不统计 continue; } wxids.add(item.info['微信号(微信ID)']); yDaKaDataObject[dInfo['id']] = yDaKaDataObject[dInfo['id']] || {}; var cnt = item.project_cnt; if (!result[cnt]) { result[cnt] = []; } var name = response.data.extra.user[item.xq_group_number]['name']; var wx_name = response.data.extra.user[item.xq_group_number]['wx_name']; if (name != wx_name) { name = name + '(' + wx_name + ')'; } var user = name; var project_left_cnt = item.project_left_cnt; if (dd === 0) highPoints.push({ user, cnt, project_left_cnt }); if (!result[cnt].includes(user)) { result[cnt].push(user); } const project = item.project; yDaKaDataObject[dInfo['id']]['n'] = yDaKaDataObject[dInfo['id']]['n'] || []; yDaKaDataObject[dInfo['id']]['y'] = yDaKaDataObject[dInfo['id']]['y'] || []; if (project) { if (project[dInfo['id']]) { yDaKaDataObject[dInfo['id']]['y'].push(user); } else { yDaKaDataObject[dInfo['id']]['n'].push(user); } } else { if (!yDaKaDataObject[dInfo['id']]['n'].includes(user)) { yDaKaDataObject[dInfo['id']]['n'].push(user); } } } } let yNoDaKaData = []; let yDaKaData = []; for (let da = 0; da < days.length; da++) { const dayDaka = yDaKaDataObject[days[da]]; const dayStep = dayInfo[days[da]]; let daKaData = { value: dayDaka['y'].length, names: dayDaka['y'], percent: (Math.round((dayDaka['y'].length / (dayDaka['y'].length+dayDaka['n'].length)) * 100) / 100), }; yDaKaData.push(daKaData); let ndaKaData = { value: dayDaka['n'].length, names: dayDaka['n'], percent: (Math.round((dayDaka['n'].length / (dayDaka['y'].length+dayDaka['n'].length)) * 100) / 100), }; yNoDaKaData.push(ndaKaData) } var text = ''; var keys = Object.keys(result); var step = 0; var _highPoints = highPoints.sort(function (a, b) { return Number(a.cnt) - Number(b.cnt); }); for (var j = 0; j < keys.length; j++) { var day = keys[j]; var people = result[day]; step = step + people.length; text += '完成打卡 ' + day + ' 天的有 ' + people.length + ' 人,他们是:' + people + '<br>'; } // console.log(text); // console.log(yNoDaKaData[yNoDaKaData.length-1].names); text += '-------------------------华丽的分割线-------------------------------------<br>' text += '今日未打卡人员>>>' + yNoDaKaData[yNoDaKaData.length - 1].names+'<br><br>'; text += '微信ID:'; for(let wId of wxids){ text += wId+' , '; } $('#text-container').html(text) var dom = document.getElementById('bf-container'); var pdom = document.getElementById('pf-container'); var myChart = echarts.init(dom, null, { renderer: 'canvas', useDirtyRect: false }); var myChart2 = echarts.init(pdom, null, { renderer: 'canvas', useDirtyRect: false }); var option; option = { tooltip: { trigger: 'axis', backgroundColor: '#FFFFFF', borderColor: '#EEF1F7', borderWidth: 1, textStyle: { width: 160, height: 250, lineHeight: 24, color: '#666666', fontSize: '14', fontFamily: 'SourceHanSansCN-Normal' }, formatter: params => { // 获取xAxis data中的数据 let dataStr = `<div><p style="font-weight:bold;margin:0 8px 15px;">${params[0].axisValue} 打卡统计</p></div>` params.forEach(item => { dataStr += `<div> <div style="margin: 0 8px;"> <span style="display:inline-block;margin-right:5px;width:10px;height:10px;background-color:${item.color};"></span> <span>${item.seriesName} ${item.data.percent}:</span> <span style="float:right;color:#000000;margin-left:20px;">${item.data.value}人</span>`; let names = item.data.names; names.forEach(name => { dataStr += `${name} ` }); // // dataStr += `</div> </div>` }) return dataStr } }, legend: { }, // grid: { // left: '3%', // right: '4%', // bottom: '3%', // containLabel: true // }, xAxis: { type: 'category', data: xData }, yAxis: [ { type: 'value', name: '积极打卡', }, { type: 'value', name: '偷懒了~', }, ], series: [ { name: '积极打卡', type: 'bar', stack: 'total', label: { show: true }, emphasis: { focus: 'series' }, data: yDaKaData, }, { name: '偷懒了~', type: 'bar', stack: 'total', label: { show: true }, emphasis: { focus: 'series' }, data: yNoDaKaData }, ] }; var option2 = { xAxis: { type: 'category', data: _highPoints.map(item => item.user), axisLabel: { show: true, interval: 0, rotate: 40, textStyle: { color: '#333' } }, }, yAxis: [ { type: 'value', name: '打卡', }, ], series: [ { name: '打卡', type: 'bar', stack: 'total', label: { show: true }, emphasis: { focus: 'series' }, data: _highPoints.map(item => item.cnt), }, ] }; if (option && typeof option === 'object') { myChart.setOption(option); } if (option2 && typeof option2 === 'object') { myChart2.setOption(option2); } window.addEventListener('resize', () => { myChart.resize(); myChart2.resize(); }); }); })();