// ==UserScript==
// @name 【收费版】2026年广东省药师协会自动学习器(执业药师继续教育)补丁版
// @namespace http://tampermonkey.net/
// @version 2.1.2
// @description 自动学习,需付费激活后使用。购买请联系:微信号:jiaobenjinlin
// @match https://www.gdysxh.com/my_classes/public_course/index.html
// @match https://www.gdysxh.com/my_classes/public_course/video/*
// @match https://www.gdysxh.com/my_classes/classes/index.html
// @match https://www.gdysxh.com/my_classes/classes/video/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
// @grant GM_setClipboard
// @grant GM_registerMenuCommand
// @grant GM_addStyle
// @grant GM_xmlhttpRequest
// ==/UserScript==
(function() {
'use strict';
const CONFIG = {
contact: "微信:jiaobenjinlin",
price: "10元/永久",
secretKey: "GDYSXH_SECRET_KEY_2024_7x9k2m4p_YOUR_OWN_STRING",
wechatQrcodeUrl: "https://s41.ax1x.com/2026/06/11/pmKcuxH.jpg",
debug: false,
speedConfig: {
public_course: {
speeds: [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0],
defaultSpeed: 4.0,
title: "公需课"
},
classes: {
speeds: [1.5, 2.0, 2.5],
defaultSpeed: 2.0,
title: "专业课"
}
}
};
function getPageType() {
const url = window.location.href;
if (url.includes('/public_course/')) {
return 'public_course';
} else if (url.includes('/classes/')) {
return 'classes';
}
return 'public_course';
}
GM_addStyle(`
#video-control-panel {
position: fixed;
top: 10px;
left: 10px;
z-index: 99999;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 12px;
padding: 12px 16px;
color: white;
font-family: system-ui, -apple-system, sans-serif;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
backdrop-filter: blur(10px);
border: 1px solid rgba(255,255,255,0.2);
min-width: 240px;
}
#video-control-panel .title {
font-size: 16px;
font-weight: bold;
margin-bottom: 8px;
text-align: center;
letter-spacing: 1px;
border-bottom: 1px solid rgba(255,255,255,0.3);
padding-bottom: 5px;
}
#video-control-panel .speed-buttons {
display: flex;
gap: 8px;
flex-wrap: wrap;
justify-content: center;
margin-bottom: 8px;
}
#video-control-panel .speed-btn {
background: rgba(255,255,255,0.2);
border: none;
color: white;
padding: 5px 12px;
border-radius: 20px;
cursor: pointer;
font-size: 14px;
transition: all 0.2s ease;
font-weight: 500;
}
#video-control-panel .speed-btn:hover {
background: rgba(255,255,255,0.4);
transform: scale(1.05);
}
#video-control-panel .speed-btn.active {
background: #ffd700;
color: #333;
box-shadow: 0 0 8px rgba(255,215,0,0.5);
}
#video-control-panel .pause-btn {
background: #ff4d4f;
border: none;
color: white;
padding: 5px 12px;
border-radius: 20px;
cursor: pointer;
font-size: 14px;
transition: all 0.2s ease;
font-weight: 500;
margin-top: 5px;
width: 100%;
}
#video-control-panel .pause-btn:hover {
background: #ff7875;
transform: scale(1.02);
}
#video-control-panel .pause-btn.paused {
background: #52c41a;
}
#video-control-panel .speed-note {
font-size: 12px;
text-align: center;
color: rgba(255,255,255,0.7);
border-top: 1px solid rgba(255,255,255,0.2);
padding-top: 6px;
margin-top: 4px;
line-height: 1.3;
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateX(-20px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
#video-control-panel {
animation: slideIn 0.3s ease;
}
.activation-modal {
background: white;
padding: 30px;
border-radius: 12px;
max-width: 500px;
width: 90%;
max-height: 90vh;
overflow-y: auto;
box-shadow: 0 5px 20px rgba(0,0,0,0.3);
font-family: system-ui, -apple-system, sans-serif;
}
.activation-modal h2 {
margin: 0 0 10px 0;
color: #333;
text-align: center;
}
.activation-modal .desc {
color: #666;
margin-bottom: 20px;
text-align: center;
}
.activation-modal .machine-box {
background: #f5f5f5;
padding: 12px;
border-radius: 6px;
margin-bottom: 20px;
}
.activation-modal .machine-label {
font-size: 12px;
color: #999;
margin-bottom: 5px;
}
.activation-modal .machine-code {
font-family: monospace;
font-size: 13px;
word-break: break-all;
background: #fff;
padding: 8px;
border-radius: 4px;
border: 1px solid #ddd;
}
.activation-modal .btn-copy {
margin-top: 8px;
padding: 4px 12px;
background: #1890ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
width: 100%;
}
.activation-modal .qr-area {
text-align: center;
margin-bottom: 20px;
padding: 15px;
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
border-radius: 12px;
}
.activation-modal .qr-title {
font-size: 15px;
color: #2c3e50;
margin-bottom: 12px;
font-weight: bold;
}
.activation-modal .qr-img {
width: 180px;
height: 180px;
border-radius: 12px;
border: 2px solid #fff;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
object-fit: contain;
}
.activation-modal .qr-note {
font-size: 12px;
color: #555;
margin-top: 12px;
}
.activation-modal .license-input {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 6px;
font-family: monospace;
box-sizing: border-box;
margin-bottom: 20px;
}
.activation-modal .btn-activate {
flex: 1;
padding: 10px;
background: #52c41a;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
font-weight: bold;
}
.activation-modal .btn-activate:hover {
background: #45a817;
}
.activation-modal .btn-close {
padding: 10px 20px;
background: #999;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
}
.activation-modal .btn-close:hover {
background: #777;
}
.activation-modal .footer {
border-top: 1px solid #eee;
padding-top: 15px;
font-size: 12px;
color: #999;
text-align: center;
}
.activation-modal .btn-group {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
.status-badge {
position: fixed;
bottom: 20px;
right: 20px;
background: #52c41a;
color: white;
padding: 6px 12px;
border-radius: 20px;
font-size: 12px;
z-index: 99999;
font-family: system-ui, -apple-system, sans-serif;
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
cursor: pointer;
transition: all 0.3s ease;
}
.status-badge:hover {
transform: scale(1.05);
background: #45a817;
}
.status-badge.inactive {
background: #ff4d4f;
}
`);
function getMachineId() {
let machineId = GM_getValue('machine_id', null);
if (!machineId) {
machineId = generateMachineFingerprint();
GM_setValue('machine_id', machineId);
if (CONFIG.debug) console.log('[激活] 生成本机ID:', machineId);
}
return machineId;
}
function generateMachineFingerprint() {
const components = [
navigator.userAgent,
navigator.language,
screen.width + 'x' + screen.height,
screen.colorDepth,
new Date().getTimezoneOffset(),
navigator.hardwareConcurrency || 0,
navigator.deviceMemory || 0
];
let fingerprint = components.join('|');
let hash = 0;
for (let i = 0; i < fingerprint.length; i++) {
hash = ((hash << 5) - hash) + fingerprint.charCodeAt(i);
hash |= 0;
}
return 'MACHINE_' + Math.abs(hash).toString(16) + '_' + generateRandomString(8);
}
function generateRandomString(length) {
let result = '';
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < length; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
function simpleHash(str) {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = ((hash << 5) - hash) + str.charCodeAt(i);
hash |= 0;
}
return Math.abs(hash).toString(16);
}
function verifyLicense(license, currentMachineId) {
if (!license || license.length < 10) {
return { valid: false, reason: '激活码格式错误' };
}
try {
let decoded;
try {
decoded = atob(license);
} catch(e) {
return { valid: false, reason: '激活码格式错误' };
}
let decrypted = '';
for (let i = 0; i < decoded.length; i++) {
decrypted += String.fromCharCode(decoded.charCodeAt(i) ^ 0x55);
}
const parts = decrypted.split('|');
if (parts.length !== 3) {
return { valid: false, reason: '激活码格式错误' };
}
const [machineId, expireTimestamp, checksum] = parts;
if (machineId !== currentMachineId) {
return { valid: false, reason: '机器码不匹配,请使用本机的激活码' };
}
const expireTime = parseInt(expireTimestamp);
if (isNaN(expireTime)) {
return { valid: false, reason: '激活码格式错误' };
}
if (expireTime < Date.now()) {
return { valid: false, reason: '激活码已过期' };
}
const expectedChecksum = simpleHash(machineId + '|' + expireTimestamp + '|' + CONFIG.secretKey);
if (checksum !== expectedChecksum) {
return { valid: false, reason: '激活码无效' };
}
return { valid: true, expireTimestamp: expireTime };
} catch(e) {
if (CONFIG.debug) console.error('[激活] 验证错误:', e);
return { valid: false, reason: '激活码无效' };
}
}
function isActivated() {
let activated = GM_getValue('activated', false);
if (!activated) {
return false;
}
const expireTime = GM_getValue('expire_time', null);
if (expireTime && expireTime < Date.now()) {
console.log('[激活] 激活码已过期,需要重新激活');
GM_setValue('activated', false);
GM_deleteValue('expire_time');
return false;
}
return true;
}
function showActivationUI() {
const existingOverlay = document.getElementById('activation-overlay');
if (existingOverlay) {
existingOverlay.remove();
}
const machineId = getMachineId();
const overlay = document.createElement('div');
overlay.id = 'activation-overlay';
overlay.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.85);
z-index: 999999;
display: flex;
justify-content: center;
align-items: center;
overflow-y: auto;
`;
const qrcodeHtml = CONFIG.wechatQrcodeUrl && CONFIG.wechatQrcodeUrl !== "https://your-image-host.com/wechat-qrcode.png"
? ``
: `