组件大师
|
目前大家往勋章博物馆贴属性,多采用截图的形式
导致有两个缺点:
1. 获取的图片不是gif而是静态图片,不能完整地展示勋章卡面
2. 如果勋章描述是英文、日文、火星文、摩尔斯电码之类的内容,手打和文字识别起来有亿亿点困难
3. 图片太长太大,不够美观
现在既然我是勋章博物馆的站员了,那么我就应该负起责任
于是基于黑达克之前的勋章属性格式,我写了一个脚本
方便大家在勋章博物馆贴属性的时候,快速的获取勋章卡面和属性,同时也避免打错字之类的情况发生
安装这个脚本时候,可以在我的勋章界面,或者帖子中任意一个勋章点击Ctrl+右键
粘贴板里面暂存了对应勋章的勋章卡面图片链接 + 勋章描述 + 勋章属性
其中勋章卡面是直接使用了勋章的图片链接,所以无需右键另存为图片再重新上传
其中勋章属性因为不知道是手动升级还是自动升级,所以给出了两种格式供大家手动删除
在新勋章上新的时间点推出这个脚本,希望大家都安装使用
使用方法:在我的勋章界面和帖子内的勋章,ctrl+鼠标右键,复制好属性,然后找个地方粘贴即可
在升级的时候右键保存一下属性和图片链接
先暂存到本地的TXT和Word文档内,等勋章博物馆发了勋章贴之后再贴属性
此外推荐大家使用纯文本编辑模式,这样能保证格式更不容易受到影响
效果演示
@Name @Match
- // ==UserScript==
- // @name GM论坛勋章博物馆属性复制助手
- // @namespace http://tampermonkey.net/
- // @version 1.2
- // @description 使用方法,ctrl+鼠标右键,复制
- // @author YourName
- // @match https://www.gamemale.com/wodexunzhang-showxunzhang.html?action=my
- // @match https://www.gamemale.com/thread-*
- // @match https://www.gamemale.com/forum.php?mod=viewthread&tid=*
- // @grant none
- // @icon https://www.gamemale.com/template/mwt2/extend/img/favicon.ico
- // ==/UserScript==
- (function () {
- 'use strict'
- document.addEventListener('contextmenu', async (e) => {
- if (!e.ctrlKey) return
- e.preventDefault()
- try {
- const target = findValidTarget(e.target)
- if (!target) return
- // 统一数据采集
- const rawData = collectRawData(target)
- // 统一数据处理
- const formattedData = processRawData(rawData)
- console.log(formattedData)
- const result = formatFinalData(formattedData)
- await navigator.clipboard.writeText(result)
- showFeedback('✅ 数据已复制')
- } catch (err) {
- console.error('处理失败:', err)
- showFeedback('⚠ 数据提取失败')
- }
- })
- // 统一数据采集
- function collectRawData(target) {
- const isCase1 = target.matches('img[tip]')
- const isCase2 = target.matches('.mytip')
- if (isCase1) {
- return {
- type: 'case1',
- imgSrc: target.src,
- tipHtml: target.getAttribute('tip'),
- element: target
- }
- }
- if (isCase2) {
- const myblok = target.closest('.myblok')
- return {
- type: 'case2',
- imgSrc: myblok?.querySelector('.myimg img')?.src,
- titleHtml: target.querySelector('.mingcheng')?.innerHTML,
- descriptionText: target.querySelector('.shuoming')?.textContent,
- attributes: Array.from(target.querySelectorAll('.jiage.shuxing'))
- .map(p => p.innerHTML),
- element: myblok
- }
- }
- throw new Error('未知的数据类型')
- }
- // 统一数据处理
- function processRawData(rawData) {
- // 公共字段
- const baseData = {
- imgSrc: rawData.imgSrc || '无图片地址',
- nextLevel: null
- }
- // 类型专属处理
- if (rawData.type === 'case1') {
- const doc = new DOMParser().parseFromString(rawData.tipHtml, 'text/html')
- return {
- ...baseData,
- titleHtml: doc.querySelector('h4')?.innerHTML || '',
- descriptionText: doc.querySelector('p:not(.wode_shuxing p)')?.textContent || '',
- attributes: Array.from(doc.querySelectorAll('.wode_shuxing p'))
- .map(p => p.innerHTML),
- nextLevel: findNextLevel(doc)
- }
- }
- if (rawData.type === 'case2') {
- return {
- ...baseData,
- titleHtml: rawData.titleHtml || '',
- descriptionText: rawData.descriptionText || '',
- attributes: rawData.attributes,
- nextLevel: findNextLevel(rawData.element)
- }
- }
- }
- // 统一字段格式化
- function formatFinalData(processedData) {
- const formattedData = [
- `[img]${processedData.imgSrc}[/img]`,
- `[font=黑体][b]${formatTitle(processedData.titleHtml)}[/b][/font]`,
- `[font=仿宋,仿宋_GB2312][b][color=Gray]${formatDescription(processedData.descriptionText)}[/color][/b][/font]`,
- `[font=楷体,楷体_GB2312][b]${formatAttributes(processedData.attributes)}[/b][/font]` +
- (processedData.nextLevel ? `[font=微软雅黑][b]▕▏[/b][/font][font=楷体, 楷体_GB2312][b]升级条件:${processedData.nextLevel}[/b][/font]` : ''),
- ].filter(Boolean)
- // 添加空行,避免影响后面的格式
- // 看不出来,还是算了吧
- // formattedData.push('')
- return formattedData.join('\n')
- }
- // 格式化函数组
- function formatTitle(html) {
- return html
- .replace(/<\/?h4>/g, '')
- .replace(/<b>/g, '')
- .replace(/<\/b>/g, ' ')
- }
- function formatDescription(text) {
- return text.trim().replace(/\s+/g, ' ')
- }
- function formatAttributes(attrs = []) {
- // 分类存储数据
- const { trigger, reply, post } = attrs.reduce((acc, item) => {
- const text = item.replace(/\s+|( )+/g, ' ').replace(/ (\+|-)/g, '$1').trim()
- // 提取触发概率
- if (text.includes('触发几率')) {
- acc.trigger = text.match(/\d+%/) || []
- return acc
- }
- // 分类回帖/发帖属性
- const [type, ...values] = text.split(' ')
- if (type === '回帖') acc.reply.push(...values)
- if (type === '发帖') acc.post.push(...values)
- return acc
- }, { trigger: '', reply: [], post: [] })
- // console.log(trigger, reply, post)
- // 构建结果字符串
- const parts = []
- if (trigger) parts.push(trigger)
- if (reply.length) parts.push(`回帖${reply.join(' ')}`)
- if (post.length) parts.push(`发帖${post.join(' ')}`)
- if (attrs.length === 0) {
- return '无属性'
- } else {
- return parts.join('、').replace(/(%)、/, '$1 ')
- }
- }
- // 辅助函数
- function findValidTarget(startElement) {
- if (startElement.matches('img[tip]')) return startElement
- const myblok = startElement.closest('.myblok')
- if (myblok) {
- const mytip = myblok.querySelector('.mytip')
- if (mytip) return mytip
- }
- throw new Error('未找到有效数据元素')
- }
- // 消耗xx属性,或者属性≥xx
- function findNextLevel(element) {
- const nextLevelDiv = Array.from(element.querySelectorAll('.wode_shuxing, .jiage'))
- .find(el => el.textContent.includes('下一级'))
- if (!nextLevelDiv) return null
- // 清理文本
- const processedText = nextLevelDiv.textContent
- .replace(/下一级/g, '')
- .replace(/ /g, ' ')
- .replace(/\s+/g, ' ')
- .trim()
- // 使用正则匹配【属性名 数字/数字】格式
- const matches = processedText.match(/([\u4e00-\u9fa5]+)\s*(\d+)\/(-?\d+)/)
- if (!matches) return null
- const attribute = matches[1] // 属性名(如发帖数、金币等)
- const requiredValue = matches[3] // 斜杠后的数字(如404)
- return `消耗${requiredValue}${attribute} 或者 ${attribute}≥${requiredValue}`
- }
- function showFeedback(message) {
- showPrompt(null, null, `<i>${message}</i>`, 2000)
- }
- })()
复制代码
此外我最近也抽空把几乎所有的博物馆勋章都进行了整理
主要内容是,如果你的帖子包含的所有的属性、卡面、描述的其中之一,且不是截图的形式,都会被我置顶方便查看
如果一个勋章的属性、卡面、描述,由多个回帖人共同提供,我则会自己弄一份整合版方便置顶,
目前还有以下勋章缺乏完整的属性、卡面、描述。放在折叠的部分,期待有缘人补充
(过于古老的故事类和奖品类勋章未统计,因为发行量稀少且难以补充)
最后希望大家多多支持我的工作,把勋章博物馆弄得整整齐齐漂漂亮亮的
同时发现这是我的第100个主题帖,那就爆500金币庆祝一下吧 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
评分
-
查看全部评分
|